@@ -641,6 +641,8 @@ impl<'db> DataclassParams<'db> {
641641pub enum Type < ' db > {
642642 /// The dynamic type: a statically unknown set of values
643643 Dynamic ( DynamicType < ' db > ) ,
644+ /// A cycle marker used during recursive type inference.
645+ Divergent ( DivergentType ) ,
644646 /// The empty set of values
645647 Never ,
646648 /// A specific function object
@@ -777,11 +779,11 @@ impl<'db> Type<'db> {
777779 }
778780
779781 pub ( crate ) fn divergent ( id : salsa:: Id ) -> Self {
780- Self :: Dynamic ( DynamicType :: Divergent ( DivergentType { id } ) )
782+ Self :: Divergent ( DivergentType { id } )
781783 }
782784
783785 pub ( crate ) const fn is_divergent ( & self ) -> bool {
784- matches ! ( self , Type :: Dynamic ( DynamicType :: Divergent ( _) ) )
786+ matches ! ( self , Type :: Divergent ( _) )
785787 }
786788
787789 pub const fn is_unknown ( & self ) -> bool {
@@ -925,7 +927,6 @@ impl<'db> Type<'db> {
925927 DynamicType :: Any
926928 | DynamicType :: Unknown
927929 | DynamicType :: UnknownGeneric ( _)
928- | DynamicType :: Divergent ( _)
929930 | DynamicType :: UnspecializedTypeVar => false ,
930931 DynamicType :: Todo ( _)
931932 | DynamicType :: TodoStarredExpression
@@ -976,7 +977,7 @@ impl<'db> Type<'db> {
976977 }
977978
978979 pub ( crate ) const fn is_dynamic ( & self ) -> bool {
979- matches ! ( self , Type :: Dynamic ( _) )
980+ matches ! ( self , Type :: Dynamic ( _) | Type :: Divergent ( _ ) )
980981 }
981982
982983 const fn is_non_divergent_dynamic ( & self ) -> bool {
@@ -1551,7 +1552,7 @@ impl<'db> Type<'db> {
15511552 match self {
15521553 Type :: Never => Type :: object ( ) ,
15531554
1554- Type :: Dynamic ( _) => * self ,
1555+ Type :: Dynamic ( _) | Type :: Divergent ( _ ) => * self ,
15551556
15561557 Type :: NominalInstance ( instance) if instance. is_object ( ) => Type :: Never ,
15571558
@@ -1619,6 +1620,7 @@ impl<'db> Type<'db> {
16191620 | Type :: TypeAlias ( _)
16201621 | Type :: SubclassOf ( _) => true ,
16211622 Type :: Intersection ( _)
1623+ | Type :: Divergent ( _)
16221624 | Type :: SpecialForm ( _)
16231625 | Type :: BoundSuper ( _)
16241626 | Type :: BoundMethod ( _)
@@ -1814,6 +1816,7 @@ impl<'db> Type<'db> {
18141816 Type :: TypeGuard ( type_guard) => {
18151817 recursive_type_normalize_type_guard_like ( db, type_guard, div, nested)
18161818 }
1819+ Type :: Divergent ( _) => Some ( self ) ,
18171820 Type :: Dynamic ( dynamic) => Some ( Type :: Dynamic ( dynamic. recursive_type_normalized ( ) ) ) ,
18181821 Type :: TypedDict ( _) => {
18191822 // TODO: Normalize TypedDicts
@@ -1925,7 +1928,7 @@ impl<'db> Type<'db> {
19251928 /// for more complicated types that are actually singletons.
19261929 pub ( crate ) fn is_singleton ( self , db : & ' db dyn Db ) -> bool {
19271930 match self {
1928- Type :: Dynamic ( _) | Type :: Never => false ,
1931+ Type :: Dynamic ( _) | Type :: Divergent ( _ ) | Type :: Never => false ,
19291932
19301933 Type :: LiteralValue ( literal) => match literal. kind ( ) {
19311934 LiteralValueTypeKind :: Int ( ..)
@@ -2114,6 +2117,7 @@ impl<'db> Type<'db> {
21142117 Type :: TypeAlias ( alias) => alias. value_type ( db) . is_single_valued ( db) ,
21152118
21162119 Type :: Dynamic ( _)
2120+ | Type :: Divergent ( _)
21172121 | Type :: Never
21182122 | Type :: Union ( ..)
21192123 | Type :: Intersection ( ..)
@@ -2161,7 +2165,7 @@ impl<'db> Type<'db> {
21612165 } ) )
21622166 }
21632167
2164- Type :: Dynamic ( _) | Type :: Never => Some ( Place :: bound ( self ) . into ( ) ) ,
2168+ Type :: Dynamic ( _) | Type :: Divergent ( _ ) | Type :: Never => Some ( Place :: bound ( self ) . into ( ) ) ,
21652169
21662170 Type :: ClassLiteral ( class) if class. is_typed_dict ( db) => {
21672171 Some ( class. typed_dict_member ( db, None , name, policy) )
@@ -2363,7 +2367,7 @@ impl<'db> Type<'db> {
23632367 Type :: Intersection ( intersection) => intersection
23642368 . map_with_boundness_and_qualifiers ( db, |elem| elem. instance_member ( db, name) ) ,
23652369
2366- Type :: Dynamic ( _) | Type :: Never => Place :: bound ( self ) . into ( ) ,
2370+ Type :: Dynamic ( _) | Type :: Divergent ( _ ) | Type :: Never => Place :: bound ( self ) . into ( ) ,
23672371
23682372 Type :: NominalInstance ( instance) => instance. class ( db) . instance_member ( db, name) ,
23692373 Type :: NewTypeInstance ( newtype) => {
@@ -2587,7 +2591,7 @@ impl<'db> Type<'db> {
25872591 PlaceAndQualifiers {
25882592 place :
25892593 Place :: Defined ( DefinedPlace {
2590- ty : Type :: Dynamic ( _) | Type :: Never ,
2594+ ty : Type :: Dynamic ( _) | Type :: Divergent ( _ ) | Type :: Never ,
25912595 ..
25922596 } ) ,
25932597 qualifiers : _,
@@ -2906,7 +2910,7 @@ impl<'db> Type<'db> {
29062910 elem. member_lookup_with_policy ( db, name_str. into ( ) , policy)
29072911 } ) ,
29082912
2909- Type :: Dynamic ( ..) | Type :: Never => Place :: bound ( self ) . into ( ) ,
2913+ Type :: Dynamic ( ..) | Type :: Divergent ( _ ) | Type :: Never => Place :: bound ( self ) . into ( ) ,
29102914
29112915 Type :: FunctionLiteral ( function) if name == "__get__" => Place :: bound (
29122916 Type :: KnownBoundMethod ( KnownBoundMethodType :: FunctionTypeDunderGet ( function) ) ,
@@ -3775,7 +3779,7 @@ impl<'db> Type<'db> {
37753779
37763780 // Dynamic types are callable, and the return type is the same dynamic type. Similarly,
37773781 // `Never` is always callable and returns `Never`.
3778- Type :: Dynamic ( _) | Type :: Never => {
3782+ Type :: Dynamic ( _) | Type :: Divergent ( _ ) | Type :: Never => {
37793783 Binding :: single ( self , Signature :: dynamic ( self ) ) . into ( )
37803784 }
37813785
@@ -4870,7 +4874,7 @@ impl<'db> Type<'db> {
48704874 return_ty : return_builder. map ( IntersectionBuilder :: build) ,
48714875 } )
48724876 }
4873- ty @ ( Type :: Dynamic ( _) | Type :: Never ) => Some ( GeneratorTypes {
4877+ ty @ ( Type :: Dynamic ( _) | Type :: Divergent ( _ ) | Type :: Never ) => Some ( GeneratorTypes {
48744878 yield_ty : Some ( ty) ,
48754879 send_ty : Some ( ty) ,
48764880 return_ty : Some ( ty) ,
@@ -4892,7 +4896,7 @@ impl<'db> Type<'db> {
48924896 #[ must_use]
48934897 pub ( crate ) fn to_instance ( self , db : & ' db dyn Db ) -> Option < Type < ' db > > {
48944898 match self {
4895- Type :: Dynamic ( _) | Type :: Never => Some ( self ) ,
4899+ Type :: Dynamic ( _) | Type :: Divergent ( _ ) | Type :: Never => Some ( self ) ,
48964900 Type :: ClassLiteral ( class) => Some ( Type :: instance ( db, class. default_specialization ( db) ) ) ,
48974901 Type :: GenericAlias ( alias) => Some ( Type :: instance ( db, ClassType :: from ( alias) ) ) ,
48984902 Type :: SubclassOf ( subclass_of_ty) => Some ( subclass_of_ty. to_instance ( db) ) ,
@@ -5109,7 +5113,7 @@ impl<'db> Type<'db> {
51095113 }
51105114 }
51115115
5112- Type :: Dynamic ( _) => Ok ( * self ) ,
5116+ Type :: Dynamic ( _) | Type :: Divergent ( _ ) => Ok ( * self ) ,
51135117
51145118 Type :: NominalInstance ( instance) => match instance. known_class ( db) {
51155119 Some ( KnownClass :: NoneType ) => Ok ( Type :: none ( db) ) ,
@@ -5191,6 +5195,7 @@ impl<'db> Type<'db> {
51915195 Type :: GenericAlias ( alias) => ClassType :: from ( alias) . metaclass ( db) ,
51925196 Type :: SubclassOf ( subclass_of_ty) => subclass_of_ty. to_meta_type ( db) ,
51935197 Type :: Dynamic ( dynamic) => SubclassOfType :: from ( db, SubclassOfInner :: Dynamic ( dynamic) ) ,
5198+ Type :: Divergent ( _) => self ,
51945199 // TODO intersections
51955200 Type :: Intersection ( _) => {
51965201 SubclassOfType :: try_from_type ( db, todo_type ! ( "Intersection meta-type" ) )
@@ -5525,19 +5530,15 @@ impl<'db> Type<'db> {
55255530 TypeMapping :: ReplaceParameterDefaults |
55265531 TypeMapping :: EagerExpansion |
55275532 TypeMapping :: RescopeReturnCallables ( _) => self ,
5528- TypeMapping :: Materialize ( materialization_kind) => match self {
5529- // `Divergent` is an internal cycle marker rather than a gradual type like
5530- // `Any` or `Unknown`. Materializing it away would destroy the marker we rely
5531- // on for recursive alias convergence.
5532- // TODO: We elsewhere treat `Divergent` as a dynamic type, so failing to
5533- // materialize it away here could lead to odd behavior.
5534- Type :: Dynamic ( DynamicType :: Divergent ( _) ) => self ,
5535- _ => match materialization_kind {
5536- MaterializationKind :: Top => Type :: object ( ) ,
5537- MaterializationKind :: Bottom => Type :: Never ,
5538- } ,
5533+ TypeMapping :: Materialize ( materialization_kind) => match materialization_kind {
5534+ MaterializationKind :: Top => Type :: object ( ) ,
5535+ MaterializationKind :: Bottom => Type :: Never ,
55395536 }
55405537 }
5538+ // `Divergent` is an internal cycle marker rather than a gradual type like `Any` or
5539+ // `Unknown`. Materializing it away would destroy the marker we rely on for recursive
5540+ // alias convergence.
5541+ Type :: Divergent ( _) => self ,
55415542
55425543 Type :: Never
55435544 | Type :: AlwaysTruthy
@@ -5613,6 +5614,7 @@ impl<'db> Type<'db> {
56135614 typevars. insert ( bound_typevar) ;
56145615 }
56155616 }
5617+ Type :: Divergent ( _) => { }
56165618
56175619 Type :: FunctionLiteral ( function) => {
56185620 visitor. visit ( self , || {
@@ -5970,9 +5972,9 @@ impl<'db> Type<'db> {
59705972 Self :: AlwaysFalsy => Type :: SpecialForm ( SpecialFormType :: AlwaysFalsy ) . definition ( db) ,
59715973
59725974 // These types have no definition
5973- Self :: Dynamic (
5974- DynamicType :: Divergent ( _ )
5975- | DynamicType :: Todo ( _)
5975+ Self :: Divergent ( _ )
5976+ | Self :: Dynamic (
5977+ DynamicType :: Todo ( _)
59765978 | DynamicType :: TodoUnpack
59775979 | DynamicType :: TodoStarredExpression
59785980 | DynamicType :: TodoTypeVarTuple
@@ -6149,6 +6151,7 @@ impl<'db> VarianceInferable<'db> for Type<'db> {
61496151 Type :: TypeGuard ( type_guard_type) => type_guard_type. variance_of ( db, typevar) ,
61506152 Type :: KnownInstance ( known_instance) => known_instance. variance_of ( db, typevar) ,
61516153 Type :: Dynamic ( _)
6154+ | Type :: Divergent ( _)
61526155 | Type :: Never
61536156 | Type :: WrapperDescriptor ( _)
61546157 | Type :: KnownBoundMethod ( _)
@@ -6459,8 +6462,6 @@ pub enum DynamicType<'db> {
64596462 TodoStarredExpression ,
64606463 /// A special Todo-variant for `TypeVarTuple` instances encountered in type expressions
64616464 TodoTypeVarTuple ,
6462- /// A type that is determined to be divergent during recursive type inference.
6463- Divergent ( DivergentType ) ,
64646465}
64656466
64666467impl DynamicType < ' _ > {
@@ -6485,7 +6486,6 @@ impl std::fmt::Display for DynamicType<'_> {
64856486 DynamicType :: TodoUnpack => f. write_str ( "@Todo(typing.Unpack)" ) ,
64866487 DynamicType :: TodoStarredExpression => f. write_str ( "@Todo(StarredExpression)" ) ,
64876488 DynamicType :: TodoTypeVarTuple => f. write_str ( "@Todo(TypeVarTuple)" ) ,
6488- DynamicType :: Divergent ( _) => f. write_str ( "Divergent" ) ,
64896489 }
64906490 }
64916491}
0 commit comments