@@ -318,9 +318,10 @@ impl<'db> TypeInferenceBuilder<'db> {
318
318
self . types . has_deferred |= inference. has_deferred ;
319
319
}
320
320
321
- /// Are we currently inferring types in a stub file?
322
- fn is_stub ( & self ) -> bool {
323
- self . file . is_stub ( self . db . upcast ( ) )
321
+ /// Are we currently inferring types in file with deferred types?
322
+ /// This is true for stub files and files with `__future__.annotations`
323
+ fn are_all_types_deferred ( & self ) -> bool {
324
+ self . index . has_future_annotations ( ) || self . file . is_stub ( self . db . upcast ( ) )
324
325
}
325
326
326
327
/// Are we currently inferring deferred types?
@@ -703,7 +704,7 @@ impl<'db> TypeInferenceBuilder<'db> {
703
704
self . infer_parameters ( parameters) ;
704
705
705
706
// TODO: this should also be applied to parameter annotations.
706
- if self . is_stub ( ) {
707
+ if self . are_all_types_deferred ( ) {
707
708
self . types . has_deferred = true ;
708
709
} else {
709
710
self . infer_optional_annotation_expression ( returns. as_deref ( ) ) ;
@@ -831,9 +832,9 @@ impl<'db> TypeInferenceBuilder<'db> {
831
832
self . infer_expression ( & keyword. value ) ;
832
833
}
833
834
834
- // inference of bases deferred in stubs
835
+ // Inference of bases deferred in stubs
835
836
// TODO also defer stringified generic type parameters
836
- if self . is_stub ( ) {
837
+ if self . are_all_types_deferred ( ) {
837
838
self . types . has_deferred = true ;
838
839
} else {
839
840
for base in class. bases ( ) {
@@ -843,13 +844,11 @@ impl<'db> TypeInferenceBuilder<'db> {
843
844
}
844
845
845
846
fn infer_function_deferred ( & mut self , function : & ast:: StmtFunctionDef ) {
846
- if self . is_stub ( ) {
847
- self . infer_optional_annotation_expression ( function. returns . as_deref ( ) ) ;
848
- }
847
+ self . infer_optional_annotation_expression ( function. returns . as_deref ( ) ) ;
849
848
}
850
849
851
850
fn infer_class_deferred ( & mut self , class : & ast:: StmtClassDef ) {
852
- if self . is_stub ( ) {
851
+ if self . are_all_types_deferred ( ) {
853
852
for base in class. bases ( ) {
854
853
self . infer_expression ( base) ;
855
854
}
@@ -4166,6 +4165,63 @@ mod tests {
4166
4165
Ok ( ( ) )
4167
4166
}
4168
4167
4168
+ #[ test]
4169
+ fn deferred_annotation_in_stubs_always_resolve ( ) -> anyhow:: Result < ( ) > {
4170
+ let mut db = setup_db ( ) ;
4171
+
4172
+ // Stub files should always resolve deferred annotations
4173
+ db. write_dedented (
4174
+ "/src/stub.pyi" ,
4175
+ "
4176
+ def get_foo() -> Foo: ...
4177
+ class Foo: ...
4178
+ foo = get_foo()
4179
+ " ,
4180
+ ) ?;
4181
+ assert_public_ty ( & db, "/src/stub.pyi" , "foo" , "Foo" ) ;
4182
+
4183
+ Ok ( ( ) )
4184
+ }
4185
+
4186
+ #[ test]
4187
+ fn deferred_annotations_regular_source_fails ( ) -> anyhow:: Result < ( ) > {
4188
+ let mut db = setup_db ( ) ;
4189
+
4190
+ // In (regular) source files, deferred annotations are *not* resolved
4191
+ // Also tests imports from `__future__` that are not annotations
4192
+ db. write_dedented (
4193
+ "/src/source.py" ,
4194
+ "
4195
+ from __future__ import with_statement as annotations
4196
+ def get_foo() -> Foo: ...
4197
+ class Foo: ...
4198
+ foo = get_foo()
4199
+ " ,
4200
+ ) ?;
4201
+ assert_public_ty ( & db, "/src/source.py" , "foo" , "Unknown" ) ;
4202
+
4203
+ Ok ( ( ) )
4204
+ }
4205
+
4206
+ #[ test]
4207
+ fn deferred_annotation_in_sources_with_future_resolves ( ) -> anyhow:: Result < ( ) > {
4208
+ let mut db = setup_db ( ) ;
4209
+
4210
+ // In source files with `__future__.annotations`, deferred annotations are resolved
4211
+ db. write_dedented (
4212
+ "/src/source_with_future.py" ,
4213
+ "
4214
+ from __future__ import annotations
4215
+ def get_foo() -> Foo: ...
4216
+ class Foo: ...
4217
+ foo = get_foo()
4218
+ " ,
4219
+ ) ?;
4220
+ assert_public_ty ( & db, "/src/source_with_future.py" , "foo" , "Foo" ) ;
4221
+
4222
+ Ok ( ( ) )
4223
+ }
4224
+
4169
4225
#[ test]
4170
4226
fn narrow_not_none ( ) -> anyhow:: Result < ( ) > {
4171
4227
let mut db = setup_db ( ) ;
0 commit comments