Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gccrs: Fix compilation of trait-items which map to impl items #3414

Merged
merged 1 commit into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions gcc/rust/backend/rust-compile-expr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1394,8 +1394,8 @@ CompileExpr::visit (HIR::MethodCallExpr &expr)
TyTy::FnType *fntype = static_cast<TyTy::FnType *> (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
Expand Down Expand Up @@ -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;
Expand Down
27 changes: 25 additions & 2 deletions gcc/rust/backend/rust-compile-item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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<TyTy::FnType *> (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<TyTy::FnType *> (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<TyTy::FnType> ());
fntype = resolved->as<TyTy::FnType> ();
}

fntype->monomorphize ();
}
else
{
Expand Down
16 changes: 10 additions & 6 deletions gcc/rust/backend/rust-compile-resolve-path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<TyTy::FnType> ());
auto fn = lookup->as<TyTy::FnType> ();
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);
Expand Down
6 changes: 0 additions & 6 deletions gcc/rust/typecheck/rust-hir-type-check-expr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 0 additions & 3 deletions gcc/rust/typecheck/rust-hir-type-check-path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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<Resolver2_0::NameResolutionContext &> (
Expand Down
4 changes: 0 additions & 4 deletions gcc/rust/typecheck/rust-hir-type-check-type.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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<Resolver2_0::NameResolutionContext &> (
Expand Down
4 changes: 0 additions & 4 deletions gcc/rust/typecheck/rust-hir-type-check.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -282,7 +279,6 @@ class TypeCheckContext
std::vector<TyTy::BaseType *> loop_type_stack;
StackedContexts<TypeCheckBlockContextItem> block_stack;
std::map<DefId, TraitReference> trait_context;
std::map<HirId, TyTy::BaseType *> receiver_context;
std::map<HirId, AssociatedImplTrait> associated_impl_traits;

// trait-id -> list of < self-tyty:impl-id>
Expand Down
17 changes: 0 additions & 17 deletions gcc/rust/typecheck/rust-typecheck-context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
90 changes: 90 additions & 0 deletions gcc/testsuite/rust/execute/torture/issue-3381.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/* { dg-output "Err: 15\r*\n" } */
#[lang = "sized"]
trait Sized {}

enum Result<T, E> {
#[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<Self::Ok, Self::Error>;

#[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<T, E> Try for Result<T, E> {
type Ok = T;
type Error = E;

fn into_result(self) -> Result<T, E> {
self
}

fn from_ok(v: T) -> Self {
Result::Ok(v)
}

fn from_error(v: E) -> Self {
Result::Err(v)
}
}

pub trait From<T>: Sized {
fn from(_: T) -> Self;
}

impl<T> From<T> 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<i32, i32> {
Result::Err(15)
}

fn foo() -> Result<i32, i32> {
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
}