aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/Make-lang.in2
-rw-r--r--gcc/rust/backend/rust-compile-base.cc14
-rw-r--r--gcc/rust/backend/rust-compile-base.h9
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc103
-rw-r--r--gcc/rust/backend/rust-compile-expr.h28
-rw-r--r--gcc/rust/backend/rust-compile-extern.h9
-rw-r--r--gcc/rust/backend/rust-compile-implitem.cc10
-rw-r--r--gcc/rust/backend/rust-compile-item.cc9
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.cc6
-rw-r--r--gcc/rust/backend/rust-compile-stmt.h3
-rw-r--r--gcc/rust/backend/rust-compile.cc55
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h26
-rw-r--r--gcc/rust/rust-backend.h8
-rw-r--r--gcc/rust/rust-gcc.cc24
-rw-r--r--gcc/rust/typecheck/rust-autoderef.cc124
-rw-r--r--gcc/rust/typecheck/rust-autoderef.h21
-rw-r--r--gcc/rust/typecheck/rust-coercion.cc92
-rw-r--r--gcc/rust/typecheck/rust-coercion.h70
-rw-r--r--gcc/rust/typecheck/rust-hir-dot-operator.cc177
-rw-r--r--gcc/rust/typecheck/rust-hir-dot-operator.h41
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.cc22
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.h3
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.cc157
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h155
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-stmt.h3
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-struct.cc16
-rw-r--r--gcc/rust/typecheck/rust-tyty-call.cc269
-rw-r--r--gcc/rust/typecheck/rust-tyty-cmp.h106
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc238
-rw-r--r--gcc/testsuite/rust/compile/generics4.rs7
-rw-r--r--gcc/testsuite/rust/compile/reference1.rs3
-rw-r--r--gcc/testsuite/rust/compile/shadow1.rs3
-rw-r--r--gcc/testsuite/rust/compile/type-bindings1.rs1
-rw-r--r--gcc/testsuite/rust/execute/torture/issue-1198.rs75
34 files changed, 1122 insertions, 767 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 78c3d0f..886bafb 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -106,6 +106,7 @@ GRS_OBJS = \
rust/rust-pub-restricted-visitor.o \
rust/rust-privacy-reporter.o \
rust/rust-tyty.o \
+ rust/rust-tyty-call.o \
rust/rust-tyctx.o \
rust/rust-tyty-bounds.o \
rust/rust-hir-type-check-util.o \
@@ -117,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.cc b/gcc/rust/backend/rust-compile-base.cc
index 28f3941..a640a48 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -411,7 +411,7 @@ HIRCompileBase::mark_addressable (tree exp, Location locus)
}
tree
-HIRCompileBase::address_expression (tree expr, tree ptrtype, Location location)
+HIRCompileBase::address_expression (tree expr, Location location)
{
if (expr == error_mark_node)
return error_mark_node;
@@ -419,8 +419,16 @@ HIRCompileBase::address_expression (tree expr, tree ptrtype, Location location)
if (!mark_addressable (expr, location))
return error_mark_node;
- return build_fold_addr_expr_with_type_loc (location.gcc_location (), expr,
- ptrtype);
+ return build_fold_addr_expr_loc (location.gcc_location (), expr);
+}
+
+tree
+HIRCompileBase::indirect_expression (tree expr, Location locus)
+{
+ if (expr == error_mark_node)
+ return error_mark_node;
+
+ return build_fold_indirect_ref_loc (locus.gcc_location (), expr);
}
std::vector<Bvariable *>
diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h
index f993d06..5a0ac8f 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,
@@ -101,7 +104,9 @@ protected:
static void setup_abi_options (tree fndecl, ABI abi);
- static tree address_expression (tree expr, tree ptrtype, Location locus);
+ static tree address_expression (tree expr, Location locus);
+
+ static tree indirect_expression (tree expr, Location locus);
static bool mark_addressable (tree, Location);
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 7aa691e..38d10d2 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -134,8 +134,7 @@ CompileExpr::visit (HIR::BorrowExpr &expr)
&tyty))
return;
- tree ptrtype = TyTyResolveCompile::compile (ctx, tyty);
- translated = address_expression (main_expr, ptrtype, expr.get_locus ());
+ translated = address_expression (main_expr, expr.get_locus ());
}
void
@@ -175,10 +174,7 @@ CompileExpr::visit (HIR::DereferenceExpr &expr)
return;
}
- bool known_valid = true;
- translated
- = ctx->get_backend ()->indirect_expression (expected_type, main_expr,
- known_valid, expr.get_locus ());
+ translated = indirect_expression (main_expr, expr.get_locus ());
}
// Helper for sort_tuple_patterns.
@@ -857,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);
@@ -955,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);
@@ -1039,9 +1036,11 @@ CompileExpr::visit (HIR::MethodCallExpr &expr)
}
// lookup the autoderef mappings
+ HirId autoderef_mappings_id
+ = expr.get_receiver ()->get_mappings ().get_hirid ();
std::vector<Resolver::Adjustment> *adjustments = nullptr;
- ok = ctx->get_tyctx ()->lookup_autoderef_mappings (
- expr.get_mappings ().get_hirid (), &adjustments);
+ ok = ctx->get_tyctx ()->lookup_autoderef_mappings (autoderef_mappings_id,
+ &adjustments);
rust_assert (ok);
// apply adjustments for the fn call
@@ -1071,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);
@@ -1111,15 +1110,7 @@ CompileExpr::get_fn_addr_from_dyn (const TyTy::DynamicObjectType *dyn,
// get any indirection sorted out
if (receiver->get_kind () == TyTy::TypeKind::REF)
{
- TyTy::ReferenceType *r = static_cast<TyTy::ReferenceType *> (receiver);
- auto indirect_ty = r->get_base ();
- tree indrect_compiled_tyty
- = TyTyResolveCompile::compile (ctx, indirect_ty);
-
- tree indirect
- = ctx->get_backend ()->indirect_expression (indrect_compiled_tyty,
- receiver_ref, true,
- expr_locus);
+ tree indirect = indirect_expression (receiver_ref, expr_locus);
receiver_ref = indirect;
}
@@ -1149,17 +1140,8 @@ CompileExpr::get_receiver_from_dyn (const TyTy::DynamicObjectType *dyn,
{
// get any indirection sorted out
if (receiver->get_kind () == TyTy::TypeKind::REF)
-
{
- TyTy::ReferenceType *r = static_cast<TyTy::ReferenceType *> (receiver);
- auto indirect_ty = r->get_base ();
- tree indrect_compiled_tyty
- = TyTyResolveCompile::compile (ctx, indirect_ty);
-
- tree indirect
- = ctx->get_backend ()->indirect_expression (indrect_compiled_tyty,
- receiver_ref, true,
- expr_locus);
+ tree indirect = indirect_expression (receiver_ref, expr_locus);
receiver_ref = indirect;
}
@@ -1179,8 +1161,7 @@ CompileExpr::resolve_method_address (TyTy::FnType *fntype, HirId ref,
tree fn = NULL_TREE;
if (ctx->lookup_function_decl (fntype->get_ty_ref (), &fn))
{
- return address_expression (fn, build_pointer_type (TREE_TYPE (fn)),
- expr_locus);
+ return address_expression (fn, expr_locus);
}
// Now we can try and resolve the address since this might be a forward
@@ -1307,7 +1288,7 @@ CompileExpr::resolve_operator_overload (
// lookup the autoderef mappings
std::vector<Resolver::Adjustment> *adjustments = nullptr;
ok = ctx->get_tyctx ()->lookup_autoderef_mappings (
- expr.get_mappings ().get_hirid (), &adjustments);
+ expr.get_lvalue_mappings ().get_hirid (), &adjustments);
rust_assert (ok);
// apply adjustments for the fn call
@@ -1440,8 +1421,7 @@ CompileExpr::compile_string_literal (const HIR::LiteralExpr &expr,
auto base = ctx->get_backend ()->string_constant_expression (
literal_value.as_string ());
- tree data = address_expression (base, build_pointer_type (TREE_TYPE (base)),
- expr.get_locus ());
+ tree data = address_expression (base, expr.get_locus ());
TyTy::BaseType *usize = nullptr;
bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
@@ -1487,8 +1467,7 @@ CompileExpr::compile_byte_string_literal (const HIR::LiteralExpr &expr,
vals,
expr.get_locus ());
- return address_expression (constructed, build_pointer_type (array_type),
- expr.get_locus ());
+ return address_expression (constructed, expr.get_locus ());
}
tree
@@ -1734,10 +1713,7 @@ HIRCompileBase::resolve_adjustements (
case Resolver::Adjustment::AdjustmentType::MUT_REF: {
if (!SLICE_TYPE_P (TREE_TYPE (e)))
{
- tree ptrtype
- = TyTyResolveCompile::compile (ctx,
- adjustment.get_expected ());
- e = address_expression (e, ptrtype, locus);
+ e = address_expression (e, locus);
}
}
break;
@@ -1785,10 +1761,7 @@ HIRCompileBase::resolve_deref_adjustment (Resolver::Adjustment &adjustment,
!= Resolver::Adjustment::AdjustmentType::ERROR;
if (needs_borrow)
{
- adjusted_argument
- = address_expression (expression,
- build_reference_type (TREE_TYPE (expression)),
- locus);
+ adjusted_argument = address_expression (expression, locus);
}
// make the call
@@ -1800,12 +1773,7 @@ tree
HIRCompileBase::resolve_indirection_adjustment (
Resolver::Adjustment &adjustment, tree expression, Location locus)
{
- tree expected_type
- = TyTyResolveCompile::compile (ctx, adjustment.get_expected ());
-
- return ctx->get_backend ()->indirect_expression (expected_type, expression,
- true, /* known_valid*/
- locus);
+ return indirect_expression (expression, locus);
}
tree
@@ -1824,9 +1792,7 @@ HIRCompileBase::resolve_unsized_adjustment (Resolver::Adjustment &adjustment,
= TyTyResolveCompile::compile (ctx, adjustment.get_expected ());
// make a constructor for this
- tree data
- = address_expression (expression,
- build_reference_type (TREE_TYPE (expression)), locus);
+ tree data = address_expression (expression, locus);
// fetch the size from the domain
tree domain = TYPE_DOMAIN (expr_type);
@@ -1919,8 +1885,7 @@ CompileExpr::visit (HIR::IdentifierExpr &expr)
else if (ctx->lookup_function_decl (ref, &fn))
{
TREE_USED (fn) = 1;
- translated = address_expression (fn, build_pointer_type (TREE_TYPE (fn)),
- expr.get_locus ());
+ translated = address_expression (fn, expr.get_locus ());
}
else if (ctx->lookup_var_decl (ref, &var))
{
@@ -2091,20 +2056,10 @@ CompileExpr::visit (HIR::ArrayIndexExpr &expr)
return;
}
- // lookup the expected type for this expression
- TyTy::BaseType *tyty = nullptr;
- bool ok
- = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
- &tyty);
- rust_assert (ok);
- tree expected_type = TyTyResolveCompile::compile (ctx, tyty);
-
// rust deref always returns a reference from this overload then we can
// actually do the indirection
translated
- = ctx->get_backend ()->indirect_expression (expected_type,
- operator_overload_call,
- true, expr.get_locus ());
+ = indirect_expression (operator_overload_call, expr.get_locus ());
return;
}
@@ -2118,14 +2073,8 @@ CompileExpr::visit (HIR::ArrayIndexExpr &expr)
// do we need to add an indirect reference
if (array_expr_ty->get_kind () == TyTy::TypeKind::REF)
{
- TyTy::ReferenceType *r
- = static_cast<TyTy::ReferenceType *> (array_expr_ty);
- TyTy::BaseType *tuple_type = r->get_base ();
- tree array_tyty = TyTyResolveCompile::compile (ctx, tuple_type);
-
array_reference
- = ctx->get_backend ()->indirect_expression (array_tyty, array_reference,
- true, expr.get_locus ());
+ = indirect_expression (array_reference, expr.get_locus ());
}
translated
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index 48a516a..9b8976d 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -53,14 +53,7 @@ public:
// do we need to add an indirect reference
if (tuple_expr_ty->get_kind () == TyTy::TypeKind::REF)
{
- TyTy::ReferenceType *r
- = static_cast<TyTy::ReferenceType *> (tuple_expr_ty);
- TyTy::BaseType *tuple_type = r->get_base ();
- tree tuple_tyty = TyTyResolveCompile::compile (ctx, tuple_type);
-
- tree indirect
- = ctx->get_backend ()->indirect_expression (tuple_tyty, receiver_ref,
- true, expr.get_locus ());
+ tree indirect = indirect_expression (receiver_ref, expr.get_locus ());
receiver_ref = indirect;
}
@@ -184,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,
@@ -442,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
@@ -476,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);
}
@@ -552,10 +547,7 @@ public:
&field_index);
rust_assert (ok);
- tree adt_tyty = TyTyResolveCompile::compile (ctx, adt);
- tree indirect
- = ctx->get_backend ()->indirect_expression (adt_tyty, receiver_ref,
- true, expr.get_locus ());
+ tree indirect = indirect_expression (receiver_ref, expr.get_locus ());
receiver_ref = indirect;
}
diff --git a/gcc/rust/backend/rust-compile-extern.h b/gcc/rust/backend/rust-compile-extern.h
index 4355e4a..45a507e 100644
--- a/gcc/rust/backend/rust-compile-extern.h
+++ b/gcc/rust/backend/rust-compile-extern.h
@@ -110,10 +110,7 @@ public:
if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup,
fntype->get_id (), fntype))
{
- reference
- = address_expression (lookup, build_pointer_type (TREE_TYPE (lookup)),
- ref_locus);
-
+ reference = address_expression (lookup, ref_locus);
return;
}
@@ -155,9 +152,7 @@ public:
ctx->insert_function_decl (fntype, fndecl);
- reference
- = address_expression (fndecl, build_pointer_type (TREE_TYPE (fndecl)),
- ref_locus);
+ reference = address_expression (fndecl, ref_locus);
}
private:
diff --git a/gcc/rust/backend/rust-compile-implitem.cc b/gcc/rust/backend/rust-compile-implitem.cc
index 735dede..d0f70a7 100644
--- a/gcc/rust/backend/rust-compile-implitem.cc
+++ b/gcc/rust/backend/rust-compile-implitem.cc
@@ -67,10 +67,8 @@ CompileTraitItem::visit (HIR::TraitItemFunc &func)
{
ctx->insert_function_decl (fntype, lookup);
}
- reference
- = address_expression (lookup,
- build_pointer_type (TREE_TYPE (lookup)),
- ref_locus);
+
+ reference = address_expression (lookup, ref_locus);
return;
}
}
@@ -96,9 +94,7 @@ CompileTraitItem::visit (HIR::TraitItemFunc &func)
func.get_outer_attrs (), func.get_locus (),
func.get_block_expr ().get (), canonical_path, fntype,
function.has_return_type ());
- reference
- = address_expression (fndecl, build_pointer_type (TREE_TYPE (fndecl)),
- ref_locus);
+ reference = address_expression (fndecl, ref_locus);
}
} // namespace Compile
diff --git a/gcc/rust/backend/rust-compile-item.cc b/gcc/rust/backend/rust-compile-item.cc
index 1f2e479..ceba51c 100644
--- a/gcc/rust/backend/rust-compile-item.cc
+++ b/gcc/rust/backend/rust-compile-item.cc
@@ -144,10 +144,7 @@ CompileItem::visit (HIR::Function &function)
ctx->insert_function_decl (fntype, lookup);
}
- reference
- = address_expression (lookup,
- build_pointer_type (TREE_TYPE (lookup)),
- ref_locus);
+ reference = address_expression (lookup, ref_locus);
return;
}
}
@@ -171,9 +168,7 @@ CompileItem::visit (HIR::Function &function)
function.get_outer_attrs (), function.get_locus (),
function.get_definition ().get (), canonical_path,
fntype, function.has_function_return_type ());
- reference
- = address_expression (fndecl, build_pointer_type (TREE_TYPE (fndecl)),
- ref_locus);
+ reference = address_expression (fndecl, ref_locus);
}
void
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc
index b5bfa3c..8c1b7ef 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -129,16 +129,14 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment,
if (ctx->lookup_function_decl (fntype->get_ty_ref (), &fn))
{
TREE_USED (fn) = 1;
- return address_expression (fn, build_pointer_type (TREE_TYPE (fn)),
- expr_locus);
+ return address_expression (fn, expr_locus);
}
else if (fntype->get_abi () == ABI::INTRINSIC)
{
Intrinsics compile (ctx);
fn = compile.compile (fntype);
TREE_USED (fn) = 1;
- return address_expression (fn, build_pointer_type (TREE_TYPE (fn)),
- expr_locus);
+ return address_expression (fn, expr_locus);
}
}
diff --git a/gcc/rust/backend/rust-compile-stmt.h b/gcc/rust/backend/rust-compile-stmt.h
index aa17a4a..9bb4b7b 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 9bcd01c..8a614f2 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -198,10 +198,26 @@ 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;
@@ -225,20 +241,14 @@ HIRCompileBase::coercion_site (tree rvalue, const TyTy::BaseType *rval,
const TyTy::ReferenceType *act
= static_cast<const TyTy::ReferenceType *> (actual);
- tree expected_type = TyTyResolveCompile::compile (ctx, act->get_base ());
- tree deref_rvalue
- = ctx->get_backend ()->indirect_expression (expected_type, rvalue,
- false /*known_valid*/,
- rvalue_locus);
+ 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;
- return address_expression (coerced,
- build_reference_type (TREE_TYPE (coerced)),
- rvalue_locus);
+ return address_expression (coerced, rvalue_locus);
}
else if (expected->get_kind () == TyTy::TypeKind::POINTER)
{
@@ -258,14 +268,12 @@ HIRCompileBase::coercion_site (tree rvalue, const TyTy::BaseType *rval,
= static_cast<const TyTy::ReferenceType *> (expected);
TyTy::BaseType *actual_base = nullptr;
- tree expected_type = error_mark_node;
if (actual->get_kind () == TyTy::TypeKind::REF)
{
const TyTy::ReferenceType *act
= static_cast<const TyTy::ReferenceType *> (actual);
actual_base = act->get_base ();
- expected_type = TyTyResolveCompile::compile (ctx, act->get_base ());
}
else if (actual->get_kind () == TyTy::TypeKind::POINTER)
{
@@ -273,22 +281,18 @@ HIRCompileBase::coercion_site (tree rvalue, const TyTy::BaseType *rval,
= static_cast<const TyTy::PointerType *> (actual);
actual_base = act->get_base ();
- expected_type = TyTyResolveCompile::compile (ctx, act->get_base ());
}
rust_assert (actual_base != nullptr);
- tree deref_rvalue
- = ctx->get_backend ()->indirect_expression (expected_type, rvalue,
- false /*known_valid*/,
- rvalue_locus);
- tree coerced = coercion_site (deref_rvalue, actual_base, exp->get_base (),
- lvalue_locus, rvalue_locus);
+ tree deref_rvalue = indirect_expression (rvalue, 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;
- return address_expression (coerced,
- build_pointer_type (TREE_TYPE (coerced)),
- rvalue_locus);
+ return address_expression (coerced, rvalue_locus);
}
else if (expected->get_kind () == TyTy::TypeKind::ARRAY)
{
@@ -350,10 +354,7 @@ HIRCompileBase::coerce_to_dyn_object (tree compiled_ref,
tree address_of_compiled_ref = null_pointer_node;
if (!actual->is_unit ())
- address_of_compiled_ref
- = address_expression (compiled_ref,
- build_pointer_type (TREE_TYPE (compiled_ref)),
- locus);
+ address_of_compiled_ref = address_expression (compiled_ref, locus);
std::vector<tree> vtable_ctor_elems;
std::vector<unsigned long> vtable_ctor_idx;
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h
index d16ac92..7cb86a6 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -4120,31 +4120,47 @@ class OperatorExprMeta
{
public:
OperatorExprMeta (HIR::CompoundAssignmentExpr &expr)
- : node_mappings (expr.get_mappings ()), locus (expr.get_locus ())
+ : node_mappings (expr.get_mappings ()),
+ lvalue_mappings (expr.get_expr ()->get_mappings ()),
+ locus (expr.get_locus ())
{}
OperatorExprMeta (HIR::ArithmeticOrLogicalExpr &expr)
- : node_mappings (expr.get_mappings ()), locus (expr.get_locus ())
+ : node_mappings (expr.get_mappings ()),
+ lvalue_mappings (expr.get_expr ()->get_mappings ()),
+ locus (expr.get_locus ())
{}
OperatorExprMeta (HIR::NegationExpr &expr)
- : node_mappings (expr.get_mappings ()), locus (expr.get_locus ())
+ : node_mappings (expr.get_mappings ()),
+ lvalue_mappings (expr.get_expr ()->get_mappings ()),
+ locus (expr.get_locus ())
{}
OperatorExprMeta (HIR::DereferenceExpr &expr)
- : node_mappings (expr.get_mappings ()), locus (expr.get_locus ())
+ : node_mappings (expr.get_mappings ()),
+ lvalue_mappings (expr.get_expr ()->get_mappings ()),
+ locus (expr.get_locus ())
{}
OperatorExprMeta (HIR::ArrayIndexExpr &expr)
- : node_mappings (expr.get_mappings ()), locus (expr.get_locus ())
+ : node_mappings (expr.get_mappings ()),
+ lvalue_mappings (expr.get_array_expr ()->get_mappings ()),
+ locus (expr.get_locus ())
{}
const Analysis::NodeMapping &get_mappings () const { return node_mappings; }
+ const Analysis::NodeMapping &get_lvalue_mappings () const
+ {
+ return lvalue_mappings;
+ }
+
Location get_locus () const { return locus; }
private:
const Analysis::NodeMapping node_mappings;
+ const Analysis::NodeMapping lvalue_mappings;
Location locus;
};
diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h
index 6d631a0..f7c0b08 100644
--- a/gcc/rust/rust-backend.h
+++ b/gcc/rust/rust-backend.h
@@ -178,14 +178,6 @@ public:
// Create a reference to a variable.
virtual tree var_expression (Bvariable *var, Location) = 0;
- // Create an expression that indirects through the pointer expression EXPR
- // (i.e., return the expression for *EXPR). KNOWN_VALID is true if the pointer
- // is known to point to a valid memory location. BTYPE is the expected type
- // of the indirected EXPR.
- virtual tree indirect_expression (tree btype, tree expr, bool known_valid,
- Location)
- = 0;
-
// Return an expression for the multi-precision integer VAL in BTYPE.
virtual tree integer_constant_expression (tree btype, mpz_t val) = 0;
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index 4fea6fb..27196e8 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -201,8 +201,6 @@ public:
tree var_expression (Bvariable *var, Location);
- tree indirect_expression (tree, tree expr, bool known_valid, Location);
-
tree integer_constant_expression (tree type, mpz_t val);
tree float_constant_expression (tree type, mpfr_t val);
@@ -1053,28 +1051,6 @@ Gcc_backend::var_expression (Bvariable *var, Location location)
return var->get_tree (location);
}
-// An expression that indirectly references an expression.
-
-tree
-Gcc_backend::indirect_expression (tree type_tree, tree expr_tree,
- bool known_valid, Location location)
-{
- if (expr_tree == error_mark_node || type_tree == error_mark_node)
- return error_mark_node;
-
- // If the type of EXPR is a recursive pointer type, then we
- // need to insert a cast before indirecting.
- tree target_type_tree = TREE_TYPE (TREE_TYPE (expr_tree));
- if (VOID_TYPE_P (target_type_tree))
- expr_tree = fold_convert_loc (location.gcc_location (),
- build_pointer_type (type_tree), expr_tree);
-
- tree ret = build_fold_indirect_ref_loc (location.gcc_location (), expr_tree);
- if (known_valid)
- TREE_THIS_NOTRAP (ret) = 1;
- return ret;
-}
-
// Return a typed value as a constant integer.
tree
diff --git a/gcc/rust/typecheck/rust-autoderef.cc b/gcc/rust/typecheck/rust-autoderef.cc
index 986ff46..0025e7e 100644
--- a/gcc/rust/typecheck/rust-autoderef.cc
+++ b/gcc/rust/typecheck/rust-autoderef.cc
@@ -268,5 +268,129 @@ resolve_operator_overload_fn (
return true;
}
+AutoderefCycle::AutoderefCycle (bool autoderef_flag)
+ : autoderef_flag (autoderef_flag)
+{}
+
+AutoderefCycle::~AutoderefCycle () {}
+
+void
+AutoderefCycle::try_hook (const TyTy::BaseType &)
+{}
+
+bool
+AutoderefCycle::cycle (const TyTy::BaseType *receiver)
+{
+ const TyTy::BaseType *r = receiver;
+ while (true)
+ {
+ if (try_autoderefed (r))
+ return true;
+
+ // 4. deref to to 1, if cannot deref then quit
+ if (autoderef_flag)
+ return false;
+
+ // try unsize
+ Adjustment unsize = Adjuster::try_unsize_type (r);
+ if (!unsize.is_error ())
+ {
+ adjustments.push_back (unsize);
+ auto unsize_r = unsize.get_expected ();
+
+ if (try_autoderefed (unsize_r))
+ return true;
+
+ adjustments.pop_back ();
+ }
+
+ Adjustment deref
+ = Adjuster::try_deref_type (r, Analysis::RustLangItem::ItemType::DEREF);
+ if (!deref.is_error ())
+ {
+ auto deref_r = deref.get_expected ();
+ adjustments.push_back (deref);
+
+ if (try_autoderefed (deref_r))
+ return true;
+
+ adjustments.pop_back ();
+ }
+
+ Adjustment deref_mut = Adjuster::try_deref_type (
+ r, Analysis::RustLangItem::ItemType::DEREF_MUT);
+ if (!deref_mut.is_error ())
+ {
+ auto deref_r = deref_mut.get_expected ();
+ adjustments.push_back (deref_mut);
+
+ if (try_autoderefed (deref_r))
+ return true;
+
+ adjustments.pop_back ();
+ }
+
+ if (!deref_mut.is_error ())
+ {
+ auto deref_r = deref_mut.get_expected ();
+ adjustments.push_back (deref_mut);
+ Adjustment raw_deref = Adjuster::try_raw_deref_type (deref_r);
+ adjustments.push_back (raw_deref);
+ deref_r = raw_deref.get_expected ();
+
+ if (try_autoderefed (deref_r))
+ return true;
+
+ adjustments.pop_back ();
+ adjustments.pop_back ();
+ }
+
+ if (!deref.is_error ())
+ {
+ r = deref.get_expected ();
+ adjustments.push_back (deref);
+ }
+ Adjustment raw_deref = Adjuster::try_raw_deref_type (r);
+ if (raw_deref.is_error ())
+ return false;
+
+ r = raw_deref.get_expected ();
+ adjustments.push_back (raw_deref);
+ }
+ return false;
+}
+
+bool
+AutoderefCycle::try_autoderefed (const TyTy::BaseType *r)
+{
+ try_hook (*r);
+
+ // 1. try raw
+ if (select (*r))
+ return true;
+
+ // 2. try ref
+ TyTy::ReferenceType *r1
+ = new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()),
+ Mutability::Imm);
+ adjustments.push_back (Adjustment (Adjustment::AdjustmentType::IMM_REF, r1));
+ if (select (*r1))
+ return true;
+
+ adjustments.pop_back ();
+
+ // 3. try mut ref
+ TyTy::ReferenceType *r2
+ = new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()),
+ Mutability::Mut);
+ adjustments.push_back (Adjustment (Adjustment::AdjustmentType::MUT_REF, r2));
+ if (select (*r2))
+ return true;
+
+ adjustments.pop_back ();
+
+ return false;
+}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-autoderef.h b/gcc/rust/typecheck/rust-autoderef.h
index 369744e..220b6f4 100644
--- a/gcc/rust/typecheck/rust-autoderef.h
+++ b/gcc/rust/typecheck/rust-autoderef.h
@@ -144,6 +144,27 @@ private:
const TyTy::BaseType *base;
};
+class AutoderefCycle
+{
+protected:
+ AutoderefCycle (bool autoderef_flag);
+
+ virtual ~AutoderefCycle ();
+
+ virtual bool select (const TyTy::BaseType &autoderefed) = 0;
+
+ // optional: this is a chance to hook in to grab predicate items on the raw
+ // type
+ virtual void try_hook (const TyTy::BaseType &);
+
+ virtual bool cycle (const TyTy::BaseType *receiver);
+
+ bool try_autoderefed (const TyTy::BaseType *r);
+
+ bool autoderef_flag;
+ std::vector<Adjustment> adjustments;
+};
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc
new file mode 100644
index 0000000..e6e82c3
--- /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
+// <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
diff --git a/gcc/rust/typecheck/rust-coercion.h b/gcc/rust/typecheck/rust-coercion.h
new file mode 100644
index 0000000..c3d5d02
--- /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
+// <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
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc b/gcc/rust/typecheck/rust-hir-dot-operator.cc
index 104bd16..d45f090 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.cc
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc
@@ -23,151 +23,32 @@
namespace Rust {
namespace Resolver {
+MethodResolver::MethodResolver (bool autoderef_flag,
+ const HIR::PathIdentSegment &segment_name)
+ : AutoderefCycle (autoderef_flag), mappings (Analysis::Mappings::get ()),
+ context (TypeCheckContext::get ()), segment_name (segment_name),
+ try_result (MethodCandidate::get_error ())
+{}
+
MethodCandidate
MethodResolver::Probe (const TyTy::BaseType *receiver,
const HIR::PathIdentSegment &segment_name,
bool autoderef_flag)
{
- const TyTy::BaseType *r = receiver;
- std::vector<Adjustment> adjustments;
- while (true)
- {
- auto res = Try (r, segment_name, adjustments);
- if (!res.is_error ())
- return res;
-
- // 4. deref to to 1, if cannot deref then quit
- if (autoderef_flag)
- return MethodCandidate::get_error ();
-
- // try unsize
- Adjustment unsize = Adjuster::try_unsize_type (r);
- if (!unsize.is_error ())
- {
- adjustments.push_back (unsize);
- auto unsize_r = unsize.get_expected ();
- auto res = Try (unsize_r, segment_name, adjustments);
- if (!res.is_error ())
- {
- return res;
- }
-
- adjustments.pop_back ();
- }
-
- Adjustment deref
- = Adjuster::try_deref_type (r, Analysis::RustLangItem::ItemType::DEREF);
- if (!deref.is_error ())
- {
- auto deref_r = deref.get_expected ();
- adjustments.push_back (deref);
- auto res = Try (deref_r, segment_name, adjustments);
- if (!res.is_error ())
- {
- return res;
- }
-
- adjustments.pop_back ();
- }
-
- Adjustment deref_mut = Adjuster::try_deref_type (
- r, Analysis::RustLangItem::ItemType::DEREF_MUT);
- if (!deref_mut.is_error ())
- {
- auto deref_r = deref_mut.get_expected ();
- adjustments.push_back (deref_mut);
- auto res = Try (deref_r, segment_name, adjustments);
- if (!res.is_error ())
- {
- return res;
- }
-
- adjustments.pop_back ();
- }
-
- if (!deref_mut.is_error ())
- {
- auto deref_r = deref_mut.get_expected ();
- adjustments.push_back (deref_mut);
- Adjustment raw_deref = Adjuster::try_raw_deref_type (deref_r);
- adjustments.push_back (raw_deref);
- deref_r = raw_deref.get_expected ();
-
- auto res = Try (deref_r, segment_name, adjustments);
- if (!res.is_error ())
- {
- return res;
- }
-
- adjustments.pop_back ();
- adjustments.pop_back ();
- }
-
- if (!deref.is_error ())
- {
- r = deref.get_expected ();
- adjustments.push_back (deref);
- }
- Adjustment raw_deref = Adjuster::try_raw_deref_type (r);
- if (raw_deref.is_error ())
- return MethodCandidate::get_error ();
-
- r = raw_deref.get_expected ();
- adjustments.push_back (raw_deref);
- }
- return MethodCandidate::get_error ();
+ MethodResolver resolver (autoderef_flag, segment_name);
+ bool ok = resolver.cycle (receiver);
+ return ok ? resolver.try_result : MethodCandidate::get_error ();
}
-MethodCandidate
-MethodResolver::Try (const TyTy::BaseType *r,
- const HIR::PathIdentSegment &segment_name,
- std::vector<Adjustment> &adjustments)
+void
+MethodResolver::try_hook (const TyTy::BaseType &r)
{
- PathProbeCandidate c = PathProbeCandidate::get_error ();
- const std::vector<TyTy::TypeBoundPredicate> &specified_bounds
- = r->get_specified_bounds ();
- const std::vector<MethodResolver::predicate_candidate> predicate_items
- = get_predicate_items (segment_name, *r, specified_bounds);
-
- // 1. try raw
- MethodResolver raw (*r, segment_name, predicate_items);
- c = raw.select ();
- if (!c.is_error ())
- {
- return MethodCandidate{c, adjustments};
- }
-
- // 2. try ref
- TyTy::ReferenceType *r1
- = new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()),
- Mutability::Imm);
- MethodResolver imm_ref (*r1, segment_name, predicate_items);
- c = imm_ref.select ();
- if (!c.is_error ())
- {
- adjustments.push_back (
- Adjustment (Adjustment::AdjustmentType::IMM_REF, r1));
- return MethodCandidate{c, adjustments};
- }
-
- // 3. try mut ref
- TyTy::ReferenceType *r2
- = new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()),
- Mutability::Mut);
- MethodResolver mut_ref (*r2, segment_name, predicate_items);
- c = mut_ref.select ();
- if (!c.is_error ())
- {
- adjustments.push_back (
- Adjustment (Adjustment::AdjustmentType::MUT_REF, r2));
- return MethodCandidate{c, adjustments};
- }
-
- return MethodCandidate::get_error ();
+ const auto &specified_bounds = r.get_specified_bounds ();
+ predicate_items = get_predicate_items (segment_name, r, specified_bounds);
}
-PathProbeCandidate
-MethodResolver::select ()
+bool
+MethodResolver::select (const TyTy::BaseType &receiver)
{
struct impl_item_candidate
{
@@ -300,9 +181,11 @@ MethodResolver::select ()
{
PathProbeCandidate::ImplItemCandidate c{impl_item.item,
impl_item.impl_block};
- return PathProbeCandidate (
- PathProbeCandidate::CandidateType::IMPL_FUNC, fn,
- impl_item.item->get_locus (), c);
+ try_result = MethodCandidate{
+ PathProbeCandidate (PathProbeCandidate::CandidateType::IMPL_FUNC,
+ fn, impl_item.item->get_locus (), c),
+ adjustments};
+ return true;
}
}
@@ -317,9 +200,11 @@ MethodResolver::select ()
PathProbeCandidate::TraitItemCandidate c{trait_item.reference,
trait_item.item_ref,
nullptr};
- return PathProbeCandidate (
- PathProbeCandidate::CandidateType::TRAIT_FUNC, fn,
- trait_item.item->get_locus (), c);
+ try_result = MethodCandidate{
+ PathProbeCandidate (PathProbeCandidate::CandidateType::TRAIT_FUNC,
+ fn, trait_item.item->get_locus (), c),
+ adjustments};
+ return true;
}
}
@@ -338,13 +223,15 @@ MethodResolver::select ()
PathProbeCandidate::TraitItemCandidate c{trait_ref, trait_item,
nullptr};
- return PathProbeCandidate (
- PathProbeCandidate::CandidateType::TRAIT_FUNC, fn->clone (),
- trait_item->get_locus (), c);
+ try_result = MethodCandidate{
+ PathProbeCandidate (PathProbeCandidate::CandidateType::TRAIT_FUNC,
+ fn->clone (), trait_item->get_locus (), c),
+ adjustments};
+ return true;
}
}
- return PathProbeCandidate::get_error ();
+ return false;
}
std::vector<MethodResolver::predicate_candidate>
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h b/gcc/rust/typecheck/rust-hir-dot-operator.h
index ef1038b..750601a 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.h
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.h
@@ -37,43 +37,42 @@ struct MethodCandidate
bool is_error () const { return candidate.is_error (); }
};
-class MethodResolver : public TypeCheckBase
+class MethodResolver : protected AutoderefCycle
{
-protected:
- using Rust::Resolver::TypeCheckBase::visit;
-
public:
- static MethodCandidate Probe (const TyTy::BaseType *receiver,
- const HIR::PathIdentSegment &segment_name,
- bool autoderef_flag = false);
-
-protected:
struct predicate_candidate
{
TyTy::TypeBoundPredicateItem lookup;
TyTy::FnType *fntype;
};
- static MethodCandidate Try (const TyTy::BaseType *r,
- const HIR::PathIdentSegment &segment_name,
- std::vector<Adjustment> &adjustments);
+ static MethodCandidate Probe (const TyTy::BaseType *receiver,
+ const HIR::PathIdentSegment &segment_name,
+ bool autoderef_flag = false);
static std::vector<predicate_candidate> get_predicate_items (
const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver,
const std::vector<TyTy::TypeBoundPredicate> &specified_bounds);
- PathProbeCandidate select ();
+protected:
+ MethodResolver (bool autoderef_flag,
+ const HIR::PathIdentSegment &segment_name);
- MethodResolver (
- const TyTy::BaseType &receiver, const HIR::PathIdentSegment &segment_name,
- const std::vector<MethodResolver::predicate_candidate> &predicate_items)
- : receiver (receiver), segment_name (segment_name),
- predicate_items (predicate_items)
- {}
+ void try_hook (const TyTy::BaseType &r) override;
- const TyTy::BaseType &receiver;
+ bool select (const TyTy::BaseType &receiver) override;
+
+private:
+ // context info
+ Analysis::Mappings *mappings;
+ TypeCheckContext *context;
+
+ // search
const HIR::PathIdentSegment &segment_name;
- const std::vector<MethodResolver::predicate_candidate> &predicate_items;
+ std::vector<MethodResolver::predicate_candidate> predicate_items;
+
+ // mutable fields
+ MethodCandidate try_result;
};
} // 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 2a47c58..c501998 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 @@
// <http://www.gnu.org/licenses/>.
#include "rust-hir-type-check-base.h"
+#include "rust-coercion.h"
namespace Rust {
namespace Resolver {
@@ -327,5 +328,26 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, Location locus)
return repr;
}
+TyTy::BaseType *
+TypeCheckBase::coercion_site (HirId id, TyTy::BaseType *expected,
+ TyTy::BaseType *expr, Location locus)
+{
+ 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
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h
index f7a1bd4..4078697 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.h
@@ -39,6 +39,9 @@ public:
virtual ~TypeCheckBase () {}
+ static TyTy::BaseType *coercion_site (HirId id, TyTy::BaseType *lhs,
+ TyTy::BaseType *rhs, Location locus);
+
protected:
TypeCheckBase ()
: mappings (Analysis::Mappings::get ()), resolver (Resolver::get ()),
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index d96a85c..9c31284 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -295,6 +295,161 @@ TypeCheckExpr::visit (HIR::ArrayIndexExpr &expr)
infered = array_type->get_element_type ()->clone ();
}
+void
+TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
+{
+ auto receiver_tyty = TypeCheckExpr::Resolve (expr.get_receiver ().get ());
+ if (receiver_tyty->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ rust_error_at (expr.get_receiver ()->get_locus (),
+ "failed to resolve receiver in MethodCallExpr");
+ return;
+ }
+
+ context->insert_receiver (expr.get_mappings ().get_hirid (), receiver_tyty);
+
+ auto candidate
+ = MethodResolver::Probe (receiver_tyty,
+ expr.get_method_name ().get_segment ());
+ if (candidate.is_error ())
+ {
+ rust_error_at (
+ expr.get_method_name ().get_locus (),
+ "failed to resolve method for %<%s%>",
+ expr.get_method_name ().get_segment ().as_string ().c_str ());
+ return;
+ }
+
+ // Get the adjusted self
+ Adjuster adj (receiver_tyty);
+ TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
+
+ // store the adjustments for code-generation to know what to do which must be
+ // stored onto the receiver to so as we don't trigger duplicate deref mappings
+ // ICE when an argument is a method call
+ HirId autoderef_mappings_id
+ = expr.get_receiver ()->get_mappings ().get_hirid ();
+ context->insert_autoderef_mappings (autoderef_mappings_id,
+ std::move (candidate.adjustments));
+
+ PathProbeCandidate &resolved_candidate = candidate.candidate;
+ TyTy::BaseType *lookup_tyty = candidate.candidate.ty;
+ NodeId resolved_node_id
+ = resolved_candidate.is_impl_candidate ()
+ ? resolved_candidate.item.impl.impl_item->get_impl_mappings ()
+ .get_nodeid ()
+ : resolved_candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
+
+ if (lookup_tyty->get_kind () != TyTy::TypeKind::FNDEF)
+ {
+ RichLocation r (expr.get_method_name ().get_locus ());
+ r.add_range (resolved_candidate.locus);
+ rust_error_at (r, "associated impl item is not a method");
+ return;
+ }
+
+ TyTy::BaseType *lookup = lookup_tyty;
+ TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
+ if (!fn->is_method ())
+ {
+ RichLocation r (expr.get_method_name ().get_locus ());
+ r.add_range (resolved_candidate.locus);
+ rust_error_at (r, "associated function is not a method");
+ return;
+ }
+
+ auto root = receiver_tyty->get_root ();
+ if (root->get_kind () == TyTy::TypeKind::ADT)
+ {
+ const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (root);
+ if (adt->has_substitutions () && fn->needs_substitution ())
+ {
+ // consider the case where we have:
+ //
+ // struct Foo<X,Y>(X,Y);
+ //
+ // impl<T> Foo<T, i32> {
+ // fn test<X>(self, a:X) -> (T,X) { (self.0, a) }
+ // }
+ //
+ // In this case we end up with an fn type of:
+ //
+ // fn <T,X> test(self:Foo<T,i32>, a:X) -> (T,X)
+ //
+ // This means the instance or self we are calling this method for
+ // will be substituted such that we can get the inherited type
+ // arguments but then need to use the turbo fish if available or
+ // infer the remaining arguments. Luckily rust does not allow for
+ // default types GenericParams on impl blocks since these must
+ // always be at the end of the list
+
+ auto s = fn->get_self_type ()->get_root ();
+ rust_assert (s->can_eq (adt, false));
+ rust_assert (s->get_kind () == TyTy::TypeKind::ADT);
+ const TyTy::ADTType *self_adt
+ = static_cast<const TyTy::ADTType *> (s);
+
+ // we need to grab the Self substitutions as the inherit type
+ // parameters for this
+ if (self_adt->needs_substitution ())
+ {
+ rust_assert (adt->was_substituted ());
+
+ TyTy::SubstitutionArgumentMappings used_args_in_prev_segment
+ = GetUsedSubstArgs::From (adt);
+
+ TyTy::SubstitutionArgumentMappings inherit_type_args
+ = self_adt->solve_mappings_from_receiver_for_self (
+ used_args_in_prev_segment);
+
+ // there may or may not be inherited type arguments
+ if (!inherit_type_args.is_error ())
+ {
+ // need to apply the inherited type arguments to the
+ // function
+ lookup = fn->handle_substitions (inherit_type_args);
+ }
+ }
+ }
+ }
+
+ // apply any remaining generic arguments
+ if (expr.get_method_name ().has_generic_args ())
+ {
+ HIR::GenericArgs &args = expr.get_method_name ().get_generic_args ();
+ lookup
+ = SubstMapper::Resolve (lookup, expr.get_method_name ().get_locus (),
+ &args);
+ if (lookup->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+ }
+ else if (lookup->needs_generic_substitutions ())
+ {
+ lookup = SubstMapper::InferSubst (lookup,
+ expr.get_method_name ().get_locus ());
+ }
+
+ TyTy::BaseType *function_ret_tyty
+ = TyTy::TypeCheckMethodCallExpr::go (lookup, expr, adjusted_self, context);
+ if (function_ret_tyty == nullptr
+ || function_ret_tyty->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ rust_error_at (expr.get_locus (),
+ "failed to lookup type to MethodCallExpr");
+ return;
+ }
+
+ // store the expected fntype
+ context->insert_type (expr.get_method_name ().get_mappings (), lookup);
+
+ // set up the resolved name on the path
+ resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
+ resolved_node_id);
+
+ // return the result of the function back
+ infered = function_ret_tyty;
+}
+
bool
TypeCheckExpr::resolve_operator_overload (
Analysis::RustLangItem::ItemType lang_item_type, HIR::OperatorExprMeta expr,
@@ -365,7 +520,7 @@ TypeCheckExpr::resolve_operator_overload (
}
// store the adjustments for code-generation to know what to do
- context->insert_autoderef_mappings (expr.get_mappings ().get_hirid (),
+ context->insert_autoderef_mappings (expr.get_lvalue_mappings ().get_hirid (),
std::move (candidate.adjustments));
// now its just like a method-call-expr
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index df07cb3..de542ca 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -220,157 +220,7 @@ public:
= TyTy::TypeCheckCallExpr::go (function_tyty, expr, variant, context);
}
- void visit (HIR::MethodCallExpr &expr) override
- {
- auto receiver_tyty = TypeCheckExpr::Resolve (expr.get_receiver ().get ());
- if (receiver_tyty->get_kind () == TyTy::TypeKind::ERROR)
- {
- rust_error_at (expr.get_receiver ()->get_locus (),
- "failed to resolve receiver in MethodCallExpr");
- return;
- }
-
- context->insert_receiver (expr.get_mappings ().get_hirid (), receiver_tyty);
-
- auto candidate
- = MethodResolver::Probe (receiver_tyty,
- expr.get_method_name ().get_segment ());
- if (candidate.is_error ())
- {
- rust_error_at (
- expr.get_method_name ().get_locus (),
- "failed to resolve method for %<%s%>",
- expr.get_method_name ().get_segment ().as_string ().c_str ());
- return;
- }
-
- // Get the adjusted self
- Adjuster adj (receiver_tyty);
- TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
-
- // store the adjustments for code-generation to know what to do
- context->insert_autoderef_mappings (expr.get_mappings ().get_hirid (),
- std::move (candidate.adjustments));
-
- PathProbeCandidate &resolved_candidate = candidate.candidate;
- TyTy::BaseType *lookup_tyty = candidate.candidate.ty;
- NodeId resolved_node_id
- = resolved_candidate.is_impl_candidate ()
- ? resolved_candidate.item.impl.impl_item->get_impl_mappings ()
- .get_nodeid ()
- : resolved_candidate.item.trait.item_ref->get_mappings ()
- .get_nodeid ();
-
- if (lookup_tyty->get_kind () != TyTy::TypeKind::FNDEF)
- {
- RichLocation r (expr.get_method_name ().get_locus ());
- r.add_range (resolved_candidate.locus);
- rust_error_at (r, "associated impl item is not a method");
- return;
- }
-
- TyTy::BaseType *lookup = lookup_tyty;
- TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
- if (!fn->is_method ())
- {
- RichLocation r (expr.get_method_name ().get_locus ());
- r.add_range (resolved_candidate.locus);
- rust_error_at (r, "associated function is not a method");
- return;
- }
-
- auto root = receiver_tyty->get_root ();
- if (root->get_kind () == TyTy::TypeKind::ADT)
- {
- const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (root);
- if (adt->has_substitutions () && fn->needs_substitution ())
- {
- // consider the case where we have:
- //
- // struct Foo<X,Y>(X,Y);
- //
- // impl<T> Foo<T, i32> {
- // fn test<X>(self, a:X) -> (T,X) { (self.0, a) }
- // }
- //
- // In this case we end up with an fn type of:
- //
- // fn <T,X> test(self:Foo<T,i32>, a:X) -> (T,X)
- //
- // This means the instance or self we are calling this method for
- // will be substituted such that we can get the inherited type
- // arguments but then need to use the turbo fish if available or
- // infer the remaining arguments. Luckily rust does not allow for
- // default types GenericParams on impl blocks since these must
- // always be at the end of the list
-
- auto s = fn->get_self_type ()->get_root ();
- rust_assert (s->can_eq (adt, false));
- rust_assert (s->get_kind () == TyTy::TypeKind::ADT);
- const TyTy::ADTType *self_adt
- = static_cast<const TyTy::ADTType *> (s);
-
- // we need to grab the Self substitutions as the inherit type
- // parameters for this
- if (self_adt->needs_substitution ())
- {
- rust_assert (adt->was_substituted ());
-
- TyTy::SubstitutionArgumentMappings used_args_in_prev_segment
- = GetUsedSubstArgs::From (adt);
-
- TyTy::SubstitutionArgumentMappings inherit_type_args
- = self_adt->solve_mappings_from_receiver_for_self (
- used_args_in_prev_segment);
-
- // there may or may not be inherited type arguments
- if (!inherit_type_args.is_error ())
- {
- // need to apply the inherited type arguments to the
- // function
- lookup = fn->handle_substitions (inherit_type_args);
- }
- }
- }
- }
-
- // apply any remaining generic arguments
- if (expr.get_method_name ().has_generic_args ())
- {
- HIR::GenericArgs &args = expr.get_method_name ().get_generic_args ();
- lookup
- = SubstMapper::Resolve (lookup, expr.get_method_name ().get_locus (),
- &args);
- if (lookup->get_kind () == TyTy::TypeKind::ERROR)
- return;
- }
- else if (lookup->needs_generic_substitutions ())
- {
- lookup = SubstMapper::InferSubst (lookup,
- expr.get_method_name ().get_locus ());
- }
-
- TyTy::BaseType *function_ret_tyty
- = TyTy::TypeCheckMethodCallExpr::go (lookup, expr, adjusted_self,
- context);
- if (function_ret_tyty == nullptr
- || function_ret_tyty->get_kind () == TyTy::TypeKind::ERROR)
- {
- rust_error_at (expr.get_locus (),
- "failed to lookup type to MethodCallExpr");
- return;
- }
-
- // store the expected fntype
- context->insert_type (expr.get_method_name ().get_mappings (), lookup);
-
- // set up the resolved name on the path
- resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
- resolved_node_id);
-
- // return the result of the function back
- infered = function_ret_tyty;
- }
+ void visit (HIR::MethodCallExpr &expr) override;
void visit (HIR::AssignmentExpr &expr) override
{
@@ -380,7 +230,8 @@ public:
auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ());
auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ());
- lhs->coerce (rhs);
+ 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 b2b68c0..f8bf6e0 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
- specified_ty->coerce (init_expr_ty);
+ 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 6634ad4..5b52277 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
@@ -42,8 +42,8 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr)
{
TyTy::BaseType *base_resolved
= TypeCheckExpr::Resolve (struct_expr.struct_base->base_struct.get ());
- struct_def
- = (TyTy::ADTType *) struct_path_resolved->coerce (base_resolved);
+ struct_def = static_cast<TyTy::ADTType *> (
+ struct_path_resolved->coerce (base_resolved));
if (struct_def == nullptr)
{
rust_fatal_error (struct_expr.struct_base->base_struct->get_locus (),
@@ -221,7 +221,9 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field)
}
TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value ());
- resolved_field_value_expr = field_type->get_field_type ()->coerce (value);
+ resolved_field_value_expr
+ = 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);
@@ -250,7 +252,9 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field)
}
TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value ());
- resolved_field_value_expr = field_type->get_field_type ()->coerce (value);
+ resolved_field_value_expr
+ = 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);
@@ -284,7 +288,9 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field)
field.get_locus ());
TyTy::BaseType *value = TypeCheckExpr::Resolve (&expr);
- resolved_field_value_expr = field_type->get_field_type ()->coerce (value);
+ resolved_field_value_expr
+ = 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
new file mode 100644
index 0000000..b810bd8
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-call.cc
@@ -0,0 +1,269 @@
+// 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-tyty-call.h"
+#include "rust-hir-type-check-expr.h"
+
+namespace Rust {
+namespace TyTy {
+
+void
+TypeCheckCallExpr::visit (ADTType &type)
+{
+ rust_assert (!variant.is_error ());
+ if (variant.get_variant_type () != TyTy::VariantDef::VariantType::TUPLE)
+ {
+ rust_error_at (
+ call.get_locus (),
+ "expected function, tuple struct or tuple variant, found struct %<%s%>",
+ type.get_name ().c_str ());
+ return;
+ }
+
+ if (call.num_params () != variant.num_fields ())
+ {
+ rust_error_at (call.get_locus (),
+ "unexpected number of arguments %lu expected %lu",
+ (unsigned long) call.num_params (),
+ (unsigned long) variant.num_fields ());
+ return;
+ }
+
+ size_t i = 0;
+ for (auto &argument : call.get_arguments ())
+ {
+ StructFieldType *field = variant.get_field_at_index (i);
+ BaseType *field_tyty = field->get_field_type ();
+
+ BaseType *arg = Resolver::TypeCheckExpr::Resolve (argument.get ());
+ if (arg->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ rust_error_at (argument->get_locus (),
+ "failed to resolve argument type");
+ return;
+ }
+
+ 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;
+ }
+
+ delete res;
+ i++;
+ }
+
+ if (i != call.num_params ())
+ {
+ rust_error_at (call.get_locus (),
+ "unexpected number of arguments %lu expected %lu",
+ (unsigned long) i, (unsigned long) call.num_params ());
+ return;
+ }
+
+ resolved = type.clone ();
+}
+
+void
+TypeCheckCallExpr::visit (FnType &type)
+{
+ type.monomorphize ();
+ if (call.num_params () != type.num_params ())
+ {
+ if (type.is_varadic ())
+ {
+ if (call.num_params () < type.num_params ())
+ {
+ rust_error_at (call.get_locus (),
+ "unexpected number of arguments %lu expected %lu",
+ (unsigned long) call.num_params (),
+ (unsigned long) type.num_params ());
+ return;
+ }
+ }
+ else
+ {
+ rust_error_at (call.get_locus (),
+ "unexpected number of arguments %lu expected %lu",
+ (unsigned long) call.num_params (),
+ (unsigned long) type.num_params ());
+ return;
+ }
+ }
+
+ size_t i = 0;
+ for (auto &argument : call.get_arguments ())
+ {
+ auto argument_expr_tyty
+ = Resolver::TypeCheckExpr::Resolve (argument.get ());
+ if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ rust_error_at (
+ argument->get_locus (),
+ "failed to resolve type for argument expr in CallExpr");
+ return;
+ }
+
+ // it might be a varadic function
+ if (i < type.num_params ())
+ {
+ auto fnparam = type.param_at (i);
+ 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 (),
+ "Type Resolution failure on parameter");
+ return;
+ }
+ }
+
+ context->insert_type (argument->get_mappings (), argument_expr_tyty);
+
+ i++;
+ }
+
+ if (i < call.num_params ())
+ {
+ rust_error_at (call.get_locus (),
+ "unexpected number of arguments %lu expected %lu",
+ (unsigned long) i, (unsigned long) call.num_params ());
+ return;
+ }
+
+ type.monomorphize ();
+ resolved = type.get_return_type ()->clone ();
+}
+
+void
+TypeCheckCallExpr::visit (FnPtr &type)
+{
+ if (call.num_params () != type.num_params ())
+ {
+ rust_error_at (call.get_locus (),
+ "unexpected number of arguments %lu expected %lu",
+ (unsigned long) call.num_params (),
+ (unsigned long) type.num_params ());
+ return;
+ }
+
+ size_t i = 0;
+ for (auto &argument : call.get_arguments ())
+ {
+ auto fnparam = type.param_at (i);
+ auto argument_expr_tyty
+ = Resolver::TypeCheckExpr::Resolve (argument.get ());
+ if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ rust_error_at (
+ argument->get_locus (),
+ "failed to resolve type for argument expr in CallExpr");
+ return;
+ }
+
+ 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 (),
+ "Type Resolution failure on parameter");
+ return;
+ }
+
+ context->insert_type (argument->get_mappings (), argument_expr_tyty);
+
+ i++;
+ }
+
+ if (i != call.num_params ())
+ {
+ rust_error_at (call.get_locus (),
+ "unexpected number of arguments %lu expected %lu",
+ (unsigned long) i, (unsigned long) call.num_params ());
+ return;
+ }
+
+ resolved = type.get_return_type ()->monomorphized_clone ();
+}
+
+// method call checker
+
+void
+TypeCheckMethodCallExpr::visit (FnType &type)
+{
+ type.get_self_type ()->unify (adjusted_self);
+
+ // +1 for the receiver self
+ size_t num_args_to_call = call.num_params () + 1;
+ if (num_args_to_call != type.num_params ())
+ {
+ rust_error_at (call.get_locus (),
+ "unexpected number of arguments %lu expected %lu",
+ (unsigned long) call.num_params (),
+ (unsigned long) type.num_params ());
+ return;
+ }
+
+ size_t i = 1;
+ for (auto &argument : call.get_arguments ())
+ {
+ auto fnparam = type.param_at (i);
+ auto argument_expr_tyty
+ = Resolver::TypeCheckExpr::Resolve (argument.get ());
+ if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ rust_error_at (
+ argument->get_locus (),
+ "failed to resolve type for argument expr in CallExpr");
+ return;
+ }
+
+ 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 (),
+ "Type Resolution failure on parameter");
+ return;
+ }
+
+ context->insert_type (argument->get_mappings (), argument_expr_tyty);
+
+ i++;
+ }
+
+ if (i != num_args_to_call)
+ {
+ rust_error_at (call.get_locus (),
+ "unexpected number of arguments %lu expected %lu",
+ (unsigned long) i, (unsigned long) call.num_params ());
+ return;
+ }
+
+ type.monomorphize ();
+
+ resolved = type.get_return_type ()->monomorphized_clone ();
+}
+
+} // namespace TyTy
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h
index f3118ba..07d1dea 100644
--- a/gcc/rust/typecheck/rust-tyty-cmp.h
+++ b/gcc/rust/typecheck/rust-tyty-cmp.h
@@ -36,12 +36,7 @@ public:
if (other->get_kind () == TypeKind::PARAM)
{
const ParamType *p = static_cast<const ParamType *> (other);
- if (p->can_resolve ())
- {
- const BaseType *resolved = p->resolve ();
- resolved->accept_vis (*this);
- return ok;
- }
+ other = p->resolve ();
}
if (other->get_kind () == TypeKind::PLACEHOLDER)
{
@@ -861,6 +856,17 @@ public:
: BaseCmp (base, emit_errors), base (base)
{}
+ void visit (const InferType &type) override
+ {
+ if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
+ {
+ BaseCmp::visit (type);
+ return;
+ }
+
+ ok = true;
+ }
+
private:
const BaseType *get_base () const override { return base; }
const ClosureType *base;
@@ -889,6 +895,17 @@ public:
ok = true;
}
+ void visit (const InferType &type) override
+ {
+ if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
+ {
+ BaseCmp::visit (type);
+ return;
+ }
+
+ ok = true;
+ }
+
private:
const BaseType *get_base () const override { return base; }
const ArrayType *base;
@@ -917,6 +934,17 @@ public:
ok = true;
}
+ void visit (const InferType &type) override
+ {
+ if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
+ {
+ BaseCmp::visit (type);
+ return;
+ }
+
+ ok = true;
+ }
+
private:
const BaseType *get_base () const override { return base; }
const SliceType *base;
@@ -1074,6 +1102,17 @@ public:
ok = true;
}
+ void visit (const InferType &type) override
+ {
+ if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
+ {
+ BaseCmp::visit (type);
+ return;
+ }
+
+ ok = true;
+ }
+
private:
const BaseType *get_base () const override { return base; }
const ADTType *base;
@@ -1111,6 +1150,17 @@ public:
ok = true;
}
+ void visit (const InferType &type) override
+ {
+ if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
+ {
+ BaseCmp::visit (type);
+ return;
+ }
+
+ ok = true;
+ }
+
private:
const BaseType *get_base () const override { return base; }
const TupleType *base;
@@ -1209,6 +1259,17 @@ public:
ok = true;
}
+ void visit (const InferType &type) override
+ {
+ if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
+ {
+ BaseCmp::visit (type);
+ return;
+ }
+
+ ok = true;
+ }
+
private:
const BaseType *get_base () const override { return base; }
const ReferenceType *base;
@@ -1246,6 +1307,17 @@ public:
ok = true;
}
+ void visit (const InferType &type) override
+ {
+ if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
+ {
+ BaseCmp::visit (type);
+ return;
+ }
+
+ ok = true;
+ }
+
private:
const BaseType *get_base () const override { return base; }
const PointerType *base;
@@ -1344,6 +1416,17 @@ public:
void visit (const StrType &type) override { ok = true; }
+ void visit (const InferType &type) override
+ {
+ if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
+ {
+ BaseCmp::visit (type);
+ return;
+ }
+
+ ok = true;
+ }
+
private:
const BaseType *get_base () const override { return base; }
const StrType *base;
@@ -1360,6 +1443,17 @@ public:
void visit (const NeverType &type) override { ok = true; }
+ void visit (const InferType &type) override
+ {
+ if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
+ {
+ BaseCmp::visit (type);
+ return;
+ }
+
+ ok = true;
+ }
+
private:
const BaseType *get_base () const override { return base; }
const NeverType *base;
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 05cd8ce..daedfc3 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -3205,243 +3205,5 @@ DynamicObjectType::get_object_items () const
return items;
}
-// rust-tyty-call.h
-
-void
-TypeCheckCallExpr::visit (ADTType &type)
-{
- rust_assert (!variant.is_error ());
- if (variant.get_variant_type () != TyTy::VariantDef::VariantType::TUPLE)
- {
- rust_error_at (
- call.get_locus (),
- "expected function, tuple struct or tuple variant, found struct %<%s%>",
- type.get_name ().c_str ());
- return;
- }
-
- if (call.num_params () != variant.num_fields ())
- {
- rust_error_at (call.get_locus (),
- "unexpected number of arguments %lu expected %lu",
- (unsigned long) call.num_params (),
- (unsigned long) variant.num_fields ());
- return;
- }
-
- size_t i = 0;
- for (auto &argument : call.get_arguments ())
- {
- StructFieldType *field = variant.get_field_at_index (i);
- BaseType *field_tyty = field->get_field_type ();
-
- BaseType *arg = Resolver::TypeCheckExpr::Resolve (argument.get ());
- if (arg->get_kind () == TyTy::TypeKind::ERROR)
- {
- rust_error_at (argument->get_locus (),
- "failed to resolve argument type");
- return;
- }
-
- auto res = field_tyty->coerce (arg);
- if (res->get_kind () == TyTy::TypeKind::ERROR)
- {
- return;
- }
-
- delete res;
- i++;
- }
-
- if (i != call.num_params ())
- {
- rust_error_at (call.get_locus (),
- "unexpected number of arguments %lu expected %lu",
- (unsigned long) i, (unsigned long) call.num_params ());
- return;
- }
-
- resolved = type.clone ();
-}
-
-void
-TypeCheckCallExpr::visit (FnType &type)
-{
- type.monomorphize ();
- if (call.num_params () != type.num_params ())
- {
- if (type.is_varadic ())
- {
- if (call.num_params () < type.num_params ())
- {
- rust_error_at (call.get_locus (),
- "unexpected number of arguments %lu expected %lu",
- (unsigned long) call.num_params (),
- (unsigned long) type.num_params ());
- return;
- }
- }
- else
- {
- rust_error_at (call.get_locus (),
- "unexpected number of arguments %lu expected %lu",
- (unsigned long) call.num_params (),
- (unsigned long) type.num_params ());
- return;
- }
- }
-
- size_t i = 0;
- for (auto &argument : call.get_arguments ())
- {
- auto argument_expr_tyty
- = Resolver::TypeCheckExpr::Resolve (argument.get ());
- if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
- {
- rust_error_at (
- argument->get_locus (),
- "failed to resolve type for argument expr in CallExpr");
- return;
- }
-
- // it might be a varadic function
- if (i < type.num_params ())
- {
- auto fnparam = type.param_at (i);
- auto resolved_argument_type
- = fnparam.second->coerce (argument_expr_tyty);
- if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
- {
- rust_error_at (argument->get_locus (),
- "Type Resolution failure on parameter");
- return;
- }
- }
-
- context->insert_type (argument->get_mappings (), argument_expr_tyty);
-
- i++;
- }
-
- if (i < call.num_params ())
- {
- rust_error_at (call.get_locus (),
- "unexpected number of arguments %lu expected %lu",
- (unsigned long) i, (unsigned long) call.num_params ());
- return;
- }
-
- type.monomorphize ();
- resolved = type.get_return_type ()->clone ();
-}
-
-void
-TypeCheckCallExpr::visit (FnPtr &type)
-{
- if (call.num_params () != type.num_params ())
- {
- rust_error_at (call.get_locus (),
- "unexpected number of arguments %lu expected %lu",
- (unsigned long) call.num_params (),
- (unsigned long) type.num_params ());
- return;
- }
-
- size_t i = 0;
- for (auto &argument : call.get_arguments ())
- {
- auto fnparam = type.param_at (i);
- auto argument_expr_tyty
- = Resolver::TypeCheckExpr::Resolve (argument.get ());
- if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
- {
- rust_error_at (
- argument->get_locus (),
- "failed to resolve type for argument expr in CallExpr");
- return;
- }
-
- auto resolved_argument_type = fnparam->coerce (argument_expr_tyty);
- if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
- {
- rust_error_at (argument->get_locus (),
- "Type Resolution failure on parameter");
- return;
- }
-
- context->insert_type (argument->get_mappings (), argument_expr_tyty);
-
- i++;
- }
-
- if (i != call.num_params ())
- {
- rust_error_at (call.get_locus (),
- "unexpected number of arguments %lu expected %lu",
- (unsigned long) i, (unsigned long) call.num_params ());
- return;
- }
-
- resolved = type.get_return_type ()->monomorphized_clone ();
-}
-
-// method call checker
-
-void
-TypeCheckMethodCallExpr::visit (FnType &type)
-{
- type.get_self_type ()->unify (adjusted_self);
-
- // +1 for the receiver self
- size_t num_args_to_call = call.num_params () + 1;
- if (num_args_to_call != type.num_params ())
- {
- rust_error_at (call.get_locus (),
- "unexpected number of arguments %lu expected %lu",
- (unsigned long) call.num_params (),
- (unsigned long) type.num_params ());
- return;
- }
-
- size_t i = 1;
- for (auto &argument : call.get_arguments ())
- {
- auto fnparam = type.param_at (i);
- auto argument_expr_tyty
- = Resolver::TypeCheckExpr::Resolve (argument.get ());
- if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
- {
- rust_error_at (
- argument->get_locus (),
- "failed to resolve type for argument expr in CallExpr");
- return;
- }
-
- auto resolved_argument_type = fnparam.second->coerce (argument_expr_tyty);
- if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
- {
- rust_error_at (argument->get_locus (),
- "Type Resolution failure on parameter");
- return;
- }
-
- context->insert_type (argument->get_mappings (), argument_expr_tyty);
-
- i++;
- }
-
- if (i != num_args_to_call)
- {
- rust_error_at (call.get_locus (),
- "unexpected number of arguments %lu expected %lu",
- (unsigned long) i, (unsigned long) call.num_params ());
- return;
- }
-
- type.monomorphize ();
-
- resolved = type.get_return_type ()->monomorphized_clone ();
-}
-
} // namespace TyTy
} // namespace Rust
diff --git a/gcc/testsuite/rust/compile/generics4.rs b/gcc/testsuite/rust/compile/generics4.rs
index 4eaaea7..8af1358 100644
--- a/gcc/testsuite/rust/compile/generics4.rs
+++ b/gcc/testsuite/rust/compile/generics4.rs
@@ -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 }
diff --git a/gcc/testsuite/rust/compile/reference1.rs b/gcc/testsuite/rust/compile/reference1.rs
index 3d97926..ff79153 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 730b53d..77410e9 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 <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 }
}
diff --git a/gcc/testsuite/rust/compile/type-bindings1.rs b/gcc/testsuite/rust/compile/type-bindings1.rs
index 3f61b8b4e..ad85ed9 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 \[<tyty::error>\]} "" { 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 0000000..fce44ad
--- /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<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
+}