aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.cc2
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-implitem.cc3
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-path.cc3
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.cc195
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h9
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h38
-rw-r--r--gcc/rust/typecheck/rust-typecheck-context.cc64
-rw-r--r--gcc/testsuite/rust/compile/issue-2907.rs33
-rw-r--r--gcc/testsuite/rust/compile/nr2/exclude1
9 files changed, 287 insertions, 61 deletions
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index 0361420..4f94d0f 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -278,6 +278,7 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
}
self->inherit_bounds (specified_bounds);
+ context->push_block_context (TypeCheckBlockContextItem (trait_reference));
std::vector<TraitItemReference> item_refs;
for (auto &item : trait_reference->get_trait_items ())
{
@@ -307,6 +308,7 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
// resolve the blocks of functions etc because it can end up in a recursive
// loop of trying to resolve traits as required by the types
tref->on_resolved ();
+ context->pop_block_context ();
return tref;
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
index 6a748f4..a72ab97 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
@@ -335,7 +335,10 @@ TypeCheckImplItem::Resolve (
// resolve
TypeCheckImplItem resolver (parent, self, substitutions);
+ resolver.context->push_block_context (TypeCheckBlockContextItem (&parent));
item.accept_vis (resolver);
+ resolver.context->pop_block_context ();
+
return resolver.result;
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc
index 08ec718..d3f3412 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -355,6 +355,7 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
NodeId resolved_node_id = root_resolved_node_id;
TyTy::BaseType *prev_segment = tyseg;
bool reciever_is_generic = prev_segment->get_kind () == TyTy::TypeKind::PARAM;
+ bool reciever_is_dyn = prev_segment->get_kind () == TyTy::TypeKind::DYNAMIC;
for (size_t i = offset; i < segments.size (); i++)
{
@@ -434,7 +435,7 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
}
}
- if (associated_impl_block != nullptr)
+ if (associated_impl_block != nullptr && !reciever_is_dyn)
{
// associated types
HirId impl_block_id
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index c17e324..aaff8db 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -133,11 +133,16 @@ TypeCheckType::visit (HIR::TypePath &path)
// this can happen so we need to look up the root then resolve the
// remaining segments if possible
+ bool wasBigSelf = false;
size_t offset = 0;
NodeId resolved_node_id = UNKNOWN_NODEID;
- TyTy::BaseType *root = resolve_root_path (path, &offset, &resolved_node_id);
+ TyTy::BaseType *root
+ = resolve_root_path (path, &offset, &resolved_node_id, &wasBigSelf);
if (root->get_kind () == TyTy::TypeKind::ERROR)
- return;
+ {
+ rust_debug_loc (path.get_locus (), "failed to resolve type-path type");
+ return;
+ }
TyTy::BaseType *path_type = root->clone ();
path_type->set_ref (path.get_mappings ().get_hirid ());
@@ -147,13 +152,18 @@ TypeCheckType::visit (HIR::TypePath &path)
if (fully_resolved)
{
translated = path_type;
+ rust_debug_loc (path.get_locus (), "root resolved type-path to: [%s]",
+ translated->debug_str ().c_str ());
return;
}
translated
= resolve_segments (resolved_node_id, path.get_mappings ().get_hirid (),
path.get_segments (), offset, path_type,
- path.get_mappings (), path.get_locus ());
+ path.get_mappings (), path.get_locus (), wasBigSelf);
+
+ rust_debug_loc (path.get_locus (), "resolved type-path to: [%s]",
+ translated->debug_str ().c_str ());
}
void
@@ -192,10 +202,11 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path)
}
rust_assert (ok);
- translated = resolve_segments (root_resolved_node_id,
- path.get_mappings ().get_hirid (),
- path.get_segments (), 0, translated,
- path.get_mappings (), path.get_locus ());
+ translated
+ = resolve_segments (root_resolved_node_id,
+ path.get_mappings ().get_hirid (),
+ path.get_segments (), 0, translated,
+ path.get_mappings (), path.get_locus (), false);
return;
}
@@ -356,12 +367,14 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path)
translated
= resolve_segments (root_resolved_node_id,
path.get_mappings ().get_hirid (), path.get_segments (),
- 0, translated, path.get_mappings (), path.get_locus ());
+ 0, translated, path.get_mappings (), path.get_locus (),
+ false);
}
TyTy::BaseType *
TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
- NodeId *root_resolved_node_id)
+ NodeId *root_resolved_node_id,
+ bool *wasBigSelf)
{
TyTy::BaseType *root_tyty = nullptr;
*offset = 0;
@@ -403,6 +416,9 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
return root_tyty;
}
+ if (seg->is_ident_only () && seg->as_string () == "Self")
+ *wasBigSelf = true;
+
// node back to HIR
tl::optional<HirId> hid = mappings.lookup_node_to_hir (ref_node_id);
if (!hid.has_value ())
@@ -509,12 +525,57 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
return root_tyty;
}
+bool
+TypeCheckType::resolve_associated_type (const std::string &search,
+ TypeCheckBlockContextItem &ctx,
+ TyTy::BaseType **result)
+{
+ if (ctx.is_trait_block ())
+ {
+ HIR::Trait &trait = ctx.get_trait ();
+ for (auto &item : trait.get_trait_items ())
+ {
+ if (item->get_item_kind () != HIR::TraitItem::TraitItemKind::TYPE)
+ continue;
+
+ if (item->trait_identifier () == search)
+ {
+ HirId item_id = item->get_mappings ().get_hirid ();
+ if (query_type (item_id, result))
+ return true;
+ }
+ }
+
+ // FIXME
+ // query any parent trait?
+
+ return false;
+ }
+
+ // look for any segment in here which matches
+ HIR::ImplBlock &block = ctx.get_impl_block ();
+ for (auto &item : block.get_impl_items ())
+ {
+ if (item->get_impl_item_type () != HIR::ImplItem::TYPE_ALIAS)
+ continue;
+
+ if (item->get_impl_item_name () == search)
+ {
+ HirId item_id = item->get_impl_mappings ().get_hirid ();
+ if (query_type (item_id, result))
+ return true;
+ }
+ }
+
+ return false;
+}
+
TyTy::BaseType *
TypeCheckType::resolve_segments (
NodeId root_resolved_node_id, HirId expr_id,
std::vector<std::unique_ptr<HIR::TypePathSegment>> &segments, size_t offset,
TyTy::BaseType *tyseg, const Analysis::NodeMapping &expr_mappings,
- location_t expr_locus)
+ location_t expr_locus, bool tySegIsBigSelf)
{
NodeId resolved_node_id = root_resolved_node_id;
TyTy::BaseType *prev_segment = tyseg;
@@ -527,66 +588,84 @@ TypeCheckType::resolve_segments (
bool probe_bounds = true;
bool probe_impls = !reciever_is_generic;
bool ignore_mandatory_trait_items = !reciever_is_generic;
+ bool first_segment = i == offset;
+ bool selfResolveOk = false;
- // probe the path is done in two parts one where we search impls if no
- // candidate is found then we search extensions from traits
- auto candidates
- = PathProbeType::Probe (prev_segment, seg->get_ident_segment (),
- probe_impls, false,
- ignore_mandatory_trait_items);
- if (candidates.size () == 0)
+ if (first_segment && tySegIsBigSelf && context->have_block_context ()
+ && context->peek_block_context ().is_impl_block ())
+ {
+ TypeCheckBlockContextItem ctx = context->peek_block_context ();
+ TyTy::BaseType *lookup = nullptr;
+ selfResolveOk
+ = resolve_associated_type (seg->as_string (), ctx, &lookup);
+ if (selfResolveOk)
+ {
+ prev_segment = tyseg;
+ tyseg = lookup;
+ }
+ }
+ if (!selfResolveOk)
{
- candidates
+ // probe the path is done in two parts one where we search impls if no
+ // candidate is found then we search extensions from traits
+ auto candidates
= PathProbeType::Probe (prev_segment, seg->get_ident_segment (),
- false, probe_bounds,
+ probe_impls, false,
ignore_mandatory_trait_items);
-
if (candidates.size () == 0)
{
- rust_error_at (
- seg->get_locus (),
- "failed to resolve path segment using an impl Probe");
+ candidates
+ = PathProbeType::Probe (prev_segment, seg->get_ident_segment (),
+ false, probe_bounds,
+ ignore_mandatory_trait_items);
+ if (candidates.size () == 0)
+ {
+ rust_error_at (
+ seg->get_locus (),
+ "failed to resolve path segment using an impl Probe");
+ return new TyTy::ErrorType (expr_id);
+ }
+ }
+
+ if (candidates.size () > 1)
+ {
+ ReportMultipleCandidateError::Report (candidates,
+ seg->get_ident_segment (),
+ seg->get_locus ());
return new TyTy::ErrorType (expr_id);
}
- }
- if (candidates.size () > 1)
- {
- ReportMultipleCandidateError::Report (candidates,
- seg->get_ident_segment (),
- seg->get_locus ());
- return new TyTy::ErrorType (expr_id);
- }
+ auto &candidate = *candidates.begin ();
+ prev_segment = tyseg;
+ tyseg = candidate.ty;
- auto &candidate = *candidates.begin ();
- prev_segment = tyseg;
- tyseg = candidate.ty;
+ if (candidate.is_enum_candidate ())
+ {
+ TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyseg);
+ auto last_variant = adt->get_variants ();
+ TyTy::VariantDef *variant = last_variant.back ();
- if (candidate.is_enum_candidate ())
- {
- TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyseg);
- auto last_variant = adt->get_variants ();
- TyTy::VariantDef *variant = last_variant.back ();
-
- rich_location richloc (line_table, seg->get_locus ());
- richloc.add_fixit_replace ("not a type");
-
- rust_error_at (richloc, ErrorCode::E0573,
- "expected type, found variant of %<%s::%s%>",
- adt->get_name ().c_str (),
- variant->get_identifier ().c_str ());
- return new TyTy::ErrorType (expr_id);
- }
+ rich_location richloc (line_table, seg->get_locus ());
+ richloc.add_fixit_replace ("not a type");
- if (candidate.is_impl_candidate ())
- {
- resolved_node_id
- = candidate.item.impl.impl_item->get_impl_mappings ().get_nodeid ();
- }
- else
- {
- resolved_node_id
- = candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
+ rust_error_at (richloc, ErrorCode::E0573,
+ "expected type, found variant of %<%s::%s%>",
+ adt->get_name ().c_str (),
+ variant->get_identifier ().c_str ());
+ return new TyTy::ErrorType (expr_id);
+ }
+
+ if (candidate.is_impl_candidate ())
+ {
+ resolved_node_id
+ = candidate.item.impl.impl_item->get_impl_mappings ()
+ .get_nodeid ();
+ }
+ else
+ {
+ resolved_node_id
+ = candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
+ }
}
if (seg->is_generic_segment ())
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h
index 814903f..10acde0 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.h
@@ -82,13 +82,18 @@ private:
{}
TyTy::BaseType *resolve_root_path (HIR::TypePath &path, size_t *offset,
- NodeId *root_resolved_node_id);
+ NodeId *root_resolved_node_id,
+ bool *wasBigSelf);
TyTy::BaseType *resolve_segments (
NodeId root_resolved_node_id, HirId expr_id,
std::vector<std::unique_ptr<HIR::TypePathSegment>> &segments, size_t offset,
TyTy::BaseType *tyseg, const Analysis::NodeMapping &expr_mappings,
- location_t expr_locus);
+ location_t expr_locus, bool tySegIsBigSelf);
+
+ bool resolve_associated_type (const std::string &search,
+ TypeCheckBlockContextItem &ctx,
+ TyTy::BaseType **result);
TyTy::BaseType *translated;
};
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index 5a78f62..65c929a 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -82,6 +82,37 @@ private:
Item item;
};
+class TypeCheckBlockContextItem
+{
+public:
+ enum ItemType
+ {
+ IMPL_BLOCK,
+ TRAIT
+ };
+
+ TypeCheckBlockContextItem (HIR::ImplBlock *block);
+ TypeCheckBlockContextItem (HIR::Trait *trait);
+
+ bool is_impl_block () const;
+ bool is_trait_block () const;
+
+ HIR::ImplBlock &get_impl_block ();
+ HIR::Trait &get_trait ();
+
+private:
+ union Item
+ {
+ HIR::ImplBlock *block;
+ HIR::Trait *trait;
+
+ Item (HIR::ImplBlock *block);
+ Item (HIR::Trait *trait);
+ };
+ ItemType type;
+ Item item;
+};
+
/**
* Interned lifetime representation in TyTy
*
@@ -154,6 +185,12 @@ public:
void push_return_type (TypeCheckContextItem item,
TyTy::BaseType *return_type);
void pop_return_type ();
+
+ bool have_block_context () const;
+ TypeCheckBlockContextItem peek_block_context ();
+ void push_block_context (TypeCheckBlockContextItem item);
+ void pop_block_context ();
+
void iterate (std::function<bool (HirId, TyTy::BaseType *)> cb);
bool have_loop_context () const;
@@ -245,6 +282,7 @@ private:
std::vector<std::pair<TypeCheckContextItem, TyTy::BaseType *>>
return_type_stack;
std::vector<TyTy::BaseType *> loop_type_stack;
+ std::vector<TypeCheckBlockContextItem> block_stack;
std::map<DefId, TraitReference> trait_context;
std::map<HirId, TyTy::BaseType *> receiver_context;
std::map<HirId, AssociatedImplTrait> associated_impl_traits;
diff --git a/gcc/rust/typecheck/rust-typecheck-context.cc b/gcc/rust/typecheck/rust-typecheck-context.cc
index 418abd3..b37be49 100644
--- a/gcc/rust/typecheck/rust-typecheck-context.cc
+++ b/gcc/rust/typecheck/rust-typecheck-context.cc
@@ -177,6 +177,32 @@ TypeCheckContext::peek_context ()
return return_type_stack.back ().first;
}
+bool
+TypeCheckContext::have_block_context () const
+{
+ return !block_stack.empty ();
+}
+
+TypeCheckBlockContextItem
+TypeCheckContext::peek_block_context ()
+{
+ rust_assert (!block_stack.empty ());
+ return block_stack.back ();
+}
+
+void
+TypeCheckContext::push_block_context (TypeCheckBlockContextItem block)
+{
+ block_stack.push_back (block);
+}
+
+void
+TypeCheckContext::pop_block_context ()
+{
+ rust_assert (!block_stack.empty ());
+ block_stack.pop_back ();
+}
+
void
TypeCheckContext::iterate (std::function<bool (HirId, TyTy::BaseType *)> cb)
{
@@ -802,5 +828,43 @@ TypeCheckContextItem::get_defid () const
return UNKNOWN_DEFID;
}
+// TypeCheckBlockContextItem
+
+TypeCheckBlockContextItem::Item::Item (HIR::ImplBlock *b) : block (b) {}
+
+TypeCheckBlockContextItem::Item::Item (HIR::Trait *t) : trait (t) {}
+
+TypeCheckBlockContextItem::TypeCheckBlockContextItem (HIR::ImplBlock *block)
+ : type (TypeCheckBlockContextItem::ItemType::IMPL_BLOCK), item (block)
+{}
+
+TypeCheckBlockContextItem::TypeCheckBlockContextItem (HIR::Trait *trait)
+ : type (TypeCheckBlockContextItem::ItemType::TRAIT), item (trait)
+{}
+
+bool
+TypeCheckBlockContextItem::is_impl_block () const
+{
+ return type == IMPL_BLOCK;
+}
+
+bool
+TypeCheckBlockContextItem::is_trait_block () const
+{
+ return type == TRAIT;
+}
+
+HIR::ImplBlock &
+TypeCheckBlockContextItem::get_impl_block ()
+{
+ return *(item.block);
+}
+
+HIR::Trait &
+TypeCheckBlockContextItem::get_trait ()
+{
+ return *(item.trait);
+}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/testsuite/rust/compile/issue-2907.rs b/gcc/testsuite/rust/compile/issue-2907.rs
new file mode 100644
index 0000000..1af843f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2907.rs
@@ -0,0 +1,33 @@
+#![feature(lang_items)]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+pub trait Bar {}
+
+pub trait Foo {
+ type Ty;
+
+ fn foo(self) -> Self::Ty;
+}
+
+impl<B: Bar> Foo for B {
+ type Ty = u32;
+
+ fn foo(self) -> Self::Ty {
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+ 14
+ }
+}
+
+struct Qux;
+
+impl Bar for Qux {}
+
+fn main() {
+ let a = Qux;
+ a.foo();
+
+ let b = Qux;
+ Foo::foo(b);
+}
diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude
index b282f05..00ac704 100644
--- a/gcc/testsuite/rust/compile/nr2/exclude
+++ b/gcc/testsuite/rust/compile/nr2/exclude
@@ -205,4 +205,5 @@ issue-2953-2.rs
issue-1773.rs
issue-2905-1.rs
issue-2905-2.rs
+issue-2907.rs
# please don't delete the trailing newline