Skip to content

Commit

Permalink
Update spans used for some type mismatch errors (#1098)
Browse files Browse the repository at this point in the history
This change adds some additonal logic to better select error spans and
expected/actual types for both if-expressions and callable blocks.

Fixes #970
  • Loading branch information
swernli authored Feb 3, 2024
1 parent 8265cc4 commit 65a7fff
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 12 deletions.
2 changes: 2 additions & 0 deletions compiler/qsc_frontend/src/typeck/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ impl Checker {
callable_input: &decl.input,
spec_input: None,
output: &output,
output_span: decl.output.span,
block,
},
),
Expand All @@ -144,6 +145,7 @@ impl Checker {
callable_input: &decl.input,
spec_input: Some(input),
output: &output,
output_span: decl.output.span,
block,
},
);
Expand Down
28 changes: 21 additions & 7 deletions compiler/qsc_frontend/src/typeck/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,12 @@ impl<'a> Context<'a> {
self.return_ty = Some(spec.output.clone());
let block = self.infer_block(spec.block);
if let Some(return_ty) = self.return_ty.take() {
let span = spec.block.stmts.last().map_or(spec.block.span, |s| s.span);
self.inferrer.eq(span, return_ty, block.ty);
if block.ty == Ty::UNIT {
self.inferrer.eq(spec.output_span, block.ty, return_ty);
} else {
let span = spec.block.stmts.last().map_or(spec.block.span, |s| s.span);
self.inferrer.eq(span, return_ty, block.ty);
}
}
}

Expand Down Expand Up @@ -285,15 +289,24 @@ impl<'a> Context<'a> {
let cond_span = cond.span;
let cond = self.infer_expr(cond);
self.inferrer.eq(cond_span, Ty::Prim(Prim::Bool), cond.ty);
let if_true_span = if_true.span;
let if_true = self.infer_block(if_true);
let if_false = if_false
.as_ref()
.map_or(converge(Ty::UNIT), |e| self.infer_expr(e));
self.inferrer.eq(expr.span, if_true.ty.clone(), if_false.ty);
let if_false_diverges = match if_false {
None => {
self.inferrer.eq(if_true_span, Ty::UNIT, if_true.ty.clone());
false
}
Some(if_false) => {
let if_false = self.infer_expr(if_false);
self.inferrer
.eq(if_true_span, if_true.ty.clone(), if_false.ty);
if_false.diverges
}
};
self.diverge_if(
cond.diverges,
Partial {
diverges: if_true.diverges && if_false.diverges,
diverges: if_true.diverges && if_false_diverges,
..if_true
},
)
Expand Down Expand Up @@ -770,6 +783,7 @@ pub(super) struct SpecImpl<'a> {
pub(super) callable_input: &'a Pat,
pub(super) spec_input: Option<&'a Pat>,
pub(super) output: &'a Ty,
pub(super) output_span: Span,
pub(super) block: &'a Block,
}

Expand Down
10 changes: 5 additions & 5 deletions compiler/qsc_frontend/src/typeck/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ fn return_semi() {
#6 30-32 "()" : Unit
#10 39-45 "{ 4; }" : Unit
#12 41-42 "4" : Int
Error(Type(Error(TyMismatch("Int", "Unit", Span { lo: 41, hi: 43 }))))
Error(Type(Error(TyMismatch("Unit", "Int", Span { lo: 35, hi: 38 }))))
"#]],
);
}
Expand Down Expand Up @@ -835,7 +835,7 @@ fn if_no_else_must_be_unit() {
#2 3-7 "true" : Bool
#3 8-13 "{ 4 }" : Int
#5 10-11 "4" : Int
Error(Type(Error(TyMismatch("Int", "Unit", Span { lo: 0, hi: 13 }))))
Error(Type(Error(TyMismatch("Unit", "Int", Span { lo: 8, hi: 13 }))))
"#]],
);
}
Expand Down Expand Up @@ -2321,7 +2321,7 @@ fn local_function_last_stmt_is_unit_block() {
#21 76-78 "()" : Unit
#25 85-90 "{ 4 }" : Int
#27 87-88 "4" : Int
Error(Type(Error(TyMismatch("Int", "Unit", Span { lo: 64, hi: 90 }))))
Error(Type(Error(TyMismatch("Unit", "Int", Span { lo: 35, hi: 38 }))))
"#]],
);
}
Expand Down Expand Up @@ -3580,8 +3580,8 @@ fn inference_infinite_recursion_should_fail() {
#50 180-187 "A and B" : (((?2[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][], ?3) -> ?1[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]) -> ?1[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][])
#51 180-181 "A" : (((?2[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][], ?3) -> ?1[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]) -> ?1[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][])
#54 186-187 "B" : (((?1[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][], ?3) -> ?1[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]) -> ?2[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][])
Error(Type(Error(TyMismatch("'U1[]", "Unit", Span { lo: 68, hi: 75 }))))
Error(Type(Error(TyMismatch("'T2", "Unit", Span { lo: 133, hi: 140 }))))
Error(Type(Error(TyMismatch("Unit", "'U1[]", Span { lo: 62, hi: 67 }))))
Error(Type(Error(TyMismatch("Unit", "'T2", Span { lo: 129, hi: 132 }))))
Error(Type(Error(TyMismatch("Bool", "(((?[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][], ?) -> ?[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]) -> ?[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][])", Span { lo: 180, hi: 181 }))))
Error(Type(Error(TyMismatch("Unit", "(((?[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][], ?) -> ?[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]) -> ?[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][])", Span { lo: 180, hi: 187 }))))
Error(Type(Error(AmbiguousTy(Span { lo: 186, hi: 187 }))))
Expand Down

0 comments on commit 65a7fff

Please sign in to comment.