about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-03-31 14:00:55 +0000
committerbors <bors@rust-lang.org>2020-03-31 14:00:55 +0000
commit75ff3110ac6d8a0259023b83fd20d7ab295f8dd6 (patch)
tree16273bf92f9580d0c1a3fbb99b10d32c234902b7
parent2113659479a82ea69633b23ef710b58ab127755e (diff)
parent976f8d59dddac2ccddbe940953ee6247454e6736 (diff)
Auto merge of #70617 - Centril:rollup-063ycso, r=Centril
Rollup of 9 pull requests

Successful merges:

 - #69784 (Optimize strip_prefix and strip_suffix with str patterns)
 - #70548 (Add long error code for error E0226)
 - #70555 (resolve, `try_resolve_as_non_binding`: use `delay_span_bug` due to parser recovery)
 - #70561 (remove obsolete comment)
 - #70562 (infer array len from pattern)
 - #70585 (std: Fix over-aligned allocations on wasm32-wasi)
 - #70587 (Add `Rust` to the code snippet)
 - #70588 (Fix incorrect documentation for `str::{split_at, split_at_mut}`)
 - #70613 (more clippy fixes)

Failed merges:

r? @ghost
-rw-r--r--.github/ISSUE_TEMPLATE/ice.md2
-rw-r--r--src/liballoc/string.rs15
-rw-r--r--src/libcore/str/mod.rs41
-rw-r--r--src/libcore/str/pattern.rs85
-rw-r--r--src/librustc_error_codes/error_codes.rs2
-rw-r--r--src/librustc_error_codes/error_codes/E0226.md21
-rw-r--r--src/librustc_error_codes/error_codes/E0730.md4
-rw-r--r--src/librustc_interface/passes.rs2
-rw-r--r--src/librustc_mir/interpret/terminator.rs2
-rw-r--r--src/librustc_parse/lexer/mod.rs3
-rw-r--r--src/librustc_resolve/late.rs16
-rw-r--r--src/librustc_resolve/lib.rs1
-rw-r--r--src/librustc_save_analysis/lib.rs2
-rw-r--r--src/librustc_session/config.rs2
-rw-r--r--src/librustc_target/spec/i686_apple_darwin.rs2
-rw-r--r--src/librustc_target/spec/x86_64_apple_darwin.rs2
-rw-r--r--src/librustc_typeck/check/pat.rs45
-rw-r--r--src/librustdoc/clean/auto_trait.rs7
-rw-r--r--src/librustdoc/clean/mod.rs32
-rw-r--r--src/librustdoc/clean/utils.rs31
-rw-r--r--src/librustdoc/html/markdown.rs123
-rw-r--r--src/librustdoc/html/render.rs13
-rw-r--r--src/librustdoc/html/render/cache.rs2
-rw-r--r--src/libstd/io/stdio.rs4
-rw-r--r--src/libstd/sys/unix/process/process_unix.rs2
-rw-r--r--src/libstd/sys/wasi/alloc.rs2
-rw-r--r--src/test/ui/array-slice-vec/infer_array_len.rs21
-rw-r--r--src/test/ui/array-slice-vec/infer_array_len.stderr11
-rw-r--r--src/test/ui/array-slice-vec/match_arr_unknown_len.rs11
-rw-r--r--src/test/ui/array-slice-vec/match_arr_unknown_len.stderr20
-rw-r--r--src/test/ui/const-generics/infer_arg_from_pat.rs27
-rw-r--r--src/test/ui/const-generics/infer_arg_from_pat.stderr8
-rw-r--r--src/test/ui/const-generics/infer_arr_len_from_pat.rs13
-rw-r--r--src/test/ui/const-generics/infer_arr_len_from_pat.stderr8
-rw-r--r--src/test/ui/error-codes/E0730.rs2
-rw-r--r--src/test/ui/error-codes/E0730.stderr4
-rw-r--r--src/test/ui/parser/issue-70549-resolve-after-recovered-self-ctor.rs18
-rw-r--r--src/test/ui/parser/issue-70549-resolve-after-recovered-self-ctor.stderr56
-rw-r--r--src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr4
39 files changed, 470 insertions, 196 deletions
diff --git a/.github/ISSUE_TEMPLATE/ice.md b/.github/ISSUE_TEMPLATE/ice.md
index e669e4912f8..03bc4bab451 100644
--- a/.github/ISSUE_TEMPLATE/ice.md
+++ b/.github/ISSUE_TEMPLATE/ice.md
@@ -14,7 +14,7 @@ http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/
 
 ### Code
 
-```
+```Rust
 <code>
 ```
 
diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index 7c89d38caa4..1e5fe125c55 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -1849,6 +1849,21 @@ impl<'a, 'b> Pattern<'a> for &'b String {
     fn is_prefix_of(self, haystack: &'a str) -> bool {
         self[..].is_prefix_of(haystack)
     }
+
+    #[inline]
+    fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> {
+        self[..].strip_prefix_of(haystack)
+    }
+
+    #[inline]
+    fn is_suffix_of(self, haystack: &'a str) -> bool {
+        self[..].is_suffix_of(haystack)
+    }
+
+    #[inline]
+    fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str> {
+        self[..].strip_suffix_of(haystack)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 013ca182c13..dc7637cfdb9 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -9,7 +9,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use self::pattern::Pattern;
-use self::pattern::{DoubleEndedSearcher, ReverseSearcher, SearchStep, Searcher};
+use self::pattern::{DoubleEndedSearcher, ReverseSearcher, Searcher};
 
 use crate::char;
 use crate::fmt::{self, Write};
@@ -2642,7 +2642,7 @@ impl str {
     /// # Panics
     ///
     /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is
-    /// beyond the last code point of the string slice.
+    /// past the end of the last code point of the string slice.
     ///
     /// # Examples
     ///
@@ -2683,7 +2683,7 @@ impl str {
     /// # Panics
     ///
     /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is
-    /// beyond the last code point of the string slice.
+    /// past the end of the last code point of the string slice.
     ///
     /// # Examples
     ///
@@ -3986,26 +3986,15 @@ impl str {
     /// ```
     /// #![feature(str_strip)]
     ///
-    /// assert_eq!("foobar".strip_prefix("foo"), Some("bar"));
-    /// assert_eq!("foobar".strip_prefix("bar"), None);
+    /// assert_eq!("foo:bar".strip_prefix("foo:"), Some("bar"));
+    /// assert_eq!("foo:bar".strip_prefix("bar"), None);
     /// assert_eq!("foofoo".strip_prefix("foo"), Some("foo"));
     /// ```
     #[must_use = "this returns the remaining substring as a new slice, \
                   without modifying the original"]
     #[unstable(feature = "str_strip", reason = "newly added", issue = "67302")]
     pub fn strip_prefix<'a, P: Pattern<'a>>(&'a self, prefix: P) -> Option<&'a str> {
-        let mut matcher = prefix.into_searcher(self);
-        if let SearchStep::Match(start, len) = matcher.next() {
-            debug_assert_eq!(
-                start, 0,
-                "The first search step from Searcher \
-                 must include the first character"
-            );
-            // SAFETY: `Searcher` is known to return valid indices.
-            unsafe { Some(self.get_unchecked(len..)) }
-        } else {
-            None
-        }
+        prefix.strip_prefix_of(self)
     }
 
     /// Returns a string slice with the suffix removed.
@@ -4020,8 +4009,8 @@ impl str {
     ///
     /// ```
     /// #![feature(str_strip)]
-    /// assert_eq!("barfoo".strip_suffix("foo"), Some("bar"));
-    /// assert_eq!("barfoo".strip_suffix("bar"), None);
+    /// assert_eq!("bar:foo".strip_suffix(":foo"), Some("bar"));
+    /// assert_eq!("bar:foo".strip_suffix("bar"), None);
     /// assert_eq!("foofoo".strip_suffix("foo"), Some("foo"));
     /// ```
     #[must_use = "this returns the remaining substring as a new slice, \
@@ -4032,19 +4021,7 @@ impl str {
         P: Pattern<'a>,
         <P as Pattern<'a>>::Searcher: ReverseSearcher<'a>,
     {
-        let mut matcher = suffix.into_searcher(self);
-        if let SearchStep::Match(start, end) = matcher.next_back() {
-            debug_assert_eq!(
-                end,
-                self.len(),
-                "The first search step from ReverseSearcher \
-                 must include the last character"
-            );
-            // SAFETY: `Searcher` is known to return valid indices.
-            unsafe { Some(self.get_unchecked(..start)) }
-        } else {
-            None
-        }
+        suffix.strip_suffix_of(self)
     }
 
     /// Returns a string slice with all suffixes that match a pattern
diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs
index ffa418cba6c..30fd55f7b7f 100644
--- a/src/libcore/str/pattern.rs
+++ b/src/libcore/str/pattern.rs
@@ -47,6 +47,22 @@ pub trait Pattern<'a>: Sized {
         matches!(self.into_searcher(haystack).next(), SearchStep::Match(0, _))
     }
 
+    /// Removes the pattern from the front of haystack, if it matches.
+    #[inline]
+    fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> {
+        if let SearchStep::Match(start, len) = self.into_searcher(haystack).next() {
+            debug_assert_eq!(
+                start, 0,
+                "The first search step from Searcher \
+                 must include the first character"
+            );
+            // SAFETY: `Searcher` is known to return valid indices.
+            unsafe { Some(haystack.get_unchecked(len..)) }
+        } else {
+            None
+        }
+    }
+
     /// Checks whether the pattern matches at the back of the haystack
     #[inline]
     fn is_suffix_of(self, haystack: &'a str) -> bool
@@ -55,6 +71,26 @@ pub trait Pattern<'a>: Sized {
     {
         matches!(self.into_searcher(haystack).next_back(), SearchStep::Match(_, j) if haystack.len() == j)
     }
+
+    /// Removes the pattern from the back of haystack, if it matches.
+    #[inline]
+    fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str>
+    where
+        Self::Searcher: ReverseSearcher<'a>,
+    {
+        if let SearchStep::Match(start, end) = self.into_searcher(haystack).next_back() {
+            debug_assert_eq!(
+                end,
+                haystack.len(),
+                "The first search step from ReverseSearcher \
+                 must include the last character"
+            );
+            // SAFETY: `Searcher` is known to return valid indices.
+            unsafe { Some(haystack.get_unchecked(..start)) }
+        } else {
+            None
+        }
+    }
 }
 
 // Searcher
@@ -449,12 +485,25 @@ impl<'a> Pattern<'a> for char {
     }
 
     #[inline]
+    fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> {
+        self.encode_utf8(&mut [0u8; 4]).strip_prefix_of(haystack)
+    }
+
+    #[inline]
     fn is_suffix_of(self, haystack: &'a str) -> bool
     where
         Self::Searcher: ReverseSearcher<'a>,
     {
         self.encode_utf8(&mut [0u8; 4]).is_suffix_of(haystack)
     }
+
+    #[inline]
+    fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str>
+    where
+        Self::Searcher: ReverseSearcher<'a>,
+    {
+        self.encode_utf8(&mut [0u8; 4]).strip_suffix_of(haystack)
+    }
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -570,12 +619,25 @@ macro_rules! pattern_methods {
         }
 
         #[inline]
+        fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> {
+            ($pmap)(self).strip_prefix_of(haystack)
+        }
+
+        #[inline]
         fn is_suffix_of(self, haystack: &'a str) -> bool
         where
             $t: ReverseSearcher<'a>,
         {
             ($pmap)(self).is_suffix_of(haystack)
         }
+
+        #[inline]
+        fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str>
+        where
+            $t: ReverseSearcher<'a>,
+        {
+            ($pmap)(self).strip_suffix_of(haystack)
+        }
     };
 }
 
@@ -715,11 +777,34 @@ impl<'a, 'b> Pattern<'a> for &'b str {
         haystack.as_bytes().starts_with(self.as_bytes())
     }
 
+    /// Removes the pattern from the front of haystack, if it matches.
+    #[inline]
+    fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> {
+        if self.is_prefix_of(haystack) {
+            // SAFETY: prefix was just verified to exist.
+            unsafe { Some(haystack.get_unchecked(self.as_bytes().len()..)) }
+        } else {
+            None
+        }
+    }
+
     /// Checks whether the pattern matches at the back of the haystack
     #[inline]
     fn is_suffix_of(self, haystack: &'a str) -> bool {
         haystack.as_bytes().ends_with(self.as_bytes())
     }
+
+    /// Removes the pattern from the back of haystack, if it matches.
+    #[inline]
+    fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str> {
+        if self.is_suffix_of(haystack) {
+            let i = haystack.len() - self.as_bytes().len();
+            // SAFETY: suffix was just verified to exist.
+            unsafe { Some(haystack.get_unchecked(..i)) }
+        } else {
+            None
+        }
+    }
 }
 
 /////////////////////////////////////////////////////////////////////////////
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index 2f0a3fc1d1c..6e690655f60 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -119,6 +119,7 @@ E0222: include_str!("./error_codes/E0222.md"),
 E0223: include_str!("./error_codes/E0223.md"),
 E0224: include_str!("./error_codes/E0224.md"),
 E0225: include_str!("./error_codes/E0225.md"),
+E0226: include_str!("./error_codes/E0226.md"),
 E0229: include_str!("./error_codes/E0229.md"),
 E0230: include_str!("./error_codes/E0230.md"),
 E0231: include_str!("./error_codes/E0231.md"),
@@ -475,7 +476,6 @@ E0751: include_str!("./error_codes/E0751.md"),
 //  E0217, // ambiguous associated type, defined in multiple supertraits
 //  E0218, // no associated type defined
 //  E0219, // associated type defined in higher-ranked supertrait
-    E0226, // only a single explicit lifetime bound is permitted
     E0227, // ambiguous lifetime bound, explicit lifetime bound required
     E0228, // explicit lifetime bound required
 //  E0233,
diff --git a/src/librustc_error_codes/error_codes/E0226.md b/src/librustc_error_codes/error_codes/E0226.md
new file mode 100644
index 00000000000..4e65132ff0d
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0226.md
@@ -0,0 +1,21 @@
+More than one explicit lifetime bound was used on a trait object.
+
+Example of erroneous code:
+
+```compile_fail,E0226
+trait Foo {}
+
+type T<'a, 'b> = dyn Foo + 'a + 'b; // error: Trait object `arg` has two
+                                    //        lifetime bound, 'a and 'b.
+```
+
+Here `T` is a trait object with two explicit lifetime bounds, 'a and 'b.
+
+Only a single explicit lifetime bound is permitted on trait objects.
+To fix this error, consider removing one of the lifetime bounds:
+
+```
+trait Foo {}
+
+type T<'a> = dyn Foo + 'a;
+```
diff --git a/src/librustc_error_codes/error_codes/E0730.md b/src/librustc_error_codes/error_codes/E0730.md
index bf1f72be325..c2a71ca5669 100644
--- a/src/librustc_error_codes/error_codes/E0730.md
+++ b/src/librustc_error_codes/error_codes/E0730.md
@@ -7,8 +7,8 @@ Example of erroneous code:
 
 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
+        [1, 2, ..] => true, // error: cannot pattern-match on an
+                            //        array without a fixed length
         _ => false
     }
 }
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 7d066a31a07..e3fc4fa52fb 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -711,7 +711,7 @@ impl<'tcx> QueryContext<'tcx> {
     }
 
     pub fn print_stats(&mut self) {
-        self.enter(|tcx| ty::query::print_stats(tcx))
+        self.enter(ty::query::print_stats)
     }
 }
 
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index a490a0f9bcc..8e7abcd09c2 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -30,7 +30,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 trace!("SwitchInt({:?})", *discr);
 
                 // Branch to the `otherwise` case by default, if no match is found.
-                assert!(targets.len() > 0);
+                assert!(!targets.is_empty());
                 let mut target_block = targets[targets.len() - 1];
 
                 for (index, &const_int) in values.iter().enumerate() {
diff --git a/src/librustc_parse/lexer/mod.rs b/src/librustc_parse/lexer/mod.rs
index ac58cbb9e8d..c7ea10ec812 100644
--- a/src/librustc_parse/lexer/mod.rs
+++ b/src/librustc_parse/lexer/mod.rs
@@ -93,9 +93,6 @@ impl<'a> StringReader<'a> {
     }
 
     /// Returns the next token, including trivia like whitespace or comments.
-    ///
-    /// `Err(())` means that some errors were encountered, which can be
-    /// retrieved using `buffer_fatal_errors`.
     pub fn next_token(&mut self) -> Token {
         let start_src_index = self.src_index(self.pos);
         let text: &str = &self.src[start_src_index..self.end_src_index];
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index 1b40d2bea06..2b90527a825 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -1536,20 +1536,18 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Not);
 
         match res {
-            Res::Def(DefKind::Ctor(_, CtorKind::Const), _)
-            | Res::Def(DefKind::Const, _)
-            | Res::Def(DefKind::ConstParam, _)
-                if is_syntactic_ambiguity =>
-            {
+            Res::SelfCtor(_) // See #70549.
+            | Res::Def(
+                DefKind::Ctor(_, CtorKind::Const) | DefKind::Const | DefKind::ConstParam,
+                _,
+            ) if is_syntactic_ambiguity => {
                 // Disambiguate in favor of a unit struct/variant or constant pattern.
                 if let Some(binding) = binding {
                     self.r.record_use(ident, ValueNS, binding, false);
                 }
                 Some(res)
             }
-            Res::Def(DefKind::Ctor(..), _)
-            | Res::Def(DefKind::Const, _)
-            | Res::Def(DefKind::Static, _) => {
+            Res::Def(DefKind::Ctor(..) | DefKind::Const | DefKind::Static, _) => {
                 // This is unambiguously a fresh binding, either syntactically
                 // (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves
                 // to something unusable as a pattern (e.g., constructor function),
@@ -1572,7 +1570,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
             _ => span_bug!(
                 ident.span,
                 "unexpected resolution for an identifier in pattern: {:?}",
-                res
+                res,
             ),
         }
     }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 57454b62cdd..75c5dfb8d18 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -10,6 +10,7 @@
 #![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
 #![feature(nll)]
+#![feature(or_patterns)]
 #![recursion_limit = "256"]
 
 pub use rustc_hir::def::{Namespace, PerNS};
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 277848a7d61..24b7be0c9b3 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -591,7 +591,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                 Some(Data::RefData(Ref {
                     kind: RefKind::Function,
                     span,
-                    ref_id: def_id.or(decl_id).map(id_from_def_id).unwrap_or_else(|| null_id()),
+                    ref_id: def_id.or(decl_id).map(id_from_def_id).unwrap_or_else(null_id),
                 }))
             }
             ast::ExprKind::Path(_, ref path) => {
diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs
index 663cfa223c7..54481bd124d 100644
--- a/src/librustc_session/config.rs
+++ b/src/librustc_session/config.rs
@@ -1650,7 +1650,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
 
     check_thread_count(&debugging_opts, error_format);
 
-    let incremental = cg.incremental.as_ref().map(|m| PathBuf::from(m));
+    let incremental = cg.incremental.as_ref().map(PathBuf::from);
 
     if debugging_opts.profile && incremental.is_some() {
         early_error(
diff --git a/src/librustc_target/spec/i686_apple_darwin.rs b/src/librustc_target/spec/i686_apple_darwin.rs
index 033b87b110e..b7a34f9740a 100644
--- a/src/librustc_target/spec/i686_apple_darwin.rs
+++ b/src/librustc_target/spec/i686_apple_darwin.rs
@@ -16,7 +16,7 @@ pub fn target() -> TargetResult {
     let llvm_target = super::apple_base::macos_llvm_target(&arch);
 
     Ok(Target {
-        llvm_target: llvm_target,
+        llvm_target,
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
diff --git a/src/librustc_target/spec/x86_64_apple_darwin.rs b/src/librustc_target/spec/x86_64_apple_darwin.rs
index e846f42f8f8..31011e84749 100644
--- a/src/librustc_target/spec/x86_64_apple_darwin.rs
+++ b/src/librustc_target/spec/x86_64_apple_darwin.rs
@@ -16,7 +16,7 @@ pub fn target() -> TargetResult {
     let llvm_target = super::apple_base::macos_llvm_target(&arch);
 
     Ok(Target {
-        llvm_target: llvm_target,
+        llvm_target,
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
         target_c_int_width: "32".to_string(),
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index fc91142dd7d..b3cace8298a 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -1355,16 +1355,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> Ty<'tcx> {
         let err = self.tcx.types.err;
         let expected = self.structurally_resolved_type(span, expected);
-        let (inner_ty, slice_ty, expected) = match expected.kind {
+        let (element_ty, slice_ty, inferred) = match expected.kind {
             // An array, so we might have something like `let [a, b, c] = [0, 1, 2];`.
-            ty::Array(inner_ty, len) => {
+            ty::Array(element_ty, len) => {
                 let min = before.len() as u64 + after.len() as u64;
-                let slice_ty = self
-                    .check_array_pat_len(span, slice, len, min)
-                    .map_or(err, |len| self.tcx.mk_array(inner_ty, len));
-                (inner_ty, slice_ty, expected)
+                let (slice_ty, expected) =
+                    self.check_array_pat_len(span, element_ty, expected, slice, len, min);
+                (element_ty, slice_ty, expected)
             }
-            ty::Slice(inner_ty) => (inner_ty, expected, expected),
+            ty::Slice(element_ty) => (element_ty, expected, expected),
             // The expected type must be an array or slice, but was neither, so error.
             _ => {
                 if !expected.references_error() {
@@ -1376,7 +1375,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Type check all the patterns before `slice`.
         for elt in before {
-            self.check_pat(&elt, inner_ty, def_bm, ti);
+            self.check_pat(&elt, element_ty, def_bm, ti);
         }
         // Type check the `slice`, if present, against its expected type.
         if let Some(slice) = slice {
@@ -1384,22 +1383,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
         // Type check the elements after `slice`, if present.
         for elt in after {
-            self.check_pat(&elt, inner_ty, def_bm, ti);
+            self.check_pat(&elt, element_ty, def_bm, ti);
         }
-        expected
+        inferred
     }
 
     /// Type check the length of an array pattern.
     ///
-    /// Return the length of the variable length pattern,
-    /// if it exists and there are no errors.
+    /// Returns both the type of the variable length pattern
+    /// (or `tcx.err` in case there is none),
+    /// and the potentially inferred array type.
     fn check_array_pat_len(
         &self,
         span: Span,
+        element_ty: Ty<'tcx>,
+        arr_ty: Ty<'tcx>,
         slice: Option<&'tcx Pat<'tcx>>,
         len: &ty::Const<'tcx>,
         min_len: u64,
-    ) -> Option<u64> {
+    ) -> (Ty<'tcx>, Ty<'tcx>) {
         if let Some(len) = len.try_eval_usize(self.tcx, self.param_env) {
             // Now we know the length...
             if slice.is_none() {
@@ -1409,21 +1411,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if min_len != len {
                     self.error_scrutinee_inconsistent_length(span, min_len, len);
                 }
-            } else if let r @ Some(_) = len.checked_sub(min_len) {
+            } else if let Some(pat_len) = len.checked_sub(min_len) {
                 // The variable-length pattern was there,
                 // so it has an array type with the remaining elements left as its size...
-                return r;
+                return (self.tcx.mk_array(element_ty, pat_len), arr_ty);
             } else {
                 // ...however, in this case, there were no remaining elements.
                 // That is, the slice pattern requires more than the array type offers.
                 self.error_scrutinee_with_rest_inconsistent_length(span, min_len, len);
             }
+        } else if slice.is_none() {
+            // We have a pattern with a fixed length,
+            // which we can use to infer the length of the array.
+            let updated_arr_ty = self.tcx.mk_array(element_ty, min_len);
+            self.demand_eqtype(span, updated_arr_ty, arr_ty);
+            return (self.tcx.types.err, updated_arr_ty);
         } else {
-            // No idea what the length is, which happens if we have e.g.,
-            // `let [a, b] = arr` where `arr: [T; N]` where `const N: usize`.
+            // We have a variable-length pattern and don't know the array length.
+            // This happens if we have e.g.,
+            // `let [a, b, ..] = arr` where `arr: [T; N]` where `const N: usize`.
             self.error_scrutinee_unfixed_length(span);
         }
-        None
+        (self.tcx.types.err, arr_ty)
     }
 
     fn error_scrutinee_inconsistent_length(&self, span: Span, min_len: u64, size: u64) {
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index bf64da56ade..9f327b0b743 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -497,11 +497,8 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                     // of the type.
                     // Therefore, we make sure that we never add a ?Sized
                     // bound for projections
-                    match &ty {
-                        &Type::QPath { .. } => {
-                            has_sized.insert(ty.clone());
-                        }
-                        _ => {}
+                    if let Type::QPath { .. } = ty {
+                        has_sized.insert(ty.clone());
                     }
 
                     if bounds.is_empty() {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index c09e7411864..f8e44bc5a1a 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -521,11 +521,8 @@ impl<'tcx> Clean<Option<WherePredicate>>
     fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
         let ty::OutlivesPredicate(ref a, ref b) = *self;
 
-        match (a, b) {
-            (ty::ReEmpty(_), ty::ReEmpty(_)) => {
-                return None;
-            }
-            _ => {}
+        if let (ty::ReEmpty(_), ty::ReEmpty(_)) = (a, b) {
+            return None;
         }
 
         Some(WherePredicate::RegionPredicate {
@@ -539,9 +536,8 @@ impl<'tcx> Clean<Option<WherePredicate>> for ty::OutlivesPredicate<Ty<'tcx>, ty:
     fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
         let ty::OutlivesPredicate(ref ty, ref lt) = *self;
 
-        match lt {
-            ty::ReEmpty(_) => return None,
-            _ => {}
+        if let ty::ReEmpty(_) = lt {
+            return None;
         }
 
         Some(WherePredicate::BoundPredicate {
@@ -2239,15 +2235,12 @@ impl Clean<Vec<Item>> for doctree::Import<'_> {
         } else {
             let name = self.name;
             if !please_inline {
-                match path.res {
-                    Res::Def(DefKind::Mod, did) => {
-                        if !did.is_local() && did.index == CRATE_DEF_INDEX {
-                            // if we're `pub use`ing an extern crate root, don't inline it unless we
-                            // were specifically asked for it
-                            denied = true;
-                        }
+                if let Res::Def(DefKind::Mod, did) = path.res {
+                    if !did.is_local() && did.index == CRATE_DEF_INDEX {
+                        // if we're `pub use`ing an extern crate root, don't inline it unless we
+                        // were specifically asked for it
+                        denied = true;
                     }
-                    _ => {}
                 }
             }
             if !denied {
@@ -2426,10 +2419,9 @@ impl From<GenericBound> for SimpleBound {
             GenericBound::TraitBound(t, mod_) => match t.trait_ {
                 Type::ResolvedPath { path, param_names, .. } => SimpleBound::TraitBound(
                     path.segments,
-                    param_names.map_or_else(
-                        || Vec::new(),
-                        |v| v.iter().map(|p| SimpleBound::from(p.clone())).collect(),
-                    ),
+                    param_names.map_or_else(Vec::new, |v| {
+                        v.iter().map(|p| SimpleBound::from(p.clone())).collect()
+                    }),
                     t.generic_params,
                     mod_,
                 ),
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 05a8302ebab..9e96015d306 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -121,7 +121,7 @@ pub fn external_generic_args(
     let args: Vec<_> = substs
         .iter()
         .filter_map(|kind| match kind.unpack() {
-            GenericArgKind::Lifetime(lt) => lt.clean(cx).map(|lt| GenericArg::Lifetime(lt)),
+            GenericArgKind::Lifetime(lt) => lt.clean(cx).map(GenericArg::Lifetime),
             GenericArgKind::Type(_) if skip_self => {
                 skip_self = false;
                 None
@@ -198,27 +198,24 @@ pub fn get_real_types(
         }) {
             let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]);
             for bound in bounds.iter() {
-                match *bound {
-                    GenericBound::TraitBound(ref poly_trait, _) => {
-                        for x in poly_trait.generic_params.iter() {
-                            if !x.is_type() {
-                                continue;
-                            }
-                            if let Some(ty) = x.get_type() {
-                                let adds = get_real_types(generics, &ty, cx, recurse + 1);
-                                if !adds.is_empty() {
-                                    res.extend(adds);
-                                } else if !ty.is_full_generic() {
-                                    if let Some(did) = ty.def_id() {
-                                        if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
-                                            res.insert((ty, kind));
-                                        }
+                if let GenericBound::TraitBound(ref poly_trait, _) = *bound {
+                    for x in poly_trait.generic_params.iter() {
+                        if !x.is_type() {
+                            continue;
+                        }
+                        if let Some(ty) = x.get_type() {
+                            let adds = get_real_types(generics, &ty, cx, recurse + 1);
+                            if !adds.is_empty() {
+                                res.extend(adds);
+                            } else if !ty.is_full_generic() {
+                                if let Some(did) = ty.def_id() {
+                                    if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
+                                        res.insert((ty, kind));
                                     }
                                 }
                             }
                         }
                     }
-                    _ => {}
                 }
             }
         }
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index e13bf270440..9fe3e35d197 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -448,7 +448,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for SummaryLine<'a, I> {
         if !self.started {
             self.started = true;
         }
-        while let Some(event) = self.inner.next() {
+        if let Some(event) = self.inner.next() {
             let mut is_start = true;
             let is_allowed_tag = match event {
                 Event::Start(Tag::CodeBlock(_)) | Event::End(Tag::CodeBlock(_)) => {
@@ -944,75 +944,70 @@ crate fn rust_code_blocks(md: &str) -> Vec<RustCodeBlock> {
     let mut p = Parser::new_ext(md, opts()).into_offset_iter();
 
     while let Some((event, offset)) = p.next() {
-        match event {
-            Event::Start(Tag::CodeBlock(syntax)) => {
-                let (syntax, code_start, code_end, range, is_fenced) = match syntax {
-                    CodeBlockKind::Fenced(syntax) => {
-                        let syntax = syntax.as_ref();
-                        let lang_string = if syntax.is_empty() {
-                            LangString::all_false()
-                        } else {
-                            LangString::parse(&*syntax, ErrorCodes::Yes, false)
-                        };
-                        if !lang_string.rust {
+        if let Event::Start(Tag::CodeBlock(syntax)) = event {
+            let (syntax, code_start, code_end, range, is_fenced) = match syntax {
+                CodeBlockKind::Fenced(syntax) => {
+                    let syntax = syntax.as_ref();
+                    let lang_string = if syntax.is_empty() {
+                        LangString::all_false()
+                    } else {
+                        LangString::parse(&*syntax, ErrorCodes::Yes, false)
+                    };
+                    if !lang_string.rust {
+                        continue;
+                    }
+                    let syntax = if syntax.is_empty() { None } else { Some(syntax.to_owned()) };
+                    let (code_start, mut code_end) = match p.next() {
+                        Some((Event::Text(_), offset)) => (offset.start, offset.end),
+                        Some((_, sub_offset)) => {
+                            let code = Range { start: sub_offset.start, end: sub_offset.start };
+                            code_blocks.push(RustCodeBlock {
+                                is_fenced: true,
+                                range: offset,
+                                code,
+                                syntax,
+                            });
                             continue;
                         }
-                        let syntax = if syntax.is_empty() { None } else { Some(syntax.to_owned()) };
-                        let (code_start, mut code_end) = match p.next() {
-                            Some((Event::Text(_), offset)) => (offset.start, offset.end),
-                            Some((_, sub_offset)) => {
-                                let code = Range { start: sub_offset.start, end: sub_offset.start };
-                                code_blocks.push(RustCodeBlock {
-                                    is_fenced: true,
-                                    range: offset,
-                                    code,
-                                    syntax,
-                                });
-                                continue;
-                            }
-                            None => {
-                                let code = Range { start: offset.end, end: offset.end };
-                                code_blocks.push(RustCodeBlock {
-                                    is_fenced: true,
-                                    range: offset,
-                                    code,
-                                    syntax,
-                                });
-                                continue;
-                            }
-                        };
-                        while let Some((Event::Text(_), offset)) = p.next() {
-                            code_end = offset.end;
+                        None => {
+                            let code = Range { start: offset.end, end: offset.end };
+                            code_blocks.push(RustCodeBlock {
+                                is_fenced: true,
+                                range: offset,
+                                code,
+                                syntax,
+                            });
+                            continue;
                         }
-                        (syntax, code_start, code_end, offset, true)
+                    };
+                    while let Some((Event::Text(_), offset)) = p.next() {
+                        code_end = offset.end;
                     }
-                    CodeBlockKind::Indented => {
-                        // The ending of the offset goes too far sometime so we reduce it by one in
-                        // these cases.
-                        if offset.end > offset.start
-                            && md.get(offset.end..=offset.end) == Some(&"\n")
-                        {
-                            (
-                                None,
-                                offset.start,
-                                offset.end,
-                                Range { start: offset.start, end: offset.end - 1 },
-                                false,
-                            )
-                        } else {
-                            (None, offset.start, offset.end, offset, false)
-                        }
+                    (syntax, code_start, code_end, offset, true)
+                }
+                CodeBlockKind::Indented => {
+                    // The ending of the offset goes too far sometime so we reduce it by one in
+                    // these cases.
+                    if offset.end > offset.start && md.get(offset.end..=offset.end) == Some(&"\n") {
+                        (
+                            None,
+                            offset.start,
+                            offset.end,
+                            Range { start: offset.start, end: offset.end - 1 },
+                            false,
+                        )
+                    } else {
+                        (None, offset.start, offset.end, offset, false)
                     }
-                };
+                }
+            };
 
-                code_blocks.push(RustCodeBlock {
-                    is_fenced,
-                    range,
-                    code: Range { start: code_start, end: code_end },
-                    syntax,
-                });
-            }
-            _ => (),
+            code_blocks.push(RustCodeBlock {
+                is_fenced,
+                range,
+                code: Range { start: code_start, end: code_end },
+                syntax,
+            });
         }
     }
 
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 1377338ce4a..f51f47a8d33 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -782,7 +782,7 @@ themePicker.onblur = handleThemeButtonsBlur;
                         .split('"')
                         .next()
                         .map(|s| s.to_owned())
-                        .unwrap_or_else(|| String::new()),
+                        .unwrap_or_else(String::new),
                 );
             }
         }
@@ -2158,7 +2158,7 @@ fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean:
                     docs = MarkdownSummaryLine(doc_value, &myitem.links()).to_string(),
                     class = myitem.type_(),
                     add = add,
-                    stab = stab.unwrap_or_else(|| String::new()),
+                    stab = stab.unwrap_or_else(String::new),
                     unsafety_flag = unsafety_flag,
                     href = item_path(myitem.type_(), myitem.name.as_ref().unwrap()),
                     title = [full_path(cx, myitem), myitem.type_().to_string()]
@@ -4593,12 +4593,9 @@ fn collect_paths_for_type(first_ty: clean::Type) -> Vec<String> {
                 let get_extern = || cache.external_paths.get(&did).map(|s| s.0.clone());
                 let fqp = cache.exact_paths.get(&did).cloned().or_else(get_extern);
 
-                match fqp {
-                    Some(path) => {
-                        out.push(path.join("::"));
-                    }
-                    _ => {}
-                };
+                if let Some(path) = fqp {
+                    out.push(path.join("::"));
+                }
             }
             clean::Type::Tuple(tys) => {
                 work.extend(tys.into_iter());
diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs
index 450f44ffeaf..d9f6f7b466a 100644
--- a/src/librustdoc/html/render/cache.rs
+++ b/src/librustdoc/html/render/cache.rs
@@ -590,7 +590,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
     for item in search_index {
         item.parent_idx = item.parent.and_then(|defid| {
             if defid_to_pathid.contains_key(&defid) {
-                defid_to_pathid.get(&defid).map(|x| *x)
+                defid_to_pathid.get(&defid).copied()
             } else {
                 let pathid = lastpathid;
                 defid_to_pathid.insert(defid, pathid);
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index 9a82ae7626d..a064c552c84 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -496,7 +496,7 @@ pub fn stdout() -> Stdout {
         unsafe {
             let ret = Arc::new(ReentrantMutex::new(RefCell::new(LineWriter::new(stdout))));
             ret.init();
-            return ret;
+            ret
         }
     }
 }
@@ -664,7 +664,7 @@ pub fn stderr() -> Stderr {
             *INSTANCE.lock().borrow_mut() = Maybe::Real(stderr);
         }
     });
-    return Stderr { inner: &INSTANCE };
+    Stderr { inner: &INSTANCE }
 }
 
 impl Stderr {
diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs
index 07d0fbf61fe..f389c60615f 100644
--- a/src/libstd/sys/unix/process/process_unix.rs
+++ b/src/libstd/sys/unix/process/process_unix.rs
@@ -72,7 +72,7 @@ impl Command {
             }
         };
 
-        let mut p = Process { pid: pid, status: None };
+        let mut p = Process { pid, status: None };
         drop(output);
         let mut bytes = [0; 8];
 
diff --git a/src/libstd/sys/wasi/alloc.rs b/src/libstd/sys/wasi/alloc.rs
index e9760d050e1..bc614162784 100644
--- a/src/libstd/sys/wasi/alloc.rs
+++ b/src/libstd/sys/wasi/alloc.rs
@@ -10,7 +10,7 @@ unsafe impl GlobalAlloc for System {
         if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
             libc::malloc(layout.size()) as *mut u8
         } else {
-            libc::aligned_alloc(layout.size(), layout.align()) as *mut u8
+            libc::aligned_alloc(layout.align(), layout.size()) as *mut u8
         }
     }
 
diff --git a/src/test/ui/array-slice-vec/infer_array_len.rs b/src/test/ui/array-slice-vec/infer_array_len.rs
new file mode 100644
index 00000000000..22fe7cb8838
--- /dev/null
+++ b/src/test/ui/array-slice-vec/infer_array_len.rs
@@ -0,0 +1,21 @@
+// see issue #70529
+struct A;
+
+impl From<A> for [u8; 2] {
+    fn from(a: A) -> Self {
+        [0; 2]
+    }
+}
+
+impl From<A> for [u8; 3] {
+    fn from(a: A) -> Self {
+        [0; 3]
+    }
+}
+
+
+fn main() {
+    let a = A;
+    let [_, _] = a.into();
+    //~^ ERROR type annotations needed
+}
diff --git a/src/test/ui/array-slice-vec/infer_array_len.stderr b/src/test/ui/array-slice-vec/infer_array_len.stderr
new file mode 100644
index 00000000000..6eed4ce4f0c
--- /dev/null
+++ b/src/test/ui/array-slice-vec/infer_array_len.stderr
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/infer_array_len.rs:19:9
+   |
+LL |     let [_, _] = a.into();
+   |         ^^^^^^ consider giving this pattern a type
+   |
+   = note: type must be known at this point
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/array-slice-vec/match_arr_unknown_len.rs b/src/test/ui/array-slice-vec/match_arr_unknown_len.rs
new file mode 100644
index 00000000000..7f3da75ddcb
--- /dev/null
+++ b/src/test/ui/array-slice-vec/match_arr_unknown_len.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] => true, //~ ERROR mismatched types
+        _ => false
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr b/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr
new file mode 100644
index 00000000000..9edb139028b
--- /dev/null
+++ b/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr
@@ -0,0 +1,20 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/match_arr_unknown_len.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0308]: mismatched types
+  --> $DIR/match_arr_unknown_len.rs:6:9
+   |
+LL |         [1, 2] => true,
+   |         ^^^^^^ expected `2usize`, found `N`
+   |
+   = note: expected array `[u32; 2]`
+              found array `[u32; _]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/infer_arg_from_pat.rs b/src/test/ui/const-generics/infer_arg_from_pat.rs
new file mode 100644
index 00000000000..a4e3d3dee4a
--- /dev/null
+++ b/src/test/ui/const-generics/infer_arg_from_pat.rs
@@ -0,0 +1,27 @@
+// run-pass
+//
+// see issue #70529
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+struct A<const N: usize> {
+    arr: [u8; N],
+}
+
+impl<const N: usize> A<N> {
+    fn new() -> Self {
+        A {
+            arr: [0; N],
+        }
+    }
+
+    fn value(&self) -> usize {
+        N
+    }
+}
+
+fn main() {
+    let a = A::new();
+    let [_, _] = a.arr;
+    assert_eq!(a.value(), 2);
+}
diff --git a/src/test/ui/const-generics/infer_arg_from_pat.stderr b/src/test/ui/const-generics/infer_arg_from_pat.stderr
new file mode 100644
index 00000000000..ad6bf3e235a
--- /dev/null
+++ b/src/test/ui/const-generics/infer_arg_from_pat.stderr
@@ -0,0 +1,8 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/infer_arg_from_pat.rs:4:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
diff --git a/src/test/ui/const-generics/infer_arr_len_from_pat.rs b/src/test/ui/const-generics/infer_arr_len_from_pat.rs
new file mode 100644
index 00000000000..70633bbb141
--- /dev/null
+++ b/src/test/ui/const-generics/infer_arr_len_from_pat.rs
@@ -0,0 +1,13 @@
+// check-pass
+//
+// see issue #70529
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+fn as_chunks<const N: usize>() -> [u8; N] {
+    loop {}
+}
+
+fn main() {
+    let [_, _] = as_chunks();
+}
diff --git a/src/test/ui/const-generics/infer_arr_len_from_pat.stderr b/src/test/ui/const-generics/infer_arr_len_from_pat.stderr
new file mode 100644
index 00000000000..6f5b601e14c
--- /dev/null
+++ b/src/test/ui/const-generics/infer_arr_len_from_pat.stderr
@@ -0,0 +1,8 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/infer_arr_len_from_pat.rs:4:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
diff --git a/src/test/ui/error-codes/E0730.rs b/src/test/ui/error-codes/E0730.rs
index e5048d6e6e3..66a6e1c817a 100644
--- a/src/test/ui/error-codes/E0730.rs
+++ b/src/test/ui/error-codes/E0730.rs
@@ -3,7 +3,7 @@
 
 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
+        [1, 2, ..] => true, //~ ERROR cannot pattern-match on an array without a fixed length
         _ => false
     }
 }
diff --git a/src/test/ui/error-codes/E0730.stderr b/src/test/ui/error-codes/E0730.stderr
index 9309ee99064..fb53ae31c0b 100644
--- a/src/test/ui/error-codes/E0730.stderr
+++ b/src/test/ui/error-codes/E0730.stderr
@@ -9,8 +9,8 @@ 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,
-   |         ^^^^^^^^^
+LL |         [1, 2, ..] => true,
+   |         ^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-70549-resolve-after-recovered-self-ctor.rs b/src/test/ui/parser/issue-70549-resolve-after-recovered-self-ctor.rs
new file mode 100644
index 00000000000..aeccd0d9f76
--- /dev/null
+++ b/src/test/ui/parser/issue-70549-resolve-after-recovered-self-ctor.rs
@@ -0,0 +1,18 @@
+struct S {}
+
+impl S {
+    fn foo(&mur Self) {}
+    //~^ ERROR expected identifier, found keyword `Self`
+    //~| ERROR expected one of `:`, `@`
+    //~| ERROR the `Self` constructor can only be used with
+    fn bar(&'static mur Self) {}
+    //~^ ERROR unexpected lifetime
+    //~| ERROR expected identifier, found keyword `Self`
+    //~| ERROR expected one of `:`, `@`
+    //~| ERROR the `Self` constructor can only be used with
+
+    fn baz(&mur Self @ _) {}
+    //~^ ERROR expected one of `:`, `@`
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-70549-resolve-after-recovered-self-ctor.stderr b/src/test/ui/parser/issue-70549-resolve-after-recovered-self-ctor.stderr
new file mode 100644
index 00000000000..421f1454036
--- /dev/null
+++ b/src/test/ui/parser/issue-70549-resolve-after-recovered-self-ctor.stderr
@@ -0,0 +1,56 @@
+error: expected identifier, found keyword `Self`
+  --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:4:17
+   |
+LL |     fn foo(&mur Self) {}
+   |                 ^^^^ expected identifier, found keyword
+
+error: expected one of `:`, `@`, or `|`, found keyword `Self`
+  --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:4:17
+   |
+LL |     fn foo(&mur Self) {}
+   |            -----^^^^
+   |            |    |
+   |            |    expected one of `:`, `@`, or `|`
+   |            help: declare the type after the parameter binding: `<identifier>: <type>`
+
+error: unexpected lifetime `'static` in pattern
+  --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:8:13
+   |
+LL |     fn bar(&'static mur Self) {}
+   |             ^^^^^^^ help: remove the lifetime
+
+error: expected identifier, found keyword `Self`
+  --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:8:25
+   |
+LL |     fn bar(&'static mur Self) {}
+   |                         ^^^^ expected identifier, found keyword
+
+error: expected one of `:`, `@`, or `|`, found keyword `Self`
+  --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:8:25
+   |
+LL |     fn bar(&'static mur Self) {}
+   |            -------------^^^^
+   |            |            |
+   |            |            expected one of `:`, `@`, or `|`
+   |            help: declare the type after the parameter binding: `<identifier>: <type>`
+
+error: expected one of `:`, `@`, or `|`, found keyword `Self`
+  --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:14:17
+   |
+LL |     fn baz(&mur Self @ _) {}
+   |                 ^^^^ expected one of `:`, `@`, or `|`
+
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:4:17
+   |
+LL |     fn foo(&mur Self) {}
+   |                 ^^^^ help: use curly brackets: `Self { /* fields */ }`
+
+error: the `Self` constructor can only be used with tuple or unit structs
+  --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:8:25
+   |
+LL |     fn bar(&'static mur Self) {}
+   |                         ^^^^ help: use curly brackets: `Self { /* fields */ }`
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr b/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr
index 184cead2123..ea9be77a3e8 100644
--- a/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr
+++ b/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr
@@ -31,5 +31,5 @@ LL | struct Foo<'a,'b,'c> {
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0392, E0478.
-For more information about an error, try `rustc --explain E0392`.
+Some errors have detailed explanations: E0226, E0392, E0478.
+For more information about an error, try `rustc --explain E0226`.