diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-11-23 11:54:25 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-23 11:54:25 +0000 |
commit | a41851dfb5bec6f40fd89db01ae75fee557306ee (patch) | |
tree | 56443032f9c5e6fbc5d2999926f2c9387c0dab56 | |
parent | a60de84632f5df6e4d54e2736bb7e04f9655af6a (diff) | |
parent | 88995535f6415e70d485e48006f606b90374bc75 (diff) | |
download | gcc-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.h | 37 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-bounds.h | 12 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-type.cc | 58 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/torture/associated_types1.rs | 14 |
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() {} |