Skip to content

Commit c7d8ad5

Browse files
committed
Report "missing lifetime specifier" when an anonymous lifetime is used in bounds.
1 parent c318799 commit c7d8ad5

33 files changed

+317
-343
lines changed

compiler/rustc_error_codes/src/error_codes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,6 @@ E0633: include_str!("./error_codes/E0633.md"),
374374
E0634: include_str!("./error_codes/E0634.md"),
375375
E0635: include_str!("./error_codes/E0635.md"),
376376
E0636: include_str!("./error_codes/E0636.md"),
377-
E0637: include_str!("./error_codes/E0637.md"),
378377
E0638: include_str!("./error_codes/E0638.md"),
379378
E0639: include_str!("./error_codes/E0639.md"),
380379
E0641: include_str!("./error_codes/E0641.md"),
@@ -632,6 +631,7 @@ E0787: include_str!("./error_codes/E0787.md"),
632631
// E0629, // missing 'feature' (rustc_const_unstable)
633632
// E0630, // rustc_const_unstable attribute must be paired with stable/unstable
634633
// attribute
634+
// E0637, // merged into E0106
635635
E0640, // infer outlives requirements
636636
// E0645, // trait aliases not finished
637637
// E0694, // an unknown tool name found in scoped attributes

compiler/rustc_error_codes/src/error_codes/E0637.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
#### Note: this error code is no longer emitted by the compiler.
2+
13
`'_` lifetime name or `&T` without an explicit lifetime name has been used
24
on illegal place.
35

46
Erroneous code example:
57

6-
```compile_fail,E0106,E0637
8+
```compile_fail,E0106
79
fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str {
810
//^^ `'_` is a reserved lifetime name
911
if str1.len() > str2.len() {

compiler/rustc_resolve/src/late.rs

+90-125
Original file line numberDiff line numberDiff line change
@@ -224,11 +224,6 @@ enum LifetimeRibKind {
224224
/// For **Deprecated** cases, report an error.
225225
AnonymousCreateParameter(NodeId),
226226

227-
/// Give a hard error when either `&` or `'_` is written. Used to
228-
/// rule out things like `where T: Foo<'_>`. Does not imply an
229-
/// error on default object bounds (e.g., `Box<dyn Foo>`).
230-
AnonymousReportError,
231-
232227
/// Pass responsibility to `resolve_lifetime` code for all cases.
233228
AnonymousPassThrough(NodeId),
234229
}
@@ -881,40 +876,38 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
881876
debug!("visit_where_predicate {:?}", p);
882877
let previous_value =
883878
replace(&mut self.diagnostic_metadata.current_where_predicate, Some(p));
884-
self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
885-
if let WherePredicate::BoundPredicate(WhereBoundPredicate {
886-
ref bounded_ty,
887-
ref bounds,
888-
ref bound_generic_params,
889-
span: predicate_span,
890-
..
891-
}) = p
892-
{
893-
let span = if bound_generic_params.is_empty() {
894-
predicate_span.shrink_to_lo()
895-
} else {
896-
*predicate_span
897-
};
898-
this.with_generic_param_rib(
899-
&bound_generic_params,
900-
NormalRibKind,
901-
LifetimeRibKind::Generics {
902-
parent: bounded_ty.id,
903-
kind: LifetimeBinderKind::WhereBound,
904-
span,
905-
},
906-
|this| {
907-
this.visit_generic_param_vec(&bound_generic_params, false);
908-
this.visit_ty(bounded_ty);
909-
for bound in bounds {
910-
this.visit_param_bound(bound, BoundKind::Bound)
911-
}
912-
},
913-
);
879+
if let WherePredicate::BoundPredicate(WhereBoundPredicate {
880+
ref bounded_ty,
881+
ref bounds,
882+
ref bound_generic_params,
883+
span: predicate_span,
884+
..
885+
}) = p
886+
{
887+
let span = if bound_generic_params.is_empty() {
888+
predicate_span.shrink_to_lo()
914889
} else {
915-
visit::walk_where_predicate(this, p);
916-
}
917-
});
890+
*predicate_span
891+
};
892+
self.with_generic_param_rib(
893+
&bound_generic_params,
894+
NormalRibKind,
895+
LifetimeRibKind::Generics {
896+
parent: bounded_ty.id,
897+
kind: LifetimeBinderKind::WhereBound,
898+
span,
899+
},
900+
|this| {
901+
this.visit_generic_param_vec(&bound_generic_params, false);
902+
this.visit_ty(bounded_ty);
903+
for bound in bounds {
904+
this.visit_param_bound(bound, BoundKind::Bound)
905+
}
906+
},
907+
);
908+
} else {
909+
visit::walk_where_predicate(self, p);
910+
}
918911
self.diagnostic_metadata.current_where_predicate = previous_value;
919912
}
920913

@@ -1093,62 +1086,56 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
10931086
forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
10941087
}
10951088

1096-
self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
1097-
for param in params {
1098-
match param.kind {
1099-
GenericParamKind::Lifetime => {
1100-
for bound in &param.bounds {
1101-
this.visit_param_bound(bound, BoundKind::Bound);
1102-
}
1089+
for param in params {
1090+
match param.kind {
1091+
GenericParamKind::Lifetime => {
1092+
for bound in &param.bounds {
1093+
self.visit_param_bound(bound, BoundKind::Bound);
1094+
}
1095+
}
1096+
GenericParamKind::Type { ref default } => {
1097+
for bound in &param.bounds {
1098+
self.visit_param_bound(bound, BoundKind::Bound);
11031099
}
1104-
GenericParamKind::Type { ref default } => {
1105-
for bound in &param.bounds {
1106-
this.visit_param_bound(bound, BoundKind::Bound);
1107-
}
1108-
1109-
if let Some(ref ty) = default {
1110-
this.ribs[TypeNS].push(forward_ty_ban_rib);
1111-
this.ribs[ValueNS].push(forward_const_ban_rib);
1112-
this.visit_ty(ty);
1113-
forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap();
1114-
forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap();
1115-
}
11161100

1117-
// Allow all following defaults to refer to this type parameter.
1118-
forward_ty_ban_rib
1119-
.bindings
1120-
.remove(&Ident::with_dummy_span(param.ident.name));
1101+
if let Some(ref ty) = default {
1102+
self.ribs[TypeNS].push(forward_ty_ban_rib);
1103+
self.ribs[ValueNS].push(forward_const_ban_rib);
1104+
self.visit_ty(ty);
1105+
forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap();
1106+
forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap();
11211107
}
1122-
GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
1123-
// Const parameters can't have param bounds.
1124-
assert!(param.bounds.is_empty());
1125-
1126-
this.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind));
1127-
this.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind));
1128-
this.with_lifetime_rib(LifetimeRibKind::ConstGeneric, |this| {
1129-
this.visit_ty(ty)
1130-
});
1131-
this.ribs[TypeNS].pop().unwrap();
1132-
this.ribs[ValueNS].pop().unwrap();
1133-
1134-
if let Some(ref expr) = default {
1135-
this.ribs[TypeNS].push(forward_ty_ban_rib);
1136-
this.ribs[ValueNS].push(forward_const_ban_rib);
1137-
this.with_lifetime_rib(LifetimeRibKind::ConstGeneric, |this| {
1138-
this.resolve_anon_const(expr, IsRepeatExpr::No)
1139-
});
1140-
forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap();
1141-
forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap();
1142-
}
11431108

1144-
// Allow all following defaults to refer to this const parameter.
1145-
forward_const_ban_rib
1146-
.bindings
1147-
.remove(&Ident::with_dummy_span(param.ident.name));
1109+
// Allow all following defaults to refer to this type parameter.
1110+
forward_ty_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name));
1111+
}
1112+
GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
1113+
// Const parameters can't have param bounds.
1114+
assert!(param.bounds.is_empty());
1115+
1116+
self.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind));
1117+
self.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind));
1118+
self.with_lifetime_rib(LifetimeRibKind::ConstGeneric, |this| this.visit_ty(ty));
1119+
self.ribs[TypeNS].pop().unwrap();
1120+
self.ribs[ValueNS].pop().unwrap();
1121+
1122+
if let Some(ref expr) = default {
1123+
self.ribs[TypeNS].push(forward_ty_ban_rib);
1124+
self.ribs[ValueNS].push(forward_const_ban_rib);
1125+
self.with_lifetime_rib(LifetimeRibKind::ConstGeneric, |this| {
1126+
this.resolve_anon_const(expr, IsRepeatExpr::No)
1127+
});
1128+
forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap();
1129+
forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap();
11481130
}
1131+
1132+
// Allow all following defaults to refer to this const parameter.
1133+
forward_const_ban_rib
1134+
.bindings
1135+
.remove(&Ident::with_dummy_span(param.ident.name));
11491136
}
11501137
}
1151-
})
1138+
}
11521139
}
11531140

11541141
#[tracing::instrument(level = "debug", skip(self, work))]
@@ -1226,28 +1213,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
12261213
self.create_fresh_lifetime(lifetime.id, lifetime.ident, item_node_id);
12271214
return;
12281215
}
1229-
LifetimeRibKind::AnonymousReportError => {
1230-
let (msg, note) = if elided {
1231-
(
1232-
"`&` without an explicit lifetime name cannot be used here",
1233-
"explicit lifetime name needed here",
1234-
)
1235-
} else {
1236-
("`'_` cannot be used here", "`'_` is a reserved lifetime name")
1237-
};
1238-
rustc_errors::struct_span_err!(
1239-
self.r.session,
1240-
lifetime.ident.span,
1241-
E0637,
1242-
"{}",
1243-
msg,
1244-
)
1245-
.span_label(lifetime.ident.span, note)
1246-
.emit();
1247-
1248-
self.record_lifetime_res(lifetime.id, LifetimeRes::Error);
1249-
return;
1250-
}
12511216
LifetimeRibKind::AnonymousPassThrough(node_id) => {
12521217
self.record_lifetime_res(
12531218
lifetime.id,
@@ -1372,7 +1337,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
13721337
res = LifetimeRes::Anonymous { binder, elided: true };
13731338
break;
13741339
}
1375-
LifetimeRibKind::AnonymousReportError | LifetimeRibKind::Item => {
1340+
LifetimeRibKind::Item => {
13761341
// FIXME(cjgillot) This resolution is wrong, but this does not matter
13771342
// since these cases are erroneous anyway. Lifetime resolution should
13781343
// emit a "missing lifetime specifier" diagnostic.
@@ -2028,28 +1993,28 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
20281993
self.with_generic_param_rib(&generics.params, ItemRibKind(HasGenericParams::Yes), LifetimeRibKind::Generics { span: generics.span, parent: item_id, kind: LifetimeBinderKind::ImplBlock }, |this| {
20291994
// Dummy self type for better errors if `Self` is used in the trait path.
20301995
this.with_self_rib(Res::SelfTy { trait_: None, alias_to: None }, |this| {
2031-
this.with_lifetime_rib(LifetimeRibKind::AnonymousCreateParameter(item_id), |this| {
2032-
// Resolve the trait reference, if necessary.
2033-
this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
2034-
let item_def_id = this.r.local_def_id(item_id);
2035-
2036-
// Register the trait definitions from here.
2037-
if let Some(trait_id) = trait_id {
2038-
this.r.trait_impls.entry(trait_id).or_default().push(item_def_id);
2039-
}
1996+
// Resolve the trait reference, if necessary.
1997+
this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
1998+
let item_def_id = this.r.local_def_id(item_id);
1999+
2000+
// Register the trait definitions from here.
2001+
if let Some(trait_id) = trait_id {
2002+
this.r.trait_impls.entry(trait_id).or_default().push(item_def_id);
2003+
}
20402004

2041-
let item_def_id = item_def_id.to_def_id();
2042-
let res =
2043-
Res::SelfTy { trait_: trait_id, alias_to: Some((item_def_id, false)) };
2044-
this.with_self_rib(res, |this| {
2005+
let item_def_id = item_def_id.to_def_id();
2006+
let res =
2007+
Res::SelfTy { trait_: trait_id, alias_to: Some((item_def_id, false)) };
2008+
this.with_self_rib(res, |this| {
2009+
// Resolve the generic parameters.
2010+
this.visit_generics(generics);
2011+
this.with_lifetime_rib(LifetimeRibKind::AnonymousCreateParameter(item_id), |this| {
20452012
if let Some(trait_ref) = opt_trait_reference.as_ref() {
20462013
// Resolve type arguments in the trait path.
20472014
visit::walk_trait_ref(this, trait_ref);
20482015
}
20492016
// Resolve the self type.
20502017
this.visit_ty(self_type);
2051-
// Resolve the generic parameters.
2052-
this.visit_generics(generics);
20532018

20542019
// Resolve the items within the impl.
20552020
this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough(item_id),
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,58 @@
1-
error[E0637]: `&` without an explicit lifetime name cannot be used here
1+
error[E0106]: missing lifetime specifier
22
--> $DIR/const-param-elided-lifetime.rs:9:19
33
|
44
LL | struct A<const N: &u8>;
5-
| ^ explicit lifetime name needed here
5+
| ^ expected named lifetime parameter
6+
|
7+
help: consider introducing a named lifetime parameter
8+
|
9+
LL | struct A<'a, const N: &'a u8>;
10+
| +++ ++
611

7-
error[E0637]: `&` without an explicit lifetime name cannot be used here
12+
error[E0106]: missing lifetime specifier
813
--> $DIR/const-param-elided-lifetime.rs:14:15
914
|
1015
LL | impl<const N: &u8> A<N> {
11-
| ^ explicit lifetime name needed here
16+
| ^ expected named lifetime parameter
17+
|
18+
help: consider introducing a named lifetime parameter
19+
|
20+
LL | impl<'a, const N: &'a u8> A<N> {
21+
| +++ ++
1222

13-
error[E0637]: `&` without an explicit lifetime name cannot be used here
14-
--> $DIR/const-param-elided-lifetime.rs:17:21
23+
error[E0106]: missing lifetime specifier
24+
--> $DIR/const-param-elided-lifetime.rs:16:21
1525
|
1626
LL | fn foo<const M: &u8>(&self) {}
17-
| ^ explicit lifetime name needed here
27+
| ^ expected named lifetime parameter
28+
|
29+
help: consider introducing a named lifetime parameter
30+
|
31+
LL | fn foo<'a, const M: &'a u8>(&self) {}
32+
| +++ ++
1833

19-
error[E0637]: `&` without an explicit lifetime name cannot be used here
20-
--> $DIR/const-param-elided-lifetime.rs:22:15
34+
error[E0106]: missing lifetime specifier
35+
--> $DIR/const-param-elided-lifetime.rs:20:15
2136
|
2237
LL | impl<const N: &u8> B for A<N> {}
23-
| ^ explicit lifetime name needed here
38+
| ^ expected named lifetime parameter
39+
|
40+
help: consider introducing a named lifetime parameter
41+
|
42+
LL | impl<'a, const N: &'a u8> B for A<N> {}
43+
| +++ ++
2444

25-
error[E0637]: `&` without an explicit lifetime name cannot be used here
26-
--> $DIR/const-param-elided-lifetime.rs:26:17
45+
error[E0106]: missing lifetime specifier
46+
--> $DIR/const-param-elided-lifetime.rs:23:17
2747
|
2848
LL | fn bar<const N: &u8>() {}
29-
| ^ explicit lifetime name needed here
49+
| ^ expected named lifetime parameter
50+
|
51+
help: consider introducing a named lifetime parameter
52+
|
53+
LL | fn bar<'a, const N: &'a u8>() {}
54+
| +++ ++
3055

3156
error: aborting due to 5 previous errors
3257

33-
For more information about this error, try `rustc --explain E0637`.
58+
For more information about this error, try `rustc --explain E0106`.

0 commit comments

Comments
 (0)