aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-11-23 11:54:25 +0000
committerGitHub <noreply@github.com>2021-11-23 11:54:25 +0000
commita41851dfb5bec6f40fd89db01ae75fee557306ee (patch)
tree56443032f9c5e6fbc5d2999926f2c9387c0dab56
parenta60de84632f5df6e4d54e2736bb7e04f9655af6a (diff)
parent88995535f6415e70d485e48006f606b90374bc75 (diff)
downloadgcc-a41851dfb5bec6f40fd89db01ae75fee557306ee.zip
gcc-a41851dfb5bec6f40fd89db01ae75fee557306ee.tar.gz
gcc-a41851dfb5bec6f40fd89db01ae75fee557306ee.tar.bz2
Merge #813
813: Support QualifiedPathInType's within the same Trait r=philberty a=philberty The first implementation of qualified paths assumed that they only exist within trait-impl blocks. Trait impl blocks have the same canonical paths of <type as trait_path>::segment form but this type of path is more generic than this. see the commit for more details on the implementation. Fixes #739 Co-authored-by: Philip Herron <philip.herron@embecosm.com>
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.h37
-rw-r--r--gcc/rust/typecheck/rust-hir-type-bounds.h12
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.cc58
-rw-r--r--gcc/testsuite/rust/compile/torture/associated_types1.rs14
4 files changed, 73 insertions, 48 deletions
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h
index 2bcf79d..9e5b1e2 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.h
+++ b/gcc/rust/resolve/rust-ast-resolve-type.h
@@ -191,28 +191,25 @@ class ResolveRelativeTypePath : public ResolveTypeToCanonicalPath
using ResolveTypeToCanonicalPath::visit;
public:
- static NodeId go (AST::QualifiedPathInType &path, NodeId parent,
- bool canonicalize_type_with_generics)
+ static bool go (AST::QualifiedPathInType &path, NodeId parent,
+ bool canonicalize_type_with_generics)
{
+ // resolve the type and trait path
auto &qualified_path = path.get_qualified_path_type ();
CanonicalPath result = CanonicalPath::create_empty ();
if (!resolve_qual_seg (qualified_path, result))
- return UNKNOWN_NODEID;
+ return false;
- // resolve the associated impl
+ // resolve the associated impl if available but it can also be from a trait
+ // and this is allowed to fail
auto resolver = Resolver::get ();
NodeId projection_resolved_id = UNKNOWN_NODEID;
- if (!resolver->get_name_scope ().lookup (result, &projection_resolved_id))
+ if (resolver->get_name_scope ().lookup (result, &projection_resolved_id))
{
- rust_error_at (path.get_locus (),
- "failed to resolve associated path: %s",
- result.get ().c_str ());
-
- return UNKNOWN_NODEID;
+ // mark the resolution for this
+ resolver->insert_resolved_name (qualified_path.get_node_id (),
+ projection_resolved_id);
}
- // mark the resolution for this
- resolver->insert_resolved_name (qualified_path.get_node_id (),
- projection_resolved_id);
// qualified types are similar to other paths in that we cannot guarantee
// that we can resolve the path at name resolution. We must look up
@@ -224,18 +221,16 @@ public:
associated->accept_vis (o);
if (o.failure_flag)
- return UNKNOWN_NODEID;
+ return false;
for (auto &seg : path.get_segments ())
{
seg->accept_vis (o);
if (o.failure_flag)
- return UNKNOWN_NODEID;
+ return false;
}
- // we only return the projection id for now since we need the type system to
- // resolve the associated types in this path
- return projection_resolved_id;
+ return true;
}
private:
@@ -352,10 +347,8 @@ public:
void visit (AST::QualifiedPathInType &path) override
{
- resolved_node
- = ResolveRelativeTypePath::go (path, parent,
- canonicalize_type_with_generics);
- ok = resolved_node != UNKNOWN_NODEID;
+ ok = ResolveRelativeTypePath::go (path, parent,
+ canonicalize_type_with_generics);
}
void visit (AST::ArrayType &type) override;
diff --git a/gcc/rust/typecheck/rust-hir-type-bounds.h b/gcc/rust/typecheck/rust-hir-type-bounds.h
index 1ba6049..50cf34f 100644
--- a/gcc/rust/typecheck/rust-hir-type-bounds.h
+++ b/gcc/rust/typecheck/rust-hir-type-bounds.h
@@ -42,14 +42,22 @@ public:
static bool is_bound_satisfied_for_type (TyTy::BaseType *receiver,
TraitReference *ref)
{
+ for (auto &bound : receiver->get_specified_bounds ())
+ {
+ const TraitReference *b = bound.get ();
+ if (b->is_equal (*ref))
+ return true;
+ }
+
std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> bounds
= Probe (receiver);
for (auto &bound : bounds)
{
- TraitReference *b = bound.first;
- if (b == ref)
+ const TraitReference *b = bound.first;
+ if (b->is_equal (*ref))
return true;
}
+
return false;
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index 391ea40..cfe9652 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -140,29 +140,16 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path)
// does this type actually implement this type-bound?
if (!TypeBoundsProbe::is_bound_satisfied_for_type (root, trait_ref))
- 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 (path.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);
+ {
+ rust_error_at (qual_path_type.get_locus (),
+ "root does not satisfy specified trait-bound");
+ return;
+ }
std::unique_ptr<HIR::TypePathSegment> &item_seg
= path.get_associated_segment ();
-
const TraitItemReference *trait_item_ref = nullptr;
- ok
+ bool ok
= trait_ref->lookup_trait_item (item_seg->get_ident_segment ().as_string (),
&trait_item_ref);
if (!ok)
@@ -171,16 +158,39 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path)
return;
}
- // project
- lookup_associated->setup_associated_types ();
+ // this will be the placeholder from the trait but we may be able to project
+ // it based on the impl block
+ translated = trait_item_ref->get_tyty ();
+ // this is the associated generics we need to potentially apply
HIR::GenericArgs trait_generics = qual_path_type.trait_has_generic_args ()
? qual_path_type.get_trait_generic_args ()
: HIR::GenericArgs::create_empty ();
- translated = lookup_associated->get_projected_type (
- trait_item_ref, root, item_seg->get_mappings ().get_hirid (),
- trait_generics, item_seg->get_locus ());
+ // we need resolve to the impl block
+ NodeId impl_resolved_id = UNKNOWN_NODEID;
+ bool have_associated_impl = resolver->lookup_resolved_name (
+ qual_path_type.get_mappings ().get_nodeid (), &impl_resolved_id);
+ if (have_associated_impl)
+ {
+ HirId impl_block_id;
+ bool ok
+ = mappings->lookup_node_to_hir (path.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);
+
+ // project
+ lookup_associated->setup_associated_types ();
+ translated = lookup_associated->get_projected_type (
+ trait_item_ref, root, item_seg->get_mappings ().get_hirid (),
+ trait_generics, item_seg->get_locus ());
+ }
if (translated->get_kind () == TyTy::TypeKind::PLACEHOLDER)
{
diff --git a/gcc/testsuite/rust/compile/torture/associated_types1.rs b/gcc/testsuite/rust/compile/torture/associated_types1.rs
new file mode 100644
index 0000000..0d4b4c7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/associated_types1.rs
@@ -0,0 +1,14 @@
+pub trait Foo {
+ type A;
+
+ fn boo(&self) -> <Self as Foo>::A;
+ // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
+}
+
+fn foo2<I: Foo>(x: I) {
+ // { dg-warning "function is never used: .foo2." "" { target *-*-* } .-1 }
+ // { dg-warning "unused name .foo2." "" { target *-*-* } .-2 }
+ x.boo();
+}
+
+pub fn main() {}