diff options
Diffstat (limited to 'gcc')
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 +} |