diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index a72156b6aa3..021495afb93 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -1394,8 +1394,8 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) TyTy::FnType *fntype = static_cast (lookup_fntype); TyTy::BaseType *receiver = nullptr; - ok = ctx->get_tyctx ()->lookup_receiver (expr.get_mappings ().get_hirid (), - &receiver); + ok = ctx->get_tyctx ()->lookup_type ( + expr.get_receiver ().get_mappings ().get_hirid (), &receiver); rust_assert (ok); bool is_dyn_dispatch @@ -1532,8 +1532,8 @@ CompileExpr::resolve_operator_overload ( TyTy::BaseType *receiver = nullptr; bool ok - = ctx->get_tyctx ()->lookup_receiver (expr.get_mappings ().get_hirid (), - &receiver); + = ctx->get_tyctx ()->lookup_type (lhs_expr.get_mappings ().get_hirid (), + &receiver); rust_assert (ok); bool is_generic_receiver = receiver->get_kind () == TyTy::TypeKind::PARAM; diff --git a/gcc/rust/backend/rust-compile-item.cc b/gcc/rust/backend/rust-compile-item.cc index 2b6836ac391..3e028c3b943 100644 --- a/gcc/rust/backend/rust-compile-item.cc +++ b/gcc/rust/backend/rust-compile-item.cc @@ -19,6 +19,8 @@ #include "rust-compile-item.h" #include "rust-compile-implitem.h" #include "rust-compile-extern.h" +#include "rust-substitution-mapper.h" +#include "rust-type-util.h" #include "rust-immutable-name-resolution-context.h" namespace Rust { @@ -165,12 +167,33 @@ CompileItem::visit (HIR::Function &function) // is given if (concrete == nullptr) return; - else + + rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF); + TyTy::FnType *concrete_fnty = static_cast (concrete); + bool is_trait_item_concrete + = ctx->get_mappings () + .lookup_trait_item_defid (concrete_fnty->get_id ()) + .has_value (); + if (!is_trait_item_concrete) { rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF); fntype = static_cast (concrete); - fntype->monomorphize (); } + else + { + TyTy::BaseType *infer + = Resolver::SubstMapper::InferSubst (fntype, function.get_locus ()); + TyTy::BaseType *resolved + = Resolver::unify_site (function.get_mappings ().get_hirid (), + TyTy::TyWithLocation (infer), + TyTy::TyWithLocation (concrete), + function.get_locus ()); + + rust_assert (resolved->is ()); + fntype = resolved->as (); + } + + fntype->monomorphize (); } else { diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index c862a81e212..1b9dee69a10 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -297,16 +297,20 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup, trait->get_mappings ().get_defid (), &trait_ref); rust_assert (ok); - TyTy::BaseType *receiver = nullptr; - ok = ctx->get_tyctx ()->lookup_receiver (mappings.get_hirid (), - &receiver); - rust_assert (ok); - receiver = receiver->destructure (); - // the type resolver can only resolve type bounds to their trait // item so its up to us to figure out if this path should resolve // to an trait-impl-block-item or if it can be defaulted to the // trait-impl-item's definition + // + // because we know this is resolved to a trait item we can actually + // just grab the Self type parameter here for the receiver to match + // the appropriate impl block + + rust_assert (lookup->is ()); + auto fn = lookup->as (); + rust_assert (fn->get_num_type_params () > 0); + auto &self = fn->get_substs ().at (0); + auto receiver = self.get_param_ty (); auto candidates = Resolver::PathProbeImplTrait::Probe (receiver, final_segment, trait_ref); diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index 356a960f317..2fb4d3cba34 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -1105,8 +1105,6 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr) return; } - context->insert_receiver (expr.get_mappings ().get_hirid (), receiver_tyty); - rust_debug_loc (expr.get_locus (), "attempting to resolve method for %s", receiver_tyty->debug_str ().c_str ()); auto candidates @@ -1750,9 +1748,6 @@ TypeCheckExpr::resolve_operator_overload ( context->insert_autoderef_mappings (expr.get_lvalue_mappings ().get_hirid (), std::move (candidate.adjustments)); - // now its just like a method-call-expr - context->insert_receiver (expr.get_mappings ().get_hirid (), lhs); - PathProbeCandidate &resolved_candidate = candidate.candidate; TyTy::BaseType *lookup_tyty = candidate.candidate.ty; NodeId resolved_node_id @@ -1997,7 +1992,6 @@ TypeCheckExpr::resolve_fn_trait_call (HIR::CallExpr &expr, HirId autoderef_mappings_id = fnexpr.get_mappings ().get_hirid (); context->insert_autoderef_mappings (autoderef_mappings_id, std::move (candidate.adjustments)); - context->insert_receiver (expr.get_mappings ().get_hirid (), receiver_tyty); PathProbeCandidate &resolved_candidate = candidate.candidate; TyTy::BaseType *lookup_tyty = candidate.candidate.ty; diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index a4f294b5290..73d97384789 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -171,7 +171,6 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr) resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (), root_resolved_node_id); } - context->insert_receiver (expr.get_mappings ().get_hirid (), root); return; } @@ -559,8 +558,6 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id, } rust_assert (resolved_node_id != UNKNOWN_NODEID); - context->insert_receiver (expr_mappings.get_hirid (), prev_segment); - if (flag_name_resolution_2_0) { auto &nr_ctx = const_cast ( diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index 6dc62d68f72..ff6813a513d 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -360,8 +360,6 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path) resolver->insert_resolved_type (path.get_mappings ().get_nodeid (), root_resolved_node_id); } - - context->insert_receiver (path.get_mappings ().get_hirid (), root); return; } @@ -704,9 +702,7 @@ TypeCheckType::resolve_segments ( } } - context->insert_receiver (expr_mappings.get_hirid (), prev_segment); rust_assert (resolved_node_id != UNKNOWN_NODEID); - if (flag_name_resolution_2_0) { auto &nr_ctx = const_cast ( diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index 42ef2d14325..21ecf2ce786 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -202,9 +202,6 @@ class TypeCheckContext void insert_trait_reference (DefId id, TraitReference &&ref); bool lookup_trait_reference (DefId id, TraitReference **ref); - void insert_receiver (HirId id, TyTy::BaseType *t); - bool lookup_receiver (HirId id, TyTy::BaseType **ref); - void insert_associated_trait_impl (HirId id, AssociatedImplTrait &&associated); bool lookup_associated_trait_impl (HirId id, @@ -282,7 +279,6 @@ class TypeCheckContext std::vector loop_type_stack; StackedContexts block_stack; std::map trait_context; - std::map receiver_context; std::map associated_impl_traits; // trait-id -> list of < self-tyty:impl-id> diff --git a/gcc/rust/typecheck/rust-typecheck-context.cc b/gcc/rust/typecheck/rust-typecheck-context.cc index d3ff29a4bdb..4cee74ae250 100644 --- a/gcc/rust/typecheck/rust-typecheck-context.cc +++ b/gcc/rust/typecheck/rust-typecheck-context.cc @@ -254,23 +254,6 @@ TypeCheckContext::lookup_trait_reference (DefId id, TraitReference **ref) return true; } -void -TypeCheckContext::insert_receiver (HirId id, TyTy::BaseType *t) -{ - receiver_context[id] = t; -} - -bool -TypeCheckContext::lookup_receiver (HirId id, TyTy::BaseType **ref) -{ - auto it = receiver_context.find (id); - if (it == receiver_context.end ()) - return false; - - *ref = it->second; - return true; -} - void TypeCheckContext::insert_associated_trait_impl ( HirId id, AssociatedImplTrait &&associated) diff --git a/gcc/testsuite/rust/execute/torture/issue-3381.rs b/gcc/testsuite/rust/execute/torture/issue-3381.rs new file mode 100644 index 00000000000..62dbcd0b2fd --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/issue-3381.rs @@ -0,0 +1,90 @@ +/* { dg-output "Err: 15\r*\n" } */ +#[lang = "sized"] +trait Sized {} + +enum Result { + #[lang = "Ok"] + Ok(T), + #[lang = "Err"] + Err(E), +} + +#[lang = "try"] +pub trait Try { + type Ok; + type Error; + + #[lang = "into_result"] + #[unstable(feature = "try_trait", issue = "42327")] + fn into_result(self) -> Result; + + #[lang = "from_error"] + #[unstable(feature = "try_trait", issue = "42327")] + fn from_error(v: Self::Ok) -> Self; + + #[lang = "from_ok"] + #[unstable(feature = "try_trait", issue = "42327")] + fn from_ok(v: Self::Error) -> Self; +} + +impl Try for Result { + type Ok = T; + type Error = E; + + fn into_result(self) -> Result { + self + } + + fn from_ok(v: T) -> Self { + Result::Ok(v) + } + + fn from_error(v: E) -> Self { + Result::Err(v) + } +} + +pub trait From: Sized { + fn from(_: T) -> Self; +} + +impl From for T { + fn from(t: T) -> Self { + t + } +} + +fn print(s: &str, value: i32) { + extern "C" { + fn printf(s: *const i8, ...); + } + + unsafe { + printf(s as *const str as *const i8, value); + } +} + +fn baz() -> Result { + Result::Err(15) +} + +fn foo() -> Result { + let b = match baz() { + Result::Ok(value) => value, + Result::Err(err) => { + return Try::from_error(From::from(err)); + } + }; + + Result::Ok(15 + b) +} + +fn main() -> i32 { + let a = foo(); + match a { + Result::Ok(value) => print("Ok: %i\n", value), + Result::Err(err) => print("Err: %i\n", err), + }; + + 0 +}