pylance-release icon indicating copy to clipboard operation
pylance-release copied to clipboard

Can't go to definition on `shutil.rmtree`

Open Evan0000000000 opened this issue 1 year ago • 2 comments

Forgive me if this is a duplicate question, I did some searching around the issues and didn't see anything but I also might not be using the right magic words.

Using VSCode 1.85.1, pylance v2024.2.1, Python 3.9 and given statement: from shutil import copyfile, copy, rmtree

The editor highlights copyfile and copy as functions as I'd expect, and Go To Definition navigates to shutil.py in the python install. rmtree however has type _RMtreeType which is in shutil.pyi in the typeshed fallback files in Pylance.

I think I gather from reading here that typeshed falls back to its own stubs for libraries that don't declare themselves to support typing yet, but I'm not clear why (whether a product of bad settings on my part or what) you'd see a mix of these behaviors within one library.

Evan0000000000 avatar Feb 14 '24 20:02 Evan0000000000

This is probably due to the fact that the stubs define rmtree as a class (to be precise, a callback Protocol), while at runtime it is defined as a function. Pylance probaby tries to find the runtime definition of the object from the stub definition by making use of the type (i.e. it tries to find a rmtree class in the source file), but fails as it is a function.

Viicos avatar Feb 16 '24 21:02 Viicos

@Viicos, yes, that's what's going on. We find rmtree as a variable in the stubs and then try to find a matching variable in the source file. SourceMapper._addVariableDeclarations gets called and ignores anything that isn't either a variable or an alias.

SourceMapper._addVariableDeclarations (c:\src\pyrx\packages\pyright\packages\pyright-internal\src\analyzer\sourceMapper.ts:482)
SourceMapper._findVariableDeclarationsByName (c:\src\pyrx\packages\pyright\packages\pyright-internal\src\analyzer\sourceMapper.ts:365)
<anonymous> (c:\src\pyrx\packages\pyright\packages\pyright-internal\src\analyzer\sourceMapper.ts:198)
SourceMapper._findVariableDeclarations (c:\src\pyrx\packages\pyright\packages\pyright-internal\src\analyzer\sourceMapper.ts:197)
SourceMapper.findDeclarations (c:\src\pyrx\packages\pyright\packages\pyright-internal\src\analyzer\sourceMapper.ts:87)
<anonymous> (c:\src\pyrx\packages\pyright\packages\pyright-internal\src\languageService\definitionProvider.ts:114)
addDeclarationsToDefinitions (c:\src\pyrx\packages\pyright\packages\pyright-internal\src\languageService\definitionProvider.ts:54)
DefinitionProvider.resolveDeclarations (c:\src\pyrx\packages\pyright\packages\pyright-internal\src\languageService\definitionProvider.ts:185)
DefinitionProvider.getDefinitionsForNode (c:\src\pyrx\packages\pyright\packages\pyright-internal\src\languageService\definitionProvider.ts:170)
DefinitionProvider.getDefinitions (c:\src\pyrx\packages\pyright\packages\pyright-internal\src\languageService\definitionProvider.ts:228)

I verified that go to def works for rmtree if I modify _addVariableDeclarations to also add function decls, but I don't know what the best fix is here.

        } else if (isFunctionDeclaration(decl)) {
            this._addClassOrFunctionDeclarations(decl, result, recursiveDeclCache);
        }

debonte avatar Feb 17 '24 00:02 debonte

Thank you both for taking a look and providing the details (and for updating to a better title Erik); I'm happy to provide further info if I can help, just @ me.

Evan0000000000 avatar Feb 19 '24 15:02 Evan0000000000