From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1643) id E530A385735D; Mon, 29 Aug 2022 15:31:37 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E530A385735D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1661787097; bh=t7vn25EEuM0MtgWGfg2/Ovu2xUV1FUAv3HVsoKhpm+s=; h=From:To:Subject:Date:From; b=saYg8WIyGLTi2aVQn2wV979h+zHNaLnfRH6S6kaBnkPOPi3WVJrvLkXOoBTn7+MFn G5ANnvU82/+7vvKj9WzbdrQsGqfUr7fEd8YhUbMl3hmyKQ1XH9Oh8ltO6ClhjrnNHU joRqp1frAY442Y4YnjEbV285Gw9z9+6aRlZx6iHY= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Thomas Schwinge To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/rust/master] Refactor our casts to follow the Rustc implemention X-Act-Checkin: gcc X-Git-Author: Philip Herron X-Git-Refname: refs/heads/devel/rust/master X-Git-Oldrev: 0f4ec11e8c2399ca20f80b4006e294794f9b2e0f X-Git-Newrev: 36a9255b1b6683bb060021c637997de396445049 Message-Id: <20220829153137.E530A385735D@sourceware.org> Date: Mon, 29 Aug 2022 15:31:37 +0000 (GMT) List-Id: https://gcc.gnu.org/g:36a9255b1b6683bb060021c637997de396445049 commit 36a9255b1b6683bb060021c637997de396445049 Author: Philip Herron Date: Mon Aug 22 15:54:14 2022 +0100 Refactor our casts to follow the Rustc implemention This gets rid of our old visitor system for cast type checking. Casts depend on type coercions as they are meant to attempt a type coercion before trying a simple cast. This explicitly defines the rules which should be allowed for simple casts. In rustc they use match expressions to write a list of casts which should not be allowed. We have likely missed some rules of what should be allowed but this is at least the start of how to implement this. Fixes #1496 Diff: --- gcc/rust/Make-lang.in | 1 + gcc/rust/backend/rust-compile-expr.cc | 24 +- gcc/rust/typecheck/rust-casts.cc | 292 +++++ gcc/rust/typecheck/rust-casts.h | 53 + gcc/rust/typecheck/rust-coercion.cc | 89 +- gcc/rust/typecheck/rust-coercion.h | 16 +- gcc/rust/typecheck/rust-hir-type-check-base.cc | 33 +- gcc/rust/typecheck/rust-hir-type-check-base.h | 7 +- gcc/rust/typecheck/rust-hir-type-check-expr.cc | 15 +- gcc/rust/typecheck/rust-hir-type-check.h | 20 + gcc/rust/typecheck/rust-tyty-cast.h | 1425 ---------------------- gcc/rust/typecheck/rust-tyty.cc | 178 +-- gcc/rust/typecheck/rust-tyty.h | 64 +- 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 49be3a1b473..f687cc2f667 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 412ca091a42..865ad250f2c 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 *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 00000000000..61004dfabc3 --- /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 +// . + +#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 (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 (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 (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 (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 (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 (*from.get_ty ()); + TyTy::ReferenceType &t + = static_cast (*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 00000000000..e908f49b656 --- /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 +// . + +#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 b7ef6774afd..2ad2b8007ff 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 f2f440afd8b..da28c7c5e1b 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 f7b21ea60d9..ac5c3b97475 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> &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 449ff6ab92a..aa42d9d6dfd 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 6d8bbda428c..4371f5a59a5 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 07c7a5cf60b..21694dd302b 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 &&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 **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> autoderef_mappings; + std::map> cast_autoderef_mappings; // operator overloads std::map 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 5ca68d07aa2..00000000000 --- 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 -// . - -#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 (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 (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 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 { a: T }; When we invoke it we can do either: - // - // foo{ 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 24969dbdac6..3c2c6786940 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) { @@ -417,13 +426,6 @@ InferType::can_eq (const BaseType *other, bool emit_errors) const return r.can_eq (other); } -BaseType * -InferType::cast (BaseType *other) -{ - InferCastRules r (this); - return r.cast (other); -} - BaseType * InferType::clone () const { @@ -518,12 +520,6 @@ ErrorType::can_eq (const BaseType *other, bool emit_errors) const return get_kind () == other->get_kind (); } -BaseType * -ErrorType::cast (BaseType *other) -{ - return this; -} - BaseType * ErrorType::clone () const { @@ -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 { @@ -2969,13 +2818,6 @@ DynamicObjectType::can_eq (const BaseType *other, bool emit_errors) const return r.can_eq (other); } -BaseType * -DynamicObjectType::cast (BaseType *other) -{ - DynamicCastRules r (this); - return r.cast (other); -} - BaseType * DynamicObjectType::clone () const { diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 56a0e05cd94..c47921d44d7 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 00000000000..9f08b2ae98a --- /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 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 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); +impl Deref for Foo { + 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 +}