From: Philip Herron <[email protected]>
Unify rules are not the same as coercion rules. The coercion of ! is
allowed to any type but not for a unify site which is different.
Match arms are another least upper bound coercion.
gcc/rust/ChangeLog:
* backend/rust-compile-expr.cc (CompileExpr::visit): implement coercion
* typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): this is
an LUB
* typecheck/rust-unify.cc (UnifyRules::go): remove unify ! coercion
Signed-off-by: Philip Herron <[email protected]>
---
gcc/rust/backend/rust-compile-expr.cc | 13 ++++++++++++-
gcc/rust/typecheck/rust-hir-type-check-expr.cc | 7 ++++---
gcc/rust/typecheck/rust-unify.cc | 10 ----------
3 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/gcc/rust/backend/rust-compile-expr.cc
b/gcc/rust/backend/rust-compile-expr.cc
index b40aa33866e..353a498dc4e 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -1156,8 +1156,19 @@ CompileExpr::visit (HIR::MatchExpr &expr)
location_t arm_locus = kase_arm.get_locus ();
tree kase_expr_tree = CompileExpr::Compile (kase.get_expr (), ctx);
tree result_reference = Backend::var_expression (tmp, arm_locus);
+
+ TyTy::BaseType *actual = nullptr;
+ bool ok = ctx->get_tyctx ()->lookup_type (
+ kase.get_expr ().get_mappings ().get_hirid (), &actual);
+ rust_assert (ok);
+
+ tree coerced_result
+ = coercion_site (kase.get_expr ().get_mappings ().get_hirid (),
+ kase_expr_tree, actual, expr_tyty,
+ expr.get_locus (), arm_locus);
+
tree assignment
- = Backend::assignment_statement (result_reference, kase_expr_tree,
+ = Backend::assignment_statement (result_reference, coerced_result,
arm_locus);
ctx->add_statement (assignment);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 7899b1a7943..113f43f6c72 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -1532,9 +1532,10 @@ TypeCheckExpr::visit (HIR::MatchExpr &expr)
for (size_t i = 1; i < kase_block_tys.size (); i++)
{
TyTy::BaseType *kase_ty = kase_block_tys.at (i);
- infered = unify_site (expr.get_mappings ().get_hirid (),
- TyTy::TyWithLocation (infered),
- TyTy::TyWithLocation (kase_ty), expr.get_locus ());
+ infered
+ = coercion_site (expr.get_mappings ().get_hirid (),
+ TyTy::TyWithLocation (infered),
+ TyTy::TyWithLocation (kase_ty), expr.get_locus ());
}
}
diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc
index 8159c7d52bb..b779e7d4614 100644
--- a/gcc/rust/typecheck/rust-unify.cc
+++ b/gcc/rust/typecheck/rust-unify.cc
@@ -17,7 +17,6 @@
// <http://www.gnu.org/licenses/>.
#include "rust-unify.h"
-#include "rust-tyty.h"
namespace Rust {
namespace Resolver {
@@ -238,15 +237,6 @@ UnifyRules::go ()
}
}
- // The never type should always get coerced to the type it's being matched
- // against, so in that case, ltype. This avoids doing the same check in all
- // the `expect_*` functions.
- // However, this does not work if we have an annoying ltype - like INFER.
- // TODO: Is ltype == Infer the only special case here? What about
projections?
- // references?
- if (rtype->get_kind () == TyTy::NEVER && ltype->get_kind () != TyTy::INFER)
- return ltype->clone ();
-
switch (ltype->get_kind ())
{
case TyTy::INFER:
--
2.45.2