Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 59 additions & 10 deletions compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ struct BoundVarContext<'a, 'tcx> {
rbv: &'a mut ResolveBoundVars,
disambiguator: &'a mut DisambiguatorState,
scope: ScopeRef<'a>,
opaque_capture_errors: RefCell<Option<OpaqueHigherRankedLifetimeCaptureErrors>>,
}

struct OpaqueHigherRankedLifetimeCaptureErrors {
bad_place: &'static str,
capture_spans: Vec<Span>,
decl_spans: Vec<Span>,
}

#[derive(Debug)]
Expand Down Expand Up @@ -253,6 +260,7 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou
rbv: &mut rbv,
scope: &Scope::Root { opt_parent_item: None },
disambiguator: &mut DisambiguatorState::new(),
opaque_capture_errors: RefCell::new(None),
};
match tcx.hir_owner_node(local_def_id) {
hir::OwnerNode::Item(item) => visitor.visit_item(item),
Expand Down Expand Up @@ -597,6 +605,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
})
});

self.emit_opaque_capture_errors();

let captures = captures.into_inner().into_iter().collect();
debug!(?captures);
self.rbv.opaque_captured_lifetimes.insert(opaque.def_id, captures);
Expand Down Expand Up @@ -1089,12 +1099,20 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>),
{
let BoundVarContext { tcx, rbv, disambiguator, .. } = self;
let mut this = BoundVarContext { tcx: *tcx, rbv, disambiguator, scope: &wrap_scope };
let nested_errors = RefCell::new(self.opaque_capture_errors.borrow_mut().take());
let mut this = BoundVarContext {
tcx: *tcx,
rbv,
disambiguator,
scope: &wrap_scope,
opaque_capture_errors: nested_errors,
};
let span = debug_span!("scope", scope = ?this.scope.debug_truncated());
{
let _enter = span.enter();
f(&mut this);
}
*self.opaque_capture_errors.borrow_mut() = this.opaque_capture_errors.into_inner();
}

fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec<ty::BoundVariableKind>) {
Expand Down Expand Up @@ -1424,21 +1442,52 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
};

let decl_span = self.tcx.def_span(lifetime_def_id);
let (span, label) = if capture_span != decl_span {
(capture_span, None)
} else {
let opaque_span = self.tcx.def_span(opaque_def_id);
(opaque_span, Some(opaque_span))
};
let opaque_span = self.tcx.def_span(opaque_def_id);

let mut errors = self.opaque_capture_errors.borrow_mut();
let error_info = errors.get_or_insert_with(|| OpaqueHigherRankedLifetimeCaptureErrors {
bad_place,
capture_spans: Vec::new(),
decl_spans: Vec::new(),
});

if error_info.capture_spans.is_empty() {
error_info.capture_spans.push(opaque_span);
}

if capture_span != decl_span && capture_span != opaque_span {
error_info.capture_spans.push(capture_span);
}

if !error_info.decl_spans.contains(&decl_span) {
error_info.decl_spans.push(decl_span);
}

// Errors should be emitted by `emit_opaque_capture_errors`.
Err(self.tcx.dcx().span_delayed_bug(capture_span, "opaque capture error not emitted"))
}

fn emit_opaque_capture_errors(&self) -> Option<ErrorGuaranteed> {
let errors = self.opaque_capture_errors.borrow_mut().take()?;
if errors.capture_spans.is_empty() {
return None;
}

let mut span = rustc_errors::MultiSpan::from_span(errors.capture_spans[0]);
for &capture_span in &errors.capture_spans[1..] {
span.push_span_label(capture_span, "");
}
let decl_span = rustc_errors::MultiSpan::from_spans(errors.decl_spans);

// Ensure that the parent of the def is an item, not HRTB
let guar = self.tcx.dcx().emit_err(errors::OpaqueCapturesHigherRankedLifetime {
span,
label,
label: Some(errors.capture_spans[0]),
decl_span,
bad_place,
bad_place: errors.bad_place,
});
Err(guar)

Some(guar)
}

#[instrument(level = "trace", skip(self, opaque_capture_scopes), ret)]
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1562,11 +1562,11 @@ pub(crate) struct UnconstrainedGenericParameter {
#[diag(hir_analysis_opaque_captures_higher_ranked_lifetime, code = E0657)]
pub(crate) struct OpaqueCapturesHigherRankedLifetime {
#[primary_span]
pub span: Span,
pub span: MultiSpan,
#[label]
pub label: Option<Span>,
#[note]
pub decl_span: Span,
pub decl_span: MultiSpan,
pub bad_place: &'static str,
}

Expand Down
8 changes: 4 additions & 4 deletions tests/ui/error-codes/E0657.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
--> $DIR/E0657.rs:10:35
--> $DIR/E0657.rs:10:27
|
LL | -> Box<dyn for<'a> Id<impl Lt<'a>>>
| ^^
| ^^^^^^^^--^ `impl Trait` implicitly captures all lifetimes in scope
|
note: lifetime declared here
--> $DIR/E0657.rs:10:20
Expand All @@ -11,10 +11,10 @@ LL | -> Box<dyn for<'a> Id<impl Lt<'a>>>
| ^^

error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
--> $DIR/E0657.rs:19:39
--> $DIR/E0657.rs:19:31
|
LL | -> Box<dyn for<'a> Id<impl Lt<'a>>>
| ^^
| ^^^^^^^^--^ `impl Trait` implicitly captures all lifetimes in scope
|
note: lifetime declared here
--> $DIR/E0657.rs:19:24
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
--> $DIR/higher-ranked-lifetime-capture-deduplication.rs:19:44
|
LL | fn f() -> impl for<'a, 'b> Trait<'a, Out = impl Sized + 'a + 'b> {
| ^^^^^^^^^^^^^--^^^--
| |
| `impl Trait` implicitly captures all lifetimes in scope
|
note: lifetime declared here
--> $DIR/higher-ranked-lifetime-capture-deduplication.rs:19:20
|
LL | fn f() -> impl for<'a, 'b> Trait<'a, Out = impl Sized + 'a + 'b> {
| ^^ ^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0657`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
--> $DIR/higher-ranked-lifetime-capture-deduplication.rs:19:44
|
LL | fn f() -> impl for<'a, 'b> Trait<'a, Out = impl Sized + 'a + 'b> {
| ^^^^^^^^^^^^^--^^^--
| |
| `impl Trait` implicitly captures all lifetimes in scope
|
note: lifetime declared here
--> $DIR/higher-ranked-lifetime-capture-deduplication.rs:19:20
|
LL | fn f() -> impl for<'a, 'b> Trait<'a, Out = impl Sized + 'a + 'b> {
| ^^ ^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0657`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//@revisions: edition2015 edition2024
//@[edition2015] edition:2015
//@[edition2024] edition:2024

trait Trait<'a> {
type Out;
fn call(&'a self) -> Self::Out;
}

struct X(());

impl<'a> Trait<'a> for X {
type Out = ();
fn call(&'a self) -> Self::Out {
()
}
}

fn f() -> impl for<'a, 'b> Trait<'a, Out = impl Sized + 'a + 'b> {
//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
X(())
}

fn main() {
let _ = f();
}
18 changes: 12 additions & 6 deletions tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ LL + fn d() -> impl Fn() -> (impl Debug + 'static) {
|

error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
--> $DIR/impl-fn-hrtb-bounds.rs:4:41
--> $DIR/impl-fn-hrtb-bounds.rs:4:28
|
LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) {
| ^^
| ^^^^^^^^^^^^^--
| |
| `impl Trait` implicitly captures all lifetimes in scope
|
note: lifetime declared here
--> $DIR/impl-fn-hrtb-bounds.rs:4:19
Expand All @@ -24,10 +26,12 @@ LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) {
| ^

error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
--> $DIR/impl-fn-hrtb-bounds.rs:9:52
--> $DIR/impl-fn-hrtb-bounds.rs:9:39
|
LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) {
| ^^
| ^^^^^^^^^^^^^--
| |
| `impl Trait` implicitly captures all lifetimes in scope
|
note: lifetime declared here
--> $DIR/impl-fn-hrtb-bounds.rs:9:20
Expand All @@ -36,10 +40,12 @@ LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) {
| ^^

error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
--> $DIR/impl-fn-hrtb-bounds.rs:14:52
--> $DIR/impl-fn-hrtb-bounds.rs:14:39
|
LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) {
| ^^
| ^^^^^^^^^^^^^--
| |
| `impl Trait` implicitly captures all lifetimes in scope
|
note: lifetime declared here
--> $DIR/impl-fn-hrtb-bounds.rs:14:20
Expand Down
6 changes: 4 additions & 2 deletions tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ LL | fn b() -> impl Fn() -> (impl Debug + Send) {
| + +

error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
--> $DIR/impl-fn-parsing-ambiguities.rs:4:40
--> $DIR/impl-fn-parsing-ambiguities.rs:4:27
|
LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ {
| ^^
| ^^^^^^^^^^^^^--
| |
| `impl Trait` implicitly captures all lifetimes in scope
|
note: lifetime declared here
--> $DIR/impl-fn-parsing-ambiguities.rs:4:19
Expand Down
6 changes: 4 additions & 2 deletions tests/ui/impl-trait/issues/issue-54895.edition2015.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
--> $DIR/issue-54895.rs:18:53
--> $DIR/issue-54895.rs:18:40
|
LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
| ^^
| ^^^^^^^^^^^^^--
| |
| `impl Trait` implicitly captures all lifetimes in scope
|
note: lifetime declared here
--> $DIR/issue-54895.rs:18:20
Expand Down
18 changes: 4 additions & 14 deletions tests/ui/impl-trait/issues/issue-54895.edition2024.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,16 @@ error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `imp
--> $DIR/issue-54895.rs:18:40
|
LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
| ^^^^^^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope
| ^^^^^^^^^^^^^--
| |
| `impl Trait` implicitly captures all lifetimes in scope
|
note: lifetime declared here
--> $DIR/issue-54895.rs:18:20
|
LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
| ^^

error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
--> $DIR/issue-54895.rs:18:53
|
LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
| ^^
|
note: lifetime declared here
--> $DIR/issue-54895.rs:18:20
|
LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
| ^^

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0657`.
1 change: 0 additions & 1 deletion tests/ui/impl-trait/issues/issue-54895.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ impl<'a> Trait<'a> for X {

fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
//[edition2024]~^^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
X(())
}

Expand Down
6 changes: 4 additions & 2 deletions tests/ui/impl-trait/issues/issue-67830.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
--> $DIR/issue-67830.rs:20:64
--> $DIR/issue-67830.rs:20:48
|
LL | fn test() -> impl for<'a> MyFn<&'a A, Output = impl Iterator + 'a> {
| ^^
| ^^^^^^^^^^^^^^^^--
| |
| `impl Trait` implicitly captures all lifetimes in scope
|
note: lifetime declared here
--> $DIR/issue-67830.rs:20:23
Expand Down
18 changes: 12 additions & 6 deletions tests/ui/impl-trait/issues/issue-88236-2.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
--> $DIR/issue-88236-2.rs:15:61
--> $DIR/issue-88236-2.rs:15:49
|
LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
| ^^
| ^^^^^^^^^^^^--
| |
| `impl Trait` implicitly captures all lifetimes in scope
|
note: lifetime declared here
--> $DIR/issue-88236-2.rs:15:28
Expand All @@ -11,10 +13,12 @@ LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
| ^^

error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
--> $DIR/issue-88236-2.rs:18:80
--> $DIR/issue-88236-2.rs:18:68
|
LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
| ^^
| ^^^^^^^^^^^^--
| |
| `impl Trait` implicitly captures all lifetimes in scope
|
note: lifetime declared here
--> $DIR/issue-88236-2.rs:18:47
Expand All @@ -23,10 +27,12 @@ LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Sen
| ^^

error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
--> $DIR/issue-88236-2.rs:23:78
--> $DIR/issue-88236-2.rs:23:66
|
LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
| ^^
| ^^^^^^^^^^^^--
| |
| `impl Trait` implicitly captures all lifetimes in scope
|
note: lifetime declared here
--> $DIR/issue-88236-2.rs:23:45
Expand Down
6 changes: 4 additions & 2 deletions tests/ui/impl-trait/issues/issue-88236.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
--> $DIR/issue-88236.rs:15:61
--> $DIR/issue-88236.rs:15:49
|
LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
| ^^
| ^^^^^^^^^^^^--
| |
| `impl Trait` implicitly captures all lifetimes in scope
|
note: lifetime declared here
--> $DIR/issue-88236.rs:15:28
Expand Down
Loading
Loading