diff --git a/compiler/can/src/expr.rs b/compiler/can/src/expr.rs index ec1c8080bb..e2db985092 100644 --- a/compiler/can/src/expr.rs +++ b/compiler/can/src/expr.rs @@ -204,10 +204,13 @@ pub enum Expr { lambda_set_variables: Vec, }, - // Test + /// Test Expect(Box>, Box>), - // Compiles, but will crash if reached + /// Rendered as empty box in editor + TypedHole(Variable), + + /// Compiles, but will crash if reached RuntimeError(RuntimeError), } @@ -247,7 +250,9 @@ impl Expr { }, &Self::OpaqueRef { name, .. } => Category::OpaqueWrap(name), Self::Expect(..) => Category::Expect, - Self::RuntimeError(..) => Category::Unknown, + + // these nodes place no constraints on the expression's type + Self::TypedHole(_) | Self::RuntimeError(..) => Category::Unknown, } } } @@ -1391,6 +1396,7 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) -> | other @ Var(_) | other @ AbilityMember(..) | other @ RunLowLevel { .. } + | other @ TypedHole { .. } | other @ ForeignCall { .. } => other, List { diff --git a/compiler/can/src/module.rs b/compiler/can/src/module.rs index 4abd93c703..e93e17b7c7 100644 --- a/compiler/can/src/module.rs +++ b/compiler/can/src/module.rs @@ -710,6 +710,7 @@ fn fix_values_captured_in_closure_expr( | Var(_) | AbilityMember(..) | EmptyRecord + | TypedHole { .. } | RuntimeError(_) | ZeroArgumentTag { .. } | Accessor { .. } => {} diff --git a/compiler/can/src/traverse.rs b/compiler/can/src/traverse.rs index 5938c2fc3a..71f61f7f82 100644 --- a/compiler/can/src/traverse.rs +++ b/compiler/can/src/traverse.rs @@ -168,6 +168,7 @@ pub fn walk_expr(visitor: &mut V, expr: &Expr, var: Variable) { visitor.visit_expr(&e1.value, e1.region, Variable::NULL); visitor.visit_expr(&e2.value, e2.region, Variable::NULL); } + Expr::TypedHole(_) => { /* terminal */ } Expr::RuntimeError(..) => { /* terminal */ } } } diff --git a/compiler/constrain/src/expr.rs b/compiler/constrain/src/expr.rs index 83abcc8f71..5a106697cc 100644 --- a/compiler/constrain/src/expr.rs +++ b/compiler/constrain/src/expr.rs @@ -1144,6 +1144,15 @@ pub fn constrain_expr( arg_cons.push(eq); constraints.exists_many(vars, arg_cons) } + TypedHole(var) => { + // store the expected type for this position + constraints.equal_types_var( + *var, + expected, + Category::Storage(std::file!(), std::line!()), + region, + ) + } RuntimeError(_) => { // Runtime Errors have no constraints because they're going to crash. Constraint::True diff --git a/compiler/mono/src/copy.rs b/compiler/mono/src/copy.rs index 35c94df620..b4dc4348d7 100644 --- a/compiler/mono/src/copy.rs +++ b/compiler/mono/src/copy.rs @@ -366,6 +366,8 @@ pub fn deep_copy_type_vars_into_expr<'a>( Expect(e1, e2) => Expect(Box::new(e1.map(go_help)), Box::new(e2.map(go_help))), + TypedHole(v) => TypedHole(sub!(*v)), + RuntimeError(err) => RuntimeError(err.clone()), } } diff --git a/compiler/mono/src/ir.rs b/compiler/mono/src/ir.rs index 2bf17490fa..4044d16729 100644 --- a/compiler/mono/src/ir.rs +++ b/compiler/mono/src/ir.rs @@ -5229,6 +5229,7 @@ pub fn with_hole<'a>( } } } + TypedHole(_) => Stmt::RuntimeError("Hit a blank"), RuntimeError(e) => Stmt::RuntimeError(env.arena.alloc(format!("{:?}", e))), } }