about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_resolve/src/late/lifetimes.rs25
-rw-r--r--src/test/ui/lifetimes/issue-95023.rs11
-rw-r--r--src/test/ui/lifetimes/issue-95023.stderr38
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
4 files changed, 73 insertions, 3 deletions
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index ecdbe12c9ab..bcae735bb7e 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -1,3 +1,4 @@
+// ignore-tidy-filelength
 //! Name resolution for lifetimes.
 //!
 //! Name resolution for lifetimes follows *much* simpler rules than the
@@ -230,6 +231,10 @@ enum Scope<'a> {
         hir_id: hir::HirId,
 
         s: ScopeRef<'a>,
+
+        /// In some cases not allowing late bounds allows us to avoid ICEs.
+        /// This is almost ways set to true.
+        allow_late_bound: bool,
     },
 
     /// Lifetimes introduced by a fn are scoped to the call-site for that fn,
@@ -302,6 +307,7 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
                 scope_type,
                 hir_id,
                 s: _,
+                allow_late_bound,
             } => f
                 .debug_struct("Binder")
                 .field("lifetimes", lifetimes)
@@ -311,6 +317,7 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
                 .field("scope_type", scope_type)
                 .field("hir_id", hir_id)
                 .field("s", &"..")
+                .field("allow_late_bound", allow_late_bound)
                 .finish(),
             Scope::Body { id, s: _ } => {
                 f.debug_struct("Body").field("id", id).field("s", &"..").finish()
@@ -703,6 +710,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     track_lifetime_uses: true,
                     opaque_type_parent: false,
                     scope_type: BinderScopeType::Normal,
+                    allow_late_bound: true,
                 };
                 self.with(scope, move |_old_scope, this| {
                     intravisit::walk_fn(this, fk, fd, b, s, hir_id)
@@ -828,6 +836,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     track_lifetime_uses,
                     scope_type: BinderScopeType::Normal,
                     s: ROOT_SCOPE,
+                    allow_late_bound: false,
                 };
                 self.with(scope, |old_scope, this| {
                     this.check_lifetime_params(old_scope, &generics.params);
@@ -896,6 +905,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     track_lifetime_uses: true,
                     opaque_type_parent: false,
                     scope_type: BinderScopeType::Normal,
+                    allow_late_bound: true,
                 };
                 self.with(scope, |old_scope, this| {
                     // a bare fn has no bounds, so everything
@@ -1077,6 +1087,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                             track_lifetime_uses: true,
                             opaque_type_parent: false,
                             scope_type: BinderScopeType::Normal,
+                            allow_late_bound: false,
                         };
                         this.with(scope, |_old_scope, this| {
                             this.visit_generics(generics);
@@ -1097,6 +1108,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                         track_lifetime_uses: true,
                         opaque_type_parent: false,
                         scope_type: BinderScopeType::Normal,
+                        allow_late_bound: false,
                     };
                     self.with(scope, |_old_scope, this| {
                         let scope = Scope::TraitRefBoundary { s: this.scope };
@@ -1156,6 +1168,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     track_lifetime_uses: true,
                     opaque_type_parent: true,
                     scope_type: BinderScopeType::Normal,
+                    allow_late_bound: false,
                 };
                 self.with(scope, |old_scope, this| {
                     this.check_lifetime_params(old_scope, &generics.params);
@@ -1225,6 +1238,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     track_lifetime_uses: true,
                     opaque_type_parent: true,
                     scope_type: BinderScopeType::Normal,
+                    allow_late_bound: true,
                 };
                 self.with(scope, |old_scope, this| {
                     this.check_lifetime_params(old_scope, &generics.params);
@@ -1378,6 +1392,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                             track_lifetime_uses: true,
                             opaque_type_parent: false,
                             scope_type: BinderScopeType::Normal,
+                            allow_late_bound: true,
                         };
                         this.with(scope, |old_scope, this| {
                             this.check_lifetime_params(old_scope, &bound_generic_params);
@@ -1425,6 +1440,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     track_lifetime_uses: true,
                     opaque_type_parent: false,
                     scope_type,
+                    allow_late_bound: true,
                 };
                 self.with(scope, |_, this| {
                     intravisit::walk_param_bound(this, bound);
@@ -1477,6 +1493,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             track_lifetime_uses: true,
             opaque_type_parent: false,
             scope_type,
+            allow_late_bound: true,
         };
         self.with(scope, |old_scope, this| {
             this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params);
@@ -2180,6 +2197,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             opaque_type_parent: true,
             track_lifetime_uses: false,
             scope_type: BinderScopeType::Normal,
+            allow_late_bound: true,
         };
         self.with(scope, move |old_scope, this| {
             this.check_lifetime_params(old_scope, &generics.params);
@@ -2602,7 +2620,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         let mut scope = &*self.scope;
         let hir_id = loop {
             match scope {
-                Scope::Binder { hir_id, .. } => {
+                Scope::Binder { hir_id, allow_late_bound: true, .. } => {
                     break *hir_id;
                 }
                 Scope::ObjectLifetimeDefault { ref s, .. }
@@ -2611,8 +2629,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 | Scope::TraitRefBoundary { ref s, .. } => {
                     scope = *s;
                 }
-                Scope::Root | Scope::Body { .. } => {
+                Scope::Root
+                | Scope::Body { .. }
+                | Scope::Binder { allow_late_bound: false, .. } => {
                     // See issues #83907 and #83693. Just bail out from looking inside.
+                    // See the issue #95023 for not allowing late bound
                     self.tcx.sess.delay_span_bug(
                         rustc_span::DUMMY_SP,
                         "In fn_like_elision without appropriate scope above",
diff --git a/src/test/ui/lifetimes/issue-95023.rs b/src/test/ui/lifetimes/issue-95023.rs
new file mode 100644
index 00000000000..3fba8c00c57
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-95023.rs
@@ -0,0 +1,11 @@
+struct ErrorKind;
+struct Error(ErrorKind);
+impl Fn(&isize) for Error {
+    //~^ ERROR manual implementations of `Fn` are experimental [E0183]
+    //~^^ ERROR associated type bindings are not allowed here [E0229]
+    fn foo<const N: usize>(&self) -> Self::B<{N}>;
+    //~^ ERROR associated function in `impl` without body
+    //~^^ ERROR method `foo` is not a member of trait `Fn` [E0407]
+    //~^^^ ERROR associated type `B` not found for `Self` [E0220]
+}
+fn main() {}
diff --git a/src/test/ui/lifetimes/issue-95023.stderr b/src/test/ui/lifetimes/issue-95023.stderr
new file mode 100644
index 00000000000..35c3797c77a
--- /dev/null
+++ b/src/test/ui/lifetimes/issue-95023.stderr
@@ -0,0 +1,38 @@
+error: associated function in `impl` without body
+  --> $DIR/issue-95023.rs:6:5
+   |
+LL |     fn foo<const N: usize>(&self) -> Self::B<{N}>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                                  |
+   |                                                  help: provide a definition for the function: `{ <body> }`
+
+error[E0407]: method `foo` is not a member of trait `Fn`
+  --> $DIR/issue-95023.rs:6:5
+   |
+LL |     fn foo<const N: usize>(&self) -> Self::B<{N}>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `Fn`
+
+error[E0183]: manual implementations of `Fn` are experimental
+  --> $DIR/issue-95023.rs:3:6
+   |
+LL | impl Fn(&isize) for Error {
+   |      ^^^^^^^^^^ manual implementations of `Fn` are experimental
+   |
+   = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/issue-95023.rs:3:6
+   |
+LL | impl Fn(&isize) for Error {
+   |      ^^^^^^^^^^ associated type not allowed here
+
+error[E0220]: associated type `B` not found for `Self`
+  --> $DIR/issue-95023.rs:6:44
+   |
+LL |     fn foo<const N: usize>(&self) -> Self::B<{N}>;
+   |                                            ^ associated type `B` not found
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0183, E0220, E0229, E0407.
+For more information about an error, try `rustc --explain E0183`.
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 7b932b867f2..0e5e0c2616e 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -7,7 +7,7 @@ use std::path::Path;
 
 const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
-const ROOT_ENTRY_LIMIT: usize = 984;
+const ROOT_ENTRY_LIMIT: usize = 985;
 const ISSUES_ENTRY_LIMIT: usize = 2310;
 
 fn check_entries(path: &Path, bad: &mut bool) {