@@ -43,7 +43,8 @@ use crate::{
43
43
types:: {
44
44
AttributeType , Effect , EffectSet , EntityRecordKind , OpenTag , Primitive , RequestEnv , Type ,
45
45
} ,
46
- AttributeAccess , UnexpectedTypeHelp , ValidationMode , ValidationWarning , ValidationWarningKind ,
46
+ AttributeAccess , LubContext , UnexpectedTypeHelp , ValidationMode , ValidationWarning ,
47
+ ValidationWarningKind ,
47
48
} ;
48
49
49
50
use super :: type_error:: TypeError ;
@@ -740,6 +741,7 @@ impl<'a> Typechecker<'a> {
740
741
e,
741
742
vec ! [ typ_then. data( ) . clone( ) , typ_else. data( ) . clone( ) ] ,
742
743
type_errors,
744
+ LubContext :: Conditional ,
743
745
) ;
744
746
let has_lub = lub_ty. is_some ( ) ;
745
747
let annot_expr = ExprBuilder :: with_data ( lub_ty)
@@ -1271,6 +1273,7 @@ impl<'a> Typechecker<'a> {
1271
1273
e,
1272
1274
elem_expr_types. iter ( ) . map ( |ety| ety. data ( ) . clone ( ) ) ,
1273
1275
type_errors,
1276
+ LubContext :: Set ,
1274
1277
) ;
1275
1278
match elem_lub {
1276
1279
_ if self . mode . is_strict ( ) && exprs. is_empty ( ) => {
@@ -1388,6 +1391,7 @@ impl<'a> Typechecker<'a> {
1388
1391
lhs_ty. data ( ) ,
1389
1392
rhs_ty. data ( ) ,
1390
1393
type_errors,
1394
+ LubContext :: Equality ,
1391
1395
)
1392
1396
} else {
1393
1397
TypecheckAnswer :: success (
@@ -1517,6 +1521,7 @@ impl<'a> Typechecker<'a> {
1517
1521
} ,
1518
1522
expr_ty_arg2. data ( ) ,
1519
1523
type_errors,
1524
+ LubContext :: Contains ,
1520
1525
)
1521
1526
} else {
1522
1527
TypecheckAnswer :: success (
@@ -1573,6 +1578,7 @@ impl<'a> Typechecker<'a> {
1573
1578
expr_ty_arg1. data ( ) ,
1574
1579
expr_ty_arg2. data ( ) ,
1575
1580
type_errors,
1581
+ LubContext :: ContainsAnyAll ,
1576
1582
)
1577
1583
} else {
1578
1584
TypecheckAnswer :: success (
@@ -1594,6 +1600,7 @@ impl<'a> Typechecker<'a> {
1594
1600
lhs_ty : & Option < Type > ,
1595
1601
rhs_ty : & Option < Type > ,
1596
1602
type_errors : & mut Vec < TypeError > ,
1603
+ context : LubContext ,
1597
1604
) -> TypecheckAnswer < ' b > {
1598
1605
match annotated_expr. data ( ) {
1599
1606
Some ( Type :: False ) => {
@@ -1603,20 +1610,25 @@ impl<'a> Typechecker<'a> {
1603
1610
TypecheckAnswer :: success ( ExprBuilder :: with_data ( Some ( Type :: True ) ) . val ( true ) )
1604
1611
}
1605
1612
_ => match ( lhs_ty, rhs_ty) {
1606
- ( Some ( lhs_ty) , Some ( rhs_ty) )
1607
- if Type :: least_upper_bound ( self . schema , lhs_ty, rhs_ty, self . mode )
1608
- . is_none ( ) =>
1609
- {
1610
- type_errors. push ( TypeError :: incompatible_types (
1611
- unannotated_expr. clone ( ) ,
1612
- [ lhs_ty. clone ( ) , rhs_ty. clone ( ) ] ,
1613
- ) ) ;
1614
- TypecheckAnswer :: fail ( annotated_expr)
1613
+ ( Some ( lhs_ty) , Some ( rhs_ty) ) => {
1614
+ if let Err ( lub_hint) =
1615
+ Type :: least_upper_bound ( self . schema , lhs_ty, rhs_ty, self . mode )
1616
+ {
1617
+ type_errors. push ( TypeError :: incompatible_types (
1618
+ unannotated_expr. clone ( ) ,
1619
+ [ lhs_ty. clone ( ) , rhs_ty. clone ( ) ] ,
1620
+ lub_hint,
1621
+ context,
1622
+ ) ) ;
1623
+ TypecheckAnswer :: fail ( annotated_expr)
1624
+ } else {
1625
+ // We had `Some` type for lhs and rhs and these types
1626
+ // were compatible.
1627
+ TypecheckAnswer :: success ( annotated_expr)
1628
+ }
1615
1629
}
1616
- // Either we had `Some` type for lhs and rhs and these types
1617
- // were compatible, or we failed to a compute a type for either
1618
- // lhs or rhs, meaning we already failed typechecking for that
1619
- // expression.
1630
+ // We failed to compute a type for either lhs or rhs, meaning
1631
+ // we already failed typechecking for that expression.
1620
1632
_ => TypecheckAnswer :: success ( annotated_expr) ,
1621
1633
} ,
1622
1634
}
@@ -2383,6 +2395,7 @@ impl<'a> Typechecker<'a> {
2383
2395
expr : & Expr ,
2384
2396
answers : impl IntoIterator < Item = Option < Type > > ,
2385
2397
type_errors : & mut Vec < TypeError > ,
2398
+ context : LubContext ,
2386
2399
) -> Option < Type > {
2387
2400
answers
2388
2401
. into_iter ( )
@@ -2393,17 +2406,22 @@ impl<'a> Typechecker<'a> {
2393
2406
. and_then ( |typechecked_types| {
2394
2407
let lub =
2395
2408
Type :: reduce_to_least_upper_bound ( self . schema , & typechecked_types, self . mode ) ;
2396
- if lub. is_none ( ) {
2397
- // A type error is generated if we could not find a least
2398
- // upper bound for the types. The computed least upper bound
2399
- // will be None, so this function will correctly report this
2400
- // as a failure.
2401
- type_errors. push ( TypeError :: incompatible_types (
2402
- expr. clone ( ) ,
2403
- typechecked_types,
2404
- ) ) ;
2409
+ match lub {
2410
+ Err ( lub_hint) => {
2411
+ // A type error is generated if we could not find a least
2412
+ // upper bound for the types. The computed least upper bound
2413
+ // will be None, so this function will correctly report this
2414
+ // as a failure.
2415
+ type_errors. push ( TypeError :: incompatible_types (
2416
+ expr. clone ( ) ,
2417
+ typechecked_types,
2418
+ lub_hint,
2419
+ context,
2420
+ ) ) ;
2421
+ None
2422
+ }
2423
+ Ok ( lub) => Some ( lub) ,
2405
2424
}
2406
- lub
2407
2425
} )
2408
2426
}
2409
2427
0 commit comments