From: Owen Avery <[email protected]>
gcc/rust/ChangeLog:
* resolve/rust-default-resolver.cc (DefaultResolver::visit): Use
visit_impl_type to visit the self types of impl blocks.
* resolve/rust-default-resolver.h
(DefaultResolver::visit_impl_type): New member function
declaration.
* resolve/rust-late-name-resolver-2.0.cc (Late::Late):
Initialize member variable block_big_self.
(Late::visit_impl_type): New member function definition.
(Late::visit): Check for Self while inside impl block self
types.
* resolve/rust-late-name-resolver-2.0.h (Late::visit_impl_type):
New member function.
(Late::block_big_self): New member variable.
gcc/testsuite/ChangeLog:
* rust/compile/issue-3671.rs: Remove usage of Self.
* rust/compile/nr2/exclude: Remove issue-3671.rs.
* rust/compile/self-in-impl.rs: New test.
Signed-off-by: Owen Avery <[email protected]>
---
gcc/rust/resolve/rust-default-resolver.cc | 4 ++--
gcc/rust/resolve/rust-default-resolver.h | 1 +
.../resolve/rust-late-name-resolver-2.0.cc | 22 ++++++++++++++++++-
.../resolve/rust-late-name-resolver-2.0.h | 4 ++++
gcc/testsuite/rust/compile/issue-3671.rs | 2 +-
gcc/testsuite/rust/compile/nr2/exclude | 1 -
gcc/testsuite/rust/compile/self-in-impl.rs | 17 ++++++++++++++
7 files changed, 46 insertions(+), 5 deletions(-)
create mode 100644 gcc/testsuite/rust/compile/self-in-impl.rs
diff --git a/gcc/rust/resolve/rust-default-resolver.cc
b/gcc/rust/resolve/rust-default-resolver.cc
index 12f6e1c8334..a4793c04870 100644
--- a/gcc/rust/resolve/rust-default-resolver.cc
+++ b/gcc/rust/resolve/rust-default-resolver.cc
@@ -109,7 +109,7 @@ DefaultResolver::visit (AST::InherentImpl &impl)
visit (generic);
if (impl.has_where_clause ())
visit (impl.get_where_clause ());
- visit (impl.get_type ());
+ visit_impl_type (impl.get_type ());
ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_inner);
};
@@ -135,7 +135,7 @@ DefaultResolver::visit (AST::TraitImpl &impl)
visit (generic);
if (impl.has_where_clause ())
visit (impl.get_where_clause ());
- visit (impl.get_type ());
+ visit_impl_type (impl.get_type ());
visit (impl.get_trait_path ());
ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_inner);
diff --git a/gcc/rust/resolve/rust-default-resolver.h
b/gcc/rust/resolve/rust-default-resolver.h
index 639e87113d4..f500d9018f2 100644
--- a/gcc/rust/resolve/rust-default-resolver.h
+++ b/gcc/rust/resolve/rust-default-resolver.h
@@ -51,6 +51,7 @@ public:
void visit (AST::Trait &) override;
// used to handle Self insertion in TopLevel
virtual void maybe_insert_big_self (AST::Impl &) {}
+ virtual void visit_impl_type (AST::Type &type) { visit (type); }
void visit (AST::InherentImpl &) override;
void visit (AST::TraitImpl &) override;
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
index 062c6f2d0b1..99e79868246 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -34,7 +34,7 @@ namespace Rust {
namespace Resolver2_0 {
Late::Late (NameResolutionContext &ctx)
- : DefaultResolver (ctx), funny_error (false)
+ : DefaultResolver (ctx), funny_error (false), block_big_self (false)
{}
static NodeId
@@ -473,6 +473,16 @@ Late::visit (AST::PathInExpression &expr)
Definition (resolved->get_node_id ()));
}
+void
+Late::visit_impl_type (AST::Type &type)
+{
+ // TODO: does this have to handle reentrancy?
+ rust_assert (!block_big_self);
+ block_big_self = true;
+ visit (type);
+ block_big_self = false;
+}
+
void
Late::visit (AST::TypePath &type)
{
@@ -483,6 +493,16 @@ Late::visit (AST::TypePath &type)
DefaultResolver::visit (type);
+ // prevent "impl Self {}" and similar
+ if (type.get_segments ().size () == 1
+ && !type.get_segments ().front ()->is_lang_item ()
+ && type.get_segments ().front ()->is_big_self_seg () && block_big_self)
+ {
+ rust_error_at (type.get_locus (),
+ "%<Self%> is not valid in the self type of an impl block");
+ return;
+ }
+
// this *should* mostly work
// TODO: make sure typepath-like path resolution (?) is working
auto resolved = ctx.resolve_path (type, Namespace::Types);
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h
b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
index 5b5637d48a9..ddf14ff4940 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
@@ -59,6 +59,7 @@ public:
void visit (AST::ContinueExpr &) override;
void visit (AST::LoopLabel &) override;
void visit (AST::PathInExpression &) override;
+ void visit_impl_type (AST::Type &) override;
void visit (AST::TypePath &) override;
void visit (AST::Visibility &) override;
void visit (AST::Trait &) override;
@@ -78,6 +79,9 @@ private:
void setup_builtin_types ();
bool funny_error;
+
+ /* used to prevent "impl Self {}", "impl (Self, i32) {}", etc */
+ bool block_big_self;
};
// TODO: Add missing mappings and data structures
diff --git a/gcc/testsuite/rust/compile/issue-3671.rs
b/gcc/testsuite/rust/compile/issue-3671.rs
index e800d536e02..8015653c0bc 100644
--- a/gcc/testsuite/rust/compile/issue-3671.rs
+++ b/gcc/testsuite/rust/compile/issue-3671.rs
@@ -1,2 +1,2 @@
-impl Self<0> {}
+impl Foo<0> {}
// { dg-error "could not resolve type path" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/rust/compile/nr2/exclude
b/gcc/testsuite/rust/compile/nr2/exclude
index 70c59f9abdd..dc8d5fbcc08 100644
--- a/gcc/testsuite/rust/compile/nr2/exclude
+++ b/gcc/testsuite/rust/compile/nr2/exclude
@@ -6,7 +6,6 @@ pub_restricted_2.rs
issue-2905-2.rs
torture/alt_patterns1.rs
torture/name_resolve1.rs
-issue-3671.rs
issue-3652.rs
issue-1487.rs
issue-2015.rs
diff --git a/gcc/testsuite/rust/compile/self-in-impl.rs
b/gcc/testsuite/rust/compile/self-in-impl.rs
new file mode 100644
index 00000000000..f888162a9f0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/self-in-impl.rs
@@ -0,0 +1,17 @@
+// { dg-additional-options "-frust-name-resolution-2.0" }
+
+// the error message here is what rustc >=1.66 emits
+// rustc <1.66 emits a "cycle detected" error when
+// trying to calculate the impl type
+//
+// since we aren't trying to match error messages too closely
+// and the >=1.66 error message is nicer
+// we may as well mimic that
+
+impl ((Self, i32)) {}
+// { dg-error ".Self. is not valid in the self" "" { target *-*-* } .-1 }
+
+trait Foo {}
+
+impl Foo for ((Self, i32)) {}
+// { dg-error ".Self. is not valid in the self" "" { target *-*-* } .-1 }
--
2.49.0