@skirpichev, lets take this in the following way.
```
        integrand, limits = self.function, self.limits
        isyms = integrand.AAA #see below
        for xab in limits:
            if len(xab) == 1:
                isyms.add(xab[0])
                continue  # it may be removed later
            elif len(xab) == 3 and xab[1] == xab[2]:  # XXX naive equality test
                return True  # integral collapsed
            if xab[0] in isyms:
                # take it out of the symbols since it will be replace
                # with whatever the limits of the integral are
                isyms.remove(xab[0])
```
Consider ```self = Integral(Sum(x**n, (n, 1, 10)), (x, 1, k))``` and if ```AAA is equivalent to free_symbols``` then ```isyms will be set([x])``` and if that is ```atoms(Symbol)``` ```isyms will be set([n, x])```. Even the bound variables are taken into account using ```atoms(Symbol)```, in the last line of above code, it will be removed from ```isyms```.

Note: Since ```free_symbols``` can ignore bound variables, the last if block can be removed from the code. To be specific, second line of above code should be changed as ```isyms = self.free_symbol```

The modified code will be,
```
limits = self.limits
        isyms = self.free_symbols
        for xab in limits:
            if len(xab) == 1:
                isyms.add(xab[0])
                continue  # it may be removed later
            elif len(xab) == 3 and xab[1] == xab[2]:  # XXX naive equality test
                return True  # integral collapsed
            # add in the new symbols
            for i in xab[1:]:
                isyms.update(i.free_symbols)
        # if there are no surviving symbols then the result is a number
        return len(isyms) == 0
```