aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/rust/backend/rust-compile-context.h2
-rw-r--r--gcc/rust/backend/rust-compile-expr.h5
-rw-r--r--gcc/rust/backend/rust-compile-implitem.h3
-rw-r--r--gcc/rust/backend/rust-compile-item.h16
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.cc69
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.h18
-rw-r--r--gcc/rust/backend/rust-compile.cc19
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-ref.h4
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.cc34
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h75
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc2
-rw-r--r--gcc/rust/typecheck/rust-tyty.h12
-rw-r--r--gcc/rust/util/rust-canonical-path.h11
-rw-r--r--gcc/testsuite/rust/execute/torture/trait1.rs52
14 files changed, 274 insertions, 48 deletions
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
index 6356ccc..66d037d 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -287,7 +287,7 @@ public:
// this needs to support Legacy and V0 see github #429 or #305
std::string mangle_item (const TyTy::BaseType *ty,
- const std::string &name) const;
+ const Resolver::CanonicalPath &path) const;
std::string mangle_impl_item (const TyTy::BaseType *self,
const TyTy::BaseType *ty,
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index 4658295..80cdc5e 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -629,6 +629,11 @@ public:
expr.get_locus ());
}
+ void visit (HIR::QualifiedPathInExpression &expr) override
+ {
+ translated = ResolvePathRef::Compile (expr, ctx);
+ }
+
void visit (HIR::PathInExpression &expr) override
{
translated = ResolvePathRef::Compile (expr, ctx);
diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h
index 809cf56..7337154 100644
--- a/gcc/rust/backend/rust-compile-implitem.h
+++ b/gcc/rust/backend/rust-compile-implitem.h
@@ -352,8 +352,7 @@ public:
&canonical_path));
std::string fn_identifier = canonical_path->get ();
- std::string asm_name
- = ctx->mangle_impl_item (self, fntype, function.get_function_name ());
+ std::string asm_name = ctx->mangle_item (fntype, *canonical_path);
Bfunction *fndecl
= ctx->get_backend ()->function (compiled_fn_type, fn_identifier,
diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h
index 8b36289..a12e67e 100644
--- a/gcc/rust/backend/rust-compile-item.h
+++ b/gcc/rust/backend/rust-compile-item.h
@@ -59,7 +59,7 @@ public:
&canonical_path));
std::string name = canonical_path->get ();
- std::string asm_name = ctx->mangle_item (resolved_type, name);
+ std::string asm_name = ctx->mangle_item (resolved_type, *canonical_path);
bool is_external = false;
bool is_hidden = false;
@@ -168,12 +168,24 @@ public:
std::string ir_symbol_name
= canonical_path->get () + fntype->subst_as_string ();
+
std::string asm_name = function.get_function_name ();
// we don't mangle the main fn since we haven't implemented the main shim
// yet
if (!is_main_fn)
- asm_name = ctx->mangle_item (fntype, ir_symbol_name);
+ {
+ std::string substs_str = fntype->subst_as_string ();
+
+ Resolver::CanonicalPath mangle_me
+ = substs_str.empty ()
+ ? *canonical_path
+ : canonical_path->append (
+ Resolver::CanonicalPath::new_seg (0,
+ fntype->subst_as_string ()));
+
+ asm_name = ctx->mangle_item (fntype, mangle_me);
+ }
Bfunction *fndecl
= ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name,
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc
index 1b892d2..1539378 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -27,18 +27,33 @@ namespace Rust {
namespace Compile {
void
+ResolvePathRef::visit (HIR::QualifiedPathInExpression &expr)
+{
+ resolve (expr.get_final_segment ().get_segment (), expr.get_mappings (),
+ expr.get_locus (), true);
+}
+
+void
ResolvePathRef::visit (HIR::PathInExpression &expr)
{
+ resolve (expr.get_final_segment ().get_segment (), expr.get_mappings (),
+ expr.get_locus (), false);
+}
+
+void
+ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment,
+ const Analysis::NodeMapping &mappings,
+ Location expr_locus, bool is_qualified_path)
+{
// need to look up the reference for this identifier
NodeId ref_node_id = UNKNOWN_NODEID;
- if (ctx->get_resolver ()->lookup_resolved_name (
- expr.get_mappings ().get_nodeid (), &ref_node_id))
+ if (ctx->get_resolver ()->lookup_resolved_name (mappings.get_nodeid (),
+ &ref_node_id))
{
Resolver::Definition def;
if (!ctx->get_resolver ()->lookup_definition (ref_node_id, &def))
{
- rust_error_at (expr.get_locus (),
- "unknown reference for resolved name");
+ rust_error_at (expr_locus, "unknown reference for resolved name");
return;
}
ref_node_id = def.parent;
@@ -50,10 +65,10 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
return;
HirId ref;
- if (!ctx->get_mappings ()->lookup_node_to_hir (
- expr.get_mappings ().get_crate_num (), ref_node_id, &ref))
+ if (!ctx->get_mappings ()->lookup_node_to_hir (mappings.get_crate_num (),
+ ref_node_id, &ref))
{
- rust_error_at (expr.get_locus (), "reverse call path lookup failure");
+ rust_error_at (expr_locus, "reverse call path lookup failure");
return;
}
@@ -65,15 +80,14 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
Bvariable *var = nullptr;
if (ctx->lookup_var_decl (ref, &var))
{
- resolved = ctx->get_backend ()->var_expression (var, expr.get_locus ());
+ resolved = ctx->get_backend ()->var_expression (var, expr_locus);
return;
}
// must be a function call but it might be a generic function which needs to
// be compiled first
TyTy::BaseType *lookup = nullptr;
- bool ok = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
- &lookup);
+ bool ok = ctx->get_tyctx ()->lookup_type (mappings.get_hirid (), &lookup);
rust_assert (ok);
rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup);
@@ -82,8 +96,9 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
if (!ctx->lookup_function_decl (lookup->get_ty_ref (), &fn))
{
// it must resolve to some kind of HIR::Item or HIR::InheritImplItem
- HIR::Item *resolved_item = ctx->get_mappings ()->lookup_hir_item (
- expr.get_mappings ().get_crate_num (), ref);
+ HIR::Item *resolved_item
+ = ctx->get_mappings ()->lookup_hir_item (mappings.get_crate_num (),
+ ref);
if (resolved_item != nullptr)
{
if (!lookup->has_subsititions_defined ())
@@ -96,14 +111,14 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
HirId parent_impl_id = UNKNOWN_HIRID;
HIR::ImplItem *resolved_item
= ctx->get_mappings ()->lookup_hir_implitem (
- expr.get_mappings ().get_crate_num (), ref, &parent_impl_id);
+ mappings.get_crate_num (), ref, &parent_impl_id);
if (resolved_item == nullptr)
{
// it might be resolved to a trait item
HIR::TraitItem *trait_item
= ctx->get_mappings ()->lookup_hir_trait_item (
- expr.get_mappings ().get_crate_num (), ref);
+ mappings.get_crate_num (), ref);
HIR::Trait *trait
= ctx->get_mappings ()->lookup_trait_item_mapping (
trait_item->get_mappings ().get_hirid ());
@@ -115,8 +130,8 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
rust_assert (ok);
TyTy::BaseType *receiver = nullptr;
- ok = ctx->get_tyctx ()->lookup_receiver (
- expr.get_mappings ().get_hirid (), &receiver);
+ ok = ctx->get_tyctx ()->lookup_receiver (mappings.get_hirid (),
+ &receiver);
rust_assert (ok);
if (receiver->get_kind () == TyTy::TypeKind::PARAM)
@@ -130,10 +145,13 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
// 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
- std::vector<Resolver::PathProbeCandidate> candidates
- = Resolver::PathProbeType::Probe (
- receiver, expr.get_final_segment ().get_segment (), true,
- false, true);
+ std::vector<Resolver::PathProbeCandidate> candidates;
+ if (!is_qualified_path)
+ {
+ candidates
+ = Resolver::PathProbeType::Probe (receiver, final_segment,
+ true, false, true);
+ }
if (candidates.size () == 0)
{
@@ -152,6 +170,7 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
= ctx->get_tyctx ()
->lookup_associated_impl_mapping_for_self (
trait_mappings.get_hirid (), receiver);
+
rust_assert (associated_impl_id != UNKNOWN_HIRID);
Resolver::AssociatedImplTrait *associated = nullptr;
@@ -168,7 +187,7 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &fn))
{
resolved = ctx->get_backend ()->error_expression ();
- rust_error_at (expr.get_locus (),
+ rust_error_at (expr_locus,
"forward declaration was not compiled");
return;
}
@@ -201,7 +220,7 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
{
rust_assert (parent_impl_id != UNKNOWN_HIRID);
HIR::Item *impl_ref = ctx->get_mappings ()->lookup_hir_item (
- expr.get_mappings ().get_crate_num (), parent_impl_id);
+ mappings.get_crate_num (), parent_impl_id);
rust_assert (impl_ref != nullptr);
HIR::ImplBlock *impl = static_cast<HIR::ImplBlock *> (impl_ref);
@@ -222,14 +241,12 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
if (!ctx->lookup_function_decl (lookup->get_ty_ref (), &fn))
{
resolved = ctx->get_backend ()->error_expression ();
- rust_error_at (expr.get_locus (),
- "forward declaration was not compiled");
+ rust_error_at (expr_locus, "forward declaration was not compiled");
return;
}
}
- resolved
- = ctx->get_backend ()->function_code_expression (fn, expr.get_locus ());
+ resolved = ctx->get_backend ()->function_code_expression (fn, expr_locus);
}
} // namespace Compile
diff --git a/gcc/rust/backend/rust-compile-resolve-path.h b/gcc/rust/backend/rust-compile-resolve-path.h
index 30486d0..41067c8 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.h
+++ b/gcc/rust/backend/rust-compile-resolve-path.h
@@ -30,6 +30,14 @@ class ResolvePathRef : public HIRCompileBase
using Rust::Compile::HIRCompileBase::visit;
public:
+ static Bexpression *Compile (HIR::QualifiedPathInExpression &expr,
+ Context *ctx)
+ {
+ ResolvePathRef resolver (ctx);
+ expr.accept_vis (resolver);
+ return resolver.resolved;
+ }
+
static Bexpression *Compile (HIR::PathInExpression &expr, Context *ctx)
{
ResolvePathRef resolver (ctx);
@@ -39,8 +47,16 @@ public:
void visit (HIR::PathInExpression &expr) override;
+ void visit (HIR::QualifiedPathInExpression &expr) override;
+
private:
- ResolvePathRef (Context *ctx) : HIRCompileBase (ctx), resolved (nullptr) {}
+ ResolvePathRef (Context *ctx)
+ : HIRCompileBase (ctx), resolved (ctx->get_backend ()->error_expression ())
+ {}
+
+ void resolve (const HIR::PathIdentSegment &final_segment,
+ const Analysis::NodeMapping &mappings, Location locus,
+ bool is_qualified_path);
Bexpression *resolved;
};
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index c36f848..baaccf0 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -553,6 +553,17 @@ mangle_name (const std::string &name)
return std::to_string (name.size ()) + name;
}
+static std::string
+mangle_canonical_path (const Resolver::CanonicalPath &path)
+{
+ std::string buffer;
+ path.iterate_segs ([&] (const Resolver::CanonicalPath &p) -> bool {
+ buffer += mangle_name (p.get ());
+ return true;
+ });
+ return buffer;
+}
+
// rustc uses a sip128 hash for legacy mangling, but an fnv 128 was quicker to
// implement for now
static std::string
@@ -603,17 +614,19 @@ mangle_self (const TyTy::BaseType *self)
}
std::string
-Context::mangle_item (const TyTy::BaseType *ty, const std::string &name) const
+Context::mangle_item (const TyTy::BaseType *ty,
+ const Resolver::CanonicalPath &path) const
{
const std::string &crate_name = mappings->get_current_crate_name ();
const std::string hash = legacy_hash (ty->as_string ());
const std::string hash_sig = mangle_name (hash);
- return kMangledSymbolPrefix + mangle_name (crate_name) + mangle_name (name)
- + hash_sig + kMangledSymbolDelim;
+ return kMangledSymbolPrefix + mangle_name (crate_name)
+ + mangle_canonical_path (path) + hash_sig + kMangledSymbolDelim;
}
+// FIXME this is a wee bit broken
std::string
Context::mangle_impl_item (const TyTy::BaseType *self, const TyTy::BaseType *ty,
const std::string &name) const
diff --git a/gcc/rust/typecheck/rust-hir-trait-ref.h b/gcc/rust/typecheck/rust-hir-trait-ref.h
index 2c7a0e8..9d16e36 100644
--- a/gcc/rust/typecheck/rust-hir-trait-ref.h
+++ b/gcc/rust/typecheck/rust-hir-trait-ref.h
@@ -359,6 +359,10 @@ public:
void reset_associated_types ();
+ TyTy::BaseType *get_projected_type (const TraitItemReference *trait_item_ref,
+ TyTy::BaseType *reciever, HirId ref,
+ Location expr_locus);
+
private:
TraitReference *trait;
HIR::ImplBlock *impl;
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index 5d7c71e..cf3f2fb 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -193,5 +193,39 @@ TraitItemReference::get_parent_trait_mappings () const
return trait->get_mappings ();
}
+TyTy::BaseType *
+AssociatedImplTrait::get_projected_type (
+ const TraitItemReference *trait_item_ref, TyTy::BaseType *receiver, HirId ref,
+ Location expr_locus)
+{
+ TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty ()->clone ();
+
+ // we can substitute the Self with the receiver here
+ if (trait_item_tyty->get_kind () == TyTy::TypeKind::FNDEF)
+ {
+ TyTy::FnType *fn = static_cast<TyTy::FnType *> (trait_item_tyty);
+ TyTy::SubstitutionParamMapping *param = nullptr;
+ for (auto &param_mapping : fn->get_substs ())
+ {
+ const HIR::TypeParam &type_param = param_mapping.get_generic_param ();
+ if (type_param.get_type_representation ().compare ("Self") == 0)
+ {
+ param = &param_mapping;
+ break;
+ }
+ }
+ rust_assert (param != nullptr);
+
+ std::vector<TyTy::SubstitutionArg> mappings;
+ mappings.push_back (TyTy::SubstitutionArg (param, receiver->clone ()));
+
+ Location locus; // FIXME
+ TyTy::SubstitutionArgumentMappings args (std::move (mappings), locus);
+ trait_item_tyty = SubstMapperInternal::Resolve (trait_item_tyty, args);
+ }
+
+ return trait_item_tyty;
+}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 0ac60c2..e3347ea 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -961,33 +961,92 @@ public:
if (expr.get_segments ().empty ())
return;
+ // we need resolve to the impl block
+ NodeId impl_resolved_id = UNKNOWN_NODEID;
+ bool ok = resolver->lookup_resolved_name (
+ qual_path_type.get_mappings ().get_nodeid (), &impl_resolved_id);
+ rust_assert (ok);
+
+ HirId impl_block_id;
+ ok = mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (),
+ impl_resolved_id, &impl_block_id);
+ rust_assert (ok);
+
+ AssociatedImplTrait *lookup_associated = nullptr;
+ bool found_impl_trait
+ = context->lookup_associated_trait_impl (impl_block_id,
+ &lookup_associated);
+ rust_assert (found_impl_trait);
+
DefId resolved_item_id = UNKNOWN_DEFID;
HIR::PathExprSegment &item_seg = expr.get_segments ().at (0);
const TraitItemReference *trait_item_ref = nullptr;
- bool ok
- = trait_ref->lookup_trait_item (item_seg.get_segment ().as_string (),
- &trait_item_ref);
+ ok = trait_ref->lookup_trait_item (item_seg.get_segment ().as_string (),
+ &trait_item_ref);
if (!ok)
{
rust_error_at (item_seg.get_locus (), "unknown associated item");
return;
}
+ resolved_item_id = trait_item_ref->get_mappings ().get_defid ();
+
+ infered = lookup_associated->get_projected_type (
+ trait_item_ref, root, item_seg.get_mappings ().get_hirid (),
+ item_seg.get_locus ());
- // TODO self and generic arguments
- infered = trait_item_ref->get_tyty ();
- rust_debug_loc (expr.get_locus (), "resolved to:");
- infered->debug ();
+ // turbo-fish segment path::<ty>
+ if (item_seg.has_generic_args ())
+ {
+ if (!infered->can_substitute ())
+ {
+ rust_error_at (item_seg.get_locus (),
+ "substitutions not supported for %s",
+ infered->as_string ().c_str ());
+ infered = new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
+ return;
+ }
+ infered = SubstMapper::Resolve (infered, expr.get_locus (),
+ &item_seg.get_generic_args ());
+ }
TyTy::ProjectionType *projection
= new TyTy::ProjectionType (qual_path_type.get_mappings ().get_hirid (),
TyTy::TyVar (root->get_ref ()), trait_ref,
- resolved_item_id);
+ resolved_item_id, lookup_associated);
context->insert_type (qual_path_type.get_mappings (), projection);
// continue on as a path-in-expression
NodeId root_resolved_node_id
= trait_item_ref->get_mappings ().get_nodeid ();
+ bool fully_resolved = expr.get_segments ().size () <= 1;
+
+ if (fully_resolved)
+ {
+ // lookup if the name resolver was able to canonically resolve this or
+ // not
+ NodeId path_resolved_id = UNKNOWN_NODEID;
+ if (resolver->lookup_resolved_name (expr.get_mappings ().get_nodeid (),
+ &path_resolved_id))
+ {
+ rust_assert (path_resolved_id == root_resolved_node_id);
+ }
+ // check the type scope
+ else if (resolver->lookup_resolved_type (
+ expr.get_mappings ().get_nodeid (), &path_resolved_id))
+ {
+ rust_assert (path_resolved_id == root_resolved_node_id);
+ }
+ else
+ {
+ resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
+ root_resolved_node_id);
+ }
+
+ context->insert_receiver (expr.get_mappings ().get_hirid (), root);
+ return;
+ }
+
resolve_segments (root_resolved_node_id, expr.get_segments (), 1, infered,
expr.get_mappings (), expr.get_locus ());
}
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 18ccaee..56fdafd 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -2174,7 +2174,7 @@ BaseType *
ProjectionType::clone () const
{
return new ProjectionType (get_ref (), get_ty_ref (), base, trait, item,
- get_combined_refs ());
+ associated, get_combined_refs ());
}
// rust-tyty-call.h
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 2fc6b53..743874a 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -27,7 +27,8 @@
namespace Rust {
namespace Resolver {
class TraitReference;
-}
+class AssociatedImplTrait;
+} // namespace Resolver
namespace TyTy {
@@ -1730,16 +1731,18 @@ class ProjectionType : public BaseType
{
public:
ProjectionType (HirId ref, TyVar base, Resolver::TraitReference *trait,
- DefId item, std::set<HirId> refs = std::set<HirId> ())
+ DefId item, Resolver::AssociatedImplTrait *associated,
+ std::set<HirId> refs = std::set<HirId> ())
: BaseType (ref, ref, TypeKind::PROJECTION, refs), base (base),
- trait (trait), item (item)
+ trait (trait), item (item), associated (associated)
{}
ProjectionType (HirId ref, HirId ty_ref, TyVar base,
Resolver::TraitReference *trait, DefId item,
+ Resolver::AssociatedImplTrait *associated,
std::set<HirId> refs = std::set<HirId> ())
: BaseType (ref, ty_ref, TypeKind::PROJECTION, refs), base (base),
- trait (trait), item (item)
+ trait (trait), item (item), associated (associated)
{}
void accept_vis (TyVisitor &vis) override;
@@ -1762,6 +1765,7 @@ private:
TyVar base;
Resolver::TraitReference *trait;
DefId item;
+ Resolver::AssociatedImplTrait *associated;
};
} // namespace TyTy
diff --git a/gcc/rust/util/rust-canonical-path.h b/gcc/rust/util/rust-canonical-path.h
index d6ba90d..b5f8dd7 100644
--- a/gcc/rust/util/rust-canonical-path.h
+++ b/gcc/rust/util/rust-canonical-path.h
@@ -110,6 +110,17 @@ public:
}
}
+ void iterate_segs (std::function<bool (const CanonicalPath &)> cb) const
+ {
+ for (auto &seg : segs)
+ {
+ std::vector<std::pair<NodeId, std::string>> buf;
+ buf.push_back ({seg.first, seg.second});
+ if (!cb (CanonicalPath (buf)))
+ return;
+ }
+ }
+
size_t size () const { return segs.size (); }
NodeId get_id () const
diff --git a/gcc/testsuite/rust/execute/torture/trait1.rs b/gcc/testsuite/rust/execute/torture/trait1.rs
new file mode 100644
index 0000000..dc3cc47
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait1.rs
@@ -0,0 +1,52 @@
+/* { dg-output "S::f\nT1::f\nT2::f\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+struct S;
+
+impl S {
+ fn f() {
+ unsafe {
+ let a = "S::f\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+ }
+}
+
+trait T1 {
+ fn f() {
+ unsafe {
+ let a = "T1::f\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+ }
+}
+impl T1 for S {}
+
+trait T2 {
+ fn f() {
+ unsafe {
+ let a = "T2::f\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+ }
+}
+impl T2 for S {}
+
+fn main() -> i32 {
+ S::f();
+ <S as T1>::f();
+ <S as T2>::f();
+
+ 0
+}