From: Philip Herron <[email protected]>
When handling where clause items such as:
fn check<P>()
where
P: Deref,
P::Target: Marker
What happens is the first 'P' used to get resolved to a reference hir-id
item which meant that adding the bound to this position had no effect what
needed to occur was bind it to the parent which meant i used name resolution
to reverse lookup as a hack. This new mode for canonical gives us that
parent in the first place so we can just add the bound directly now so no
need for name resolution here
Fixes Rust-GCC/gccrs#4829
gcc/rust/ChangeLog:
* typecheck/rust-hir-type-check-type.cc (TypeCheckType::Resolve): new
mode
(TypeCheckType::visit): likewise
(ResolveWhereClauseItem::visit): remove nr usage
* typecheck/rust-hir-type-check-type.h: new mode
gcc/testsuite/ChangeLog:
* rust/compile/issue-4829-1.rs: New test.
* rust/compile/issue-4829-2.rs: New test.
Signed-off-by: Philip Herron <[email protected]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.
Commit on github:
https://github.com/Rust-GCC/gccrs/commit/2c764560d7c41f9aef6d69eb25777622d583eea1
The commit has been mentioned in the following issue(s):
- Rust-GCC/gccrs#4829: https://github.com/Rust-GCC/gccrs/issues/4829
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4840
.../typecheck/rust-hir-type-check-type.cc | 64 ++++---------------
gcc/rust/typecheck/rust-hir-type-check-type.h | 14 +++-
gcc/testsuite/rust/compile/issue-4829-1.rs | 23 +++++++
gcc/testsuite/rust/compile/issue-4829-2.rs | 18 ++++++
4 files changed, 66 insertions(+), 53 deletions(-)
create mode 100644 gcc/testsuite/rust/compile/issue-4829-1.rs
create mode 100644 gcc/testsuite/rust/compile/issue-4829-2.rs
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc
b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index 112aba4c0..e44221a7e 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -61,17 +61,17 @@ TypeCheckResolveGenericArguments::visit
(HIR::TypePathSegmentGeneric &generic)
}
TyTy::BaseType *
-TypeCheckType::Resolve (HIR::Type &type)
+TypeCheckType::Resolve (HIR::Type &type, ResolutionMode mode)
{
// is it already resolved?
auto context = TypeCheckContext::get ();
TyTy::BaseType *resolved = nullptr;
bool already_resolved
= context->lookup_type (type.get_mappings ().get_hirid (), &resolved);
- if (already_resolved)
+ if (already_resolved && mode == ResolutionMode::REFERENCE)
return resolved;
- TypeCheckType resolver (type.get_mappings ().get_hirid ());
+ TypeCheckType resolver (type.get_mappings ().get_hirid (), mode);
type.accept_vis (resolver);
rust_assert (resolver.translated != nullptr);
resolver.context->insert_type (type.get_mappings (), resolver.translated);
@@ -153,9 +153,14 @@ TypeCheckType::visit (HIR::TypePath &path)
return;
}
- TyTy::BaseType *path_type = root->clone ();
- path_type->set_ref (path.get_mappings ().get_hirid ());
- context->insert_implicit_type (path.get_mappings ().get_hirid (), path_type);
+ TyTy::BaseType *path_type = root;
+ if (mode == ResolutionMode::REFERENCE)
+ {
+ path_type = root->clone ();
+ path_type->set_ref (path.get_mappings ().get_hirid ());
+ context->insert_implicit_type (path.get_mappings ().get_hirid (),
+ path_type);
+ }
bool fully_resolved = offset >= path.get_segments ().size ();
if (fully_resolved)
@@ -1048,7 +1053,9 @@ ResolveWhereClauseItem::visit
(HIR::TypeBoundWhereClauseItem &item)
}
auto &binding_type_path = item.get_bound_type ();
- TyTy::BaseType *binding = TypeCheckType::Resolve (binding_type_path);
+ TyTy::BaseType *binding
+ = TypeCheckType::Resolve (binding_type_path,
+ TypeCheckType::ResolutionMode::CANONICAL);
// FIXME double check there might be a trait cycle here see TypeParam
handling
@@ -1089,49 +1096,6 @@ ResolveWhereClauseItem::visit
(HIR::TypeBoundWhereClauseItem &item)
}
}
binding->inherit_bounds (specified_bounds);
-
- // When we apply these bounds we must lookup which type this binding
- // resolves to, as this is the type which will be used during resolution
- // of the block.
- NodeId ast_node_id = binding_type_path.get_mappings ().get_nodeid ();
-
- // then lookup the reference_node_id
- NodeId ref_node_id = UNKNOWN_NODEID;
-
- auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
-
- if (auto id = nr_ctx.lookup (ast_node_id, Resolver2_0::Namespace::Types))
- {
- ref_node_id = *id;
- }
- else
- {
- // FIXME
- rust_error_at (UNDEF_LOCATION,
- "Failed to lookup type reference for node: %s",
- binding_type_path.to_string ().c_str ());
- return;
- }
-
- // node back to HIR
- if (auto hid = mappings.lookup_node_to_hir (ref_node_id))
- {
- // the base reference for this name _must_ have a type set
- TyTy::BaseType *lookup;
- if (!context->lookup_type (*hid, &lookup))
- {
- rust_error_at (mappings.lookup_location (*hid),
- "Failed to resolve where-clause binding type: %s",
- binding_type_path.to_string ().c_str ());
- return;
- }
-
- // FIXME
- // rust_assert (binding->is_equal (*lookup));
- lookup->inherit_bounds (specified_bounds);
- return;
- }
- rust_error_at (UNDEF_LOCATION, "where-clause reverse lookup failure");
}
} // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h
b/gcc/rust/typecheck/rust-hir-type-check-type.h
index 27d2ae40a..9cc0fdbc3 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.h
@@ -46,7 +46,14 @@ private:
class TypeCheckType : public TypeCheckBase, public HIR::HIRTypeVisitor
{
public:
- static TyTy::BaseType *Resolve (HIR::Type &type);
+ enum class ResolutionMode
+ {
+ REFERENCE,
+ CANONICAL
+ };
+
+ static TyTy::BaseType *Resolve (HIR::Type &type, ResolutionMode mode
+ = ResolutionMode::REFERENCE);
void visit (HIR::BareFunctionType &fntype) override;
void visit (HIR::TupleType &tuple) override;
@@ -67,8 +74,8 @@ public:
void visit (HIR::TraitBound &bound) override {}
private:
- TypeCheckType (HirId id)
- : TypeCheckBase (), translated (new TyTy::ErrorType (id))
+ TypeCheckType (HirId id, ResolutionMode mode)
+ : TypeCheckBase (), translated (new TyTy::ErrorType (id)), mode (mode)
{}
TyTy::BaseType *resolve_root_path (HIR::TypePath &path, size_t *offset,
@@ -89,6 +96,7 @@ private:
bool ty_seg_is_big_self, TyTy::BaseType **result);
TyTy::BaseType *translated;
+ ResolutionMode mode;
};
class TypeResolveGenericParam : public TypeCheckBase
diff --git a/gcc/testsuite/rust/compile/issue-4829-1.rs
b/gcc/testsuite/rust/compile/issue-4829-1.rs
new file mode 100644
index 000000000..906beb596
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-4829-1.rs
@@ -0,0 +1,23 @@
+#![feature(lang_items, no_core)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+trait Iterator {
+ type Item;
+}
+
+trait IntoIterator {
+ type IntoIter;
+}
+
+pub struct FlattenCompat<I, U>(I, U);
+
+pub struct Flatten<I>
+where
+ I: Iterator,
+ I::Item: IntoIterator,
+{
+ pub inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>,
+}
diff --git a/gcc/testsuite/rust/compile/issue-4829-2.rs
b/gcc/testsuite/rust/compile/issue-4829-2.rs
new file mode 100644
index 000000000..fa3643ad8
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-4829-2.rs
@@ -0,0 +1,18 @@
+#![feature(lang_items, no_core)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+trait Deref {
+ type Target;
+}
+
+trait Marker {}
+
+pub fn check<P>()
+where
+ P: Deref,
+ P::Target: Marker,
+{
+}
base-commit: eb62f35f76d3070ca32f73c3b7663484b23cd1f8
--
2.55.0