From 5d17a8b6b2c086d4df516de06ddacdf88728f6ba Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 3 Aug 2022 13:14:54 +0100 Subject: [PATCH] Support Autoderef coercions This is an incremental approach to get our coercion sites more acurate to rustc. This allows us to support coercions which require a deref by sharing the code from the autoderef cycle. The eventual goal here will allow us to remove the rust-tyty-coercion rules which is messy and cannot handle logic such as DST's very well. Fixes #1198 --- gcc/rust/Make-lang.in | 1 + gcc/rust/backend/rust-compile-base.h | 5 +- gcc/rust/backend/rust-compile-expr.cc | 13 +-- gcc/rust/backend/rust-compile-expr.h | 14 +-- gcc/rust/backend/rust-compile-stmt.h | 3 +- gcc/rust/backend/rust-compile.cc | 28 +++++- gcc/rust/typecheck/rust-autoderef.h | 2 +- gcc/rust/typecheck/rust-coercion.cc | 92 +++++++++++++++++++ gcc/rust/typecheck/rust-coercion.h | 70 ++++++++++++++ .../typecheck/rust-hir-type-check-base.cc | 21 ++++- gcc/rust/typecheck/rust-hir-type-check-base.h | 2 +- gcc/rust/typecheck/rust-hir-type-check-expr.h | 3 +- gcc/rust/typecheck/rust-hir-type-check-stmt.h | 3 +- .../typecheck/rust-hir-type-check-struct.cc | 9 +- gcc/rust/typecheck/rust-tyty-call.cc | 22 +++-- gcc/testsuite/rust/compile/generics4.rs | 7 +- gcc/testsuite/rust/compile/reference1.rs | 3 +- gcc/testsuite/rust/compile/shadow1.rs | 3 +- gcc/testsuite/rust/compile/type-bindings1.rs | 1 - .../rust/execute/torture/issue-1198.rs | 75 +++++++++++++++ 20 files changed, 330 insertions(+), 47 deletions(-) create mode 100644 gcc/rust/typecheck/rust-coercion.cc create mode 100644 gcc/rust/typecheck/rust-coercion.h create mode 100644 gcc/testsuite/rust/execute/torture/issue-1198.rs diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index ee8473f83c2..886bafbe1e0 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -118,6 +118,7 @@ GRS_OBJS = \ rust/rust-hir-type-check-pattern.o \ rust/rust-hir-type-check-expr.o \ rust/rust-hir-dot-operator.o \ + rust/rust-coercion.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-base.h b/gcc/rust/backend/rust-compile-base.h index aad0da38535..5a0ac8fe713 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -40,9 +40,12 @@ protected: protected: Context *get_context () { return ctx; } - tree coercion_site (tree rvalue, const TyTy::BaseType *actual, + tree coercion_site (HirId id, tree rvalue, const TyTy::BaseType *actual, const TyTy::BaseType *expected, Location lvalue_locus, Location rvalue_locus); + tree coercion_site1 (tree rvalue, const TyTy::BaseType *actual, + const TyTy::BaseType *expected, Location lvalue_locus, + Location rvalue_locus); tree coerce_to_dyn_object (tree compiled_ref, const TyTy::BaseType *actual, const TyTy::BaseType *expected, diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 8576cf2fd19..38d10d2d41c 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -853,8 +853,9 @@ CompileExpr::visit (HIR::CallExpr &expr) Location lvalue_locus = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ()); Location rvalue_locus = argument->get_locus (); - rvalue = coercion_site (rvalue, actual, expected, lvalue_locus, - rvalue_locus); + rvalue + = coercion_site (argument->get_mappings ().get_hirid (), rvalue, + actual, expected, lvalue_locus, rvalue_locus); // add it to the list arguments.push_back (rvalue); @@ -951,8 +952,8 @@ CompileExpr::visit (HIR::CallExpr &expr) Location lvalue_locus = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ()); Location rvalue_locus = argument->get_locus (); - rvalue - = coercion_site (rvalue, actual, expected, lvalue_locus, rvalue_locus); + rvalue = coercion_site (argument->get_mappings ().get_hirid (), rvalue, + actual, expected, lvalue_locus, rvalue_locus); // add it to the list args.push_back (rvalue); @@ -1069,8 +1070,8 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) Location lvalue_locus = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ()); Location rvalue_locus = argument->get_locus (); - rvalue - = coercion_site (rvalue, actual, expected, lvalue_locus, rvalue_locus); + rvalue = coercion_site (argument->get_mappings ().get_hirid (), rvalue, + actual, expected, lvalue_locus, rvalue_locus); // add it to the list args.push_back (rvalue); diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index bc1423991ac..9b8976de18a 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -177,9 +177,9 @@ public: expr.get_rhs ()->get_mappings ().get_hirid (), &actual); rust_assert (ok); - rvalue - = coercion_site (rvalue, actual, expected, expr.get_lhs ()->get_locus (), - expr.get_rhs ()->get_locus ()); + rvalue = coercion_site (expr.get_mappings ().get_hirid (), rvalue, actual, + expected, expr.get_lhs ()->get_locus (), + expr.get_rhs ()->get_locus ()); tree assignment = ctx->get_backend ()->assignment_statement (lvalue, rvalue, @@ -435,8 +435,9 @@ public: if (ok) { - rvalue = coercion_site (rvalue, actual, expected, lvalue_locus, - rvalue_locus); + rvalue + = coercion_site (argument->get_mappings ().get_hirid (), rvalue, + actual, expected, lvalue_locus, rvalue_locus); } // add it to the list @@ -469,7 +470,8 @@ public: // compile/torture/struct_base_init_1.rs if (ok) { - rvalue = coercion_site (rvalue, actual, expected, lvalue_locus, + rvalue = coercion_site (argument->get_mappings ().get_hirid (), + rvalue, actual, expected, lvalue_locus, rvalue_locus); } diff --git a/gcc/rust/backend/rust-compile-stmt.h b/gcc/rust/backend/rust-compile-stmt.h index aa17a4a4941..9bb4b7b07d2 100644 --- a/gcc/rust/backend/rust-compile-stmt.h +++ b/gcc/rust/backend/rust-compile-stmt.h @@ -87,7 +87,8 @@ public: Location lvalue_locus = stmt.get_pattern ()->get_locus (); Location rvalue_locus = stmt.get_init_expr ()->get_locus (); TyTy::BaseType *expected = ty; - init = coercion_site (init, actual, expected, lvalue_locus, rvalue_locus); + init = coercion_site (stmt.get_mappings ().get_hirid (), init, actual, + expected, lvalue_locus, rvalue_locus); auto fnctx = ctx->peek_fn (); if (ty->is_unit ()) diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 4f17fa6286e..8a614f200a6 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -198,9 +198,25 @@ CompileStructExprField::visit (HIR::StructExprFieldIdentifier &field) // Shared methods in compilation tree -HIRCompileBase::coercion_site (tree rvalue, const TyTy::BaseType *rval, +HIRCompileBase::coercion_site (HirId id, tree rvalue, + const TyTy::BaseType *rval, const TyTy::BaseType *lval, Location lvalue_locus, Location rvalue_locus) +{ + std::vector *adjustments = nullptr; + bool ok = ctx->get_tyctx ()->lookup_autoderef_mappings (id, &adjustments); + if (ok) + { + rvalue = resolve_adjustements (*adjustments, rvalue, rvalue_locus); + } + + return coercion_site1 (rvalue, rval, lval, lvalue_locus, rvalue_locus); +} + +tree +HIRCompileBase::coercion_site1 (tree rvalue, const TyTy::BaseType *rval, + const TyTy::BaseType *lval, + Location lvalue_locus, Location rvalue_locus) { if (rvalue == error_mark_node) return error_mark_node; @@ -227,8 +243,8 @@ HIRCompileBase::coercion_site (tree rvalue, const TyTy::BaseType *rval, tree deref_rvalue = indirect_expression (rvalue, rvalue_locus); tree coerced - = coercion_site (deref_rvalue, act->get_base (), exp->get_base (), - lvalue_locus, rvalue_locus); + = coercion_site1 (deref_rvalue, act->get_base (), exp->get_base (), + lvalue_locus, rvalue_locus); if (exp->is_dyn_object () && SLICE_TYPE_P (TREE_TYPE (coerced))) return coerced; @@ -269,8 +285,10 @@ HIRCompileBase::coercion_site (tree rvalue, const TyTy::BaseType *rval, rust_assert (actual_base != nullptr); tree deref_rvalue = indirect_expression (rvalue, rvalue_locus); - tree coerced = coercion_site (deref_rvalue, actual_base, exp->get_base (), - lvalue_locus, rvalue_locus); + tree coerced + = coercion_site1 (deref_rvalue, actual_base, exp->get_base (), + lvalue_locus, rvalue_locus); + if (exp->is_dyn_object () && SLICE_TYPE_P (TREE_TYPE (coerced))) return coerced; diff --git a/gcc/rust/typecheck/rust-autoderef.h b/gcc/rust/typecheck/rust-autoderef.h index 159f4c06cbc..220b6f45091 100644 --- a/gcc/rust/typecheck/rust-autoderef.h +++ b/gcc/rust/typecheck/rust-autoderef.h @@ -157,7 +157,7 @@ protected: // type virtual void try_hook (const TyTy::BaseType &); - bool cycle (const TyTy::BaseType *receiver); + virtual bool cycle (const TyTy::BaseType *receiver); bool try_autoderefed (const TyTy::BaseType *r); diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc new file mode 100644 index 00000000000..e6e82c3f734 --- /dev/null +++ b/gcc/rust/typecheck/rust-coercion.cc @@ -0,0 +1,92 @@ +// 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-coercion.h" + +namespace Rust { +namespace Resolver { + +AutoderefTypeCoercion::CoercionResult +AutoderefTypeCoercion::Coerce (const TyTy::BaseType *receiver, + const TyTy::BaseType *expected, Location locus) +{ + AutoderefTypeCoercion resolver (expected, locus); + bool ok = resolver.cycle (receiver); + return ok ? resolver.try_result : CoercionResult::get_error (); +} + +AutoderefTypeCoercion::AutoderefTypeCoercion (const TyTy::BaseType *expected, + Location locus) + : AutoderefCycle (false), mappings (Analysis::Mappings::get ()), + context (TypeCheckContext::get ()), expected (expected), locus (locus), + try_result (CoercionResult::get_error ()) +{} + +bool +AutoderefTypeCoercion::cycle (const TyTy::BaseType *receiver) +{ + // FIXME this is not finished and might be super simplified + // see: + // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs + + if (receiver->get_kind () == TyTy::TypeKind::REF + && expected->get_kind () == TyTy::TypeKind::REF) + { + // if we expect to get a mutable pointer we can't get that from an + // immutable one so we have to be careful + + const auto &receiver_ref + = static_cast (*receiver); + const auto &expected_ref + = static_cast (*expected); + + // we can allow for mutability changes here by casting down from + // mutability eg: mut vs const, we cant take a mutable reference from a + // const eg: const vs mut we can take a const reference from a mutable + // one + + bool mutability_ok + = !expected_ref.is_mutable () + || (expected_ref.is_mutable () == receiver_ref.is_mutable ()); + if (!mutability_ok) + { + RichLocation r (locus); + r.add_range (mappings->lookup_location (receiver_ref.get_ref ())); + r.add_range (mappings->lookup_location (expected_ref.get_ref ())); + rust_error_at (r, "mismatched mutability"); + + return false; + } + } + + return AutoderefCycle::cycle (receiver); +} + +bool +AutoderefTypeCoercion::select (const TyTy::BaseType &autoderefed) +{ + if (autoderefed.can_eq (expected, false)) + { + try_result = CoercionResult{adjustments, autoderefed.clone ()}; + return true; + } + return false; +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-coercion.h b/gcc/rust/typecheck/rust-coercion.h new file mode 100644 index 00000000000..c3d5d028e64 --- /dev/null +++ b/gcc/rust/typecheck/rust-coercion.h @@ -0,0 +1,70 @@ +// 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_COERCION +#define RUST_COERCION + +#include "rust-autoderef.h" +#include "rust-hir-type-check.h" + +namespace Rust { +namespace Resolver { + +class AutoderefTypeCoercion : protected AutoderefCycle +{ +public: + struct CoercionResult + { + std::vector adjustments; + TyTy::BaseType *tyty; + + bool is_error () + { + return tyty == nullptr || tyty->get_kind () == TyTy::TypeKind::ERROR; + } + + static CoercionResult get_error () { return CoercionResult{{}, nullptr}; } + }; + + static CoercionResult Coerce (const TyTy::BaseType *receiver, + const TyTy::BaseType *expected, Location locus); + +protected: + AutoderefTypeCoercion (const TyTy::BaseType *expected, Location locus); + + bool cycle (const TyTy::BaseType *receiver) override; + + bool select (const TyTy::BaseType &autoderefed) override; + +private: + // context info + Analysis::Mappings *mappings; + TypeCheckContext *context; + + // search + const TyTy::BaseType *expected; + Location locus; + + // mutable fields + CoercionResult try_result; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_COERCION diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc index 092b635bfa8..c50199847b7 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc @@ -17,6 +17,7 @@ // . #include "rust-hir-type-check-base.h" +#include "rust-coercion.h" namespace Rust { namespace Resolver { @@ -328,10 +329,24 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, Location locus) } TyTy::BaseType * -TypeCheckBase::coercion_site (TyTy::BaseType *lhs, TyTy::BaseType *rhs, - Location) +TypeCheckBase::coercion_site (HirId id, TyTy::BaseType *expected, + TyTy::BaseType *expr, Location locus) { - return lhs->coerce (rhs); + auto context = TypeCheckContext::get (); + if (expected->get_kind () == TyTy::TypeKind::ERROR + || expr->get_kind () == TyTy::TypeKind::ERROR) + return expr; + + // can we autoderef it? + auto result = AutoderefTypeCoercion::Coerce (expr, expected, locus); + if (!result.is_error ()) + { + // save any adjustments + context->insert_autoderef_mappings (id, std::move (result.adjustments)); + return expected->coerce (result.tyty); + } + + return expected->coerce (expr); } } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h index 9d53610151d..4078697c927 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.h +++ b/gcc/rust/typecheck/rust-hir-type-check-base.h @@ -39,7 +39,7 @@ public: virtual ~TypeCheckBase () {} - static TyTy::BaseType *coercion_site (TyTy::BaseType *lhs, + static TyTy::BaseType *coercion_site (HirId id, TyTy::BaseType *lhs, TyTy::BaseType *rhs, Location locus); protected: diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 8a0c3054cd7..de542ca70e8 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -230,7 +230,8 @@ public: auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); - coercion_site (lhs, rhs, expr.get_locus ()); + coercion_site (expr.get_mappings ().get_hirid (), lhs, rhs, + expr.get_locus ()); } void visit (HIR::CompoundAssignmentExpr &expr) override diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h index 11f4d642429..f8bf6e083dd 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -99,7 +99,8 @@ public: if (specified_ty != nullptr && init_expr_ty != nullptr) { // FIXME use this result and look at the regressions - coercion_site (specified_ty, init_expr_ty, stmt.get_locus ()); + coercion_site (stmt.get_mappings ().get_hirid (), specified_ty, + init_expr_ty, stmt.get_locus ()); context->insert_type (stmt_pattern.get_pattern_mappings (), specified_ty); } diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc index 736bc5e7857..5b522772a3e 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc @@ -222,7 +222,8 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field) TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value ()); resolved_field_value_expr - = coercion_site (field_type->get_field_type (), value, field.get_locus ()); + = coercion_site (field.get_mappings ().get_hirid (), + field_type->get_field_type (), value, field.get_locus ()); if (resolved_field_value_expr != nullptr) { fields_assigned.insert (field.field_name); @@ -252,7 +253,8 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field) TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value ()); resolved_field_value_expr - = coercion_site (field_type->get_field_type (), value, field.get_locus ()); + = coercion_site (field.get_mappings ().get_hirid (), + field_type->get_field_type (), value, field.get_locus ()); if (resolved_field_value_expr != nullptr) { fields_assigned.insert (field_name); @@ -287,7 +289,8 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field) TyTy::BaseType *value = TypeCheckExpr::Resolve (&expr); resolved_field_value_expr - = coercion_site (field_type->get_field_type (), value, field.get_locus ()); + = coercion_site (field.get_mappings ().get_hirid (), + field_type->get_field_type (), value, field.get_locus ()); if (resolved_field_value_expr != nullptr) { diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc index 416527e3436..b810bd88512 100644 --- a/gcc/rust/typecheck/rust-tyty-call.cc +++ b/gcc/rust/typecheck/rust-tyty-call.cc @@ -58,7 +58,9 @@ TypeCheckCallExpr::visit (ADTType &type) return; } - auto res = field_tyty->coerce (arg); + auto res = Resolver::TypeCheckBase::coercion_site ( + argument->get_mappings ().get_hirid (), field_tyty, arg, + argument->get_locus ()); if (res->get_kind () == TyTy::TypeKind::ERROR) { return; @@ -123,8 +125,9 @@ TypeCheckCallExpr::visit (FnType &type) if (i < type.num_params ()) { auto fnparam = type.param_at (i); - auto resolved_argument_type - = fnparam.second->coerce (argument_expr_tyty); + auto resolved_argument_type = Resolver::TypeCheckBase::coercion_site ( + argument->get_mappings ().get_hirid (), fnparam.second, + argument_expr_tyty, argument->get_locus ()); if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR) { rust_error_at (argument->get_locus (), @@ -176,9 +179,9 @@ TypeCheckCallExpr::visit (FnPtr &type) return; } - auto resolved_argument_type - = Resolver::TypeCheckBase::coercion_site (fnparam, argument_expr_tyty, - argument->get_locus ()); + auto resolved_argument_type = Resolver::TypeCheckBase::coercion_site ( + argument->get_mappings ().get_hirid (), fnparam, argument_expr_tyty, + argument->get_locus ()); if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR) { rust_error_at (argument->get_locus (), @@ -234,10 +237,9 @@ TypeCheckMethodCallExpr::visit (FnType &type) return; } - auto resolved_argument_type - = Resolver::TypeCheckBase::coercion_site (fnparam.second, - argument_expr_tyty, - argument->get_locus ()); + auto resolved_argument_type = Resolver::TypeCheckBase::coercion_site ( + argument->get_mappings ().get_hirid (), fnparam.second, + argument_expr_tyty, argument->get_locus ()); if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR) { rust_error_at (argument->get_locus (), diff --git a/gcc/testsuite/rust/compile/generics4.rs b/gcc/testsuite/rust/compile/generics4.rs index 4eaaea7786c..8af13586a37 100644 --- a/gcc/testsuite/rust/compile/generics4.rs +++ b/gcc/testsuite/rust/compile/generics4.rs @@ -3,10 +3,9 @@ struct GenericStruct(T, usize); fn main() { let a2; a2 = GenericStruct::(1, 456); // { dg-error "generic item takes at most 1 type arguments but 2 were supplied" } - // { dg-error {failed to type resolve expression} "" { target *-*-* } .-1 } - // { dg-error {Failed to resolve expression of function call} "" { target *-*-* } .-2 } - // { duplicate _dg-error {failed to type resolve expression} "" { target *-*-* } .-3 } - // { dg-error {expected \[T\?\] got \[\]} "" { target *-*-* } .-4 } + // { dg-error {failed to type resolve expression} "" { target *-*-* } .-1 } + // { dg-error {Failed to resolve expression of function call} "" { target *-*-* } .-2 } + // { duplicate _dg-error {failed to type resolve expression} "" { target *-*-* } .-3 } let b2: i32 = a2.0; // { dg-error {Expected Tuple or ADT got: T\?} "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/rust/compile/reference1.rs b/gcc/testsuite/rust/compile/reference1.rs index 3d979269cf2..ff791533754 100644 --- a/gcc/testsuite/rust/compile/reference1.rs +++ b/gcc/testsuite/rust/compile/reference1.rs @@ -1,5 +1,6 @@ fn main() { let a = &123; let b: &mut i32 = a; - // { dg-error "expected .&mut i32. got .& i32." "" { target *-*-* } .-1 } + // { dg-error "mismatched mutability" "" { target *-*-* } .-1 } + // { dg-error "expected .&mut i32. got .& i32." "" { target *-*-* } .-2 } } diff --git a/gcc/testsuite/rust/compile/shadow1.rs b/gcc/testsuite/rust/compile/shadow1.rs index 730b53dcfb9..77410e932da 100644 --- a/gcc/testsuite/rust/compile/shadow1.rs +++ b/gcc/testsuite/rust/compile/shadow1.rs @@ -3,6 +3,5 @@ fn main() { let mut x; x = true; x = x + 2; // { dg-error "cannot apply this operator to types bool and " } - // { dg-error {failed to type resolve expression} "" { target *-*-* } .-1 } - // { dg-error {expected \[bool\] got \[\]} "" { target *-*-* } .-2 } + // { dg-error {failed to type resolve expression} "" { target *-*-* } .-1 } } diff --git a/gcc/testsuite/rust/compile/type-bindings1.rs b/gcc/testsuite/rust/compile/type-bindings1.rs index 3f61b8b4e4e..ad85ed97ecb 100644 --- a/gcc/testsuite/rust/compile/type-bindings1.rs +++ b/gcc/testsuite/rust/compile/type-bindings1.rs @@ -7,5 +7,4 @@ fn main() { // { dg-error {failed to type resolve expression} "" { target *-*-* } .-2 } // { dg-error {Failed to resolve expression of function call} "" { target *-*-* } .-3 } // { duplicate _dg-error {failed to type resolve expression} "" { target *-*-* } .-4 } - // { dg-error {expected \[T\?\] got \[\]} "" { target *-*-* } .-5 } } diff --git a/gcc/testsuite/rust/execute/torture/issue-1198.rs b/gcc/testsuite/rust/execute/torture/issue-1198.rs new file mode 100644 index 00000000000..fce44ad1994 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/issue-1198.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 = Foo(123); + let bar: &i32 = &foo; + + unsafe { + let a = "%i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, *bar); + } + + 0 +}