aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/Make-lang.in1
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc24
-rw-r--r--gcc/rust/typecheck/rust-casts.cc292
-rw-r--r--gcc/rust/typecheck/rust-casts.h53
-rw-r--r--gcc/rust/typecheck/rust-coercion.cc89
-rw-r--r--gcc/rust/typecheck/rust-coercion.h16
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.cc33
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.h7
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.cc15
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h20
-rw-r--r--gcc/rust/typecheck/rust-tyty-cast.h1425
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc178
-rw-r--r--gcc/rust/typecheck/rust-tyty.h64
-rw-r--r--gcc/testsuite/rust/execute/torture/issue-1496.rs75
14 files changed, 600 insertions, 1692 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 49be3a1..f687cc2 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -122,6 +122,7 @@ GRS_OBJS = \
rust/rust-hir-type-check-implitem.o \
rust/rust-hir-dot-operator.o \
rust/rust-coercion.o \
+ rust/rust-casts.o \
rust/rust-hir-type-check-base.o \
rust/rust-autoderef.o \
rust/rust-substitution-mapper.o \
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 412ca09..865ad25 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -237,16 +237,34 @@ CompileExpr::visit (HIR::LazyBooleanExpr &expr)
void
CompileExpr::visit (HIR::TypeCastExpr &expr)
{
- TyTy::BaseType *tyty = nullptr;
+ TyTy::BaseType *type_to_cast_to_ty = nullptr;
if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
- &tyty))
+ &type_to_cast_to_ty))
{
translated = error_mark_node;
return;
}
- auto type_to_cast_to = TyTyResolveCompile::compile (ctx, tyty);
+ TyTy::BaseType *casted_tyty = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (
+ expr.get_casted_expr ()->get_mappings ().get_hirid (), &casted_tyty))
+ {
+ translated = error_mark_node;
+ return;
+ }
+
+ auto type_to_cast_to = TyTyResolveCompile::compile (ctx, type_to_cast_to_ty);
auto casted_expr = CompileExpr::Compile (expr.get_casted_expr ().get (), ctx);
+
+ std::vector<Resolver::Adjustment> *adjustments = nullptr;
+ bool ok = ctx->get_tyctx ()->lookup_cast_autoderef_mappings (
+ expr.get_mappings ().get_hirid (), &adjustments);
+ if (ok)
+ {
+ casted_expr
+ = resolve_adjustements (*adjustments, casted_expr, expr.get_locus ());
+ }
+
translated
= type_cast_expression (type_to_cast_to, casted_expr, expr.get_locus ());
}
diff --git a/gcc/rust/typecheck/rust-casts.cc b/gcc/rust/typecheck/rust-casts.cc
new file mode 100644
index 0000000..61004df
--- /dev/null
+++ b/gcc/rust/typecheck/rust-casts.cc
@@ -0,0 +1,292 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-casts.h"
+
+namespace Rust {
+namespace Resolver {
+
+TypeCastRules::TypeCastRules (Location locus, TyTy::TyWithLocation from,
+ TyTy::TyWithLocation to)
+ : locus (locus), from (from), to (to)
+{}
+
+TypeCoercionRules::CoercionResult
+TypeCastRules::resolve (Location locus, TyTy::TyWithLocation from,
+ TyTy::TyWithLocation to)
+{
+ TypeCastRules cast_rules (locus, from, to);
+ return cast_rules.check ();
+}
+
+TypeCoercionRules::CoercionResult
+TypeCastRules::check ()
+{
+ // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/cast.rs#L565-L582
+ auto possible_coercion
+ = TypeCoercionRules::TryCoerce (from.get_ty (), to.get_ty (), locus);
+ if (!possible_coercion.is_error ())
+ return possible_coercion;
+
+ // try the simple cast rules
+ auto simple_cast = cast_rules ();
+ if (!simple_cast.is_error ())
+ return simple_cast;
+
+ // failed to cast
+ emit_cast_error ();
+ return TypeCoercionRules::CoercionResult::get_error ();
+}
+
+TypeCoercionRules::CoercionResult
+TypeCastRules::cast_rules ()
+{
+ // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/cast.rs#L596
+ // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/cast.rs#L654
+
+ rust_debug ("cast_rules from={%s} to={%s}",
+ from.get_ty ()->debug_str ().c_str (),
+ to.get_ty ()->debug_str ().c_str ());
+
+ switch (from.get_ty ()->get_kind ())
+ {
+ case TyTy::TypeKind::INFER: {
+ TyTy::InferType *from_infer
+ = static_cast<TyTy::InferType *> (from.get_ty ());
+ switch (from_infer->get_infer_kind ())
+ {
+ case TyTy::InferType::InferTypeKind::GENERAL:
+ return TypeCoercionRules::CoercionResult{{},
+ to.get_ty ()->clone ()};
+
+ case TyTy::InferType::InferTypeKind::INTEGRAL:
+ switch (to.get_ty ()->get_kind ())
+ {
+ case TyTy::TypeKind::CHAR:
+ case TyTy::TypeKind::BOOL:
+ case TyTy::TypeKind::USIZE:
+ case TyTy::TypeKind::ISIZE:
+ case TyTy::TypeKind::UINT:
+ case TyTy::TypeKind::INT:
+ case TyTy::TypeKind::POINTER:
+ return TypeCoercionRules::CoercionResult{
+ {}, to.get_ty ()->clone ()};
+
+ case TyTy::TypeKind::INFER: {
+ TyTy::InferType *to_infer
+ = static_cast<TyTy::InferType *> (to.get_ty ());
+
+ switch (to_infer->get_infer_kind ())
+ {
+ case TyTy::InferType::InferTypeKind::GENERAL:
+ case TyTy::InferType::InferTypeKind::INTEGRAL:
+ return TypeCoercionRules::CoercionResult{
+ {}, to.get_ty ()->clone ()};
+
+ default:
+ return TypeCoercionRules::CoercionResult::get_error ();
+ }
+ }
+ break;
+
+ default:
+ return TypeCoercionRules::CoercionResult::get_error ();
+ }
+ break;
+
+ case TyTy::InferType::InferTypeKind::FLOAT:
+ switch (to.get_ty ()->get_kind ())
+ {
+ case TyTy::TypeKind::USIZE:
+ case TyTy::TypeKind::ISIZE:
+ case TyTy::TypeKind::UINT:
+ case TyTy::TypeKind::INT:
+ return TypeCoercionRules::CoercionResult{
+ {}, to.get_ty ()->clone ()};
+
+ case TyTy::TypeKind::INFER: {
+ TyTy::InferType *to_infer
+ = static_cast<TyTy::InferType *> (to.get_ty ());
+
+ switch (to_infer->get_infer_kind ())
+ {
+ case TyTy::InferType::InferTypeKind::GENERAL:
+ case TyTy::InferType::InferTypeKind::FLOAT:
+ return TypeCoercionRules::CoercionResult{
+ {}, to.get_ty ()->clone ()};
+
+ default:
+ return TypeCoercionRules::CoercionResult::get_error ();
+ }
+ }
+ break;
+
+ default:
+ return TypeCoercionRules::CoercionResult::get_error ();
+ }
+ break;
+ }
+ }
+ break;
+
+ case TyTy::TypeKind::BOOL:
+ switch (to.get_ty ()->get_kind ())
+ {
+ case TyTy::TypeKind::INFER:
+ case TyTy::TypeKind::USIZE:
+ case TyTy::TypeKind::ISIZE:
+ case TyTy::TypeKind::UINT:
+ case TyTy::TypeKind::INT:
+ return TypeCoercionRules::CoercionResult{{}, to.get_ty ()->clone ()};
+
+ default:
+ return TypeCoercionRules::CoercionResult::get_error ();
+ }
+ break;
+
+ case TyTy::TypeKind::CHAR:
+ case TyTy::TypeKind::USIZE:
+ case TyTy::TypeKind::ISIZE:
+ case TyTy::TypeKind::UINT:
+ case TyTy::TypeKind::INT:
+ switch (to.get_ty ()->get_kind ())
+ {
+ case TyTy::TypeKind::CHAR: {
+ // only u8 and char
+ bool was_uint = from.get_ty ()->get_kind () == TyTy::TypeKind::UINT;
+ bool was_u8 = was_uint
+ && (static_cast<TyTy::UintType *> (from.get_ty ())
+ ->get_uint_kind ()
+ == TyTy::UintType::UintKind::U8);
+ if (was_u8)
+ return TypeCoercionRules::CoercionResult{{},
+ to.get_ty ()->clone ()};
+ }
+ break;
+
+ case TyTy::TypeKind::INFER:
+ case TyTy::TypeKind::USIZE:
+ case TyTy::TypeKind::ISIZE:
+ case TyTy::TypeKind::UINT:
+ case TyTy::TypeKind::INT:
+ return TypeCoercionRules::CoercionResult{{}, to.get_ty ()->clone ()};
+
+ default:
+ return TypeCoercionRules::CoercionResult::get_error ();
+ }
+ break;
+
+ case TyTy::TypeKind::FLOAT:
+ switch (to.get_ty ()->get_kind ())
+ {
+ case TyTy::TypeKind::FLOAT:
+ return TypeCoercionRules::CoercionResult{{}, to.get_ty ()->clone ()};
+
+ case TyTy::TypeKind::INFER: {
+ TyTy::InferType *to_infer
+ = static_cast<TyTy::InferType *> (to.get_ty ());
+
+ switch (to_infer->get_infer_kind ())
+ {
+ case TyTy::InferType::InferTypeKind::GENERAL:
+ case TyTy::InferType::InferTypeKind::FLOAT:
+ return TypeCoercionRules::CoercionResult{
+ {}, to.get_ty ()->clone ()};
+
+ default:
+ return TypeCoercionRules::CoercionResult::get_error ();
+ }
+ }
+ break;
+
+ default:
+ return TypeCoercionRules::CoercionResult::get_error ();
+ }
+ break;
+
+ case TyTy::TypeKind::REF:
+ case TyTy::TypeKind::POINTER:
+ switch (to.get_ty ()->get_kind ())
+ {
+ case TyTy::TypeKind::REF:
+ case TyTy::TypeKind::POINTER:
+ return check_ptr_ptr_cast ();
+
+ // FIXME can you cast a pointer to a integral type?
+
+ default:
+ return TypeCoercionRules::CoercionResult::get_error ();
+ }
+ break;
+
+ default:
+ return TypeCoercionRules::CoercionResult::get_error ();
+ }
+
+ return TypeCoercionRules::CoercionResult::get_error ();
+}
+
+TypeCoercionRules::CoercionResult
+TypeCastRules::check_ptr_ptr_cast ()
+{
+ rust_debug ("check_ptr_ptr_cast from={%s} to={%s}",
+ from.get_ty ()->debug_str ().c_str (),
+ to.get_ty ()->debug_str ().c_str ());
+
+ bool from_is_ref = from.get_ty ()->get_kind () == TyTy::TypeKind::REF;
+ bool to_is_ref = to.get_ty ()->get_kind () == TyTy::TypeKind::REF;
+ bool from_is_ptr = from.get_ty ()->get_kind () == TyTy::TypeKind::POINTER;
+ bool to_is_ptr = to.get_ty ()->get_kind () == TyTy::TypeKind::POINTER;
+
+ if (from_is_ptr && to_is_ptr)
+ {
+ // mutability is ignored here as all pointer usage requires unsafe
+ return TypeCoercionRules::CoercionResult{{}, to.get_ty ()->clone ()};
+ }
+ else if (from_is_ref && to_is_ref)
+ {
+ // mutability must be coercedable
+ TyTy::ReferenceType &f
+ = static_cast<TyTy::ReferenceType &> (*from.get_ty ());
+ TyTy::ReferenceType &t
+ = static_cast<TyTy::ReferenceType &> (*to.get_ty ());
+
+ if (TypeCoercionRules::coerceable_mutability (f.mutability (),
+ t.mutability ()))
+ {
+ return TypeCoercionRules::CoercionResult{{}, to.get_ty ()->clone ()};
+ }
+ }
+
+ return TypeCoercionRules::CoercionResult::get_error ();
+}
+
+void
+TypeCastRules::emit_cast_error () const
+{
+ // error[E0604]
+ RichLocation r (locus);
+ r.add_range (from.get_locus ());
+ r.add_range (to.get_locus ());
+ rust_error_at (r, "invalid cast %<%s%> to %<%s%>",
+ from.get_ty ()->get_name ().c_str (),
+ to.get_ty ()->get_name ().c_str ());
+}
+
+} // namespace Resolver
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-casts.h b/gcc/rust/typecheck/rust-casts.h
new file mode 100644
index 0000000..e908f49
--- /dev/null
+++ b/gcc/rust/typecheck/rust-casts.h
@@ -0,0 +1,53 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_CASTS
+#define RUST_CASTS
+
+#include "rust-tyty.h"
+#include "rust-coercion.h"
+
+namespace Rust {
+namespace Resolver {
+
+class TypeCastRules
+{
+public:
+ static TypeCoercionRules::CoercionResult
+ resolve (Location locus, TyTy::TyWithLocation from, TyTy::TyWithLocation to);
+
+protected:
+ TypeCoercionRules::CoercionResult check ();
+ TypeCoercionRules::CoercionResult cast_rules ();
+ TypeCoercionRules::CoercionResult check_ptr_ptr_cast ();
+
+ void emit_cast_error () const;
+
+protected:
+ TypeCastRules (Location locus, TyTy::TyWithLocation from,
+ TyTy::TyWithLocation to);
+
+ Location locus;
+ TyTy::TyWithLocation from;
+ TyTy::TyWithLocation to;
+};
+
+} // namespace Resolver
+} // namespace Rust
+
+#endif // RUST_CASTS
diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc
index b7ef677..2ad2b80 100644
--- a/gcc/rust/typecheck/rust-coercion.cc
+++ b/gcc/rust/typecheck/rust-coercion.cc
@@ -21,24 +21,33 @@
namespace Rust {
namespace Resolver {
-AutoderefTypeCoercion::CoercionResult
-AutoderefTypeCoercion::Coerce (TyTy::BaseType *receiver,
- TyTy::BaseType *expected, Location locus)
+TypeCoercionRules::CoercionResult
+TypeCoercionRules::Coerce (TyTy::BaseType *receiver, TyTy::BaseType *expected,
+ Location locus)
{
- AutoderefTypeCoercion resolver (expected, locus);
+ TypeCoercionRules resolver (expected, locus, true);
bool ok = resolver.do_coercion (receiver);
return ok ? resolver.try_result : CoercionResult::get_error ();
}
-AutoderefTypeCoercion::AutoderefTypeCoercion (TyTy::BaseType *expected,
- Location locus)
+TypeCoercionRules::CoercionResult
+TypeCoercionRules::TryCoerce (TyTy::BaseType *receiver,
+ TyTy::BaseType *expected, Location locus)
+{
+ TypeCoercionRules resolver (expected, locus, false);
+ bool ok = resolver.do_coercion (receiver);
+ return ok ? resolver.try_result : CoercionResult::get_error ();
+}
+
+TypeCoercionRules::TypeCoercionRules (TyTy::BaseType *expected, Location locus,
+ bool emit_errors)
: AutoderefCycle (false), mappings (Analysis::Mappings::get ()),
context (TypeCheckContext::get ()), expected (expected), locus (locus),
- try_result (CoercionResult::get_error ())
+ try_result (CoercionResult::get_error ()), emit_errors (emit_errors)
{}
bool
-AutoderefTypeCoercion::do_coercion (TyTy::BaseType *receiver)
+TypeCoercionRules::do_coercion (TyTy::BaseType *receiver)
{
// FIXME this is not finished and might be super simplified
// see:
@@ -87,10 +96,10 @@ AutoderefTypeCoercion::do_coercion (TyTy::BaseType *receiver)
return !try_result.is_error ();
}
-AutoderefTypeCoercion::CoercionResult
-AutoderefTypeCoercion::coerce_unsafe_ptr (TyTy::BaseType *receiver,
- TyTy::PointerType *expected,
- Mutability to_mutbl)
+TypeCoercionRules::CoercionResult
+TypeCoercionRules::coerce_unsafe_ptr (TyTy::BaseType *receiver,
+ TyTy::PointerType *expected,
+ Mutability to_mutbl)
{
rust_debug ("coerce_unsafe_ptr(a={%s}, b={%s})",
receiver->debug_str ().c_str (), expected->debug_str ().c_str ());
@@ -115,8 +124,10 @@ AutoderefTypeCoercion::coerce_unsafe_ptr (TyTy::BaseType *receiver,
break;
default: {
- TyTy::BaseType *result = receiver->unify (expected);
- return CoercionResult{{}, result};
+ if (receiver->can_eq (expected, false))
+ return CoercionResult{{}, expected->clone ()};
+
+ return CoercionResult::get_error ();
}
}
@@ -125,22 +136,25 @@ AutoderefTypeCoercion::coerce_unsafe_ptr (TyTy::BaseType *receiver,
Location lhs = mappings->lookup_location (receiver->get_ref ());
Location rhs = mappings->lookup_location (expected->get_ref ());
mismatched_mutability_error (locus, lhs, rhs);
- return AutoderefTypeCoercion::CoercionResult::get_error ();
+ return TypeCoercionRules::CoercionResult::get_error ();
}
TyTy::PointerType *result
= new TyTy::PointerType (receiver->get_ref (),
TyTy::TyVar (element->get_ref ()), to_mutbl);
+ if (!result->can_eq (expected, false))
+ return CoercionResult::get_error ();
+
return CoercionResult{{}, result};
}
/// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
/// To match `A` with `B`, autoderef will be performed,
/// calling `deref`/`deref_mut` where necessary.
-AutoderefTypeCoercion::CoercionResult
-AutoderefTypeCoercion::coerce_borrowed_pointer (TyTy::BaseType *receiver,
- TyTy::ReferenceType *expected,
- Mutability to_mutbl)
+TypeCoercionRules::CoercionResult
+TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver,
+ TyTy::ReferenceType *expected,
+ Mutability to_mutbl)
{
rust_debug ("coerce_borrowed_pointer(a={%s}, b={%s})",
receiver->debug_str ().c_str (), expected->debug_str ().c_str ());
@@ -166,7 +180,7 @@ AutoderefTypeCoercion::coerce_borrowed_pointer (TyTy::BaseType *receiver,
Location lhs = mappings->lookup_location (receiver->get_ref ());
Location rhs = mappings->lookup_location (expected->get_ref ());
mismatched_mutability_error (locus, lhs, rhs);
- return AutoderefTypeCoercion::CoercionResult::get_error ();
+ return TypeCoercionRules::CoercionResult::get_error ();
}
AutoderefCycle::cycle (receiver);
@@ -176,10 +190,9 @@ AutoderefTypeCoercion::coerce_borrowed_pointer (TyTy::BaseType *receiver,
// &[T; n] or &mut [T; n] -> &[T]
// or &mut [T; n] -> &mut [T]
// or &Concrete -> &Trait, etc.
-AutoderefTypeCoercion::CoercionResult
-AutoderefTypeCoercion::coerce_unsized (TyTy::BaseType *source,
- TyTy::BaseType *target,
- bool &unsafe_error)
+TypeCoercionRules::CoercionResult
+TypeCoercionRules::coerce_unsized (TyTy::BaseType *source,
+ TyTy::BaseType *target, bool &unsafe_error)
{
rust_debug ("coerce_unsized(source={%s}, target={%s})",
source->debug_str ().c_str (), target->debug_str ().c_str ());
@@ -207,7 +220,7 @@ AutoderefTypeCoercion::coerce_unsized (TyTy::BaseType *source,
Location lhs = mappings->lookup_location (source->get_ref ());
Location rhs = mappings->lookup_location (target->get_ref ());
mismatched_mutability_error (locus, lhs, rhs);
- return AutoderefTypeCoercion::CoercionResult::get_error ();
+ return TypeCoercionRules::CoercionResult::get_error ();
}
ty_a = source_ref->get_base ();
@@ -232,7 +245,7 @@ AutoderefTypeCoercion::coerce_unsized (TyTy::BaseType *source,
Location lhs = mappings->lookup_location (source->get_ref ());
Location rhs = mappings->lookup_location (target->get_ref ());
mismatched_mutability_error (locus, lhs, rhs);
- return AutoderefTypeCoercion::CoercionResult::get_error ();
+ return TypeCoercionRules::CoercionResult::get_error ();
}
ty_a = source_ref->get_base ();
@@ -262,7 +275,7 @@ AutoderefTypeCoercion::coerce_unsized (TyTy::BaseType *source,
if (!bounds_compatible)
{
unsafe_error = true;
- return AutoderefTypeCoercion::CoercionResult::get_error ();
+ return TypeCoercionRules::CoercionResult::get_error ();
}
// return the unsize coercion
@@ -291,11 +304,11 @@ AutoderefTypeCoercion::coerce_unsized (TyTy::BaseType *source,
}
adjustments.clear ();
- return AutoderefTypeCoercion::CoercionResult::get_error ();
+ return TypeCoercionRules::CoercionResult::get_error ();
}
bool
-AutoderefTypeCoercion::select (const TyTy::BaseType &autoderefed)
+TypeCoercionRules::select (const TyTy::BaseType &autoderefed)
{
if (autoderefed.can_eq (expected, false))
{
@@ -308,16 +321,19 @@ AutoderefTypeCoercion::select (const TyTy::BaseType &autoderefed)
/// Coercing a mutable reference to an immutable works, while
/// coercing `&T` to `&mut T` should be forbidden.
bool
-AutoderefTypeCoercion::coerceable_mutability (Mutability from_mutbl,
- Mutability to_mutbl)
+TypeCoercionRules::coerceable_mutability (Mutability from_mutbl,
+ Mutability to_mutbl)
{
return to_mutbl == Mutability::Imm || (from_mutbl == to_mutbl);
}
void
-AutoderefTypeCoercion::mismatched_mutability_error (Location expr_locus,
- Location lhs, Location rhs)
+TypeCoercionRules::mismatched_mutability_error (Location expr_locus,
+ Location lhs, Location rhs)
{
+ if (!emit_errors)
+ return;
+
RichLocation r (expr_locus);
r.add_range (lhs);
r.add_range (rhs);
@@ -325,9 +341,12 @@ AutoderefTypeCoercion::mismatched_mutability_error (Location expr_locus,
}
void
-AutoderefTypeCoercion::object_unsafe_error (Location expr_locus, Location lhs,
- Location rhs)
+TypeCoercionRules::object_unsafe_error (Location expr_locus, Location lhs,
+ Location rhs)
{
+ if (!emit_errors)
+ return;
+
RichLocation r (expr_locus);
r.add_range (lhs);
r.add_range (rhs);
diff --git a/gcc/rust/typecheck/rust-coercion.h b/gcc/rust/typecheck/rust-coercion.h
index f2f440a..da28c7c 100644
--- a/gcc/rust/typecheck/rust-coercion.h
+++ b/gcc/rust/typecheck/rust-coercion.h
@@ -25,7 +25,7 @@
namespace Rust {
namespace Resolver {
-class AutoderefTypeCoercion : protected AutoderefCycle
+class TypeCoercionRules : protected AutoderefCycle
{
public:
struct CoercionResult
@@ -44,6 +44,9 @@ public:
static CoercionResult Coerce (TyTy::BaseType *receiver,
TyTy::BaseType *expected, Location locus);
+ static CoercionResult TryCoerce (TyTy::BaseType *receiver,
+ TyTy::BaseType *expected, Location locus);
+
CoercionResult coerce_unsafe_ptr (TyTy::BaseType *receiver,
TyTy::PointerType *expected,
Mutability mutability);
@@ -58,13 +61,13 @@ public:
static bool coerceable_mutability (Mutability from_mutbl,
Mutability to_mutbl);
- static void mismatched_mutability_error (Location expr_locus, Location lhs,
- Location rhs);
- static void object_unsafe_error (Location expr_locus, Location lhs,
- Location rhs);
+ void mismatched_mutability_error (Location expr_locus, Location lhs,
+ Location rhs);
+ void object_unsafe_error (Location expr_locus, Location lhs, Location rhs);
protected:
- AutoderefTypeCoercion (TyTy::BaseType *expected, Location locus);
+ TypeCoercionRules (TyTy::BaseType *expected, Location locus,
+ bool emit_errors);
bool select (const TyTy::BaseType &autoderefed) override;
@@ -81,6 +84,7 @@ private:
// mutable fields
CoercionResult try_result;
+ bool emit_errors;
};
} // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc
index f7b21ea..ac5c3b9 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc
@@ -20,6 +20,7 @@
#include "rust-hir-type-check-type.h"
#include "rust-hir-type-check-expr.h"
#include "rust-coercion.h"
+#include "rust-casts.h"
namespace Rust {
namespace Resolver {
@@ -343,7 +344,7 @@ TypeCheckBase::coercion_site (HirId id, TyTy::BaseType *expected,
return expr;
// can we autoderef it?
- auto result = AutoderefTypeCoercion::Coerce (expr, expected, locus);
+ auto result = TypeCoercionRules::Coerce (expr, expected, locus);
// the result needs to be unified
TyTy::BaseType *receiver = expr;
@@ -359,6 +360,36 @@ TypeCheckBase::coercion_site (HirId id, TyTy::BaseType *expected,
return coerced;
}
+TyTy::BaseType *
+TypeCheckBase::cast_site (HirId id, TyTy::TyWithLocation from,
+ TyTy::TyWithLocation to, Location cast_locus)
+{
+ rust_debug ("cast_site id={%u} from={%s} to={%s}", id,
+ from.get_ty ()->debug_str ().c_str (),
+ to.get_ty ()->debug_str ().c_str ());
+
+ auto context = TypeCheckContext::get ();
+ if (from.get_ty ()->get_kind () == TyTy::TypeKind::ERROR
+ || to.get_ty ()->get_kind () == TyTy::TypeKind::ERROR)
+ return to.get_ty ();
+
+ // do the cast
+ auto result = TypeCastRules::resolve (cast_locus, from, to);
+
+ // we assume error has already been emitted
+ if (result.is_error ())
+ return to.get_ty ();
+
+ // the result needs to be unified
+ TyTy::BaseType *casted_result = result.tyty;
+ rust_debug ("cast_default_unify(a={%s}, b={%s})",
+ casted_result->debug_str ().c_str (),
+ to.get_ty ()->debug_str ().c_str ());
+ TyTy::BaseType *casted = to.get_ty ()->unify (casted_result);
+ context->insert_cast_autoderef_mappings (id, std::move (result.adjustments));
+ return casted;
+}
+
void
TypeCheckBase::resolve_generic_params (
const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h
index 449ff6a..aa42d9d 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.h
@@ -36,7 +36,12 @@ public:
virtual ~TypeCheckBase () {}
static TyTy::BaseType *coercion_site (HirId id, TyTy::BaseType *lhs,
- TyTy::BaseType *rhs, Location locus);
+ TyTy::BaseType *rhs,
+ Location coercion_locus);
+
+ static TyTy::BaseType *cast_site (HirId id, TyTy::TyWithLocation from,
+ TyTy::TyWithLocation to,
+ Location cast_locus);
protected:
TypeCheckBase ()
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 6d8bbda..4371f5a 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -296,8 +296,12 @@ TypeCheckExpr::visit (HIR::ArithmeticOrLogicalExpr &expr)
switch (expr.get_expr_type ())
{
case ArithmeticOrLogicalOperator::LEFT_SHIFT:
- case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
- infered = rhs->cast (lhs);
+ case ArithmeticOrLogicalOperator::RIGHT_SHIFT: {
+ TyTy::TyWithLocation from (rhs, expr.get_rhs ()->get_locus ());
+ TyTy::TyWithLocation to (lhs, expr.get_lhs ()->get_locus ());
+ infered = cast_site (expr.get_mappings ().get_hirid (), from, to,
+ expr.get_locus ());
+ }
break;
default:
@@ -1264,7 +1268,12 @@ TypeCheckExpr::visit (HIR::TypeCastExpr &expr)
TyTy::BaseType *tyty_to_convert_to
= TypeCheckType::Resolve (expr.get_type_to_convert_to ().get ());
- infered = expr_to_convert->cast (tyty_to_convert_to);
+ TyTy::TyWithLocation from (expr_to_convert,
+ expr.get_casted_expr ()->get_locus ());
+ TyTy::TyWithLocation to (tyty_to_convert_to,
+ expr.get_type_to_convert_to ()->get_locus ());
+ infered = cast_site (expr.get_mappings ().get_hirid (), from, to,
+ expr.get_locus ());
}
void
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index 07c7a5c..21694dd 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -282,6 +282,25 @@ public:
return true;
}
+ void insert_cast_autoderef_mappings (HirId id,
+ std::vector<Adjustment> &&adjustments)
+ {
+ rust_assert (cast_autoderef_mappings.find (id)
+ == cast_autoderef_mappings.end ());
+ cast_autoderef_mappings.emplace (id, std::move (adjustments));
+ }
+
+ bool lookup_cast_autoderef_mappings (HirId id,
+ std::vector<Adjustment> **adjustments)
+ {
+ auto it = cast_autoderef_mappings.find (id);
+ if (it == cast_autoderef_mappings.end ())
+ return false;
+
+ *adjustments = &it->second;
+ return true;
+ }
+
void insert_variant_definition (HirId id, HirId variant)
{
auto it = variants.find (id);
@@ -339,6 +358,7 @@ private:
// adjustment mappings
std::map<HirId, std::vector<Adjustment>> autoderef_mappings;
+ std::map<HirId, std::vector<Adjustment>> cast_autoderef_mappings;
// operator overloads
std::map<HirId, TyTy::FnType *> operator_overloads;
diff --git a/gcc/rust/typecheck/rust-tyty-cast.h b/gcc/rust/typecheck/rust-tyty-cast.h
deleted file mode 100644
index 5ca68d0..0000000
--- a/gcc/rust/typecheck/rust-tyty-cast.h
+++ /dev/null
@@ -1,1425 +0,0 @@
-// Copyright (C) 2020-2022 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_TYTY_CAST_RULES
-#define RUST_TYTY_CAST_RULES
-
-#include "rust-diagnostics.h"
-#include "rust-tyty.h"
-#include "rust-tyty-visitor.h"
-#include "rust-hir-map.h"
-#include "rust-hir-type-check.h"
-
-extern ::Backend *
-rust_get_backend ();
-
-namespace Rust {
-namespace TyTy {
-
-class BaseCastRules : public TyVisitor
-{
-public:
- virtual ~BaseCastRules () {}
-
- virtual BaseType *cast (BaseType *other)
- {
- if (other->get_kind () == TypeKind::PARAM)
- {
- ParamType *p = static_cast<ParamType *> (other);
- if (p->can_resolve ())
- {
- other = p->resolve ();
- }
- }
-
- other->accept_vis (*this);
- if (resolved->get_kind () == TyTy::TypeKind::ERROR)
- return resolved;
-
- resolved->append_reference (get_base ()->get_ref ());
- resolved->append_reference (other->get_ref ());
- for (auto ref : get_base ()->get_combined_refs ())
- resolved->append_reference (ref);
- for (auto ref : other->get_combined_refs ())
- resolved->append_reference (ref);
-
- bool result_resolved = resolved->get_kind () != TyTy::TypeKind::INFER;
- bool result_is_infer_var = resolved->get_kind () == TyTy::TypeKind::INFER;
- bool results_is_non_general_infer_var
- = (result_is_infer_var
- && (static_cast<InferType *> (resolved))->get_infer_kind ()
- != TyTy::InferType::GENERAL);
- if (result_resolved || results_is_non_general_infer_var)
- {
- for (auto &ref : resolved->get_combined_refs ())
- {
- TyTy::BaseType *ref_tyty = nullptr;
- bool ok = context->lookup_type (ref, &ref_tyty);
- if (!ok)
- continue;
-
- // if any of the types are inference variables lets fix them
- if (ref_tyty->get_kind () == TyTy::TypeKind::INFER)
- {
- context->insert_type (
- Analysis::NodeMapping (mappings->get_current_crate (),
- UNKNOWN_NODEID, ref,
- UNKNOWN_LOCAL_DEFID),
- resolved->clone ());
- }
- }
- }
- return resolved;
- }
-
- virtual void visit (TupleType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (ADTType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (InferType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (FnType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (FnPtr &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (ArrayType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (SliceType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (BoolType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (IntType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (UintType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (USizeType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (ISizeType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (FloatType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (ErrorType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (CharType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (ReferenceType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (PointerType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (ParamType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (StrType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (NeverType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (PlaceholderType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (ProjectionType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (DynamicObjectType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
- virtual void visit (ClosureType &type) override
- {
- Location ref_locus = mappings->lookup_location (type.get_ref ());
- Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
- RichLocation r (ref_locus);
- r.add_range (base_locus);
- rust_error_at (r, "invalid cast [%s] to [%s]",
- get_base ()->as_string ().c_str (),
- type.as_string ().c_str ());
- }
-
-protected:
- BaseCastRules (BaseType *base)
- : mappings (Analysis::Mappings::get ()),
- context (Resolver::TypeCheckContext::get ()),
- resolved (new ErrorType (base->get_ref (), base->get_ref ()))
- {}
-
- Analysis::Mappings *mappings;
- Resolver::TypeCheckContext *context;
-
- /* Temporary storage for the result of a unification.
- We could return the result directly instead of storing it in the rule
- object, but that involves modifying the visitor pattern to accommodate
- the return value, which is too complex. */
- BaseType *resolved;
-
-private:
- /* Returns a pointer to the ty that created this rule. */
- virtual BaseType *get_base () = 0;
-};
-
-class InferCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- InferCastRules (InferType *base) : BaseCastRules (base), base (base) {}
-
- void visit (BoolType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseCastRules::visit (type);
- }
-
- void visit (IntType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
- || (base->get_infer_kind ()
- == TyTy::InferType::InferTypeKind::INTEGRAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseCastRules::visit (type);
- }
-
- void visit (UintType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
- || (base->get_infer_kind ()
- == TyTy::InferType::InferTypeKind::INTEGRAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseCastRules::visit (type);
- }
-
- void visit (USizeType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
- || (base->get_infer_kind ()
- == TyTy::InferType::InferTypeKind::INTEGRAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseCastRules::visit (type);
- }
-
- void visit (ISizeType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
- || (base->get_infer_kind ()
- == TyTy::InferType::InferTypeKind::INTEGRAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseCastRules::visit (type);
- }
-
- void visit (FloatType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL)
- || (base->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseCastRules::visit (type);
- }
-
- void visit (ArrayType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseCastRules::visit (type);
- }
-
- void visit (SliceType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseCastRules::visit (type);
- }
-
- void visit (ADTType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseCastRules::visit (type);
- }
-
- void visit (TupleType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseCastRules::visit (type);
- }
-
- void visit (InferType &type) override
- {
- switch (base->get_infer_kind ())
- {
- case InferType::InferTypeKind::GENERAL:
- resolved = type.clone ();
- return;
-
- case InferType::InferTypeKind::INTEGRAL: {
- if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL)
- {
- resolved = type.clone ();
- return;
- }
- else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL)
- {
- resolved = base->clone ();
- return;
- }
- }
- break;
-
- case InferType::InferTypeKind::FLOAT: {
- if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
- {
- resolved = type.clone ();
- return;
- }
- else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL)
- {
- resolved = base->clone ();
- return;
- }
- }
- break;
- }
-
- BaseCastRules::visit (type);
- }
-
- void visit (CharType &type) override
- {
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseCastRules::visit (type);
- }
- }
-
- void visit (ReferenceType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseCastRules::visit (type);
- }
-
- void visit (PointerType &type) override
- {
- bool is_general_infer_var
- = base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
- bool is_integral_infer_var
- = base->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL;
- bool is_valid = is_general_infer_var || is_integral_infer_var;
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseCastRules::visit (type);
- }
-
- void visit (ParamType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseCastRules::visit (type);
- }
-
- void visit (DynamicObjectType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseCastRules::visit (type);
- }
-
- void visit (ClosureType &type) override
- {
- bool is_valid
- = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
- if (is_valid)
- {
- resolved = type.clone ();
- return;
- }
-
- BaseCastRules::visit (type);
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- InferType *base;
-};
-
-class FnCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- FnCastRules (FnType *base) : BaseCastRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseCastRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (FnType &type) override
- {
- if (base->num_params () != type.num_params ())
- {
- BaseCastRules::visit (type);
- return;
- }
-
- for (size_t i = 0; i < base->num_params (); i++)
- {
- auto a = base->param_at (i).second;
- auto b = type.param_at (i).second;
-
- auto unified_param = a->unify (b);
- if (unified_param == nullptr)
- {
- BaseCastRules::visit (type);
- return;
- }
- }
-
- auto unified_return
- = base->get_return_type ()->unify (type.get_return_type ());
- if (unified_return == nullptr)
- {
- BaseCastRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- FnType *base;
-};
-
-class FnptrCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- FnptrCastRules (FnPtr *base) : BaseCastRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseCastRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (FnPtr &type) override
- {
- auto this_ret_type = base->get_return_type ();
- auto other_ret_type = type.get_return_type ();
- auto unified_result = this_ret_type->unify (other_ret_type);
- if (unified_result == nullptr
- || unified_result->get_kind () == TypeKind::ERROR)
- {
- BaseCastRules::visit (type);
- return;
- }
-
- if (base->num_params () != type.num_params ())
- {
- BaseCastRules::visit (type);
- return;
- }
-
- for (size_t i = 0; i < base->num_params (); i++)
- {
- auto this_param = base->param_at (i);
- auto other_param = type.param_at (i);
- auto unified_param = this_param->unify (other_param);
- if (unified_param == nullptr
- || unified_param->get_kind () == TypeKind::ERROR)
- {
- BaseCastRules::visit (type);
- return;
- }
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (FnType &type) override
- {
- auto this_ret_type = base->get_return_type ();
- auto other_ret_type = type.get_return_type ();
- auto unified_result = this_ret_type->unify (other_ret_type);
- if (unified_result == nullptr
- || unified_result->get_kind () == TypeKind::ERROR)
- {
- BaseCastRules::visit (type);
- return;
- }
-
- if (base->num_params () != type.num_params ())
- {
- BaseCastRules::visit (type);
- return;
- }
-
- for (size_t i = 0; i < base->num_params (); i++)
- {
- auto this_param = base->param_at (i);
- auto other_param = type.param_at (i).second;
- auto unified_param = this_param->unify (other_param);
- if (unified_param == nullptr
- || unified_param->get_kind () == TypeKind::ERROR)
- {
- BaseCastRules::visit (type);
- return;
- }
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- FnPtr *base;
-};
-
-class ClosureCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- ClosureCastRules (ClosureType *base) : BaseCastRules (base), base (base) {}
-
- // TODO
-
-private:
- BaseType *get_base () override { return base; }
-
- ClosureType *base;
-};
-
-class ArrayCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- ArrayCastRules (ArrayType *base) : BaseCastRules (base), base (base) {}
-
- void visit (ArrayType &type) override
- {
- // check base type
- auto base_resolved
- = base->get_element_type ()->unify (type.get_element_type ());
- if (base_resolved == nullptr)
- {
- BaseCastRules::visit (type);
- return;
- }
-
- resolved
- = new ArrayType (type.get_ref (), type.get_ty_ref (),
- type.get_ident ().locus, type.get_capacity_expr (),
- TyVar (base_resolved->get_ref ()));
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- ArrayType *base;
-};
-
-class SliceCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- SliceCastRules (SliceType *base) : BaseCastRules (base), base (base) {}
-
- void visit (SliceType &type) override
- {
- // check base type
- auto base_resolved
- = base->get_element_type ()->unify (type.get_element_type ());
- if (base_resolved == nullptr)
- {
- BaseCastRules::visit (type);
- return;
- }
-
- resolved = new SliceType (type.get_ref (), type.get_ty_ref (),
- type.get_ident ().locus,
- TyVar (base_resolved->get_ref ()));
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- SliceType *base;
-};
-
-class BoolCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- BoolCastRules (BoolType *base) : BaseCastRules (base), base (base) {}
-
- void visit (BoolType &type) override
- {
- resolved = new BoolType (type.get_ref (), type.get_ty_ref ());
- }
-
- void visit (InferType &type) override
- {
- switch (type.get_infer_kind ())
- {
- case InferType::InferTypeKind::GENERAL:
- resolved = base->clone ();
- break;
-
- default:
- BaseCastRules::visit (type);
- break;
- }
- }
-
- /* bools can be cast to any integer type (but not floats or chars). */
- void visit (IntType &type) override { resolved = type.clone (); }
- void visit (UintType &type) override { resolved = type.clone (); }
- void visit (USizeType &type) override { resolved = type.clone (); }
- void visit (ISizeType &type) override { resolved = type.clone (); }
-
-private:
- BaseType *get_base () override { return base; }
-
- BoolType *base;
-};
-
-class IntCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- IntCastRules (IntType *base) : BaseCastRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- // cant assign a float inference variable
- if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
- {
- BaseCastRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (IntType &type) override { resolved = type.clone (); }
-
- void visit (UintType &type) override { resolved = type.clone (); }
-
- void visit (FloatType &type) override { resolved = type.clone (); }
-
- void visit (USizeType &type) override { resolved = type.clone (); }
-
- void visit (ISizeType &type) override { resolved = type.clone (); }
-
- void visit (PointerType &type) override { resolved = type.clone (); }
-
-private:
- BaseType *get_base () override { return base; }
-
- IntType *base;
-};
-
-class UintCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- UintCastRules (UintType *base) : BaseCastRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- // cant assign a float inference variable
- if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
- {
- BaseCastRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (IntType &type) override { resolved = type.clone (); }
-
- void visit (UintType &type) override { resolved = type.clone (); }
-
- void visit (FloatType &type) override { resolved = type.clone (); }
-
- void visit (USizeType &type) override { resolved = type.clone (); }
-
- void visit (ISizeType &type) override { resolved = type.clone (); }
-
- void visit (PointerType &type) override { resolved = type.clone (); }
-
- void visit (CharType &type) override
- {
- // error[E0604]: only `u8` can be cast as `char`, not `i32`
- if (base->get_uint_kind () != UintType::UintKind::U8)
- {
- BaseCastRules::visit (type);
- return;
- }
-
- resolved = type.clone ();
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- UintType *base;
-};
-
-class FloatCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- FloatCastRules (FloatType *base) : BaseCastRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL)
- {
- BaseCastRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (IntType &type) override { resolved = type.clone (); }
-
- void visit (UintType &type) override { resolved = type.clone (); }
-
- void visit (FloatType &type) override { resolved = type.clone (); }
-
- void visit (USizeType &type) override { resolved = type.clone (); }
-
- void visit (ISizeType &type) override { resolved = type.clone (); }
-
-private:
- BaseType *get_base () override { return base; }
-
- FloatType *base;
-};
-
-class ADTCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- ADTCastRules (ADTType *base) : BaseCastRules (base), base (base) {}
-
- void visit (ADTType &type) override
- {
- if (base->get_adt_kind () != type.get_adt_kind ())
- {
- BaseCastRules::visit (type);
- return;
- }
-
- if (base->get_identifier ().compare (type.get_identifier ()) != 0)
- {
- BaseCastRules::visit (type);
- return;
- }
-
- if (base->number_of_variants () != type.number_of_variants ())
- {
- BaseCastRules::visit (type);
- return;
- }
-
- for (size_t i = 0; i < type.number_of_variants (); ++i)
- {
- TyTy::VariantDef *a = base->get_variants ().at (i);
- TyTy::VariantDef *b = type.get_variants ().at (i);
-
- if (a->num_fields () != b->num_fields ())
- {
- BaseCastRules::visit (type);
- return;
- }
-
- for (size_t j = 0; j < a->num_fields (); j++)
- {
- TyTy::StructFieldType *base_field = a->get_field_at_index (i);
- TyTy::StructFieldType *other_field = b->get_field_at_index (i);
-
- TyTy::BaseType *this_field_ty = base_field->get_field_type ();
- TyTy::BaseType *other_field_ty = other_field->get_field_type ();
-
- BaseType *unified_ty = this_field_ty->unify (other_field_ty);
- if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
- return;
- }
- }
-
- resolved = type.clone ();
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- ADTType *base;
-};
-
-class TupleCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- TupleCastRules (TupleType *base) : BaseCastRules (base), base (base) {}
-
- void visit (TupleType &type) override
- {
- if (base->num_fields () != type.num_fields ())
- {
- BaseCastRules::visit (type);
- return;
- }
-
- std::vector<TyVar> fields;
- for (size_t i = 0; i < base->num_fields (); i++)
- {
- BaseType *bo = base->get_field (i);
- BaseType *fo = type.get_field (i);
-
- BaseType *unified_ty = bo->unify (fo);
- if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
- return;
-
- fields.push_back (TyVar (unified_ty->get_ref ()));
- }
-
- resolved = new TyTy::TupleType (type.get_ref (), type.get_ty_ref (),
- type.get_ident ().locus, fields);
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- TupleType *base;
-};
-
-class USizeCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- USizeCastRules (USizeType *base) : BaseCastRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- // cant assign a float inference variable
- if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
- {
- BaseCastRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (IntType &type) override { resolved = type.clone (); }
-
- void visit (UintType &type) override { resolved = type.clone (); }
-
- void visit (FloatType &type) override { resolved = type.clone (); }
-
- void visit (USizeType &type) override { resolved = type.clone (); }
-
- void visit (ISizeType &type) override { resolved = type.clone (); }
-
-private:
- BaseType *get_base () override { return base; }
-
- USizeType *base;
-};
-
-class ISizeCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- ISizeCastRules (ISizeType *base) : BaseCastRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- // cant assign a float inference variable
- if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
- {
- BaseCastRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (IntType &type) override { resolved = type.clone (); }
-
- void visit (UintType &type) override { resolved = type.clone (); }
-
- void visit (FloatType &type) override { resolved = type.clone (); }
-
- void visit (USizeType &type) override { resolved = type.clone (); }
-
- void visit (ISizeType &type) override { resolved = type.clone (); }
-
-private:
- BaseType *get_base () override { return base; }
-
- ISizeType *base;
-};
-
-class CharCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- CharCastRules (CharType *base) : BaseCastRules (base), base (base) {}
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseCastRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- resolved->set_ref (type.get_ref ());
- }
-
- void visit (CharType &type) override { resolved = type.clone (); }
-
- /* chars can be cast to any integer type (but not floats or bools). */
- void visit (IntType &type) override { resolved = type.clone (); }
- void visit (UintType &type) override { resolved = type.clone (); }
- void visit (USizeType &type) override { resolved = type.clone (); }
- void visit (ISizeType &type) override { resolved = type.clone (); }
-
-private:
- BaseType *get_base () override { return base; }
-
- CharType *base;
-};
-
-class ReferenceCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- ReferenceCastRules (ReferenceType *base) : BaseCastRules (base), base (base)
- {}
-
- void visit (ReferenceType &type) override { resolved = type.clone (); }
-
- void visit (PointerType &type) override
- {
- auto base_type = base->get_base ();
- auto other_base_type = type.get_base ();
-
- TyTy::BaseType *base_resolved = base_type->unify (other_base_type);
- if (base_resolved == nullptr
- || base_resolved->get_kind () == TypeKind::ERROR)
- {
- BaseCastRules::visit (type);
- return;
- }
-
- resolved = type.clone ();
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- ReferenceType *base;
-};
-
-class PointerCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- PointerCastRules (PointerType *base) : BaseCastRules (base), base (base) {}
-
- void visit (ReferenceType &type) override
- {
- auto base_type = base->get_base ();
- auto other_base_type = type.get_base ();
-
- TyTy::BaseType *base_resolved = base_type->unify (other_base_type);
- if (base_resolved == nullptr
- || base_resolved->get_kind () == TypeKind::ERROR)
- {
- BaseCastRules::visit (type);
- return;
- }
-
- resolved = type.clone ();
- }
-
- void visit (PointerType &type) override { resolved = type.clone (); }
-
-private:
- BaseType *get_base () override { return base; }
-
- PointerType *base;
-};
-
-class ParamCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- ParamCastRules (ParamType *base) : BaseCastRules (base), base (base) {}
-
- // param types are a placeholder we shouldn't have cases where we unify
- // against it. eg: struct foo<T> { a: T }; When we invoke it we can do either:
- //
- // foo<i32>{ a: 123 }.
- // Then this enforces the i32 type to be referenced on the
- // field via an hirid.
- //
- // rust also allows for a = foo{a:123}; Where we can use an Inference Variable
- // to handle the typing of the struct
- BaseType *cast (BaseType *other) override final
- {
- if (base->get_ref () == base->get_ty_ref ())
- return BaseCastRules::cast (other);
-
- auto context = Resolver::TypeCheckContext::get ();
- BaseType *lookup = nullptr;
- bool ok = context->lookup_type (base->get_ty_ref (), &lookup);
- rust_assert (ok);
-
- return lookup->unify (other);
- }
-
- void visit (ParamType &type) override
- {
- if (base->get_symbol ().compare (type.get_symbol ()) != 0)
- {
- BaseCastRules::visit (type);
- return;
- }
-
- resolved = type.clone ();
- }
-
- void visit (InferType &type) override
- {
- if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
- {
- BaseCastRules::visit (type);
- return;
- }
-
- resolved = base->clone ();
- }
-
-private:
- BaseType *get_base () override { return base; }
-
- ParamType *base;
-};
-
-class StrCastRules : public BaseCastRules
-{
- // FIXME we will need a enum for the StrType like ByteBuf etc..
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- StrCastRules (StrType *base) : BaseCastRules (base), base (base) {}
-
- void visit (StrType &type) override { resolved = type.clone (); }
-
-private:
- BaseType *get_base () override { return base; }
-
- StrType *base;
-};
-
-class NeverCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- NeverCastRules (NeverType *base) : BaseCastRules (base), base (base) {}
-
- virtual void visit (NeverType &type) override { resolved = type.clone (); }
-
-private:
- BaseType *get_base () override { return base; }
-
- NeverType *base;
-};
-
-class PlaceholderCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- PlaceholderCastRules (PlaceholderType *base)
- : BaseCastRules (base), base (base)
- {}
-
-private:
- BaseType *get_base () override { return base; }
-
- PlaceholderType *base;
-};
-
-class DynamicCastRules : public BaseCastRules
-{
- using Rust::TyTy::BaseCastRules::visit;
-
-public:
- DynamicCastRules (DynamicObjectType *base) : BaseCastRules (base), base (base)
- {}
-
-private:
- BaseType *get_base () override { return base; }
-
- DynamicObjectType *base;
-};
-
-} // namespace TyTy
-} // namespace Rust
-
-#endif // RUST_TYTY_CAST_RULES
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 24969db..3c2c678 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -23,7 +23,6 @@
#include "rust-hir-type-check-type.h"
#include "rust-tyty-rules.h"
#include "rust-tyty-cmp.h"
-#include "rust-tyty-cast.h"
#include "rust-hir-map.h"
#include "rust-substitution-mapper.h"
#include "rust-hir-trait-ref.h"
@@ -376,6 +375,16 @@ TyVar::monomorphized_clone () const
return TyVar (c->get_ref ());
}
+TyWithLocation::TyWithLocation (BaseType *ty, Location locus)
+ : ty (ty), locus (locus)
+{}
+
+TyWithLocation::TyWithLocation (BaseType *ty) : ty (ty)
+{
+ auto mappings = Analysis::Mappings::get ();
+ locus = mappings->lookup_location (ty->get_ref ());
+}
+
void
InferType::accept_vis (TyVisitor &vis)
{
@@ -418,13 +427,6 @@ InferType::can_eq (const BaseType *other, bool emit_errors) const
}
BaseType *
-InferType::cast (BaseType *other)
-{
- InferCastRules r (this);
- return r.cast (other);
-}
-
-BaseType *
InferType::clone () const
{
// clones for inference variables are special in that they _must_ exist within
@@ -519,12 +521,6 @@ ErrorType::can_eq (const BaseType *other, bool emit_errors) const
}
BaseType *
-ErrorType::cast (BaseType *other)
-{
- return this;
-}
-
-BaseType *
ErrorType::clone () const
{
return new ErrorType (get_ref (), get_ty_ref (), get_combined_refs ());
@@ -984,13 +980,6 @@ ADTType::unify (BaseType *other)
return r.unify (other);
}
-BaseType *
-ADTType::cast (BaseType *other)
-{
- ADTCastRules r (this);
- return r.cast (other);
-}
-
bool
ADTType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1191,13 +1180,6 @@ TupleType::unify (BaseType *other)
return r.unify (other);
}
-BaseType *
-TupleType::cast (BaseType *other)
-{
- TupleCastRules r (this);
- return r.cast (other);
-}
-
bool
TupleType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1305,13 +1287,6 @@ FnType::unify (BaseType *other)
return r.unify (other);
}
-BaseType *
-FnType::cast (BaseType *other)
-{
- FnCastRules r (this);
- return r.cast (other);
-}
-
bool
FnType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1543,13 +1518,6 @@ FnPtr::unify (BaseType *other)
return r.unify (other);
}
-BaseType *
-FnPtr::cast (BaseType *other)
-{
- FnptrCastRules r (this);
- return r.cast (other);
-}
-
bool
FnPtr::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1636,14 +1604,6 @@ ClosureType::can_eq (const BaseType *other, bool emit_errors) const
return r.can_eq (other);
}
-BaseType *
-ClosureType::cast (BaseType *other)
-{
- // FIXME
- gcc_unreachable ();
- return nullptr;
-}
-
bool
ClosureType::is_equal (const BaseType &other) const
{
@@ -1696,13 +1656,6 @@ ArrayType::unify (BaseType *other)
return r.unify (other);
}
-BaseType *
-ArrayType::cast (BaseType *other)
-{
- ArrayCastRules r (this);
- return r.cast (other);
-}
-
bool
ArrayType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1786,13 +1739,6 @@ SliceType::unify (BaseType *other)
return r.unify (other);
}
-BaseType *
-SliceType::cast (BaseType *other)
-{
- SliceCastRules r (this);
- return r.cast (other);
-}
-
bool
SliceType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1876,13 +1822,6 @@ BoolType::unify (BaseType *other)
return r.unify (other);
}
-BaseType *
-BoolType::cast (BaseType *other)
-{
- BoolCastRules r (this);
- return r.cast (other);
-}
-
bool
BoolType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -1941,13 +1880,6 @@ IntType::unify (BaseType *other)
return r.unify (other);
}
-BaseType *
-IntType::cast (BaseType *other)
-{
- IntCastRules r (this);
- return r.cast (other);
-}
-
bool
IntType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2017,13 +1949,6 @@ UintType::unify (BaseType *other)
return r.unify (other);
}
-BaseType *
-UintType::cast (BaseType *other)
-{
- UintCastRules r (this);
- return r.cast (other);
-}
-
bool
UintType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2087,13 +2012,6 @@ FloatType::unify (BaseType *other)
return r.unify (other);
}
-BaseType *
-FloatType::cast (BaseType *other)
-{
- FloatCastRules r (this);
- return r.cast (other);
-}
-
bool
FloatType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2149,13 +2067,6 @@ USizeType::unify (BaseType *other)
return r.unify (other);
}
-BaseType *
-USizeType::cast (BaseType *other)
-{
- USizeCastRules r (this);
- return r.cast (other);
-}
-
bool
USizeType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2200,13 +2111,6 @@ ISizeType::unify (BaseType *other)
return r.unify (other);
}
-BaseType *
-ISizeType::cast (BaseType *other)
-{
- ISizeCastRules r (this);
- return r.cast (other);
-}
-
bool
ISizeType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2251,13 +2155,6 @@ CharType::unify (BaseType *other)
return r.unify (other);
}
-BaseType *
-CharType::cast (BaseType *other)
-{
- CharCastRules r (this);
- return r.cast (other);
-}
-
bool
CharType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2303,13 +2200,6 @@ ReferenceType::unify (BaseType *other)
return r.unify (other);
}
-BaseType *
-ReferenceType::cast (BaseType *other)
-{
- ReferenceCastRules r (this);
- return r.cast (other);
-}
-
bool
ReferenceType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2393,13 +2283,6 @@ PointerType::unify (BaseType *other)
return r.unify (other);
}
-BaseType *
-PointerType::cast (BaseType *other)
-{
- PointerCastRules r (this);
- return r.cast (other);
-}
-
bool
PointerType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2497,13 +2380,6 @@ ParamType::unify (BaseType *other)
return r.unify (other);
}
-BaseType *
-ParamType::cast (BaseType *other)
-{
- ParamCastRules r (this);
- return r.cast (other);
-}
-
bool
ParamType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2636,13 +2512,6 @@ StrType::unify (BaseType *other)
return r.unify (other);
}
-BaseType *
-StrType::cast (BaseType *other)
-{
- StrCastRules r (this);
- return r.cast (other);
-}
-
bool
StrType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2681,13 +2550,6 @@ NeverType::unify (BaseType *other)
return r.unify (other);
}
-BaseType *
-NeverType::cast (BaseType *other)
-{
- NeverCastRules r (this);
- return r.cast (other);
-}
-
bool
NeverType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2735,13 +2597,6 @@ PlaceholderType::unify (BaseType *other)
return r.unify (other);
}
-BaseType *
-PlaceholderType::cast (BaseType *other)
-{
- PlaceholderCastRules r (this);
- return r.cast (other);
-}
-
bool
PlaceholderType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2839,12 +2694,6 @@ ProjectionType::unify (BaseType *other)
return base->unify (other);
}
-BaseType *
-ProjectionType::cast (BaseType *other)
-{
- return base->cast (other);
-}
-
bool
ProjectionType::can_eq (const BaseType *other, bool emit_errors) const
{
@@ -2970,13 +2819,6 @@ DynamicObjectType::can_eq (const BaseType *other, bool emit_errors) const
}
BaseType *
-DynamicObjectType::cast (BaseType *other)
-{
- DynamicCastRules r (this);
- return r.cast (other);
-}
-
-BaseType *
DynamicObjectType::clone () const
{
return new DynamicObjectType (get_ref (), get_ty_ref (), ident,
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 56a0e05..c47921d 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -180,9 +180,6 @@ public:
// checks
virtual bool can_eq (const BaseType *other, bool emit_errors) const = 0;
- // this is the cast interface for TypeCastExpr
- virtual BaseType *cast (BaseType *other) = 0;
-
// Check value equality between two ty. Type inference rules are ignored. Two
// ty are considered equal if they're of the same kind, and
// 1. (For ADTs, arrays, tuples, refs) have the same underlying ty
@@ -314,6 +311,20 @@ private:
HirId ref;
};
+class TyWithLocation
+{
+public:
+ TyWithLocation (BaseType *ty, Location locus);
+ TyWithLocation (BaseType *ty);
+
+ BaseType *get_ty () const { return ty; }
+ Location get_locus () const { return locus; }
+
+private:
+ BaseType *ty;
+ Location locus;
+};
+
class InferType : public BaseType
{
public:
@@ -347,8 +358,6 @@ public:
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
@@ -387,8 +396,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
@@ -431,8 +438,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
@@ -531,8 +536,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
bool is_equal (const BaseType &other) const override;
size_t num_fields () const { return fields.size (); }
@@ -1360,8 +1363,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
bool is_equal (const BaseType &other) const override;
std::string get_identifier () const { return identifier; }
@@ -1497,8 +1498,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
bool is_equal (const BaseType &other) const override;
size_t num_params () const { return params.size (); }
@@ -1619,8 +1618,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
bool is_equal (const BaseType &other) const override;
BaseType *clone () const final override;
@@ -1693,8 +1690,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
bool is_equal (const BaseType &other) const override;
BaseType *clone () const final override;
@@ -1759,8 +1754,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
bool is_equal (const BaseType &other) const override;
BaseType *get_element_type () const;
@@ -1809,8 +1802,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
bool is_equal (const BaseType &other) const override;
BaseType *get_element_type () const;
@@ -1856,8 +1847,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
bool is_concrete () const override final { return true; }
@@ -1902,8 +1891,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
IntKind get_int_kind () const { return int_kind; }
BaseType *clone () const final override;
@@ -1955,8 +1942,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
UintKind get_uint_kind () const { return uint_kind; }
BaseType *clone () const final override;
@@ -2006,8 +1991,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
FloatKind get_float_kind () const { return float_kind; }
BaseType *clone () const final override;
@@ -2047,8 +2030,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
bool is_concrete () const override final { return true; }
@@ -2081,8 +2062,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
bool is_concrete () const override final { return true; }
@@ -2115,8 +2094,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
bool is_concrete () const override final { return true; }
@@ -2149,8 +2126,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
bool is_equal (const BaseType &other) const override;
BaseType *clone () const final override;
@@ -2194,8 +2169,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
bool is_equal (const BaseType &other) const override;
BaseType *clone () const final override;
@@ -2282,8 +2255,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
bool is_equal (const BaseType &other) const override;
BaseType *clone () const final override;
@@ -2371,8 +2342,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
@@ -2413,8 +2382,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
@@ -2489,8 +2456,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
-
BaseType *clone () const final override;
BaseType *monomorphized_clone () const final override;
@@ -2547,7 +2512,6 @@ public:
BaseType *unify (BaseType *other) override;
bool can_eq (const BaseType *other, bool emit_errors) const override final;
- BaseType *cast (BaseType *other) override;
bool is_equal (const BaseType &other) const override;
BaseType *clone () const final override;
diff --git a/gcc/testsuite/rust/execute/torture/issue-1496.rs b/gcc/testsuite/rust/execute/torture/issue-1496.rs
new file mode 100644
index 0000000..9f08b2a
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1496.rs
@@ -0,0 +1,75 @@
+/* { dg-output "foo_deref\nimm_deref\n123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+ type Target;
+
+ fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "imm_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+impl<T> Deref for &mut T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "mut_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ unsafe {
+ let a = "foo_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ &self.0
+ }
+}
+
+fn main() -> i32 {
+ let foo = Foo(123);
+ let bar = &foo as &i32;
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, *bar);
+ }
+
+ 0
+}