From be566f11857f7f1f33854e01911fc46e861a2b25 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Fri, 18 Mar 2022 22:04:01 +0300 Subject: [PATCH] Return err instead of ICE --- compiler/rustc_resolve/src/late/lifetimes.rs | 25 +++++++++++-- src/test/ui/lifetimes/issue-95023.rs | 11 ++++++ src/test/ui/lifetimes/issue-95023.stderr | 38 ++++++++++++++++++++ src/tools/tidy/src/ui_tests.rs | 2 +- 4 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/lifetimes/issue-95023.rs create mode 100644 src/test/ui/lifetimes/issue-95023.stderr 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(&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(&self) -> Self::B<{N}>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the function: `{ }` + +error[E0407]: method `foo` is not a member of trait `Fn` + --> $DIR/issue-95023.rs:6:5 + | +LL | fn foo(&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(&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) {