about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libcore/convert.rs2
-rw-r--r--src/librustc/hir/map/mod.rs4
-rw-r--r--src/librustc/hir/mod.rs10
-rw-r--r--src/librustc/traits/error_reporting.rs7
-rw-r--r--src/librustc/ty/layout.rs2
-rw-r--r--src/librustc_codegen_llvm/debuginfo/metadata.rs4
-rw-r--r--src/librustc_codegen_utils/symbol_names/legacy.rs2
-rw-r--r--src/librustc_mir/borrow_check/places_conflict.rs4
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs5
-rw-r--r--src/librustc_typeck/check/_match.rs59
-rw-r--r--src/librustc_typeck/check/compare_method.rs83
-rw-r--r--src/librustc_typeck/error_codes.rs32
-rw-r--r--src/libstd/macros.rs2
-rw-r--r--src/libsyntax/parse/parser.rs25
-rw-r--r--src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr4
-rw-r--r--src/test/ui/const-generics/issue-61422.rs15
-rw-r--r--src/test/ui/const-generics/issue-61422.stderr6
-rw-r--r--src/test/ui/const-generics/mut-ref-const-param-array.rs19
-rw-r--r--src/test/ui/const-generics/mut-ref-const-param-array.stderr6
-rw-r--r--src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs11
-rw-r--r--src/test/ui/const-generics/transparent-maybeunit-array-wrapper.stderr6
-rw-r--r--src/test/ui/error-codes/E0049.rs10
-rw-r--r--src/test/ui/error-codes/E0049.stderr19
-rw-r--r--src/test/ui/error-codes/E0730.rs11
-rw-r--r--src/test/ui/error-codes/E0730.stderr15
-rw-r--r--src/test/ui/fn-in-pat.stderr4
-rw-r--r--src/test/ui/issues/issue-36708.stderr4
-rw-r--r--src/test/ui/issues/issue-55587.stderr4
-rw-r--r--src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.rs1
-rw-r--r--src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.stderr9
-rw-r--r--src/test/ui/match/match-fn-call.stderr8
-rw-r--r--src/test/ui/symbol-names/issue-60925.legacy.stderr6
-rw-r--r--src/test/ui/symbol-names/issue-60925.rs6
33 files changed, 313 insertions, 92 deletions
diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs
index a2796ad0cf0..6215bf5cd65 100644
--- a/src/libcore/convert.rs
+++ b/src/libcore/convert.rs
@@ -129,7 +129,7 @@ pub const fn identity<T>(x: T) -> T { x }
 /// # Examples
 ///
 /// By using trait bounds we can accept arguments of different types as long as they can be
-/// converted a the specified type `T`.
+/// converted to the specified type `T`.
 ///
 /// For example: By creating a generic function that takes an `AsRef<str>` we express that we
 /// want to accept all references that can be converted to `&str` as an argument.
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index c84c18ce8a7..75799a19031 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -628,10 +628,6 @@ impl<'hir> Map<'hir> {
         })
     }
 
-    pub fn get_generics_span(&self, id: DefId) -> Option<Span> {
-        self.get_generics(id).map(|generics| generics.span).filter(|sp| *sp != DUMMY_SP)
-    }
-
     /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found.
     pub fn find(&self, id: NodeId) -> Option<Node<'hir>> {
         let hir_id = self.node_to_hir_id(id);
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index f7daa7a9455..210c0c9225a 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -16,7 +16,7 @@ use crate::util::nodemap::{NodeMap, FxHashSet};
 use crate::mir::mono::Linkage;
 
 use errors::FatalError;
-use syntax_pos::{Span, DUMMY_SP, symbol::InternedString};
+use syntax_pos::{Span, DUMMY_SP, symbol::InternedString, MultiSpan};
 use syntax::source_map::Spanned;
 use rustc_target::spec::abi::Abi;
 use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect};
@@ -625,6 +625,14 @@ impl Generics {
         }
         None
     }
+
+    pub fn spans(&self) -> MultiSpan {
+        if self.params.is_empty() {
+            self.span.into()
+        } else {
+            self.params.iter().map(|p| p.span).collect::<Vec<Span>>().into()
+        }
+    }
 }
 
 /// Synthetic type parameters are converted to another form during lowering; this allows
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index a29b173880a..95312d55b3b 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -914,8 +914,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             }
 
             // already reported in the query
-            ConstEvalFailure(_) => {
-                self.tcx.sess.delay_span_bug(span, "constant in type had an ignored error");
+            ConstEvalFailure(err) => {
+                self.tcx.sess.delay_span_bug(
+                    span,
+                    &format!("constant in type had an ignored error: {:?}", err),
+                );
                 return;
             }
 
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 6d7b0926c7a..6415122dd39 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -549,8 +549,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                     }
                 }
 
+                let count = count.assert_usize(tcx).ok_or(LayoutError::Unknown(ty))?;
                 let element = self.layout_of(element)?;
-                let count = count.unwrap_usize(tcx);
                 let size = element.size.checked_mul(count, dl)
                     .ok_or(LayoutError::SizeOverflow(ty))?;
 
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index b000628a3f7..42bd790ca2e 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -342,9 +342,7 @@ fn fixed_vec_metadata(
     let (size, align) = cx.size_and_align_of(array_or_slice_type);
 
     let upper_bound = match array_or_slice_type.sty {
-        ty::Array(_, len) => {
-            len.unwrap_usize(cx.tcx) as c_longlong
-        }
+        ty::Array(_, len) => len.unwrap_usize(cx.tcx) as c_longlong,
         _ => -1
     };
 
diff --git a/src/librustc_codegen_utils/symbol_names/legacy.rs b/src/librustc_codegen_utils/symbol_names/legacy.rs
index 53682b9bdc2..6eaa22afce1 100644
--- a/src/librustc_codegen_utils/symbol_names/legacy.rs
+++ b/src/librustc_codegen_utils/symbol_names/legacy.rs
@@ -440,7 +440,7 @@ impl fmt::Write for SymbolPrinter<'_, '_> {
                 '-' | ':' => self.path.temp_buf.push('.'),
 
                 // Avoid crashing LLVM in certain (LTO-related) situations, see #60925.
-                'm' if self.path.temp_buf.ends_with(".llv") => self.path.temp_buf.push_str("$6d$"),
+                'm' if self.path.temp_buf.ends_with(".llv") => self.path.temp_buf.push_str("$u6d$"),
 
                 // These are legal symbols
                 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '.' | '$' => self.path.temp_buf.push(c),
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index 74da3f96653..8aa27eef72a 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -332,8 +332,8 @@ fn place_base_conflict<'a, 'gcx: 'tcx, 'tcx>(
                 },
                 (StaticKind::Promoted(promoted_1), StaticKind::Promoted(promoted_2)) => {
                     if promoted_1 == promoted_2 {
-                        if let ty::Array(_, size) = s1.ty.sty {
-                            if size.unwrap_usize(tcx) == 0 {
+                        if let ty::Array(_, len) = s1.ty.sty {
+                            if let Some(0) = len.assert_usize(tcx) {
                                 // Ignore conflicts with promoted [T; 0].
                                 debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED");
                                 return Overlap::Disjoint;
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index a416792101f..fe94181047f 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -316,8 +316,9 @@ impl Qualif for HasMutInterior {
                     } else if let ty::Array(_, len) = ty.sty {
                         // FIXME(eddyb) the `cx.mode == Mode::Fn` condition
                         // seems unnecessary, given that this is merely a ZST.
-                        if !(len.unwrap_usize(cx.tcx) == 0 && cx.mode == Mode::Fn) {
-                            return true;
+                        match len.assert_usize(cx.tcx) {
+                            Some(0) if cx.mode == Mode::Fn => {},
+                            _ => return true,
                         }
                     } else {
                         return true;
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 5cd95a9d834..9607427baa9 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -400,27 +400,36 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 let expected_ty = self.structurally_resolved_type(pat.span, expected);
                 let (inner_ty, slice_ty) = match expected_ty.sty {
                     ty::Array(inner_ty, size) => {
-                        let size = size.unwrap_usize(tcx);
-                        let min_len = before.len() as u64 + after.len() as u64;
-                        if slice.is_none() {
-                            if min_len != size {
-                                struct_span_err!(
-                                    tcx.sess, pat.span, E0527,
-                                    "pattern requires {} elements but array has {}",
-                                    min_len, size)
-                                    .span_label(pat.span, format!("expected {} elements", size))
+                        if let Some(size) = size.assert_usize(tcx) {
+                            let min_len = before.len() as u64 + after.len() as u64;
+                            if slice.is_none() {
+                                if min_len != size {
+                                    struct_span_err!(
+                                        tcx.sess, pat.span, E0527,
+                                        "pattern requires {} elements but array has {}",
+                                        min_len, size)
+                                        .span_label(pat.span, format!("expected {} elements", size))
+                                        .emit();
+                                }
+                                (inner_ty, tcx.types.err)
+                            } else if let Some(rest) = size.checked_sub(min_len) {
+                                (inner_ty, tcx.mk_array(inner_ty, rest))
+                            } else {
+                                struct_span_err!(tcx.sess, pat.span, E0528,
+                                        "pattern requires at least {} elements but array has {}",
+                                        min_len, size)
+                                    .span_label(pat.span,
+                                        format!("pattern cannot match array of {} elements", size))
                                     .emit();
+                                (inner_ty, tcx.types.err)
                             }
-                            (inner_ty, tcx.types.err)
-                        } else if let Some(rest) = size.checked_sub(min_len) {
-                            (inner_ty, tcx.mk_array(inner_ty, rest))
                         } else {
-                            struct_span_err!(tcx.sess, pat.span, E0528,
-                                    "pattern requires at least {} elements but array has {}",
-                                    min_len, size)
-                                .span_label(pat.span,
-                                    format!("pattern cannot match array of {} elements", size))
-                                .emit();
+                            struct_span_err!(
+                                tcx.sess,
+                                pat.span,
+                                E0730,
+                                "cannot pattern-match on an array without a fixed length",
+                            ).emit();
                             (inner_ty, tcx.types.err)
                         }
                     }
@@ -1080,8 +1089,18 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
             let msg = format!("expected tuple struct/variant, found {} `{}`",
                               res.descr(),
                               hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false)));
-            struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg)
-                .span_label(pat.span, "not a tuple variant or struct").emit();
+            let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg);
+            match (res, &pat.node) {
+                (Res::Def(DefKind::Fn, _), _) | (Res::Def(DefKind::Method, _), _) => {
+                    err.span_label(pat.span, "`fn` calls are not allowed in patterns");
+                    err.help("for more information, visit \
+                              https://doc.rust-lang.org/book/ch18-00-patterns.html");
+                }
+                _ => {
+                    err.span_label(pat.span, "not a tuple variant or struct");
+                }
+            }
+            err.emit();
             on_error();
         };
 
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 1165890fe64..b4548ac7091 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -385,7 +385,7 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // the moment, give a kind of vague error message.
     if trait_params != impl_params {
         let def_span = tcx.sess.source_map().def_span(span);
-        let span = tcx.hir().get_generics_span(impl_m.def_id).unwrap_or(def_span);
+        let span = tcx.hir().get_generics(impl_m.def_id).map(|g| g.span).unwrap_or(def_span);
         let mut err = struct_span_err!(
             tcx.sess,
             span,
@@ -396,7 +396,7 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         err.span_label(span, "lifetimes do not match method in trait");
         if let Some(sp) = tcx.hir().span_if_local(trait_m.def_id) {
             let def_sp = tcx.sess.source_map().def_span(sp);
-            let sp = tcx.hir().get_generics_span(trait_m.def_id).unwrap_or(def_sp);
+            let sp = tcx.hir().get_generics(trait_m.def_id).map(|g| g.span).unwrap_or(def_sp);
             err.span_label(sp, "lifetimes in impl do not match this method in trait");
         }
         err.emit();
@@ -583,7 +583,7 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 fn compare_number_of_generics<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     impl_: &ty::AssocItem,
-    impl_span: Span,
+    _impl_span: Span,
     trait_: &ty::AssocItem,
     trait_span: Option<Span>,
 ) -> Result<(), ErrorReported> {
@@ -600,17 +600,44 @@ fn compare_number_of_generics<'a, 'tcx>(
         if impl_count != trait_count {
             err_occurred = true;
 
-            let impl_hir_id = tcx.hir().as_local_hir_id(impl_.def_id).unwrap();
-            let impl_item = tcx.hir().expect_impl_item(impl_hir_id);
-            let span = if impl_item.generics.params.is_empty()
-                || impl_item.generics.span.is_dummy() { // argument position impl Trait (#55374)
-                impl_span
+            let (
+                trait_spans,
+                impl_trait_spans,
+            ) = if let Some(trait_hir_id) = tcx.hir().as_local_hir_id(trait_.def_id) {
+                let trait_item = tcx.hir().expect_trait_item(trait_hir_id);
+                if trait_item.generics.params.is_empty() {
+                    (Some(vec![trait_item.generics.span]), vec![])
+                } else {
+                    let arg_spans: Vec<Span> = trait_item.generics.params.iter()
+                        .map(|p| p.span)
+                        .collect();
+                    let impl_trait_spans: Vec<Span> = trait_item.generics.params.iter()
+                        .filter_map(|p| match p.kind {
+                            GenericParamKind::Type {
+                                synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), ..
+                            } => Some(p.span),
+                            _ => None,
+                        }).collect();
+                    (Some(arg_spans), impl_trait_spans)
+                }
             } else {
-                impl_item.generics.span
+                (trait_span.map(|s| vec![s]), vec![])
             };
 
+            let impl_hir_id = tcx.hir().as_local_hir_id(impl_.def_id).unwrap();
+            let impl_item = tcx.hir().expect_impl_item(impl_hir_id);
+            let impl_item_impl_trait_spans: Vec<Span> = impl_item.generics.params.iter()
+                .filter_map(|p| match p.kind {
+                    GenericParamKind::Type {
+                        synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), ..
+                    } => Some(p.span),
+                    _ => None,
+                }).collect();
+            let spans = impl_item.generics.spans();
+            let span = spans.primary_span();
+
             let mut err = tcx.sess.struct_span_err_with_code(
-                span,
+                spans,
                 &format!(
                     "method `{}` has {} {kind} parameter{} but its trait \
                      declaration has {} {kind} parameter{}",
@@ -626,22 +653,36 @@ fn compare_number_of_generics<'a, 'tcx>(
 
             let mut suffix = None;
 
-            if let Some(span) = trait_span {
-                err.span_label(
-                    span,
-                    format!("expected {} {} parameter{}", trait_count, kind,
-                        if trait_count != 1 { "s" } else { "" })
-                );
+            if let Some(spans) = trait_spans {
+                let mut spans = spans.iter();
+                if let Some(span) = spans.next() {
+                    err.span_label(*span, format!(
+                        "expected {} {} parameter{}",
+                        trait_count,
+                        kind,
+                        if trait_count != 1 { "s" } else { "" },
+                    ));
+                }
+                for span in spans {
+                    err.span_label(*span, "");
+                }
             } else {
                 suffix = Some(format!(", expected {}", trait_count));
             }
 
-            err.span_label(
-                span,
-                format!("found {} {} parameter{}{}", impl_count, kind,
+            if let Some(span) = span {
+                err.span_label(span, format!(
+                    "found {} {} parameter{}{}",
+                    impl_count,
+                    kind,
                     if impl_count != 1 { "s" } else { "" },
-                    suffix.unwrap_or_else(|| String::new())),
-            );
+                    suffix.unwrap_or_else(|| String::new()),
+                ));
+            }
+
+            for span in impl_trait_spans.iter().chain(impl_item_impl_trait_spans.iter()) {
+                err.span_label(*span, "`impl Trait` introduces an implicit type parameter");
+            }
 
             err.emit();
         }
diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs
index 6dd3c0113cd..b5a50f43875 100644
--- a/src/librustc_typeck/error_codes.rs
+++ b/src/librustc_typeck/error_codes.rs
@@ -4648,6 +4648,38 @@ fn make_recursive_type() -> impl Sized {
 ```
 "##,
 
+E0730: r##"
+An array without a fixed length was pattern-matched.
+
+Example of erroneous code:
+
+```compile_fail,E0730
+#![feature(const_generics)]
+
+fn is_123<const N: usize>(x: [u32; N]) -> bool {
+    match x {
+        [1, 2, 3] => true, // error: cannot pattern-match on an
+                           //        array without a fixed length
+        _ => false
+    }
+}
+```
+
+Ensure that the pattern is consistent with the size of the matched
+array. Additional elements can be matched with `..`:
+
+```
+#![feature(slice_patterns)]
+
+let r = &[1, 2, 3, 4];
+match r {
+    &[a, b, ..] => { // ok!
+        println!("a={}, b={}", a, b);
+    }
+}
+```
+"##,
+
 }
 
 register_diagnostics! {
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index 9af7bba97aa..ef7179f0b6f 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -405,7 +405,7 @@ mod builtin {
     ///
     /// ```compile_fail
     /// #[cfg(not(any(feature = "foo", feature = "bar")))]
-    /// compile_error!("Either feature \"foo\" or \"bar\" must be enabled for this crate.")
+    /// compile_error!("Either feature \"foo\" or \"bar\" must be enabled for this crate.");
     /// ```
     ///
     /// [`panic!`]: ../std/macro.panic.html
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 92c27f883d1..7bc95ad0369 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -5050,21 +5050,22 @@ impl<'a> Parser<'a> {
     /// where   typaramseq = ( typaram ) | ( typaram , typaramseq )
     fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
         let span_lo = self.span;
-        if self.eat_lt() {
+        let (params, span) = if self.eat_lt() {
             let params = self.parse_generic_params()?;
             self.expect_gt()?;
-            Ok(ast::Generics {
-                params,
-                where_clause: WhereClause {
-                    id: ast::DUMMY_NODE_ID,
-                    predicates: Vec::new(),
-                    span: DUMMY_SP,
-                },
-                span: span_lo.to(self.prev_span),
-            })
+            (params, span_lo.to(self.prev_span))
         } else {
-            Ok(ast::Generics::default())
-        }
+            (vec![], self.prev_span.between(self.span))
+        };
+        Ok(ast::Generics {
+            params,
+            where_clause: WhereClause {
+                id: ast::DUMMY_NODE_ID,
+                predicates: Vec::new(),
+                span: DUMMY_SP,
+            },
+            span,
+        })
     }
 
     /// Parses generic args (within a path segment) with recovery for extra leading angle brackets.
diff --git a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
index cc6d5c55bd5..4c7c0d1a0df 100644
--- a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
+++ b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
@@ -36,13 +36,13 @@ LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d
    |                        ^^
 
 error[E0195]: lifetime parameters or bounds on method `wrong_bound2` do not match the trait declaration
-  --> $DIR/regions-bound-missing-bound-in-impl.rs:41:5
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:41:20
    |
 LL |     fn wrong_bound2<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
    |                    ---------------- lifetimes in impl do not match this method in trait
 ...
 LL |     fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
+   |                    ^ lifetimes do not match method in trait
 
 error[E0276]: impl has stricter requirements than trait
   --> $DIR/regions-bound-missing-bound-in-impl.rs:48:5
diff --git a/src/test/ui/const-generics/issue-61422.rs b/src/test/ui/const-generics/issue-61422.rs
new file mode 100644
index 00000000000..3ccf38e5619
--- /dev/null
+++ b/src/test/ui/const-generics/issue-61422.rs
@@ -0,0 +1,15 @@
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+use std::mem;
+
+fn foo<const SIZE: usize>() {
+    let arr: [u8; SIZE] = unsafe {
+        let mut array: [u8; SIZE] = mem::uninitialized();
+        array
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issue-61422.stderr b/src/test/ui/const-generics/issue-61422.stderr
new file mode 100644
index 00000000000..4cb76ec4fe1
--- /dev/null
+++ b/src/test/ui/const-generics/issue-61422.stderr
@@ -0,0 +1,6 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/issue-61422.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/const-generics/mut-ref-const-param-array.rs b/src/test/ui/const-generics/mut-ref-const-param-array.rs
new file mode 100644
index 00000000000..f930fb87963
--- /dev/null
+++ b/src/test/ui/const-generics/mut-ref-const-param-array.rs
@@ -0,0 +1,19 @@
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+use std::ops::AddAssign;
+
+fn inc<T: AddAssign + Clone, const N: usize>(v: &mut [T; N]) -> &mut [T; N] {
+    for x in v.iter_mut() {
+        *x += x.clone();
+    }
+    v
+}
+
+fn main() {
+    let mut v = [1, 2, 3];
+    inc(&mut v);
+    assert_eq!(v, [2, 4, 6]);
+}
diff --git a/src/test/ui/const-generics/mut-ref-const-param-array.stderr b/src/test/ui/const-generics/mut-ref-const-param-array.stderr
new file mode 100644
index 00000000000..261d3578a11
--- /dev/null
+++ b/src/test/ui/const-generics/mut-ref-const-param-array.stderr
@@ -0,0 +1,6 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/mut-ref-const-param-array.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs b/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs
new file mode 100644
index 00000000000..794048174f9
--- /dev/null
+++ b/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs
@@ -0,0 +1,11 @@
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+use std::mem::MaybeUninit;
+
+#[repr(transparent)]
+pub struct MaybeUninitWrapper<const N: usize>(MaybeUninit<[u64; N]>);
+
+fn main() {}
diff --git a/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.stderr b/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.stderr
new file mode 100644
index 00000000000..661bbd113bc
--- /dev/null
+++ b/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.stderr
@@ -0,0 +1,6 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/transparent-maybeunit-array-wrapper.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/error-codes/E0049.rs b/src/test/ui/error-codes/E0049.rs
index c141f8a8828..3dd910019bf 100644
--- a/src/test/ui/error-codes/E0049.rs
+++ b/src/test/ui/error-codes/E0049.rs
@@ -8,5 +8,15 @@ impl Foo for Bar {
     fn foo(x: bool) -> Self { Bar } //~ ERROR E0049
 }
 
+trait Fuzz {
+    fn fuzz<A: Default, B>(x: A, y: B) -> Self;
+}
+
+struct Baz;
+
+impl Fuzz for Baz {
+    fn fuzz(x: bool, y: bool) -> Self { Baz } //~ ERROR E0049
+}
+
 fn main() {
 }
diff --git a/src/test/ui/error-codes/E0049.stderr b/src/test/ui/error-codes/E0049.stderr
index 7e9b9e8efb9..c0cd31faa90 100644
--- a/src/test/ui/error-codes/E0049.stderr
+++ b/src/test/ui/error-codes/E0049.stderr
@@ -1,12 +1,23 @@
 error[E0049]: method `foo` has 0 type parameters but its trait declaration has 1 type parameter
-  --> $DIR/E0049.rs:8:5
+  --> $DIR/E0049.rs:8:11
    |
 LL |     fn foo<T: Default>(x: T) -> Self;
-   |     --------------------------------- expected 1 type parameter
+   |            - expected 1 type parameter
 ...
 LL |     fn foo(x: bool) -> Self { Bar }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ found 0 type parameters
+   |           ^ found 0 type parameters
 
-error: aborting due to previous error
+error[E0049]: method `fuzz` has 0 type parameters but its trait declaration has 2 type parameters
+  --> $DIR/E0049.rs:18:12
+   |
+LL |     fn fuzz<A: Default, B>(x: A, y: B) -> Self;
+   |             -           -
+   |             |
+   |             expected 2 type parameters
+...
+LL |     fn fuzz(x: bool, y: bool) -> Self { Baz }
+   |            ^ found 0 type parameters
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0049`.
diff --git a/src/test/ui/error-codes/E0730.rs b/src/test/ui/error-codes/E0730.rs
new file mode 100644
index 00000000000..e5048d6e6e3
--- /dev/null
+++ b/src/test/ui/error-codes/E0730.rs
@@ -0,0 +1,11 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+fn is_123<const N: usize>(x: [u32; N]) -> bool {
+    match x {
+        [1, 2, 3] => true, //~ ERROR cannot pattern-match on an array without a fixed length
+        _ => false
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0730.stderr b/src/test/ui/error-codes/E0730.stderr
new file mode 100644
index 00000000000..f9281262bb7
--- /dev/null
+++ b/src/test/ui/error-codes/E0730.stderr
@@ -0,0 +1,15 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/E0730.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
+error[E0730]: cannot pattern-match on an array without a fixed length
+  --> $DIR/E0730.rs:6:9
+   |
+LL |         [1, 2, 3] => true,
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0730`.
diff --git a/src/test/ui/fn-in-pat.stderr b/src/test/ui/fn-in-pat.stderr
index eee97fe9587..0bb24365ef4 100644
--- a/src/test/ui/fn-in-pat.stderr
+++ b/src/test/ui/fn-in-pat.stderr
@@ -2,7 +2,9 @@ error[E0164]: expected tuple struct/variant, found method `<A>::new`
   --> $DIR/fn-in-pat.rs:11:9
    |
 LL |         A::new() => (),
-   |         ^^^^^^^^ not a tuple variant or struct
+   |         ^^^^^^^^ `fn` calls are not allowed in patterns
+   |
+   = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-36708.stderr b/src/test/ui/issues/issue-36708.stderr
index 835094c4fdc..140f19f1ff7 100644
--- a/src/test/ui/issues/issue-36708.stderr
+++ b/src/test/ui/issues/issue-36708.stderr
@@ -1,8 +1,8 @@
 error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
-  --> $DIR/issue-36708.rs:8:11
+  --> $DIR/issue-36708.rs:8:12
    |
 LL |     fn foo<T>() {}
-   |           ^^^ found 1 type parameter, expected 0
+   |            ^ found 1 type parameter, expected 0
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-55587.stderr b/src/test/ui/issues/issue-55587.stderr
index 1334f249256..3928a3cd532 100644
--- a/src/test/ui/issues/issue-55587.stderr
+++ b/src/test/ui/issues/issue-55587.stderr
@@ -2,7 +2,9 @@ error[E0164]: expected tuple struct/variant, found method `<Path>::new`
   --> $DIR/issue-55587.rs:4:9
    |
 LL |     let Path::new();
-   |         ^^^^^^^^^^^ not a tuple variant or struct
+   |         ^^^^^^^^^^^ `fn` calls are not allowed in patterns
+   |
+   = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.rs b/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.rs
index 4a71932d1df..ecfa5c69e2f 100644
--- a/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.rs
+++ b/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.rs
@@ -10,6 +10,7 @@ impl Foo for u32 {
     fn foo(&self, t: impl Clone) {}
 //~^ ERROR method `foo` has 1 type parameter but its trait declaration has 0 type parameters
 //~| NOTE found 1 type parameter
+//~| NOTE `impl Trait` introduces an implicit type parameter
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.stderr b/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.stderr
index af7fdde9a8e..30322f88cca 100644
--- a/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.stderr
+++ b/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.stderr
@@ -1,11 +1,14 @@
 error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
-  --> $DIR/type-arg-mismatch-due-to-impl-trait.rs:10:5
+  --> $DIR/type-arg-mismatch-due-to-impl-trait.rs:10:22
    |
 LL |     fn foo(&self, t: Self::T);
-   |     -------------------------- expected 0 type parameters
+   |           - expected 0 type parameters
 ...
 LL |     fn foo(&self, t: impl Clone) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found 1 type parameter
+   |                      ^^^^^^^^^^
+   |                      |
+   |                      found 1 type parameter
+   |                      `impl Trait` introduces an implicit type parameter
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/match/match-fn-call.stderr b/src/test/ui/match/match-fn-call.stderr
index 4e24621706b..bd918428351 100644
--- a/src/test/ui/match/match-fn-call.stderr
+++ b/src/test/ui/match/match-fn-call.stderr
@@ -2,13 +2,17 @@ error[E0164]: expected tuple struct/variant, found method `<Path>::new`
   --> $DIR/match-fn-call.rs:6:9
    |
 LL |         Path::new("foo") => println!("foo"),
-   |         ^^^^^^^^^^^^^^^^ not a tuple variant or struct
+   |         ^^^^^^^^^^^^^^^^ `fn` calls are not allowed in patterns
+   |
+   = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html
 
 error[E0164]: expected tuple struct/variant, found method `<Path>::new`
   --> $DIR/match-fn-call.rs:8:9
    |
 LL |         Path::new("bar") => println!("bar"),
-   |         ^^^^^^^^^^^^^^^^ not a tuple variant or struct
+   |         ^^^^^^^^^^^^^^^^ `fn` calls are not allowed in patterns
+   |
+   = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/symbol-names/issue-60925.legacy.stderr b/src/test/ui/symbol-names/issue-60925.legacy.stderr
index 0bbe424aa02..7fcd2ede31b 100644
--- a/src/test/ui/symbol-names/issue-60925.legacy.stderr
+++ b/src/test/ui/symbol-names/issue-60925.legacy.stderr
@@ -1,16 +1,16 @@
-error: symbol-name(_ZN11issue_609253foo36Foo$LT$issue_60925..llv$6d$..Foo$GT$3foo17h059a991a004536adE)
+error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h059a991a004536adE)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(issue_60925::foo::Foo<issue_60925::llv$6d$..Foo$GT$::foo::h059a991a004536ad)
+error: demangling(issue_60925::foo::Foo<issue_60925::llv$u6d$..Foo$GT$::foo::h059a991a004536ad)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling-alt(issue_60925::foo::Foo<issue_60925::llv$6d$..Foo$GT$::foo)
+error: demangling-alt(issue_60925::foo::Foo<issue_60925::llv$u6d$..Foo$GT$::foo)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
diff --git a/src/test/ui/symbol-names/issue-60925.rs b/src/test/ui/symbol-names/issue-60925.rs
index 09d68eebb95..89de15cc0f3 100644
--- a/src/test/ui/symbol-names/issue-60925.rs
+++ b/src/test/ui/symbol-names/issue-60925.rs
@@ -19,9 +19,9 @@ mod foo {
 
     impl Foo<::llvm::Foo> {
         #[rustc_symbol_name]
-        //[legacy]~^ ERROR symbol-name(_ZN11issue_609253foo36Foo$LT$issue_60925..llv$6d$..Foo$GT$3foo
-        //[legacy]~| ERROR demangling(issue_60925::foo::Foo<issue_60925::llv$6d$..Foo$GT$::foo
-        //[legacy]~| ERROR demangling-alt(issue_60925::foo::Foo<issue_60925::llv$6d$..Foo$GT$::foo)
+        //[legacy]~^ ERROR symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo
+        //[legacy]~| ERROR demangling(issue_60925::foo::Foo<issue_60925::llv$u6d$..Foo$GT$::foo
+        //[legacy]~| ERROR demangling-alt(issue_60925::foo::Foo<issue_60925::llv$u6d$..Foo$GT$::foo)
          //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs4fqI2P2rA04_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
             //[v0]~| ERROR demangling(<issue_60925[317d481089b8c8fe]::foo::Foo<issue_60925[317d481089b8c8fe]::llvm::Foo>>::foo)
             //[v0]~| ERROR demangling-alt(<issue_60925::foo::Foo<issue_60925::llvm::Foo>>::foo)