diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/Make-lang.in | 1 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.cc | 24 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-casts.cc | 292 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-casts.h | 53 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-coercion.cc | 89 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-coercion.h | 16 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-base.cc | 33 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-base.h | 7 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.cc | 15 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check.h | 20 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty-cast.h | 1425 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.cc | 178 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.h | 64 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/issue-1496.rs | 75 |
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 +} |