@@ -48,8 +48,8 @@ use crate::semantic_index::SemanticIndex;
48
48
use crate :: stdlib:: builtins_module_scope;
49
49
use crate :: types:: diagnostic:: { TypeCheckDiagnostic , TypeCheckDiagnostics } ;
50
50
use crate :: types:: {
51
- builtins_symbol_ty, definitions_ty, global_symbol_ty, symbol_ty, symbol_ty_by_id ,
52
- BytesLiteralType , ClassType , FunctionType , StringLiteralType , Type , UnionBuilder ,
51
+ builtins_symbol_ty, definitions_ty, global_symbol_ty, symbol_ty, BytesLiteralType , ClassType ,
52
+ FunctionType , StringLiteralType , Type , UnionBuilder ,
53
53
} ;
54
54
use crate :: Db ;
55
55
@@ -1865,15 +1865,17 @@ impl<'db> TypeInferenceBuilder<'db> {
1865
1865
/// Look up a name reference that isn't bound in the local scope.
1866
1866
fn lookup_name ( & self , name : & ast:: name:: Name ) -> Type < ' db > {
1867
1867
let file_scope_id = self . scope . file_scope_id ( self . db ) ;
1868
- let symbols = self . index . symbol_table ( file_scope_id) ;
1869
- let symbol = symbols
1868
+ let is_defined = self
1869
+ . index
1870
+ . symbol_table ( file_scope_id)
1870
1871
. symbol_by_name ( name)
1871
- . expect ( "Expected the symbol table to create a symbol for every Name node" ) ;
1872
+ . expect ( "Symbol table should create a symbol for every Name node" )
1873
+ . is_defined ( ) ;
1872
1874
1873
1875
// In function-like scopes, any local variable (symbol that is defined in this
1874
1876
// scope) can only have a definition in this scope, or be undefined; it never references
1875
1877
// another scope. (At runtime, it would use the `LOAD_FAST` opcode.)
1876
- if !symbol . is_defined ( ) || !self . scope . is_function_like ( self . db ) {
1878
+ if !is_defined || !self . scope . is_function_like ( self . db ) {
1877
1879
// Walk up parent scopes looking for a possible enclosing scope that may have a
1878
1880
// definition of this name visible to us (would be `LOAD_DEREF` at runtime.)
1879
1881
for ( enclosing_scope_file_id, _) in self . index . ancestor_scopes ( file_scope_id) {
@@ -1921,28 +1923,35 @@ impl<'db> TypeInferenceBuilder<'db> {
1921
1923
let ast:: ExprName { range : _, id, ctx } = name;
1922
1924
let file_scope_id = self . scope . file_scope_id ( self . db ) ;
1923
1925
1924
- // if we're inferring types of deferred expressions, always treat them as public symbols
1925
- if self . is_deferred ( ) {
1926
- let symbols = self . index . symbol_table ( file_scope_id) ;
1927
- let symbol = symbols
1928
- . symbol_id_by_name ( id)
1929
- . expect ( "Expected the symbol table to create a symbol for every Name node" ) ;
1930
- return symbol_ty_by_id ( self . db , self . scope , symbol) ;
1931
- }
1932
-
1933
1926
match ctx {
1934
1927
ExprContext :: Load => {
1935
1928
let use_def = self . index . use_def_map ( file_scope_id) ;
1936
- let use_id = name. scoped_use_id ( self . db , self . scope ) ;
1937
- let may_be_unbound = use_def. use_may_be_unbound ( use_id) ;
1929
+ let symbol = self
1930
+ . index
1931
+ . symbol_table ( file_scope_id)
1932
+ . symbol_id_by_name ( id)
1933
+ . expect ( "Expected the symbol table to create a symbol for every Name node" ) ;
1934
+ // if we're inferring types of deferred expressions, always treat them as public symbols
1935
+ let ( definitions, may_be_unbound) = if self . is_deferred ( ) {
1936
+ (
1937
+ use_def. public_definitions ( symbol) ,
1938
+ use_def. public_may_be_unbound ( symbol) ,
1939
+ )
1940
+ } else {
1941
+ let use_id = name. scoped_use_id ( self . db , self . scope ) ;
1942
+ (
1943
+ use_def. use_definitions ( use_id) ,
1944
+ use_def. use_may_be_unbound ( use_id) ,
1945
+ )
1946
+ } ;
1938
1947
1939
1948
let unbound_ty = if may_be_unbound {
1940
1949
Some ( self . lookup_name ( id) )
1941
1950
} else {
1942
1951
None
1943
1952
} ;
1944
1953
1945
- definitions_ty ( self . db , use_def . use_definitions ( use_id ) , unbound_ty)
1954
+ definitions_ty ( self . db , definitions , unbound_ty)
1946
1955
}
1947
1956
ExprContext :: Store | ExprContext :: Del => Type :: None ,
1948
1957
ExprContext :: Invalid => Type :: Unknown ,
@@ -3686,6 +3695,24 @@ mod tests {
3686
3695
Ok ( ( ) )
3687
3696
}
3688
3697
3698
+ #[ test]
3699
+ fn deferred_annotation_builtin ( ) -> anyhow:: Result < ( ) > {
3700
+ let mut db = setup_db ( ) ;
3701
+ db. write_file ( "/src/a.pyi" , "class C(object): pass" ) ?;
3702
+ let file = system_path_to_file ( & db, "/src/a.pyi" ) . unwrap ( ) ;
3703
+ let ty = global_symbol_ty ( & db, file, "C" ) ;
3704
+
3705
+ let base = ty
3706
+ . expect_class ( )
3707
+ . bases ( & db)
3708
+ . next ( )
3709
+ . expect ( "there should be at least one base" ) ;
3710
+
3711
+ assert_eq ! ( base. display( & db) . to_string( ) , "Literal[object]" ) ;
3712
+
3713
+ Ok ( ( ) )
3714
+ }
3715
+
3689
3716
#[ test]
3690
3717
fn narrow_not_none ( ) -> anyhow:: Result < ( ) > {
3691
3718
let mut db = setup_db ( ) ;
0 commit comments