Skip to content

Commit b37877c

Browse files
committed
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 7a0cde9 commit b37877c

File tree

5 files changed

+47
-28
lines changed

5 files changed

+47
-28
lines changed

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -699,10 +699,15 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
699699
LifetimeName::Param(def_id) => {
700700
self.resolve_lifetime_ref(def_id, lt);
701701
}
702-
LifetimeName::Error => {}
703-
LifetimeName::ImplicitObjectLifetimeDefault
704-
| LifetimeName::Infer
705-
| LifetimeName::Static => {
702+
LifetimeName::Infer | LifetimeName::Error => {
703+
// We don't check for explicit `'_` lifetimes because we'll already have an
704+
// explicit error from late resolution explaining `use<'_>` is invalid.
705+
self.tcx.dcx().span_delayed_bug(
706+
lt.ident.span,
707+
"found infer or error lifetime but no prior error",
708+
);
709+
}
710+
LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Static => {
706711
self.tcx.dcx().emit_err(errors::BadPreciseCapture {
707712
span: lt.ident.span,
708713
kind: "lifetime",

compiler/rustc_resolve/src/late.rs

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

11181118
fn visit_precise_capturing_arg(&mut self, arg: &'ast PreciseCapturingArg) {
11191119
match arg {
1120+
PreciseCapturingArg::Lifetime(lt) if lt.ident.name == kw::UnderscoreLifetime => {
1121+
// We account for `+ use<'_>` explicitly to avoid providing an invalid suggestion
1122+
// for `+ use<'static>`.
1123+
let outer_failures = take(&mut self.diag_metadata.current_elision_failures);
1124+
visit::walk_precise_capturing_arg(self, arg);
1125+
let elision_failures =
1126+
replace(&mut self.diag_metadata.current_elision_failures, outer_failures);
1127+
if !elision_failures.is_empty() {
1128+
self.report_missing_lifetime_specifiers(elision_failures, None, true);
1129+
}
1130+
return;
1131+
}
11201132
// Lower the lifetime regularly; we'll resolve the lifetime and check
11211133
// it's a parameter later on in HIR lowering.
11221134
PreciseCapturingArg::Lifetime(_) => {}
@@ -1877,7 +1889,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
18771889
}
18781890
}
18791891
self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
1880-
self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
1892+
self.report_missing_lifetime_specifiers(vec![missing_lifetime], None, false);
18811893
}
18821894

18831895
#[instrument(level = "debug", skip(self))]
@@ -2097,7 +2109,11 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
20972109
LifetimeElisionCandidate::Ignore,
20982110
);
20992111
}
2100-
self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
2112+
self.report_missing_lifetime_specifiers(
2113+
vec![missing_lifetime],
2114+
None,
2115+
false,
2116+
);
21012117
break;
21022118
}
21032119
LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstParamTy => {}
@@ -2220,7 +2236,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
22202236
replace(&mut self.diag_metadata.current_elision_failures, outer_failures);
22212237
if !elision_failures.is_empty() {
22222238
let Err(failure_info) = elision_lifetime else { bug!() };
2223-
self.report_missing_lifetime_specifiers(elision_failures, Some(failure_info));
2239+
self.report_missing_lifetime_specifiers(elision_failures, Some(failure_info), false);
22242240
}
22252241
}
22262242

compiler/rustc_resolve/src/late/diagnostics.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -3032,6 +3032,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
30323032
&mut self,
30333033
lifetime_refs: Vec<MissingLifetime>,
30343034
function_param_lifetimes: Option<(Vec<MissingLifetime>, Vec<ElisionFnParameter>)>,
3035+
in_precise_capture: bool,
30353036
) -> ErrorGuaranteed {
30363037
let num_lifetimes: usize = lifetime_refs.iter().map(|lt| lt.count).sum();
30373038
let spans: Vec<_> = lifetime_refs.iter().map(|lt| lt.span).collect();
@@ -3043,14 +3044,22 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
30433044
"missing lifetime specifier{}",
30443045
pluralize!(num_lifetimes)
30453046
);
3046-
self.add_missing_lifetime_specifiers_label(
3047-
&mut err,
3048-
lifetime_refs,
3049-
function_param_lifetimes,
3050-
);
3047+
if in_precise_capture {
3048+
err.note(
3049+
"this function's return type specifies a borrowed `use<'_>` with an elided \
3050+
lifetime, but the lifetime cannot be derived from the arguments",
3051+
);
3052+
} else {
3053+
self.add_missing_lifetime_specifiers_label(
3054+
&mut err,
3055+
lifetime_refs,
3056+
function_param_lifetimes,
3057+
);
3058+
}
30513059
err.emit()
30523060
}
30533061

3062+
#[tracing::instrument(skip(self, err), level = "info")]
30543063
fn add_missing_lifetime_specifiers_label(
30553064
&mut self,
30563065
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-15
Original file line numberDiff line numberDiff line change
@@ -2,35 +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
5+
| ^^
96
|
10-
LL | fn no_elided_lt() -> impl Sized + use<'static> {}
11-
| ~~~~~~~
7+
= note: this function's return type specifies a borrowed `use<'_>` with an elided lifetime, but the lifetime cannot be derived from the arguments
128

139
error[E0261]: use of undeclared lifetime name `'missing`
14-
--> $DIR/bad-lifetimes.rs:8:37
10+
--> $DIR/bad-lifetimes.rs:7:37
1511
|
1612
LL | fn missing_lt() -> impl Sized + use<'missing> {}
1713
| - ^^^^^^^^ undeclared lifetime
1814
| |
1915
| help: consider introducing lifetime `'missing` here: `<'missing>`
2016

21-
error: expected lifetime parameter in `use<...>` precise captures list, found `'_`
22-
--> $DIR/bad-lifetimes.rs:1:39
23-
|
24-
LL | fn no_elided_lt() -> impl Sized + use<'_> {}
25-
| ^^
26-
2717
error: expected lifetime parameter in `use<...>` precise captures list, found `'static`
28-
--> $DIR/bad-lifetimes.rs:5:36
18+
--> $DIR/bad-lifetimes.rs:4:36
2919
|
3020
LL | fn static_lt() -> impl Sized + use<'static> {}
3121
| ^^^^^^^
3222

33-
error: aborting due to 4 previous errors
23+
error: aborting due to 3 previous errors
3424

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

0 commit comments

Comments
 (0)