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
This commit is contained in:
parent
79d0f29464
commit
5d17a8b6b2
@ -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 \
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 ())
|
||||
|
@ -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<Resolver::Adjustment> *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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
92
gcc/rust/typecheck/rust-coercion.cc
Normal file
92
gcc/rust/typecheck/rust-coercion.cc
Normal file
@ -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
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#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<const TyTy::ReferenceType &> (*receiver);
|
||||
const auto &expected_ref
|
||||
= static_cast<const TyTy::ReferenceType &> (*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
|
70
gcc/rust/typecheck/rust-coercion.h
Normal file
70
gcc/rust/typecheck/rust-coercion.h
Normal file
@ -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
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#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<Adjustment> 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
|
@ -17,6 +17,7 @@
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
||||
{
|
||||
|
@ -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 (),
|
||||
|
@ -3,10 +3,9 @@ struct GenericStruct<T>(T, usize);
|
||||
fn main() {
|
||||
let a2;
|
||||
a2 = GenericStruct::<i8, i32>(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 \[<tyty::error>\]} "" { 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 }
|
||||
|
@ -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 }
|
||||
}
|
||||
|
@ -3,6 +3,5 @@ fn main() {
|
||||
let mut x;
|
||||
x = true;
|
||||
x = x + 2; // { dg-error "cannot apply this operator to types bool and <integer>" }
|
||||
// { dg-error {failed to type resolve expression} "" { target *-*-* } .-1 }
|
||||
// { dg-error {expected \[bool\] got \[<tyty::error>\]} "" { target *-*-* } .-2 }
|
||||
// { dg-error {failed to type resolve expression} "" { target *-*-* } .-1 }
|
||||
}
|
||||
|
@ -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 \[<tyty::error>\]} "" { target *-*-* } .-5 }
|
||||
}
|
||||
|
75
gcc/testsuite/rust/execute/torture/issue-1198.rs
Normal file
75
gcc/testsuite/rust/execute/torture/issue-1198.rs
Normal file
@ -0,0 +1,75 @@
|
||||
/* { dg-output "foo_deref\nimm_deref\n123\n" } */
|
||||
extern "C" {
|
||||
fn printf(s: *const i8, ...);
|
||||
}
|
||||
|
||||
#[lang = "deref"]
|
||||
pub trait Deref {
|
||||
type Target;
|
||||
|
||||
fn deref(&self) -> &Self::Target;
|
||||
}
|
||||
|
||||
impl<T> Deref for &T {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
unsafe {
|
||||
let a = "imm_deref\n\0";
|
||||
let b = a as *const str;
|
||||
let c = b as *const i8;
|
||||
|
||||
printf(c);
|
||||
}
|
||||
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for &mut T {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
unsafe {
|
||||
let a = "mut_deref\n\0";
|
||||
let b = a as *const str;
|
||||
let c = b as *const i8;
|
||||
|
||||
printf(c);
|
||||
}
|
||||
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
struct Foo<T>(T);
|
||||
impl<T> Deref for Foo<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe {
|
||||
let a = "foo_deref\n\0";
|
||||
let b = a as *const str;
|
||||
let c = b as *const i8;
|
||||
|
||||
printf(c);
|
||||
}
|
||||
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> i32 {
|
||||
let foo: Foo<i32> = 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user