Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 0b33708

Browse files
committedFeb 13, 2025
Emit single error for + use<'_> and don't suggest use<'static>
``` error[E0106]: missing lifetime specifier --> $DIR/bad-lifetimes.rs:1:39 | LL | fn no_elided_lt() -> impl Sized + use<'_> {} | ^^ expected named lifetime parameter | help: consider introducing a named lifetime parameter | LL | fn no_elided_lt<'a>() -> impl Sized + use<'a> {} | ++++ ~~ ``` Fix #134194.
1 parent ef148cd commit 0b33708

File tree

5 files changed

+47
-29
lines changed

5 files changed

+47
-29
lines changed
 

‎compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -657,10 +657,15 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
657657
LifetimeName::Param(def_id) => {
658658
self.resolve_lifetime_ref(def_id, lt);
659659
}
660-
LifetimeName::Error => {}
661-
LifetimeName::ImplicitObjectLifetimeDefault
662-
| LifetimeName::Infer
663-
| LifetimeName::Static => {
660+
LifetimeName::Infer | LifetimeName::Error => {
661+
// We don't check for explicit `'_` lifetimes because we'll already have an
662+
// explicit error from late resolution explaining `use<'_>` is invalid.
663+
self.tcx.dcx().span_delayed_bug(
664+
lt.ident.span,
665+
"found infer or error lifetime but no prior error",
666+
);
667+
}
668+
LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Static => {
664669
self.tcx.dcx().emit_err(errors::BadPreciseCapture {
665670
span: lt.ident.span,
666671
kind: "lifetime",

‎compiler/rustc_resolve/src/late.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -1132,6 +1132,18 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
11321132

11331133
fn visit_precise_capturing_arg(&mut self, arg: &'ast PreciseCapturingArg) {
11341134
match arg {
1135+
PreciseCapturingArg::Lifetime(lt) if lt.ident.name == kw::UnderscoreLifetime => {
1136+
// We account for `+ use<'_>` explicitly to avoid providing an invalid suggestion
1137+
// for `+ use<'static>`.
1138+
let outer_failures = take(&mut self.diag_metadata.current_elision_failures);
1139+
visit::walk_precise_capturing_arg(self, arg);
1140+
let elision_failures =
1141+
replace(&mut self.diag_metadata.current_elision_failures, outer_failures);
1142+
if !elision_failures.is_empty() {
1143+
self.report_missing_lifetime_specifiers(elision_failures, None, true);
1144+
}
1145+
return;
1146+
}
11351147
// Lower the lifetime regularly; we'll resolve the lifetime and check
11361148
// it's a parameter later on in HIR lowering.
11371149
PreciseCapturingArg::Lifetime(_) => {}
@@ -1884,7 +1896,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
18841896
}
18851897
}
18861898
self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
1887-
self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
1899+
self.report_missing_lifetime_specifiers(vec![missing_lifetime], None, false);
18881900
}
18891901

18901902
#[instrument(level = "debug", skip(self))]
@@ -2104,7 +2116,11 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
21042116
LifetimeElisionCandidate::Ignore,
21052117
);
21062118
}
2107-
self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
2119+
self.report_missing_lifetime_specifiers(
2120+
vec![missing_lifetime],
2121+
None,
2122+
false,
2123+
);
21082124
break;
21092125
}
21102126
LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstParamTy => {}
@@ -2227,7 +2243,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
22272243
replace(&mut self.diag_metadata.current_elision_failures, outer_failures);
22282244
if !elision_failures.is_empty() {
22292245
let Err(failure_info) = elision_lifetime else { bug!() };
2230-
self.report_missing_lifetime_specifiers(elision_failures, Some(failure_info));
2246+
self.report_missing_lifetime_specifiers(elision_failures, Some(failure_info), false);
22312247
}
22322248
}
22332249

‎compiler/rustc_resolve/src/late/diagnostics.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -3039,6 +3039,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
30393039
&mut self,
30403040
lifetime_refs: Vec<MissingLifetime>,
30413041
function_param_lifetimes: Option<(Vec<MissingLifetime>, Vec<ElisionFnParameter>)>,
3042+
in_precise_capture: bool,
30423043
) -> ErrorGuaranteed {
30433044
let num_lifetimes: usize = lifetime_refs.iter().map(|lt| lt.count).sum();
30443045
let spans: Vec<_> = lifetime_refs.iter().map(|lt| lt.span).collect();
@@ -3050,14 +3051,22 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
30503051
"missing lifetime specifier{}",
30513052
pluralize!(num_lifetimes)
30523053
);
3053-
self.add_missing_lifetime_specifiers_label(
3054-
&mut err,
3055-
lifetime_refs,
3056-
function_param_lifetimes,
3057-
);
3054+
if in_precise_capture {
3055+
err.note(
3056+
"cannot capture elided lifetime with `use<'_>` when there is no lifetime in scope \
3057+
to capture",
3058+
);
3059+
} else {
3060+
self.add_missing_lifetime_specifiers_label(
3061+
&mut err,
3062+
lifetime_refs,
3063+
function_param_lifetimes,
3064+
);
3065+
}
30583066
err.emit()
30593067
}
30603068

3069+
#[tracing::instrument(skip(self, err), level = "info")]
30613070
fn add_missing_lifetime_specifiers_label(
30623071
&mut self,
30633072
err: &mut Diag<'_>,

‎tests/ui/impl-trait/precise-capturing/bad-lifetimes.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
fn no_elided_lt() -> impl Sized + use<'_> {}
22
//~^ ERROR missing lifetime specifier
3-
//~| ERROR expected lifetime parameter in `use<...>` precise captures list, found `'_`
43

54
fn static_lt() -> impl Sized + use<'static> {}
65
//~^ ERROR expected lifetime parameter in `use<...>` precise captures list, found `'static`

‎tests/ui/impl-trait/precise-capturing/bad-lifetimes.stderr

+5-16
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,25 @@ error[E0106]: missing lifetime specifier
22
--> $DIR/bad-lifetimes.rs:1:39
33
|
44
LL | fn no_elided_lt() -> impl Sized + use<'_> {}
5-
| ^^ expected named lifetime parameter
6-
|
7-
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
8-
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values
9-
|
10-
LL - fn no_elided_lt() -> impl Sized + use<'_> {}
11-
LL + fn no_elided_lt() -> impl Sized + use<'static> {}
5+
| ^^
126
|
7+
= note: cannot capture elided lifetime with `use<'_>` when there is no lifetime in scope to capture
138

149
error[E0261]: use of undeclared lifetime name `'missing`
15-
--> $DIR/bad-lifetimes.rs:8:37
10+
--> $DIR/bad-lifetimes.rs:7:37
1611
|
1712
LL | fn missing_lt() -> impl Sized + use<'missing> {}
1813
| - ^^^^^^^^ undeclared lifetime
1914
| |
2015
| help: consider introducing lifetime `'missing` here: `<'missing>`
2116

22-
error: expected lifetime parameter in `use<...>` precise captures list, found `'_`
23-
--> $DIR/bad-lifetimes.rs:1:39
24-
|
25-
LL | fn no_elided_lt() -> impl Sized + use<'_> {}
26-
| ^^
27-
2817
error: expected lifetime parameter in `use<...>` precise captures list, found `'static`
29-
--> $DIR/bad-lifetimes.rs:5:36
18+
--> $DIR/bad-lifetimes.rs:4:36
3019
|
3120
LL | fn static_lt() -> impl Sized + use<'static> {}
3221
| ^^^^^^^
3322

34-
error: aborting due to 4 previous errors
23+
error: aborting due to 3 previous errors
3524

3625
Some errors have detailed explanations: E0106, E0261.
3726
For more information about an error, try `rustc --explain E0106`.

0 commit comments

Comments
 (0)
Failed to load comments.