about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-08-17 17:09:33 +0000
committerbors <bors@rust-lang.org>2024-08-17 17:09:33 +0000
commit0f26ee4fd95a1c046582dfb18892f520788e2c2c (patch)
tree15a3b0d22e7c93d28f83399e95e977762ac7a1a4
parent9b318d2e93ce35e7ba32d8cfa96a1dbe63a7bed1 (diff)
parent4e6147d956e05f2f28b6fdf0d9d7c18bce603906 (diff)
downloadrust-0f26ee4fd95a1c046582dfb18892f520788e2c2c.tar.gz
rust-0f26ee4fd95a1c046582dfb18892f520788e2c2c.zip
Auto merge of #129202 - matthiaskrgr:rollup-wev7uur, r=matthiaskrgr
Rollup of 6 pull requests

Successful merges:

 - #128989 (Emit an error for invalid use of the linkage attribute)
 - #129167 (mir/pretty: use `Option` instead of `Either<Once, Empty>`)
 - #129168 (Return correct HirId when finding body owner in diagnostics)
 - #129191 (rustdoc-json: Clean up serialization and printing.)
 - #129192 (Remove useless attributes in merged doctest generated code)
 - #129196 (Remove a useless ref/id/ref round-trip from `pattern_from_hir`)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs64
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs18
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs8
-rw-r--r--compiler/rustc_passes/messages.ftl4
-rw-r--r--compiler/rustc_passes/src/check_attr.rs15
-rw-r--r--compiler/rustc_passes/src/errors.rs9
-rw-r--r--src/librustdoc/doctest/runner.rs4
-rw-r--r--src/librustdoc/json/mod.rs42
-rw-r--r--tests/crashes/128810.rs25
-rw-r--r--tests/ui/attributes/linkage.rs42
-rw-r--r--tests/ui/attributes/linkage.stderr55
-rw-r--r--tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.rs34
-rw-r--r--tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.stderr113
-rw-r--r--tests/ui/typeck/const-in-fn-call-generics.rs16
-rw-r--r--tests/ui/typeck/const-in-fn-call-generics.stderr9
15 files changed, 357 insertions, 101 deletions
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index edab6b5ebde..da08027d66b 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -554,53 +554,43 @@ impl<'hir> Map<'hir> {
     /// }
     /// ```
     pub fn get_fn_id_for_return_block(self, id: HirId) -> Option<HirId> {
-        let mut iter = self.parent_iter(id).peekable();
-        let mut ignore_tail = false;
-        if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = self.tcx.hir_node(id) {
-            // When dealing with `return` statements, we don't care about climbing only tail
-            // expressions.
-            ignore_tail = true;
-        }
+        let enclosing_body_owner = self.tcx.local_def_id_to_hir_id(self.enclosing_body_owner(id));
+
+        // Return `None` if the `id` expression is not the returned value of the enclosing body
+        let mut iter = [id].into_iter().chain(self.parent_id_iter(id)).peekable();
+        while let Some(cur_id) = iter.next() {
+            if enclosing_body_owner == cur_id {
+                break;
+            }
+
+            // A return statement is always the value returned from the enclosing body regardless of
+            // what the parent expressions are.
+            if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = self.tcx.hir_node(cur_id) {
+                break;
+            }
 
-        let mut prev_hir_id = None;
-        while let Some((hir_id, node)) = iter.next() {
-            if let (Some((_, next_node)), false) = (iter.peek(), ignore_tail) {
-                match next_node {
-                    Node::Block(Block { expr: None, .. }) => return None,
-                    // The current node is not the tail expression of its parent.
-                    Node::Block(Block { expr: Some(e), .. }) if hir_id != e.hir_id => return None,
+            // If the current expression's value doesnt get used as the parent expressions value then return `None`
+            if let Some(&parent_id) = iter.peek() {
+                match self.tcx.hir_node(parent_id) {
+                    // The current node is not the tail expression of the block expression parent expr.
+                    Node::Block(Block { expr: Some(e), .. }) if cur_id != e.hir_id => return None,
                     Node::Block(Block { expr: Some(e), .. })
                         if matches!(e.kind, ExprKind::If(_, _, None)) =>
                     {
                         return None;
                     }
+
+                    // The current expression's value does not pass up through these parent expressions
+                    Node::Block(Block { expr: None, .. })
+                    | Node::Expr(Expr { kind: ExprKind::Loop(..), .. })
+                    | Node::LetStmt(..) => return None,
+
                     _ => {}
                 }
             }
-            match node {
-                Node::Item(_)
-                | Node::ForeignItem(_)
-                | Node::TraitItem(_)
-                | Node::Expr(Expr { kind: ExprKind::Closure(_), .. })
-                | Node::ImplItem(_)
-                    // The input node `id` must be enclosed in the method's body as opposed
-                    // to some other place such as its return type (fixes #114918).
-                    // We verify that indirectly by checking that the previous node is the
-                    // current node's body
-                    if node.body_id().map(|b| b.hir_id) == prev_hir_id =>  {
-                        return Some(hir_id)
-                }
-                // Ignore `return`s on the first iteration
-                Node::Expr(Expr { kind: ExprKind::Loop(..) | ExprKind::Ret(..), .. })
-                | Node::LetStmt(_) => {
-                    return None;
-                }
-                _ => {}
-            }
-
-            prev_hir_id = Some(hir_id);
         }
-        None
+
+        Some(enclosing_body_owner)
     }
 
     /// Retrieves the `OwnerId` for `id`'s parent item, or `id` itself if no
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index f2d87814130..5dd0e69cf1f 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -1418,21 +1418,19 @@ pub fn write_allocations<'tcx>(
         alloc.inner().provenance().ptrs().values().map(|p| p.alloc_id())
     }
 
-    fn alloc_ids_from_const_val(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> + '_ {
+    fn alloc_id_from_const_val(val: ConstValue<'_>) -> Option<AllocId> {
         match val {
-            ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => {
-                Either::Left(std::iter::once(ptr.provenance.alloc_id()))
-            }
-            ConstValue::Scalar(interpret::Scalar::Int { .. }) => Either::Right(std::iter::empty()),
-            ConstValue::ZeroSized => Either::Right(std::iter::empty()),
+            ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => Some(ptr.provenance.alloc_id()),
+            ConstValue::Scalar(interpret::Scalar::Int { .. }) => None,
+            ConstValue::ZeroSized => None,
             ConstValue::Slice { .. } => {
                 // `u8`/`str` slices, shouldn't contain pointers that we want to print.
-                Either::Right(std::iter::empty())
+                None
             }
             ConstValue::Indirect { alloc_id, .. } => {
                 // FIXME: we don't actually want to print all of these, since some are printed nicely directly as values inline in MIR.
                 // Really we'd want `pretty_print_const_value` to decide which allocations to print, instead of having a separate visitor.
-                Either::Left(std::iter::once(alloc_id))
+                Some(alloc_id)
             }
         }
     }
@@ -1443,7 +1441,9 @@ pub fn write_allocations<'tcx>(
             match c.const_ {
                 Const::Ty(_, _) | Const::Unevaluated(..) => {}
                 Const::Val(val, _) => {
-                    self.0.extend(alloc_ids_from_const_val(val));
+                    if let Some(id) = alloc_id_from_const_val(val) {
+                        self.0.insert(id);
+                    }
                 }
             }
         }
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 6120b1453cf..5b5f97cb514 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -8,7 +8,7 @@ use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::lang_items::LangItem;
-use rustc_hir::{HirId, Node};
+use rustc_hir::HirId;
 use rustc_middle::bug;
 use rustc_middle::middle::region;
 use rustc_middle::thir::*;
@@ -110,11 +110,7 @@ impl<'tcx> Cx<'tcx> {
     }
 
     #[instrument(level = "debug", skip(self))]
-    fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Box<Pat<'tcx>> {
-        let p = match self.tcx.hir_node(p.hir_id) {
-            Node::Pat(p) => p,
-            node => bug!("pattern became {:?}", node),
-        };
+    fn pattern_from_hir(&mut self, p: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
         pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p)
     }
 
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 0318d34fb73..1ea4ca375f1 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -430,6 +430,10 @@ passes_link_section =
     .warn = {-passes_previously_accepted}
     .label = not a function or static
 
+passes_linkage =
+    attribute should be applied to a function or static
+    .label = not a function definition or static
+
 passes_macro_export =
     `#[macro_export]` only has an effect on macro definitions
 
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index bd157d1d619..a47add929eb 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -243,6 +243,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 [sym::coroutine, ..] => {
                     self.check_coroutine(attr, target);
                 }
+                [sym::linkage, ..] => self.check_linkage(attr, span, target),
                 [
                     // ok
                     sym::allow
@@ -256,7 +257,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     | sym::cfi_encoding // FIXME(cfi_encoding)
                     | sym::may_dangle // FIXME(dropck_eyepatch)
                     | sym::pointee // FIXME(derive_smart_pointer)
-                    | sym::linkage // FIXME(linkage)
                     | sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section)
                     | sym::used // handled elsewhere to restrict to static items
                     | sym::repr // handled elsewhere to restrict to type decls items
@@ -2347,6 +2347,19 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             }
         }
     }
+
+    fn check_linkage(&self, attr: &Attribute, span: Span, target: Target) {
+        match target {
+            Target::Fn
+            | Target::Method(..)
+            | Target::Static
+            | Target::ForeignStatic
+            | Target::ForeignFn => {}
+            _ => {
+                self.dcx().emit_err(errors::Linkage { attr_span: attr.span, span });
+            }
+        }
+    }
 }
 
 impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 36dfc40e762..3a043e0e3c1 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -644,6 +644,15 @@ pub struct CoroutineOnNonClosure {
 }
 
 #[derive(Diagnostic)]
+#[diag(passes_linkage)]
+pub struct Linkage {
+    #[primary_span]
+    pub attr_span: Span,
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(passes_empty_confusables)]
 pub(crate) struct EmptyConfusables {
     #[primary_span]
diff --git a/src/librustdoc/doctest/runner.rs b/src/librustdoc/doctest/runner.rs
index b91333e5f81..d49fa3ac5ac 100644
--- a/src/librustdoc/doctest/runner.rs
+++ b/src/librustdoc/doctest/runner.rs
@@ -75,7 +75,6 @@ impl DocTestRunner {
 #![allow(internal_features)]
 #![feature(test)]
 #![feature(rustc_attrs)]
-#![feature(coverage_attribute)]
 "
         .to_string();
 
@@ -135,7 +134,6 @@ mod __doctest_mod {{
 }}
 
 #[rustc_main]
-#[coverage(off)]
 fn main() -> std::process::ExitCode {{
 const TESTS: [test::TestDescAndFn; {nb_tests}] = [{ids}];
 let bin_marker = std::ffi::OsStr::new(__doctest_mod::BIN_OPTION);
@@ -235,11 +233,9 @@ fn main() {returns_result} {{
     writeln!(
         output,
         "
-#[rustc_test_marker = {test_name:?}]
 pub const TEST: test::TestDescAndFn = test::TestDescAndFn::new_doctest(
 {test_name:?}, {ignore}, {file:?}, {line}, {no_run}, {should_panic},
 test::StaticTestFn(
-    #[coverage(off)]
     || {{{runner}}},
 ));
 }}",
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index a424faaf999..e2860292aa3 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -39,8 +39,10 @@ pub(crate) struct JsonRenderer<'tcx> {
     /// A mapping of IDs that contains all local items for this crate which gets output as a top
     /// level field of the JSON blob.
     index: Rc<RefCell<FxHashMap<types::Id, types::Item>>>,
-    /// The directory where the blob will be written to.
-    out_path: Option<PathBuf>,
+    /// The directory where the JSON blob should be written to.
+    ///
+    /// If this is `None`, the blob will be printed to `stdout` instead.
+    out_dir: Option<PathBuf>,
     cache: Rc<Cache>,
     imported_items: DefIdSet,
 }
@@ -101,18 +103,20 @@ impl<'tcx> JsonRenderer<'tcx> {
             .unwrap_or_default()
     }
 
-    fn write<T: Write>(
+    fn serialize_and_write<T: Write>(
         &self,
-        output: types::Crate,
+        output_crate: types::Crate,
         mut writer: BufWriter<T>,
         path: &str,
     ) -> Result<(), Error> {
-        self.tcx
-            .sess
-            .time("rustdoc_json_serialization", || serde_json::ser::to_writer(&mut writer, &output))
-            .unwrap();
-        try_err!(writer.flush(), path);
-        Ok(())
+        self.sess().time("rustdoc_json_serialize_and_write", || {
+            try_err!(
+                serde_json::ser::to_writer(&mut writer, &output_crate).map_err(|e| e.to_string()),
+                path
+            );
+            try_err!(writer.flush(), path);
+            Ok(())
+        })
     }
 }
 
@@ -137,7 +141,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
             JsonRenderer {
                 tcx,
                 index: Rc::new(RefCell::new(FxHashMap::default())),
-                out_path: if options.output_to_stdout { None } else { Some(options.output) },
+                out_dir: if options.output_to_stdout { None } else { Some(options.output) },
                 cache: Rc::new(cache),
                 imported_items,
             },
@@ -237,7 +241,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
         let index = (*self.index).clone().into_inner();
 
         debug!("Constructing Output");
-        let output = types::Crate {
+        let output_crate = types::Crate {
             root: types::Id(format!("0:0:{}", e.name(self.tcx).as_u32())),
             crate_version: self.cache.crate_version.clone(),
             includes_private: self.cache.document_private,
@@ -278,20 +282,20 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
                 .collect(),
             format_version: types::FORMAT_VERSION,
         };
-        if let Some(ref out_path) = self.out_path {
-            let out_dir = out_path.clone();
+        if let Some(ref out_dir) = self.out_dir {
             try_err!(create_dir_all(&out_dir), out_dir);
 
-            let mut p = out_dir;
-            p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
+            let mut p = out_dir.clone();
+            p.push(output_crate.index.get(&output_crate.root).unwrap().name.clone().unwrap());
             p.set_extension("json");
-            self.write(
-                output,
+
+            self.serialize_and_write(
+                output_crate,
                 BufWriter::new(try_err!(File::create(&p), p)),
                 &p.display().to_string(),
             )
         } else {
-            self.write(output, BufWriter::new(stdout()), "<stdout>")
+            self.serialize_and_write(output_crate, BufWriter::new(stdout().lock()), "<stdout>")
         }
     }
 
diff --git a/tests/crashes/128810.rs b/tests/crashes/128810.rs
deleted file mode 100644
index 68214ff010c..00000000000
--- a/tests/crashes/128810.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-//@ known-bug: rust-lang/rust#128810
-
-#![feature(fn_delegation)]
-
-use std::marker::PhantomData;
-
-pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
-
-impl<'a> InvariantRef<'a, ()> {
-    pub const NEW: Self = InvariantRef::new(&());
-}
-
-trait Trait {
-    fn foo(&self) -> u8 { 0 }
-    fn bar(&self) -> u8 { 1 }
-    fn meh(&self) -> u8 { 2 }
-}
-
-struct Z(u8);
-
-impl Trait for Z {
-    reuse <u8 as Trait>::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } }
-}
-
-fn main() { }
diff --git a/tests/ui/attributes/linkage.rs b/tests/ui/attributes/linkage.rs
new file mode 100644
index 00000000000..0d5ce699fa8
--- /dev/null
+++ b/tests/ui/attributes/linkage.rs
@@ -0,0 +1,42 @@
+#![feature(linkage)]
+#![feature(stmt_expr_attributes)]
+#![deny(unused_attributes)]
+#![allow(dead_code)]
+
+#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static
+type InvalidTy = ();
+
+#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static
+mod invalid_module {}
+
+#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static
+struct F;
+
+#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static
+impl F {
+    #[linkage = "weak"]
+    fn valid(&self) {}
+}
+
+#[linkage = "weak"]
+fn f() {
+    #[linkage = "weak"]
+    {
+        1
+    };
+    //~^^^^ ERROR attribute should be applied to a function or static
+}
+
+extern "C" {
+    #[linkage = "weak"]
+    static A: *const ();
+
+    #[linkage = "weak"]
+    fn bar();
+}
+
+fn main() {
+    let _ = #[linkage = "weak"]
+    (|| 1);
+    //~^^ ERROR attribute should be applied to a function or static
+}
diff --git a/tests/ui/attributes/linkage.stderr b/tests/ui/attributes/linkage.stderr
new file mode 100644
index 00000000000..d5595529f40
--- /dev/null
+++ b/tests/ui/attributes/linkage.stderr
@@ -0,0 +1,55 @@
+error: attribute should be applied to a function or static
+  --> $DIR/linkage.rs:6:1
+   |
+LL | #[linkage = "weak"]
+   | ^^^^^^^^^^^^^^^^^^^
+LL | type InvalidTy = ();
+   | -------------------- not a function definition or static
+
+error: attribute should be applied to a function or static
+  --> $DIR/linkage.rs:9:1
+   |
+LL | #[linkage = "weak"]
+   | ^^^^^^^^^^^^^^^^^^^
+LL | mod invalid_module {}
+   | --------------------- not a function definition or static
+
+error: attribute should be applied to a function or static
+  --> $DIR/linkage.rs:12:1
+   |
+LL | #[linkage = "weak"]
+   | ^^^^^^^^^^^^^^^^^^^
+LL | struct F;
+   | --------- not a function definition or static
+
+error: attribute should be applied to a function or static
+  --> $DIR/linkage.rs:15:1
+   |
+LL |   #[linkage = "weak"]
+   |   ^^^^^^^^^^^^^^^^^^^
+LL | / impl F {
+LL | |     #[linkage = "weak"]
+LL | |     fn valid(&self) {}
+LL | | }
+   | |_- not a function definition or static
+
+error: attribute should be applied to a function or static
+  --> $DIR/linkage.rs:23:5
+   |
+LL |       #[linkage = "weak"]
+   |       ^^^^^^^^^^^^^^^^^^^
+LL | /     {
+LL | |         1
+LL | |     };
+   | |_____- not a function definition or static
+
+error: attribute should be applied to a function or static
+  --> $DIR/linkage.rs:39:13
+   |
+LL |     let _ = #[linkage = "weak"]
+   |             ^^^^^^^^^^^^^^^^^^^
+LL |     (|| 1);
+   |     ------ not a function definition or static
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.rs b/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.rs
new file mode 100644
index 00000000000..0a7ec5ab5c1
--- /dev/null
+++ b/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.rs
@@ -0,0 +1,34 @@
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+use std::marker::PhantomData;
+
+pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
+
+impl<'a> InvariantRef<'a, ()> {
+    pub const NEW: Self = InvariantRef::new(&());
+    //~^ ERROR: no function or associated item named `new` found
+}
+
+trait Trait {
+    fn foo(&self) -> u8 { 0 }
+    fn bar(&self) -> u8 { 1 }
+    fn meh(&self) -> u8 { 2 }
+}
+
+struct Z(u8);
+
+impl Trait for Z {
+    reuse <u8 as Trait>::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } }
+    //~^ ERROR: use of undeclared lifetime name `'a`
+    //~| ERROR: use of undeclared lifetime name `'a`
+    //~| ERROR: use of undeclared lifetime name `'a`
+    //~| ERROR: the trait bound `u8: Trait` is not satisfied
+    //~| ERROR: the trait bound `u8: Trait` is not satisfied
+    //~| ERROR: the trait bound `u8: Trait` is not satisfied
+    //~| ERROR: mismatched types
+    //~| ERROR: mismatched types
+    //~| ERROR: mismatched types
+}
+
+fn main() { }
diff --git a/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.stderr b/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.stderr
new file mode 100644
index 00000000000..2ce3b388073
--- /dev/null
+++ b/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.stderr
@@ -0,0 +1,113 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:68
+   |
+LL |     reuse <u8 as Trait>::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } }
+   |                                                                    ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL |     reuse <u8 as Trait>::{foo'a, , bar, meh} { &const { InvariantRef::<'a>::NEW } }
+   |                              +++
+help: consider introducing lifetime `'a` here
+   |
+LL | impl<'a> Trait for Z {
+   |     ++++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:68
+   |
+LL |     reuse <u8 as Trait>::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } }
+   |                                                                    ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL |     reuse <u8 as Trait>::{foo, bar'a, , meh} { &const { InvariantRef::<'a>::NEW } }
+   |                                   +++
+help: consider introducing lifetime `'a` here
+   |
+LL | impl<'a> Trait for Z {
+   |     ++++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:68
+   |
+LL |     reuse <u8 as Trait>::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } }
+   |                                                                    ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL |     reuse <u8 as Trait>::{foo, bar, meh'a, } { &const { InvariantRef::<'a>::NEW } }
+   |                                        +++
+help: consider introducing lifetime `'a` here
+   |
+LL | impl<'a> Trait for Z {
+   |     ++++
+
+error[E0599]: no function or associated item named `new` found for struct `InvariantRef` in the current scope
+  --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:9:41
+   |
+LL | pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
+   | -------------------------------------- function or associated item `new` not found for this struct
+...
+LL |     pub const NEW: Self = InvariantRef::new(&());
+   |                                         ^^^ function or associated item not found in `InvariantRef<'_, _>`
+
+error[E0308]: mismatched types
+  --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:53
+   |
+LL |     reuse <u8 as Trait>::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } }
+   |                                                     ^^^^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `InvariantRef<'_, ()>`
+   |
+   = note: expected type `u8`
+            found struct `InvariantRef<'_, ()>`
+
+error[E0277]: the trait bound `u8: Trait` is not satisfied
+  --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:12
+   |
+LL |     reuse <u8 as Trait>::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } }
+   |            ^^ the trait `Trait` is not implemented for `u8`
+   |
+   = help: the trait `Trait` is implemented for `Z`
+
+error[E0308]: mismatched types
+  --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:53
+   |
+LL |     reuse <u8 as Trait>::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } }
+   |                                                     ^^^^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `InvariantRef<'_, ()>`
+   |
+   = note: expected type `u8`
+            found struct `InvariantRef<'_, ()>`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0277]: the trait bound `u8: Trait` is not satisfied
+  --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:12
+   |
+LL |     reuse <u8 as Trait>::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } }
+   |            ^^ the trait `Trait` is not implemented for `u8`
+   |
+   = help: the trait `Trait` is implemented for `Z`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0308]: mismatched types
+  --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:53
+   |
+LL |     reuse <u8 as Trait>::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } }
+   |                                                     ^^^^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `InvariantRef<'_, ()>`
+   |
+   = note: expected type `u8`
+            found struct `InvariantRef<'_, ()>`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0277]: the trait bound `u8: Trait` is not satisfied
+  --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:22:12
+   |
+LL |     reuse <u8 as Trait>::{foo, bar, meh} { &const { InvariantRef::<'a>::NEW } }
+   |            ^^ the trait `Trait` is not implemented for `u8`
+   |
+   = help: the trait `Trait` is implemented for `Z`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0261, E0277, E0308, E0599.
+For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/typeck/const-in-fn-call-generics.rs b/tests/ui/typeck/const-in-fn-call-generics.rs
new file mode 100644
index 00000000000..675dbcc3054
--- /dev/null
+++ b/tests/ui/typeck/const-in-fn-call-generics.rs
@@ -0,0 +1,16 @@
+fn generic<const N: u32>() {}
+
+trait Collate<const A: u32> {
+    type Pass;
+    fn collate(self) -> Self::Pass;
+}
+
+impl<const B: u32> Collate<B> for i32 {
+    type Pass = ();
+    fn collate(self) -> Self::Pass {
+        generic::<{ true }>()
+        //~^ ERROR: mismatched types
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/typeck/const-in-fn-call-generics.stderr b/tests/ui/typeck/const-in-fn-call-generics.stderr
new file mode 100644
index 00000000000..12dd454188c
--- /dev/null
+++ b/tests/ui/typeck/const-in-fn-call-generics.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/const-in-fn-call-generics.rs:11:21
+   |
+LL |         generic::<{ true }>()
+   |                     ^^^^ expected `u32`, found `bool`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.