Skip to content

Commit

Permalink
Removes (Never, Unknown) coercion and adds checks before unifying Nev…
Browse files Browse the repository at this point in the history
…er in branches.
  • Loading branch information
esdrubal committed Feb 19, 2024
1 parent c0e9bc8 commit e429daa
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,15 @@ impl ty::TyMatchBranch {
ty::TyExpression::type_check(handler, ctx, result)?
};

// unify the return type from the typed result with the type annotation
branch_ctx.unify_with_type_annotation(
handler,
typed_result.return_type,
&typed_result.span,
);
// Check if return type is Never if it is we don't unify as it would replace the Unknown annotation with Never.
if !matches!(*type_engine.get(typed_result.return_type), TypeInfo::Never) {
// unify the return type from the typed result with the type annotation
branch_ctx.unify_with_type_annotation(
handler,
typed_result.return_type,
&typed_result.span,
);
}

// if the typed branch result is a code block, then add the contents
// of that code block to the block of code statements that we are already
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,41 @@ pub(crate) fn instantiate_if_expression(
} else {
type_engine.insert(engines, TypeInfo::Tuple(vec![]), then.span.source_id())
};
type_engine.unify(
handler,
engines,
then.return_type,
ty_to_check,
&then.span,
"`then` branch must return expected type.",
None,
);

let r#else = r#else.map(|r#else| {
// Check the else block return type
// We check then_type_is_never and else_type_is_never before unifying to make sure we don't
// unify ty_to_check with Never when another branch is not Never.
let then_type_is_never = matches!(*type_engine.get(then.return_type), TypeInfo::Never);
let else_type_is_never = r#else.is_some()
&& matches!(
*type_engine.get(r#else.as_ref().unwrap().return_type),
TypeInfo::Never
);

if r#else.is_none() || !then_type_is_never || (then_type_is_never && else_type_is_never) {
type_engine.unify(
handler,
engines,
r#else.return_type,
then.return_type,
ty_to_check,
&r#else.span,
"`else` branch must return expected type.",
&then.span,
"`then` branch must return expected type.",
None,
);
}

let r#else = r#else.map(|r#else| {
if !else_type_is_never || (then_type_is_never && else_type_is_never) {
// Check the else block return type
type_engine.unify(
handler,
engines,
r#else.return_type,
ty_to_check,
&r#else.span,
"`else` branch must return expected type.",
None,
);
}
Box::new(r#else)
});

Expand Down
5 changes: 0 additions & 5 deletions sway-core/src/type_system/unify/unifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,6 @@ impl<'a> Unifier<'a> {
),
)
}

// Removing the line below allows Unknown to be replaced with Never.
// This causes problems while doing unification of if branches as the ctx.type_annotation that was Unknown would be replaced with Never.
(Never, Unknown) => {}

// When we don't know anything about either term, assume that
// they match and make the one we know nothing about reference the
// one we may know something about.
Expand Down

0 comments on commit e429daa

Please sign in to comment.