@@ -143,7 +143,7 @@ fn symbol<'db>(db: &'db dyn Db, scope: ScopeId<'db>, name: &str) -> Symbol<'db>
143
143
}
144
144
// Symbol is possibly undeclared and (possibly) bound
145
145
Symbol :: Type ( inferred_ty, boundness) => Symbol :: Type (
146
- UnionType :: from_elements ( db, [ inferred_ty, declared_ty] . iter ( ) . copied ( ) ) ,
146
+ UnionType :: from_elements ( db, [ inferred_ty, declared_ty] ) ,
147
147
boundness,
148
148
) ,
149
149
}
@@ -159,7 +159,7 @@ fn symbol<'db>(db: &'db dyn Db, scope: ScopeId<'db>, name: &str) -> Symbol<'db>
159
159
Err ( ( declared_ty, _) ) => {
160
160
// Intentionally ignore conflicting declared types; that's not our problem,
161
161
// it's the problem of the module we are importing from.
162
- declared_ty. inner_type ( ) . into ( )
162
+ Symbol :: bound ( declared_ty. inner_type ( ) )
163
163
}
164
164
}
165
165
@@ -187,18 +187,15 @@ fn symbol<'db>(db: &'db dyn Db, scope: ScopeId<'db>, name: &str) -> Symbol<'db>
187
187
&& file_to_module ( db, scope. file ( db) )
188
188
. is_some_and ( |module| module. is_known ( KnownModule :: Typing ) )
189
189
{
190
- return Symbol :: Type ( Type :: BooleanLiteral ( true ) , Boundness :: Bound ) ;
190
+ return Symbol :: bound ( Type :: BooleanLiteral ( true ) ) ;
191
191
}
192
192
if name == "platform"
193
193
&& file_to_module ( db, scope. file ( db) )
194
194
. is_some_and ( |module| module. is_known ( KnownModule :: Sys ) )
195
195
{
196
196
match Program :: get ( db) . python_platform ( db) {
197
197
crate :: PythonPlatform :: Identifier ( platform) => {
198
- return Symbol :: Type (
199
- Type :: StringLiteral ( StringLiteralType :: new ( db, platform. as_str ( ) ) ) ,
200
- Boundness :: Bound ,
201
- ) ;
198
+ return Symbol :: bound ( Type :: string_literal ( db, platform. as_str ( ) ) ) ;
202
199
}
203
200
crate :: PythonPlatform :: All => {
204
201
// Fall through to the looked up type
@@ -401,9 +398,16 @@ fn symbol_from_bindings<'db>(
401
398
/// If we look up the declared type of `variable` in the scope of class `C`, we will get
402
399
/// the type `int`, a "declaredness" of [`Boundness::PossiblyUnbound`], and the information
403
400
/// that this comes with a [`TypeQualifiers::CLASS_VAR`] type qualifier.
401
+ #[ derive( Debug ) ]
404
402
pub ( crate ) struct SymbolAndQualifiers < ' db > ( Symbol < ' db > , TypeQualifiers ) ;
405
403
406
404
impl SymbolAndQualifiers < ' _ > {
405
+ /// Constructor that creates a [`SymbolAndQualifiers`] instance with a [`TodoType`] type
406
+ /// and no qualifiers.
407
+ fn todo ( message : & ' static str ) -> Self {
408
+ Self ( Symbol :: todo ( message) , TypeQualifiers :: empty ( ) )
409
+ }
410
+
407
411
fn is_class_var ( & self ) -> bool {
408
412
self . 1 . contains ( TypeQualifiers :: CLASS_VAR )
409
413
}
@@ -419,12 +423,6 @@ impl<'db> From<Symbol<'db>> for SymbolAndQualifiers<'db> {
419
423
}
420
424
}
421
425
422
- impl < ' db > From < Type < ' db > > for SymbolAndQualifiers < ' db > {
423
- fn from ( ty : Type < ' db > ) -> Self {
424
- SymbolAndQualifiers ( ty. into ( ) , TypeQualifiers :: empty ( ) )
425
- }
426
- }
427
-
428
426
/// The result of looking up a declared type from declarations; see [`symbol_from_declarations`].
429
427
type SymbolFromDeclarationsResult < ' db > =
430
428
Result < SymbolAndQualifiers < ' db > , ( TypeAndQualifiers < ' db > , Box < [ Type < ' db > ] > ) > ;
@@ -560,6 +558,11 @@ macro_rules! todo_type {
560
558
$crate:: types:: TodoType :: Message ( $message) ,
561
559
) )
562
560
} ;
561
+ ( $message: ident) => {
562
+ $crate:: types:: Type :: Dynamic ( $crate:: types:: DynamicType :: Todo (
563
+ $crate:: types:: TodoType :: Message ( $message) ,
564
+ ) )
565
+ } ;
563
566
}
564
567
565
568
#[ cfg( not( debug_assertions) ) ]
@@ -570,6 +573,9 @@ macro_rules! todo_type {
570
573
( $message: literal) => {
571
574
$crate:: types:: Type :: Dynamic ( $crate:: types:: DynamicType :: Todo ( crate :: types:: TodoType ) )
572
575
} ;
576
+ ( $message: ident) => {
577
+ $crate:: types:: Type :: Dynamic ( $crate:: types:: DynamicType :: Todo ( crate :: types:: TodoType ) )
578
+ } ;
573
579
}
574
580
575
581
pub ( crate ) use todo_type;
@@ -1688,17 +1694,17 @@ impl<'db> Type<'db> {
1688
1694
#[ must_use]
1689
1695
pub ( crate ) fn member ( & self , db : & ' db dyn Db , name : & str ) -> Symbol < ' db > {
1690
1696
if name == "__class__" {
1691
- return self . to_meta_type ( db) . into ( ) ;
1697
+ return Symbol :: bound ( self . to_meta_type ( db) ) ;
1692
1698
}
1693
1699
1694
1700
match self {
1695
- Type :: Dynamic ( _) => self . into ( ) ,
1701
+ Type :: Dynamic ( _) => Symbol :: bound ( self ) ,
1696
1702
1697
- Type :: Never => todo_type ! ( "attribute lookup on Never" ) . into ( ) ,
1703
+ Type :: Never => Symbol :: todo ( "attribute lookup on Never" ) ,
1698
1704
1699
1705
Type :: FunctionLiteral ( _) => match name {
1700
- "__get__" => todo_type ! ( "`__get__` method on functions" ) . into ( ) ,
1701
- "__call__" => todo_type ! ( "`__call__` method on functions" ) . into ( ) ,
1706
+ "__get__" => Symbol :: todo ( "`__get__` method on functions" ) ,
1707
+ "__call__" => Symbol :: todo ( "`__call__` method on functions" ) ,
1702
1708
_ => KnownClass :: FunctionType . to_instance ( db) . member ( db, name) ,
1703
1709
} ,
1704
1710
@@ -1711,12 +1717,12 @@ impl<'db> Type<'db> {
1711
1717
Type :: KnownInstance ( known_instance) => known_instance. member ( db, name) ,
1712
1718
1713
1719
Type :: Instance ( InstanceType { class } ) => match ( class. known ( db) , name) {
1714
- ( Some ( KnownClass :: VersionInfo ) , "major" ) => {
1715
- Type :: IntLiteral ( Program :: get ( db) . python_version ( db) . major . into ( ) ) . into ( )
1716
- }
1717
- ( Some ( KnownClass :: VersionInfo ) , "minor" ) => {
1718
- Type :: IntLiteral ( Program :: get ( db) . python_version ( db) . minor . into ( ) ) . into ( )
1719
- }
1720
+ ( Some ( KnownClass :: VersionInfo ) , "major" ) => Symbol :: bound ( Type :: IntLiteral (
1721
+ Program :: get ( db) . python_version ( db) . major . into ( ) ,
1722
+ ) ) ,
1723
+ ( Some ( KnownClass :: VersionInfo ) , "minor" ) => Symbol :: bound ( Type :: IntLiteral (
1724
+ Program :: get ( db) . python_version ( db) . minor . into ( ) ,
1725
+ ) ) ,
1720
1726
_ => {
1721
1727
let SymbolAndQualifiers ( symbol, _) = class. instance_member ( db, name) ;
1722
1728
symbol
@@ -1762,30 +1768,30 @@ impl<'db> Type<'db> {
1762
1768
Type :: Intersection ( _) => {
1763
1769
// TODO perform the get_member on each type in the intersection
1764
1770
// TODO return the intersection of those results
1765
- todo_type ! ( "Attribute access on `Intersection` types" ) . into ( )
1771
+ Symbol :: todo ( "Attribute access on `Intersection` types" )
1766
1772
}
1767
1773
1768
1774
Type :: IntLiteral ( _) => match name {
1769
- "real" | "numerator" => self . into ( ) ,
1775
+ "real" | "numerator" => Symbol :: bound ( self ) ,
1770
1776
// TODO more attributes could probably be usefully special-cased
1771
1777
_ => KnownClass :: Int . to_instance ( db) . member ( db, name) ,
1772
1778
} ,
1773
1779
1774
1780
Type :: BooleanLiteral ( bool_value) => match name {
1775
- "real" | "numerator" => Type :: IntLiteral ( i64:: from ( * bool_value) ) . into ( ) ,
1781
+ "real" | "numerator" => Symbol :: bound ( Type :: IntLiteral ( i64:: from ( * bool_value) ) ) ,
1776
1782
_ => KnownClass :: Bool . to_instance ( db) . member ( db, name) ,
1777
1783
} ,
1778
1784
1779
1785
Type :: StringLiteral ( _) => {
1780
1786
// TODO defer to `typing.LiteralString`/`builtins.str` methods
1781
1787
// from typeshed's stubs
1782
- todo_type ! ( "Attribute access on `StringLiteral` types" ) . into ( )
1788
+ Symbol :: todo ( "Attribute access on `StringLiteral` types" )
1783
1789
}
1784
1790
1785
1791
Type :: LiteralString => {
1786
1792
// TODO defer to `typing.LiteralString`/`builtins.str` methods
1787
1793
// from typeshed's stubs
1788
- todo_type ! ( "Attribute access on `LiteralString` types" ) . into ( )
1794
+ Symbol :: todo ( "Attribute access on `LiteralString` types" )
1789
1795
}
1790
1796
1791
1797
Type :: BytesLiteral ( _) => KnownClass :: Bytes . to_instance ( db) . member ( db, name) ,
@@ -1797,13 +1803,13 @@ impl<'db> Type<'db> {
1797
1803
1798
1804
Type :: Tuple ( _) => {
1799
1805
// TODO: implement tuple methods
1800
- todo_type ! ( "Attribute access on heterogeneous tuple types" ) . into ( )
1806
+ Symbol :: todo ( "Attribute access on heterogeneous tuple types" )
1801
1807
}
1802
1808
1803
1809
Type :: AlwaysTruthy | Type :: AlwaysFalsy => match name {
1804
1810
"__bool__" => {
1805
1811
// TODO should be `Callable[[], Literal[True/False]]`
1806
- todo_type ! ( "`__bool__` for `AlwaysTruthy`/`AlwaysFalsy` Type variants" ) . into ( )
1812
+ Symbol :: todo ( "`__bool__` for `AlwaysTruthy`/`AlwaysFalsy` Type variants" )
1807
1813
}
1808
1814
_ => Type :: object ( db) . member ( db, name) ,
1809
1815
} ,
@@ -2528,18 +2534,6 @@ impl<'db> From<&Type<'db>> for Type<'db> {
2528
2534
}
2529
2535
}
2530
2536
2531
- impl < ' db > From < Type < ' db > > for Symbol < ' db > {
2532
- fn from ( value : Type < ' db > ) -> Self {
2533
- Symbol :: Type ( value, Boundness :: Bound )
2534
- }
2535
- }
2536
-
2537
- impl < ' db > From < & Type < ' db > > for Symbol < ' db > {
2538
- fn from ( value : & Type < ' db > ) -> Self {
2539
- Self :: from ( * value)
2540
- }
2541
- }
2542
-
2543
2537
#[ derive( Copy , Clone , Debug , Eq , Hash , PartialEq ) ]
2544
2538
pub enum DynamicType {
2545
2539
// An explicitly annotated `typing.Any`
@@ -2572,7 +2566,7 @@ impl std::fmt::Display for DynamicType {
2572
2566
2573
2567
bitflags ! {
2574
2568
/// Type qualifiers that appear in an annotation expression.
2575
- #[ derive( Copy , Clone , Debug , Eq , PartialEq ) ]
2569
+ #[ derive( Copy , Clone , Debug , Eq , PartialEq , Default ) ]
2576
2570
pub ( crate ) struct TypeQualifiers : u8 {
2577
2571
/// `typing.ClassVar`
2578
2572
const CLASS_VAR = 1 << 0 ;
@@ -2599,6 +2593,14 @@ impl<'db> TypeAndQualifiers<'db> {
2599
2593
Self { inner, qualifiers }
2600
2594
}
2601
2595
2596
+ /// Constructor that creates a [`TypeAndQualifiers`] instance with type `Unknown` and no qualifiers.
2597
+ pub ( crate ) fn unknown ( ) -> Self {
2598
+ Self {
2599
+ inner : Type :: unknown ( ) ,
2600
+ qualifiers : TypeQualifiers :: empty ( ) ,
2601
+ }
2602
+ }
2603
+
2602
2604
/// Forget about type qualifiers and only return the inner type.
2603
2605
pub ( crate ) fn inner_type ( & self ) -> Type < ' db > {
2604
2606
self . inner
@@ -3330,7 +3332,7 @@ impl<'db> KnownInstanceType<'db> {
3330
3332
( Self :: TypeAliasType ( alias) , "__name__" ) => Type :: string_literal ( db, alias. name ( db) ) ,
3331
3333
_ => return self . instance_fallback ( db) . member ( db, name) ,
3332
3334
} ;
3333
- ty . into ( )
3335
+ Symbol :: bound ( ty )
3334
3336
}
3335
3337
}
3336
3338
@@ -3788,8 +3790,7 @@ impl<'db> ModuleLiteralType<'db> {
3788
3790
full_submodule_name. extend ( & submodule_name) ;
3789
3791
if imported_submodules. contains ( & full_submodule_name) {
3790
3792
if let Some ( submodule) = resolve_module ( db, & full_submodule_name) {
3791
- let submodule_ty = Type :: module_literal ( db, importing_file, submodule) ;
3792
- return Symbol :: Type ( submodule_ty, Boundness :: Bound ) ;
3793
+ return Symbol :: bound ( Type :: module_literal ( db, importing_file, submodule) ) ;
3793
3794
}
3794
3795
}
3795
3796
}
@@ -4123,7 +4124,7 @@ impl<'db> Class<'db> {
4123
4124
pub ( crate ) fn class_member ( self , db : & ' db dyn Db , name : & str ) -> Symbol < ' db > {
4124
4125
if name == "__mro__" {
4125
4126
let tuple_elements = self . iter_mro ( db) . map ( Type :: from) ;
4126
- return TupleType :: from_elements ( db, tuple_elements) . into ( ) ;
4127
+ return Symbol :: bound ( TupleType :: from_elements ( db, tuple_elements) ) ;
4127
4128
}
4128
4129
4129
4130
for superclass in self . iter_mro ( db) {
@@ -4163,7 +4164,9 @@ impl<'db> Class<'db> {
4163
4164
for superclass in self . iter_mro ( db) {
4164
4165
match superclass {
4165
4166
ClassBase :: Dynamic ( _) => {
4166
- return todo_type ! ( "instance attribute on class with dynamic base" ) . into ( ) ;
4167
+ return SymbolAndQualifiers :: todo (
4168
+ "instance attribute on class with dynamic base" ,
4169
+ ) ;
4167
4170
}
4168
4171
ClassBase :: Class ( class) => {
4169
4172
if let member @ SymbolAndQualifiers ( Symbol :: Type ( _, _) , _) =
@@ -4213,7 +4216,7 @@ impl<'db> Class<'db> {
4213
4216
. and_then ( |assignments| assignments. get ( name) )
4214
4217
else {
4215
4218
if inferred_type_from_class_body. is_some ( ) {
4216
- return union_of_inferred_types. build ( ) . into ( ) ;
4219
+ return Symbol :: bound ( union_of_inferred_types. build ( ) ) ;
4217
4220
}
4218
4221
return Symbol :: Unbound ;
4219
4222
} ;
@@ -4230,7 +4233,7 @@ impl<'db> Class<'db> {
4230
4233
let annotation_ty = infer_expression_type ( db, * annotation) ;
4231
4234
4232
4235
// TODO: check if there are conflicting declarations
4233
- return annotation_ty . into ( ) ;
4236
+ return Symbol :: bound ( annotation_ty ) ;
4234
4237
}
4235
4238
AttributeAssignment :: Unannotated { value } => {
4236
4239
// We found an un-annotated attribute assignment of the form:
@@ -4270,7 +4273,7 @@ impl<'db> Class<'db> {
4270
4273
}
4271
4274
}
4272
4275
4273
- union_of_inferred_types. build ( ) . into ( )
4276
+ Symbol :: bound ( union_of_inferred_types. build ( ) )
4274
4277
}
4275
4278
4276
4279
/// A helper function for `instance_member` that looks up the `name` attribute only on
@@ -4299,12 +4302,12 @@ impl<'db> Class<'db> {
4299
4302
// just a temporary heuristic to provide a broad categorization into properties
4300
4303
// and non-property methods.
4301
4304
if function. has_decorator ( db, KnownClass :: Property . to_class_literal ( db) ) {
4302
- todo_type ! ( "@property" ) . into ( )
4305
+ SymbolAndQualifiers :: todo ( "@property" )
4303
4306
} else {
4304
- todo_type ! ( "bound method" ) . into ( )
4307
+ SymbolAndQualifiers :: todo ( "bound method" )
4305
4308
}
4306
4309
} else {
4307
- SymbolAndQualifiers ( Symbol :: Type ( declared_ty, Boundness :: Bound ) , qualifiers)
4310
+ SymbolAndQualifiers ( Symbol :: bound ( declared_ty) , qualifiers)
4308
4311
}
4309
4312
}
4310
4313
Ok ( SymbolAndQualifiers ( Symbol :: Unbound , _) ) => {
@@ -4319,7 +4322,10 @@ impl<'db> Class<'db> {
4319
4322
}
4320
4323
Err ( ( declared_ty, _conflicting_declarations) ) => {
4321
4324
// There are conflicting declarations for this attribute in the class body.
4322
- SymbolAndQualifiers ( declared_ty. inner_type ( ) . into ( ) , declared_ty. qualifiers ( ) )
4325
+ SymbolAndQualifiers (
4326
+ Symbol :: bound ( declared_ty. inner_type ( ) ) ,
4327
+ declared_ty. qualifiers ( ) ,
4328
+ )
4323
4329
}
4324
4330
}
4325
4331
} else {
0 commit comments