@@ -184,7 +184,7 @@ impl<'db> ConstraintSet<'db> {
184184 typevar : BoundTypeVarInstance < ' db > ,
185185 lower : Type < ' db > ,
186186 upper : Type < ' db > ,
187- relation : TypeRelation < ' db > ,
187+ relation : TypeRelation ,
188188 ) -> Self {
189189 let ( lower, upper) = match relation {
190190 // TODO: Is this the correct constraint for redundancy?
@@ -196,9 +196,6 @@ impl<'db> ConstraintSet<'db> {
196196 lower. bottom_materialization ( db) ,
197197 upper. top_materialization ( db) ,
198198 ) ,
199- TypeRelation :: ConstraintImplication ( _) => {
200- panic ! ( "cannot constraint a typevar under constraint implication" )
201- }
202199 } ;
203200
204201 // We have an (arbitrary) ordering for typevars. If the upper and/or lower bounds are
@@ -264,6 +261,52 @@ impl<'db> ConstraintSet<'db> {
264261 self . node . is_always_satisfied ( )
265262 }
266263
264+ pub ( crate ) fn when_type_implies (
265+ self ,
266+ db : & ' db dyn Db ,
267+ lhs : Type < ' db > ,
268+ rhs : Type < ' db > ,
269+ inferable : InferableTypeVars < ' _ , ' db > ,
270+ ) -> Self {
271+ match ( lhs, rhs) {
272+ ( Type :: TypeVar ( bound_typevar) , _) => {
273+ let constrained_typevar = match rhs {
274+ Type :: TypeVar ( rhs_bound_typevar) if rhs_bound_typevar > bound_typevar => {
275+ rhs_bound_typevar
276+ }
277+ _ => bound_typevar,
278+ } ;
279+ let projected = self . project_typevar ( db, constrained_typevar. identity ( db) ) ;
280+ let constraint = ConstraintSet :: constrain_typevar (
281+ db,
282+ bound_typevar,
283+ Type :: Never ,
284+ rhs,
285+ TypeRelation :: Subtyping ,
286+ ) ;
287+ projected
288+ . and ( db, || constraint)
289+ . when_equivalent_to ( db, constraint)
290+ }
291+
292+ ( _, Type :: TypeVar ( bound_typevar) ) => {
293+ let projected = self . project_typevar ( db, bound_typevar. identity ( db) ) ;
294+ let constraint = ConstraintSet :: constrain_typevar (
295+ db,
296+ bound_typevar,
297+ lhs,
298+ Type :: object ( ) ,
299+ TypeRelation :: Subtyping ,
300+ ) ;
301+ projected
302+ . and ( db, || constraint)
303+ . when_equivalent_to ( db, constraint)
304+ }
305+
306+ _ => lhs. when_subtype_of ( db, rhs, inferable) ,
307+ }
308+ }
309+
267310 /// Updates this constraint set to hold the union of itself and another constraint set.
268311 pub ( crate ) fn union ( & mut self , db : & ' db dyn Db , other : Self ) -> Self {
269312 self . node = self . node . or ( db, other. node ) ;
@@ -317,7 +360,7 @@ impl<'db> ConstraintSet<'db> {
317360
318361 pub ( crate ) fn when_equivalent_to ( self , db : & ' db dyn Db , other : Self ) -> Self {
319362 Self {
320- node : self . node . iff ( db, other. node ) . simplify ( db, self ) ,
363+ node : self . node . iff ( db, other. node ) . simplify ( db) ,
321364 }
322365 }
323366
@@ -423,7 +466,11 @@ impl<'db> ConstrainedTypeVar<'db> {
423466 /// This is used (among other places) to simplify how we display constraint sets, by removing
424467 /// redundant constraints from a clause.
425468 fn implies ( self , db : & ' db dyn Db , other : Self ) -> bool {
426- other. contains ( db, self )
469+ if self . typevar ( db) != other. typevar ( db) {
470+ return false ;
471+ }
472+ other. lower ( db) . is_subtype_of ( db, self . lower ( db) )
473+ && self . upper ( db) . is_subtype_of ( db, other. upper ( db) )
427474 }
428475
429476 /// Returns the intersection of two range constraints, or `None` if the intersection is empty.
@@ -1176,9 +1223,9 @@ impl<'db> InteriorNode<'db> {
11761223
11771224 // Containment: The range of one constraint might completely contain the range of the
11781225 // other. If so, there are several potential simplifications.
1179- let larger_smaller = if left_constraint. implies ( db, right_constraint, constraints ) {
1226+ let larger_smaller = if left_constraint. implies ( db, right_constraint) {
11801227 Some ( ( right_constraint, left_constraint) )
1181- } else if right_constraint. implies ( db, left_constraint, constraints ) {
1228+ } else if right_constraint. implies ( db, left_constraint) {
11821229 Some ( ( left_constraint, right_constraint) )
11831230 } else {
11841231 None
@@ -1700,10 +1747,10 @@ mod tests {
17001747 let u = BoundTypeVarInstance :: synthetic ( & db, "U" , TypeVarVariance :: Invariant ) ;
17011748 let bool_type = KnownClass :: Bool . to_instance ( & db) ;
17021749 let str_type = KnownClass :: Str . to_instance ( & db) ;
1703- let t_str = ConstraintSet :: range ( & db, str_type, t. identity ( & db ) , str_type) ;
1704- let t_bool = ConstraintSet :: range ( & db, bool_type, t. identity ( & db ) , bool_type) ;
1705- let u_str = ConstraintSet :: range ( & db, str_type, u. identity ( & db ) , str_type) ;
1706- let u_bool = ConstraintSet :: range ( & db, bool_type, u. identity ( & db ) , bool_type) ;
1750+ let t_str = ConstraintSet :: range ( & db, str_type, t, str_type) ;
1751+ let t_bool = ConstraintSet :: range ( & db, bool_type, t, bool_type) ;
1752+ let u_str = ConstraintSet :: range ( & db, str_type, u, str_type) ;
1753+ let u_bool = ConstraintSet :: range ( & db, bool_type, u, bool_type) ;
17071754 let constraints = ( t_str. or ( & db, || t_bool) ) . and ( & db, || u_str. or ( & db, || u_bool) ) ;
17081755 let actual = constraints. node . display_graph ( & db, & "" ) . to_string ( ) ;
17091756 assert_eq ! ( actual, expected) ;
0 commit comments