Skip to content

Commit e699ea0

Browse files
committed
Auto merge of #61679 - zackmdavis:maybe_dont_indicate_the_anonymous_lifetime, r=oli-obk
in which we decline to suggest the anonymous lifetime in declarations The elided-lifetimes-in-path lint (part of our suite of Rust 2018 idiom lints which we are hoping to promote to Warn status) was firing with an illegal suggestion to write an anonymous lifetime in a struct/item declaration (where we don't allow it). The linting code was already deciding whether to act on the basis of a `ParamMode` enum, indicating whether the present path-segment was part of an expression, or anywhere else. The present case seemed to be part of the "anywhere else", and yet meriting different rules as far as the lint was concerned, so it seemed expedient to introduce a new enum member. We yank out `TyKind::Path` arm into its own method so that we can call it with our new `ParamMode` specifically when lowering struct fields—one would have hoped to think of something more elegant than this, but it definitely beats changing the signature of `lower_ty` to take a `ParamMode`! Resolves #61124. cc @memoryruins r? @oli-obk
2 parents 42503d5 + 7a3184a commit e699ea0

File tree

3 files changed

+52
-8
lines changed

3 files changed

+52
-8
lines changed

src/librustc/hir/lowering.rs

+33-8
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,8 @@ pub fn lower_crate(
274274
enum ParamMode {
275275
/// Any path in a type context.
276276
Explicit,
277+
/// Path in a type definition, where the anonymous lifetime `'_` is not allowed.
278+
ExplicitNamed,
277279
/// The `module::Type` in `module::Type::method` in an expression.
278280
Optional,
279281
}
@@ -1489,6 +1491,23 @@ impl<'a> LoweringContext<'a> {
14891491
P(self.lower_ty_direct(t, itctx))
14901492
}
14911493

1494+
fn lower_path_ty(
1495+
&mut self,
1496+
t: &Ty,
1497+
qself: &Option<QSelf>,
1498+
path: &Path,
1499+
param_mode: ParamMode,
1500+
itctx: ImplTraitContext<'_>
1501+
) -> hir::Ty {
1502+
let id = self.lower_node_id(t.id);
1503+
let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx);
1504+
let ty = self.ty_path(id, t.span, qpath);
1505+
if let hir::TyKind::TraitObject(..) = ty.node {
1506+
self.maybe_lint_bare_trait(t.span, t.id, qself.is_none() && path.is_global());
1507+
}
1508+
ty
1509+
}
1510+
14921511
fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::Ty {
14931512
let kind = match t.node {
14941513
TyKind::Infer => hir::TyKind::Infer,
@@ -1534,13 +1553,7 @@ impl<'a> LoweringContext<'a> {
15341553
return self.lower_ty_direct(ty, itctx);
15351554
}
15361555
TyKind::Path(ref qself, ref path) => {
1537-
let id = self.lower_node_id(t.id);
1538-
let qpath = self.lower_qpath(t.id, qself, path, ParamMode::Explicit, itctx);
1539-
let ty = self.ty_path(id, t.span, qpath);
1540-
if let hir::TyKind::TraitObject(..) = ty.node {
1541-
self.maybe_lint_bare_trait(t.span, t.id, qself.is_none() && path.is_global());
1542-
}
1543-
return ty;
1556+
return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx);
15441557
}
15451558
TyKind::ImplicitSelf => {
15461559
let res = self.expect_full_res(t.id);
@@ -3086,6 +3099,18 @@ impl<'a> LoweringContext<'a> {
30863099
}
30873100

30883101
fn lower_struct_field(&mut self, (index, f): (usize, &StructField)) -> hir::StructField {
3102+
let ty = if let TyKind::Path(ref qself, ref path) = f.ty.node {
3103+
let t = self.lower_path_ty(
3104+
&f.ty,
3105+
qself,
3106+
path,
3107+
ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124)
3108+
ImplTraitContext::disallowed()
3109+
);
3110+
P(t)
3111+
} else {
3112+
self.lower_ty(&f.ty, ImplTraitContext::disallowed())
3113+
};
30893114
hir::StructField {
30903115
span: f.span,
30913116
hir_id: self.lower_node_id(f.id),
@@ -3095,7 +3120,7 @@ impl<'a> LoweringContext<'a> {
30953120
None => Ident::new(sym::integer(index), f.span),
30963121
},
30973122
vis: self.lower_visibility(&f.vis, None),
3098-
ty: self.lower_ty(&f.ty, ImplTraitContext::disallowed()),
3123+
ty,
30993124
attrs: self.lower_attrs(&f.attrs),
31003125
}
31013126
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![deny(elided_lifetimes_in_paths)]
2+
3+
// Previously, the elided-lifetimes-in-path lint would fire, but we don't want
4+
// that, because `'_` isn't legal in struct declarations.
5+
6+
struct Betrayal<'a> { x: &'a u8 }
7+
8+
struct Heartbreak(Betrayal); //~ ERROR missing lifetime specifier
9+
10+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0106]: missing lifetime specifier
2+
--> $DIR/issue-61124-anon-lifetime-in-struct-declaration.rs:8:19
3+
|
4+
LL | struct Heartbreak(Betrayal);
5+
| ^^^^^^^^ expected lifetime parameter
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0106`.

0 commit comments

Comments
 (0)