about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/hir/lowering.rs41
-rw-r--r--src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.rs10
-rw-r--r--src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.stderr9
3 files changed, 52 insertions, 8 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index b5e9f6bd3a6..373f255e636 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -274,6 +274,8 @@ pub fn lower_crate(
 enum ParamMode {
     /// Any path in a type context.
     Explicit,
+    /// Path in a type definition, where the anonymous lifetime `'_` is not allowed.
+    ExplicitNamed,
     /// The `module::Type` in `module::Type::method` in an expression.
     Optional,
 }
@@ -1489,6 +1491,23 @@ impl<'a> LoweringContext<'a> {
         P(self.lower_ty_direct(t, itctx))
     }
 
+    fn lower_path_ty(
+        &mut self,
+        t: &Ty,
+        qself: &Option<QSelf>,
+        path: &Path,
+        param_mode: ParamMode,
+        itctx: ImplTraitContext<'_>
+    ) -> hir::Ty {
+        let id = self.lower_node_id(t.id);
+        let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx);
+        let ty = self.ty_path(id, t.span, qpath);
+        if let hir::TyKind::TraitObject(..) = ty.node {
+            self.maybe_lint_bare_trait(t.span, t.id, qself.is_none() && path.is_global());
+        }
+        ty
+    }
+
     fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::Ty {
         let kind = match t.node {
             TyKind::Infer => hir::TyKind::Infer,
@@ -1534,13 +1553,7 @@ impl<'a> LoweringContext<'a> {
                 return self.lower_ty_direct(ty, itctx);
             }
             TyKind::Path(ref qself, ref path) => {
-                let id = self.lower_node_id(t.id);
-                let qpath = self.lower_qpath(t.id, qself, path, ParamMode::Explicit, itctx);
-                let ty = self.ty_path(id, t.span, qpath);
-                if let hir::TyKind::TraitObject(..) = ty.node {
-                    self.maybe_lint_bare_trait(t.span, t.id, qself.is_none() && path.is_global());
-                }
-                return ty;
+                return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx);
             }
             TyKind::ImplicitSelf => {
                 let res = self.expect_full_res(t.id);
@@ -3086,6 +3099,18 @@ impl<'a> LoweringContext<'a> {
     }
 
     fn lower_struct_field(&mut self, (index, f): (usize, &StructField)) -> hir::StructField {
+        let ty = if let TyKind::Path(ref qself, ref path) = f.ty.node {
+            let t = self.lower_path_ty(
+                &f.ty,
+                qself,
+                path,
+                ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124)
+                ImplTraitContext::disallowed()
+            );
+            P(t)
+        } else {
+            self.lower_ty(&f.ty, ImplTraitContext::disallowed())
+        };
         hir::StructField {
             span: f.span,
             hir_id: self.lower_node_id(f.id),
@@ -3095,7 +3120,7 @@ impl<'a> LoweringContext<'a> {
                 None => Ident::new(sym::integer(index), f.span),
             },
             vis: self.lower_visibility(&f.vis, None),
-            ty: self.lower_ty(&f.ty, ImplTraitContext::disallowed()),
+            ty,
             attrs: self.lower_attrs(&f.attrs),
         }
     }
diff --git a/src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.rs b/src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.rs
new file mode 100644
index 00000000000..cf08cb7eeac
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.rs
@@ -0,0 +1,10 @@
+#![deny(elided_lifetimes_in_paths)]
+
+// Previously, the elided-lifetimes-in-path lint would fire, but we don't want
+// that, because `'_` isn't legal in struct declarations.
+
+struct Betrayal<'a> { x: &'a u8 }
+
+struct Heartbreak(Betrayal);  //~ ERROR missing lifetime specifier
+
+fn main() {}
diff --git a/src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.stderr b/src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.stderr
new file mode 100644
index 00000000000..9579abb76b3
--- /dev/null
+++ b/src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.stderr
@@ -0,0 +1,9 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-61124-anon-lifetime-in-struct-declaration.rs:8:19
+   |
+LL | struct Heartbreak(Betrayal);
+   |                   ^^^^^^^^ expected lifetime parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.