@@ -65,7 +65,9 @@ use salsa::plumbing::AsId;
6565
6666use crate :: Db ;
6767use crate :: types:: generics:: InferableTypeVars ;
68- use crate :: types:: { BoundTypeVarIdentity , IntersectionType , Type , TypeRelation , UnionType } ;
68+ use crate :: types:: {
69+ BoundTypeVarIdentity , BoundTypeVarInstance , IntersectionType , Type , TypeRelation , UnionType ,
70+ } ;
6971
7072/// An extension trait for building constraint sets from [`Option`] values.
7173pub ( crate ) trait OptionConstraintsExtension < T > {
@@ -244,20 +246,87 @@ impl<'db> ConstraintSet<'db> {
244246 pub ( crate ) fn range (
245247 db : & ' db dyn Db ,
246248 lower : Type < ' db > ,
247- typevar : BoundTypeVarIdentity < ' db > ,
249+ typevar : BoundTypeVarInstance < ' db > ,
248250 upper : Type < ' db > ,
249251 ) -> Self {
250252 let lower = lower. bottom_materialization ( db) ;
251253 let upper = upper. top_materialization ( db) ;
252- Self {
253- node : ConstrainedTypeVar :: new_node ( db, lower, typevar, upper) ,
254- }
254+
255+ // We have an (arbitrary) ordering for typevars. If the upper and/or lower bounds are
256+ // typevars, we have to ensure that the bounds are "earlier" according to that order than
257+ // the typevar being constrained.
258+ //
259+ // In the comments below, we use brackets to indicate which typevar is "larger", and
260+ // therefore the typevar that the constraint applies to.
261+ let node = match ( lower, upper) {
262+ // A ≤ T ≤ A == (T ≤ [A] ≤ T)
263+ ( Type :: TypeVar ( lower) , Type :: TypeVar ( upper) ) if lower == upper => {
264+ let ( bound, typevar) = if lower < typevar {
265+ ( lower, typevar)
266+ } else {
267+ ( typevar, lower)
268+ } ;
269+ ConstrainedTypeVar :: new_node (
270+ db,
271+ Type :: TypeVar ( bound) ,
272+ typevar. identity ( db) ,
273+ Type :: TypeVar ( bound) ,
274+ )
275+ }
276+
277+ // A ≤ T ≤ B == ([A] ≤ T) && (T ≤ [B])
278+ ( Type :: TypeVar ( lower) , Type :: TypeVar ( upper) ) if lower > typevar && upper > typevar => {
279+ let lower = ConstrainedTypeVar :: new_node (
280+ db,
281+ Type :: Never ,
282+ lower. identity ( db) ,
283+ Type :: TypeVar ( typevar) ,
284+ ) ;
285+ let upper = ConstrainedTypeVar :: new_node (
286+ db,
287+ Type :: TypeVar ( typevar) ,
288+ upper. identity ( db) ,
289+ Type :: object ( ) ,
290+ ) ;
291+ lower. and ( db, upper)
292+ }
293+
294+ // A ≤ T ≤ B == ([A] ≤ T) && ([T] ≤ B)
295+ ( Type :: TypeVar ( lower) , _) if lower > typevar => {
296+ let lower = ConstrainedTypeVar :: new_node (
297+ db,
298+ Type :: Never ,
299+ lower. identity ( db) ,
300+ Type :: TypeVar ( typevar) ,
301+ ) ;
302+ let upper =
303+ ConstrainedTypeVar :: new_node ( db, Type :: Never , typevar. identity ( db) , upper) ;
304+ lower. and ( db, upper)
305+ }
306+
307+ // A ≤ T ≤ B == (A ≤ [T]) && (T ≤ [B])
308+ ( _, Type :: TypeVar ( upper) ) if upper > typevar => {
309+ let lower =
310+ ConstrainedTypeVar :: new_node ( db, lower, typevar. identity ( db) , Type :: object ( ) ) ;
311+ let upper = ConstrainedTypeVar :: new_node (
312+ db,
313+ Type :: TypeVar ( typevar) ,
314+ upper. identity ( db) ,
315+ Type :: object ( ) ,
316+ ) ;
317+ lower. and ( db, upper)
318+ }
319+
320+ _ => ConstrainedTypeVar :: new_node ( db, lower, typevar. identity ( db) , upper) ,
321+ } ;
322+
323+ Self { node }
255324 }
256325
257326 pub ( crate ) fn negated_range (
258327 db : & ' db dyn Db ,
259328 lower : Type < ' db > ,
260- typevar : BoundTypeVarIdentity < ' db > ,
329+ typevar : BoundTypeVarInstance < ' db > ,
261330 upper : Type < ' db > ,
262331 ) -> Self {
263332 Self :: range ( db, lower, typevar, upper) . negate ( db)
0 commit comments