From 8f7eb6229cb301c2ee7900a36a13f2906518378f Mon Sep 17 00:00:00 2001 From: Julien Philippon Date: Mon, 30 Mar 2020 02:50:53 +0200 Subject: [PATCH 01/13] Add long error code for error E0226 --- src/librustc_error_codes/error_codes.rs | 2 +- src/librustc_error_codes/error_codes/E0226.md | 20 +++++++++++++++++++ ...unds-on-objects-and-type-parameters.stderr | 4 ++-- 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 src/librustc_error_codes/error_codes/E0226.md diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 2f0a3fc1d1c38..6e690655f60c5 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 0000000000000..e485771fc1b65 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0226.md @@ -0,0 +1,20 @@ +Only a single explicit lifetime bound is permitted on trait objects. + +Example of erroneous code: + +```compile_fail +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. + +To fix this error, consider removing one of the lifetime bounds: + +``` +trait Foo {} + +type T<'a> = dyn Foo + 'a; +``` 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 184cead21231f..ea9be77a3e8b5 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`. From 9f86d285378012c5c9e2621ba2b6b403e1d84422 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 30 Mar 2020 08:40:23 +0200 Subject: [PATCH 02/13] try_resolve_as_non_binding: span_bug -> delay_span_bug --- src/librustc_resolve/late.rs | 16 +++--- src/librustc_resolve/lib.rs | 1 + ...70549-resolve-after-recovered-self-ctor.rs | 18 ++++++ ...9-resolve-after-recovered-self-ctor.stderr | 56 +++++++++++++++++++ 4 files changed, 82 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/parser/issue-70549-resolve-after-recovered-self-ctor.rs create mode 100644 src/test/ui/parser/issue-70549-resolve-after-recovered-self-ctor.stderr diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 1b40d2bea06c3..2b90527a82537 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 57454b62cdd0f..75c5dfb8d18b0 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/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 0000000000000..aeccd0d9f76ca --- /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 0000000000000..421f145403623 --- /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: `: ` + +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: `: ` + +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 + From d6f71f0c9a609add86a4eff8060aa9c1d74c1d71 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Mon, 30 Mar 2020 13:38:17 +0200 Subject: [PATCH 03/13] remove obsolete comment Made obsolete by b5e35b128efeed4bfdb4b1ee9d0697389ec9f164 --- src/librustc_parse/lexer/mod.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/librustc_parse/lexer/mod.rs b/src/librustc_parse/lexer/mod.rs index ac58cbb9e8dae..c7ea10ec81258 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]; From ac478f2f610bd93c25c82491526ea153ad103ac0 Mon Sep 17 00:00:00 2001 From: Nikhil Benesch Date: Fri, 6 Mar 2020 15:11:24 -0500 Subject: [PATCH 04/13] Optimize strip_prefix and strip_suffix with str patterns Constructing a Searcher in strip_prefix and strip_suffix is unnecessarily slow when the pattern is a fixed-length string. Add strip_prefix and strip_suffix methods to the Pattern trait, and add optimized implementations of these methods in the str implementation. The old implementation is retained as the default for these methods. --- src/liballoc/string.rs | 15 +++++++ src/libcore/str/mod.rs | 37 ++++------------- src/libcore/str/pattern.rs | 85 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 30 deletions(-) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 7c89d38caa4e6..1e5fe125c550d 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 013ca182c13cd..681dfda4ad517 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}; @@ -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>,

>::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 ffa418cba6c99..30fd55f7b7f64 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 @@ -448,6 +484,11 @@ impl<'a> Pattern<'a> for char { self.encode_utf8(&mut [0u8; 4]).is_prefix_of(haystack) } + #[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 @@ -455,6 +496,14 @@ impl<'a> Pattern<'a> for char { { 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) + } } ///////////////////////////////////////////////////////////////////////////// @@ -569,6 +618,11 @@ macro_rules! pattern_methods { ($pmap)(self).is_prefix_of(haystack) } + #[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 @@ -576,6 +630,14 @@ macro_rules! pattern_methods { { ($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 + } + } } ///////////////////////////////////////////////////////////////////////////// From 50ab77384e8f990d64c7b7fd478b19da724d6e07 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Mon, 30 Mar 2020 18:13:14 +0200 Subject: [PATCH 05/13] infer arr len from pattern --- src/librustc_typeck/check/pat.rs | 44 ++++++++++++------- .../ui/const-generics/infer_arg_from_pat.rs | 27 ++++++++++++ .../const-generics/infer_arg_from_pat.stderr | 8 ++++ .../const-generics/infer_arr_len_from_pat.rs | 13 ++++++ .../infer_arr_len_from_pat.stderr | 8 ++++ src/test/ui/error-codes/E0730.rs | 2 +- src/test/ui/error-codes/E0730.stderr | 9 ++-- 7 files changed, 90 insertions(+), 21 deletions(-) create mode 100644 src/test/ui/const-generics/infer_arg_from_pat.rs create mode 100644 src/test/ui/const-generics/infer_arg_from_pat.stderr create mode 100644 src/test/ui/const-generics/infer_arr_len_from_pat.rs create mode 100644 src/test/ui/const-generics/infer_arr_len_from_pat.stderr diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index fc91142dd7da3..b3e8569f37293 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, expected) = 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 } /// 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 { + ) -> (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,29 @@ 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. + // 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/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 0000000000000..a4e3d3dee4a82 --- /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 { + arr: [u8; N], +} + +impl A { + 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 0000000000000..ad6bf3e235aeb --- /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 0000000000000..70633bbb141d4 --- /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() -> [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 0000000000000..6f5b601e14ca1 --- /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 e5048d6e6e320..45fc7e13d1782 100644 --- a/src/test/ui/error-codes/E0730.rs +++ b/src/test/ui/error-codes/E0730.rs @@ -3,7 +3,7 @@ fn is_123(x: [u32; N]) -> bool { match x { - [1, 2, 3] => true, //~ ERROR cannot pattern-match on an array without a fixed length + [1, 2, 3] => true, //~ ERROR mismatched types _ => false } } diff --git a/src/test/ui/error-codes/E0730.stderr b/src/test/ui/error-codes/E0730.stderr index 9309ee99064c9..834a3e9687059 100644 --- a/src/test/ui/error-codes/E0730.stderr +++ b/src/test/ui/error-codes/E0730.stderr @@ -6,12 +6,15 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error[E0730]: cannot pattern-match on an array without a fixed length +error[E0308]: mismatched types --> $DIR/E0730.rs:6:9 | LL | [1, 2, 3] => true, - | ^^^^^^^^^ + | ^^^^^^^^^ expected `3usize`, found `N` + | + = note: expected array `[u32; 3]` + found array `[u32; _]` error: aborting due to previous error -For more information about this error, try `rustc --explain E0730`. +For more information about this error, try `rustc --explain E0308`. From 32103b127f088906ea6a99a12c565c4013762fa3 Mon Sep 17 00:00:00 2001 From: Julien Philippon Date: Mon, 30 Mar 2020 19:02:01 +0200 Subject: [PATCH 06/13] Correct long error message according to reviews --- src/librustc_error_codes/error_codes/E0226.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0226.md b/src/librustc_error_codes/error_codes/E0226.md index e485771fc1b65..4e65132ff0d69 100644 --- a/src/librustc_error_codes/error_codes/E0226.md +++ b/src/librustc_error_codes/error_codes/E0226.md @@ -1,8 +1,8 @@ -Only a single explicit lifetime bound is permitted on trait objects. +More than one explicit lifetime bound was used on a trait object. Example of erroneous code: -```compile_fail +```compile_fail,E0226 trait Foo {} type T<'a, 'b> = dyn Foo + 'a + 'b; // error: Trait object `arg` has two @@ -11,6 +11,7 @@ type T<'a, 'b> = dyn Foo + 'a + 'b; // error: Trait object `arg` has two 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: ``` From 7f12561135e48fce7b23d58fa6ca4970d74523e3 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Mon, 30 Mar 2020 19:09:59 +0200 Subject: [PATCH 07/13] dedup docs Co-Authored-By: Mazdak Farrokhzad --- src/librustc_typeck/check/pat.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index b3e8569f37293..9dbf0489470f7 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -1423,7 +1423,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if slice.is_none() { // We have a pattern with a fixed length, // which we can use to infer the length of the array. - // 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); From 40c5eefdcde3a8696881643faeb7e2619ea0322f Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Mon, 30 Mar 2020 19:13:20 +0200 Subject: [PATCH 08/13] add test for array len inference --- .../ui/array-slice-vec/infer_array_len.rs | 21 +++++++++++++++++++ .../ui/array-slice-vec/infer_array_len.stderr | 11 ++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/test/ui/array-slice-vec/infer_array_len.rs create mode 100644 src/test/ui/array-slice-vec/infer_array_len.stderr 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 0000000000000..22fe7cb883888 --- /dev/null +++ b/src/test/ui/array-slice-vec/infer_array_len.rs @@ -0,0 +1,21 @@ +// see issue #70529 +struct A; + +impl From for [u8; 2] { + fn from(a: A) -> Self { + [0; 2] + } +} + +impl From 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 0000000000000..6eed4ce4f0c01 --- /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`. From a3df1db8ee40f8c5dc520a5d0a37adc5a70a15be Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Mon, 30 Mar 2020 19:34:16 +0200 Subject: [PATCH 09/13] update tests, improve variable names --- src/librustc_error_codes/error_codes/E0730.md | 4 ++-- src/librustc_typeck/check/pat.rs | 4 ++-- .../array-slice-vec/match_arr_unknown_len.rs | 11 ++++++++++ .../match_arr_unknown_len.stderr | 20 +++++++++++++++++++ src/test/ui/error-codes/E0730.rs | 2 +- src/test/ui/error-codes/E0730.stderr | 11 ++++------ 6 files changed, 40 insertions(+), 12 deletions(-) create mode 100644 src/test/ui/array-slice-vec/match_arr_unknown_len.rs create mode 100644 src/test/ui/array-slice-vec/match_arr_unknown_len.stderr diff --git a/src/librustc_error_codes/error_codes/E0730.md b/src/librustc_error_codes/error_codes/E0730.md index bf1f72be32589..c2a71ca5669a1 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(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_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 9dbf0489470f7..b3cace8298a92 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -1355,7 +1355,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let err = self.tcx.types.err; let expected = self.structurally_resolved_type(span, expected); - let (element_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(element_ty, len) => { let min = before.len() as u64 + after.len() as u64; @@ -1385,7 +1385,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for elt in after { self.check_pat(&elt, element_ty, def_bm, ti); } - expected + inferred } /// Type check the length of an array pattern. 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 0000000000000..7f3da75ddcbe8 --- /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(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 0000000000000..9edb139028b72 --- /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/error-codes/E0730.rs b/src/test/ui/error-codes/E0730.rs index 45fc7e13d1782..66a6e1c817a37 100644 --- a/src/test/ui/error-codes/E0730.rs +++ b/src/test/ui/error-codes/E0730.rs @@ -3,7 +3,7 @@ fn is_123(x: [u32; N]) -> bool { match x { - [1, 2, 3] => true, //~ ERROR mismatched types + [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 834a3e9687059..fb53ae31c0b42 100644 --- a/src/test/ui/error-codes/E0730.stderr +++ b/src/test/ui/error-codes/E0730.stderr @@ -6,15 +6,12 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error[E0308]: mismatched types +error[E0730]: cannot pattern-match on an array without a fixed length --> $DIR/E0730.rs:6:9 | -LL | [1, 2, 3] => true, - | ^^^^^^^^^ expected `3usize`, found `N` - | - = note: expected array `[u32; 3]` - found array `[u32; _]` +LL | [1, 2, ..] => true, + | ^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0730`. From ab2998bac3bd7ae254cacad3f0911c950691216a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 30 Mar 2020 12:30:06 -0700 Subject: [PATCH 10/13] std: Fix over-aligned allocations on wasm32-wasi The wasm32-wasi target delegates its malloc implementation to the functions in wasi-libc, but the invocation of `aligned_alloc` was incorrect by passing the number of bytes requested first rather than the alignment. This commit swaps the order of these two arguments to ensure that we allocate over-aligned memory correctly. --- src/libstd/sys/wasi/alloc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sys/wasi/alloc.rs b/src/libstd/sys/wasi/alloc.rs index e9760d050e105..bc61416278401 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 } } From 641409bd62a71484eec1cba5fdf09f1f77029c5c Mon Sep 17 00:00:00 2001 From: DutchGhost Date: Mon, 30 Mar 2020 21:33:42 +0200 Subject: [PATCH 11/13] Add `Rust` to the code snippet --- .github/ISSUE_TEMPLATE/ice.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/ice.md b/.github/ISSUE_TEMPLATE/ice.md index e669e4912f8c9..03bc4bab45137 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 ``` From fcab1f947bb760910815685ba75b4c7a85a79f89 Mon Sep 17 00:00:00 2001 From: Jacob Greenfield Date: Mon, 30 Mar 2020 15:48:52 -0400 Subject: [PATCH 12/13] Fix incorrect documentation for `str::{split_at, split_at_mut}` --- src/libcore/str/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 013ca182c13cd..2b08f7f707912 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -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 /// From 08f2904dfaf5e75fbcc1305c8b0aad5fae71a4ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 29 Mar 2020 20:19:14 +0200 Subject: [PATCH 13/13] more clippy fixes use is_empty() instead of len comparison (clippy::len_zero) use if let instead of while let loop that never loops (clippy::never_loop) remove redundant returns (clippy::needless_return) remove redundant closures (clippy::redundant_closure) use if let instead of match and wildcard pattern (clippy::single_match) don't repeat field names redundantly (clippy::redundant_field_names) --- src/librustc_interface/passes.rs | 2 +- src/librustc_mir/interpret/terminator.rs | 2 +- src/librustc_save_analysis/lib.rs | 2 +- src/librustc_session/config.rs | 2 +- src/librustc_target/spec/i686_apple_darwin.rs | 2 +- .../spec/x86_64_apple_darwin.rs | 2 +- src/librustdoc/clean/auto_trait.rs | 7 +- src/librustdoc/clean/mod.rs | 32 ++--- src/librustdoc/clean/utils.rs | 31 ++--- src/librustdoc/html/markdown.rs | 123 +++++++++--------- src/librustdoc/html/render.rs | 13 +- src/librustdoc/html/render/cache.rs | 2 +- src/libstd/io/stdio.rs | 4 +- src/libstd/sys/unix/process/process_unix.rs | 2 +- 14 files changed, 102 insertions(+), 124 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 7d066a31a0797..e3fc4fa52fb61 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 a490a0f9bcc1d..8e7abcd09c233 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_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 277848a7d6172..24b7be0c9b306 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 663cfa223c7a8..54481bd124df5 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 033b87b110e12..b7a34f9740ac4 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 e846f42f8f849..31011e8474958 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/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index bf64da56ade08..9f327b0b743d8 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 c09e74118644c..f8e44bc5a1ab7 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -521,11 +521,8 @@ impl<'tcx> Clean> fn clean(&self, cx: &DocContext<'_>) -> Option { 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> for ty::OutlivesPredicate, ty: fn clean(&self, cx: &DocContext<'_>) -> Option { 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> 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 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 05a8302ebab67..9e96015d306e4 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 e13bf270440e2..9fe3e35d197fa 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -448,7 +448,7 @@ impl<'a, I: Iterator>> 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 { 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 1377338ce4af3..f51f47a8d3387 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 { 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 450f44ffeafc1..d9f6f7b466a1f 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 9a82ae7626d97..a064c552c84f5 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 07d0fbf61fe22..f389c60615f24 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];