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 ``` 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/array/iter.rs b/src/libcore/array/iter.rs index 80eaae0d4afb5..f6b8d4ba08146 100644 --- a/src/libcore/array/iter.rs +++ b/src/libcore/array/iter.rs @@ -39,7 +39,7 @@ where alive: Range, } -impl IntoIter +impl IntoIter where [T; N]: LengthAtMost32, { @@ -99,7 +99,7 @@ where } #[stable(feature = "array_value_iter_impls", since = "1.40.0")] -impl Iterator for IntoIter +impl Iterator for IntoIter where [T; N]: LengthAtMost32, { @@ -146,7 +146,7 @@ where } #[stable(feature = "array_value_iter_impls", since = "1.40.0")] -impl DoubleEndedIterator for IntoIter +impl DoubleEndedIterator for IntoIter where [T; N]: LengthAtMost32, { @@ -182,7 +182,7 @@ where } #[stable(feature = "array_value_iter_impls", since = "1.40.0")] -impl Drop for IntoIter +impl Drop for IntoIter where [T; N]: LengthAtMost32, { @@ -195,7 +195,7 @@ where } #[stable(feature = "array_value_iter_impls", since = "1.40.0")] -impl ExactSizeIterator for IntoIter +impl ExactSizeIterator for IntoIter where [T; N]: LengthAtMost32, { @@ -210,17 +210,17 @@ where } #[stable(feature = "array_value_iter_impls", since = "1.40.0")] -impl FusedIterator for IntoIter where [T; N]: LengthAtMost32 {} +impl FusedIterator for IntoIter where [T; N]: LengthAtMost32 {} // The iterator indeed reports the correct length. The number of "alive" // elements (that will still be yielded) is the length of the range `alive`. // This range is decremented in length in either `next` or `next_back`. It is // always decremented by 1 in those methods, but only if `Some(_)` is returned. #[stable(feature = "array_value_iter_impls", since = "1.40.0")] -unsafe impl TrustedLen for IntoIter where [T; N]: LengthAtMost32 {} +unsafe impl TrustedLen for IntoIter where [T; N]: LengthAtMost32 {} #[stable(feature = "array_value_iter_impls", since = "1.40.0")] -impl Clone for IntoIter +impl Clone for IntoIter where [T; N]: LengthAtMost32, { @@ -249,7 +249,7 @@ where } #[stable(feature = "array_value_iter_impls", since = "1.40.0")] -impl fmt::Debug for IntoIter +impl fmt::Debug for IntoIter where [T; N]: LengthAtMost32, { diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 013ca182c13cd..dc7637cfdb934 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>,

>::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 + } + } } ///////////////////////////////////////////////////////////////////////////// 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..4e65132ff0d69 --- /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 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_lint/early.rs b/src/librustc_lint/early.rs index 34da29c974777..018e9da243c70 100644 --- a/src/librustc_lint/early.rs +++ b/src/librustc_lint/early.rs @@ -104,6 +104,11 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> run_early_pass!(self, check_pat_post, p); } + fn visit_anon_const(&mut self, c: &'a ast::AnonConst) { + run_early_pass!(self, check_anon_const, c); + ast_visit::walk_anon_const(self, c); + } + fn visit_expr(&mut self, e: &'a ast::Expr) { self.with_lint_attrs(e.id, &e.attrs, |cx| { run_early_pass!(cx, check_expr, e); diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 97261759aeb28..af1fad2c6608b 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -104,6 +104,7 @@ macro_rules! early_lint_passes { $args, [ UnusedParens: UnusedParens, + UnusedBraces: UnusedBraces, UnusedImportBraces: UnusedImportBraces, UnsafeCode: UnsafeCode, AnonymousParameters: AnonymousParameters, @@ -275,6 +276,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { UNUSED_FEATURES, UNUSED_LABELS, UNUSED_PARENS, + UNUSED_BRACES, REDUNDANT_SEMICOLONS ); diff --git a/src/librustc_lint/passes.rs b/src/librustc_lint/passes.rs index ace154714458e..c9e12afedbbab 100644 --- a/src/librustc_lint/passes.rs +++ b/src/librustc_lint/passes.rs @@ -170,6 +170,7 @@ macro_rules! early_lint_methods { fn check_stmt(a: &ast::Stmt); fn check_arm(a: &ast::Arm); fn check_pat(a: &ast::Pat); + fn check_anon_const(a: &ast::AnonConst); fn check_pat_post(a: &ast::Pat); fn check_expr(a: &ast::Expr); fn check_expr_post(a: &ast::Expr); diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 78a67ae6afe73..c74b399555a8a 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -1,5 +1,7 @@ +use crate::Lint; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_ast::ast; +use rustc_ast::ast::{ExprKind, StmtKind}; use rustc_ast::attr; use rustc_ast::util::parser; use rustc_ast_pretty::pprust; @@ -315,16 +317,58 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes { } } -declare_lint! { - pub(super) UNUSED_PARENS, - Warn, - "`if`, `match`, `while` and `return` do not need parentheses" +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +enum UnusedDelimsCtx { + FunctionArg, + MethodArg, + AssignedValue, + IfCond, + WhileCond, + ForIterExpr, + MatchScrutineeExpr, + ReturnValue, + BlockRetValue, + LetScrutineeExpr, + ArrayLenExpr, + AnonConst, } -declare_lint_pass!(UnusedParens => [UNUSED_PARENS]); +impl From for &'static str { + fn from(ctx: UnusedDelimsCtx) -> &'static str { + match ctx { + UnusedDelimsCtx::FunctionArg => "function argument", + UnusedDelimsCtx::MethodArg => "method argument", + UnusedDelimsCtx::AssignedValue => "assigned value", + UnusedDelimsCtx::IfCond => "`if` condition", + UnusedDelimsCtx::WhileCond => "`while` condition", + UnusedDelimsCtx::ForIterExpr => "`for` iterator expression", + UnusedDelimsCtx::MatchScrutineeExpr => "`match` scrutinee expression", + UnusedDelimsCtx::ReturnValue => "`return` value", + UnusedDelimsCtx::BlockRetValue => "block return value", + UnusedDelimsCtx::LetScrutineeExpr => "`let` scrutinee expression", + UnusedDelimsCtx::ArrayLenExpr | UnusedDelimsCtx::AnonConst => "const expression", + } + } +} -impl UnusedParens { - fn is_expr_parens_necessary(inner: &ast::Expr, followed_by_block: bool) -> bool { +/// Used by both `UnusedParens` and `UnusedBraces` to prevent code duplication. +trait UnusedDelimLint { + const DELIM_STR: &'static str; + + // this cannot be a constant is it refers to a static. + fn lint(&self) -> &'static Lint; + + fn check_unused_delims_expr( + &self, + cx: &EarlyContext<'_>, + value: &ast::Expr, + ctx: UnusedDelimsCtx, + followed_by_block: bool, + left_pos: Option, + right_pos: Option, + ); + + fn is_expr_delims_necessary(inner: &ast::Expr, followed_by_block: bool) -> bool { followed_by_block && match inner.kind { ast::ExprKind::Ret(_) | ast::ExprKind::Break(..) => true, @@ -332,98 +376,41 @@ impl UnusedParens { } } - fn check_unused_parens_expr( + fn emit_unused_delims_expr( &self, cx: &EarlyContext<'_>, value: &ast::Expr, - msg: &str, - followed_by_block: bool, + ctx: UnusedDelimsCtx, left_pos: Option, right_pos: Option, ) { - match value.kind { - ast::ExprKind::Paren(ref inner) => { - if !Self::is_expr_parens_necessary(inner, followed_by_block) - && value.attrs.is_empty() - && !value.span.from_expansion() - { - let expr_text = - if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) { - snippet - } else { - pprust::expr_to_string(value) - }; - let keep_space = ( - left_pos.map(|s| s >= value.span.lo()).unwrap_or(false), - right_pos.map(|s| s <= value.span.hi()).unwrap_or(false), - ); - Self::remove_outer_parens(cx, value.span, &expr_text, msg, keep_space); - } - } - ast::ExprKind::Let(_, ref expr) => { - // FIXME(#60336): Properly handle `let true = (false && true)` - // actually needing the parenthesis. - self.check_unused_parens_expr( - cx, - expr, - "`let` head expression", - followed_by_block, - None, - None, - ); - } - _ => {} - } + let expr_text = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) { + snippet + } else { + pprust::expr_to_string(value) + }; + let keep_space = ( + left_pos.map(|s| s >= value.span.lo()).unwrap_or(false), + right_pos.map(|s| s <= value.span.hi()).unwrap_or(false), + ); + self.emit_unused_delims(cx, value.span, &expr_text, ctx.into(), keep_space); } - fn check_unused_parens_pat( + fn emit_unused_delims( &self, - cx: &EarlyContext<'_>, - value: &ast::Pat, - avoid_or: bool, - avoid_mut: bool, - ) { - use ast::{BindingMode, Mutability, PatKind}; - - if let PatKind::Paren(inner) = &value.kind { - match inner.kind { - // The lint visitor will visit each subpattern of `p`. We do not want to lint - // any range pattern no matter where it occurs in the pattern. For something like - // `&(a..=b)`, there is a recursive `check_pat` on `a` and `b`, but we will assume - // that if there are unnecessary parens they serve a purpose of readability. - PatKind::Range(..) => return, - // Avoid `p0 | .. | pn` if we should. - PatKind::Or(..) if avoid_or => return, - // Avoid `mut x` and `mut x @ p` if we should: - PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ..) if avoid_mut => return, - // Otherwise proceed with linting. - _ => {} - } - - let pattern_text = - if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) { - snippet - } else { - pprust::pat_to_string(value) - }; - Self::remove_outer_parens(cx, value.span, &pattern_text, "pattern", (false, false)); - } - } - - fn remove_outer_parens( cx: &EarlyContext<'_>, span: Span, pattern: &str, msg: &str, keep_space: (bool, bool), ) { - cx.struct_span_lint(UNUSED_PARENS, span, |lint| { - let span_msg = format!("unnecessary parentheses around {}", msg); + cx.struct_span_lint(self.lint(), span, |lint| { + let span_msg = format!("unnecessary {} around {}", Self::DELIM_STR, msg); let mut err = lint.build(&span_msg); let mut ate_left_paren = false; let mut ate_right_paren = false; let parens_removed = pattern.trim_matches(|c| match c { - '(' => { + '(' | '{' => { if ate_left_paren { false } else { @@ -431,7 +418,7 @@ impl UnusedParens { true } } - ')' => { + ')' | '}' => { if ate_right_paren { false } else { @@ -457,61 +444,51 @@ impl UnusedParens { replace }; - err.span_suggestion_short( - span, - "remove these parentheses", - replace, - Applicability::MachineApplicable, - ); + let suggestion = format!("remove these {}", Self::DELIM_STR); + + err.span_suggestion_short(span, &suggestion, replace, Applicability::MachineApplicable); err.emit(); }); } -} -impl EarlyLintPass for UnusedParens { fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { use rustc_ast::ast::ExprKind::*; - let (value, msg, followed_by_block, left_pos, right_pos) = match e.kind { - Let(ref pat, ..) => { - self.check_unused_parens_pat(cx, pat, false, false); - return; - } - + let (value, ctx, followed_by_block, left_pos, right_pos) = match e.kind { If(ref cond, ref block, ..) => { let left = e.span.lo() + rustc_span::BytePos(2); let right = block.span.lo(); - (cond, "`if` condition", true, Some(left), Some(right)) + (cond, UnusedDelimsCtx::IfCond, true, Some(left), Some(right)) } While(ref cond, ref block, ..) => { let left = e.span.lo() + rustc_span::BytePos(5); let right = block.span.lo(); - (cond, "`while` condition", true, Some(left), Some(right)) + (cond, UnusedDelimsCtx::WhileCond, true, Some(left), Some(right)) } - ForLoop(ref pat, ref cond, ref block, ..) => { - self.check_unused_parens_pat(cx, pat, false, false); - (cond, "`for` head expression", true, None, Some(block.span.lo())) + ForLoop(_, ref cond, ref block, ..) => { + (cond, UnusedDelimsCtx::ForIterExpr, true, None, Some(block.span.lo())) } Match(ref head, _) => { let left = e.span.lo() + rustc_span::BytePos(5); - (head, "`match` head expression", true, Some(left), None) + (head, UnusedDelimsCtx::MatchScrutineeExpr, true, Some(left), None) } Ret(Some(ref value)) => { let left = e.span.lo() + rustc_span::BytePos(3); - (value, "`return` value", false, Some(left), None) + (value, UnusedDelimsCtx::ReturnValue, false, Some(left), None) } - Assign(_, ref value, _) => (value, "assigned value", false, None, None), - AssignOp(.., ref value) => (value, "assigned value", false, None, None), + Assign(_, ref value, _) | AssignOp(.., ref value) => { + (value, UnusedDelimsCtx::AssignedValue, false, None, None) + } // either function/method call, or something this lint doesn't care about ref call_or_other => { - let (args_to_check, call_kind) = match *call_or_other { - Call(_, ref args) => (&args[..], "function"), - // first "argument" is self (which sometimes needs parens) - MethodCall(_, ref args) => (&args[1..], "method"), + let (args_to_check, ctx) = match *call_or_other { + Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg), + // first "argument" is self (which sometimes needs delims) + MethodCall(_, ref args) => (&args[1..], UnusedDelimsCtx::MethodArg), // actual catch-all arm _ => { return; @@ -524,14 +501,152 @@ impl EarlyLintPass for UnusedParens { if e.span.ctxt().outer_expn_data().call_site.from_expansion() { return; } - let msg = format!("{} argument", call_kind); for arg in args_to_check { - self.check_unused_parens_expr(cx, arg, &msg, false, None, None); + self.check_unused_delims_expr(cx, arg, ctx, false, None, None); } return; } }; - self.check_unused_parens_expr(cx, &value, msg, followed_by_block, left_pos, right_pos); + self.check_unused_delims_expr(cx, &value, ctx, followed_by_block, left_pos, right_pos); + } + + fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) { + match s.kind { + StmtKind::Local(ref local) => { + if let Some(ref value) = local.init { + self.check_unused_delims_expr( + cx, + &value, + UnusedDelimsCtx::AssignedValue, + false, + None, + None, + ); + } + } + StmtKind::Expr(ref expr) => { + self.check_unused_delims_expr( + cx, + &expr, + UnusedDelimsCtx::BlockRetValue, + false, + None, + None, + ); + } + _ => {} + } + } + + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { + use ast::ItemKind::*; + + if let Const(.., Some(expr)) | Static(.., Some(expr)) = &item.kind { + self.check_unused_delims_expr( + cx, + expr, + UnusedDelimsCtx::AssignedValue, + false, + None, + None, + ); + } + } +} + +declare_lint! { + pub(super) UNUSED_PARENS, + Warn, + "`if`, `match`, `while` and `return` do not need parentheses" +} + +declare_lint_pass!(UnusedParens => [UNUSED_PARENS]); + +impl UnusedDelimLint for UnusedParens { + const DELIM_STR: &'static str = "parentheses"; + + fn lint(&self) -> &'static Lint { + UNUSED_PARENS + } + + fn check_unused_delims_expr( + &self, + cx: &EarlyContext<'_>, + value: &ast::Expr, + ctx: UnusedDelimsCtx, + followed_by_block: bool, + left_pos: Option, + right_pos: Option, + ) { + match value.kind { + ast::ExprKind::Paren(ref inner) => { + if !Self::is_expr_delims_necessary(inner, followed_by_block) + && value.attrs.is_empty() + && !value.span.from_expansion() + { + self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos) + } + } + ast::ExprKind::Let(_, ref expr) => { + // FIXME(#60336): Properly handle `let true = (false && true)` + // actually needing the parenthesis. + self.check_unused_delims_expr( + cx, + expr, + UnusedDelimsCtx::LetScrutineeExpr, + followed_by_block, + None, + None, + ); + } + _ => {} + } + } +} + +impl UnusedParens { + fn check_unused_parens_pat( + &self, + cx: &EarlyContext<'_>, + value: &ast::Pat, + avoid_or: bool, + avoid_mut: bool, + ) { + use ast::{BindingMode, Mutability, PatKind}; + + if let PatKind::Paren(inner) = &value.kind { + match inner.kind { + // The lint visitor will visit each subpattern of `p`. We do not want to lint + // any range pattern no matter where it occurs in the pattern. For something like + // `&(a..=b)`, there is a recursive `check_pat` on `a` and `b`, but we will assume + // that if there are unnecessary parens they serve a purpose of readability. + PatKind::Range(..) => return, + // Avoid `p0 | .. | pn` if we should. + PatKind::Or(..) if avoid_or => return, + // Avoid `mut x` and `mut x @ p` if we should: + PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ..) if avoid_mut => return, + // Otherwise proceed with linting. + _ => {} + } + + let pattern_text = + if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) { + snippet + } else { + pprust::pat_to_string(value) + }; + self.emit_unused_delims(cx, value.span, &pattern_text, "pattern", (false, false)); + } + } +} + +impl EarlyLintPass for UnusedParens { + fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { + if let ExprKind::Let(ref pat, ..) | ExprKind::ForLoop(ref pat, ..) = e.kind { + self.check_unused_parens_pat(cx, pat, false, false); + } + + ::check_expr(self, cx, e) } fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) { @@ -556,22 +671,16 @@ impl EarlyLintPass for UnusedParens { } } - fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) { - use ast::StmtKind::*; - - match s.kind { - Local(ref local) => { - self.check_unused_parens_pat(cx, &local.pat, false, false); + fn check_anon_const(&mut self, cx: &EarlyContext<'_>, c: &ast::AnonConst) { + self.check_unused_delims_expr(cx, &c.value, UnusedDelimsCtx::AnonConst, false, None, None); + } - if let Some(ref value) = local.init { - self.check_unused_parens_expr(cx, &value, "assigned value", false, None, None); - } - } - Expr(ref expr) => { - self.check_unused_parens_expr(cx, &expr, "block return value", false, None, None); - } - _ => {} + fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) { + if let StmtKind::Local(ref local) = s.kind { + self.check_unused_parens_pat(cx, &local.pat, false, false); } + + ::check_stmt(self, cx, s) } fn check_param(&mut self, cx: &EarlyContext<'_>, param: &ast::Param) { @@ -587,6 +696,16 @@ impl EarlyLintPass for UnusedParens { match &r.kind { &ast::TyKind::TraitObject(..) => {} &ast::TyKind::ImplTrait(_, ref bounds) if bounds.len() > 1 => {} + &ast::TyKind::Array(_, ref len) => { + self.check_unused_delims_expr( + cx, + &len.value, + UnusedDelimsCtx::ArrayLenExpr, + false, + None, + None, + ); + } _ => { let pattern_text = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(ty.span) { @@ -595,19 +714,134 @@ impl EarlyLintPass for UnusedParens { pprust::ty_to_string(ty) }; - Self::remove_outer_parens(cx, ty.span, &pattern_text, "type", (false, false)); + self.emit_unused_delims(cx, ty.span, &pattern_text, "type", (false, false)); } } } } fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { - use ast::ItemKind::*; + ::check_item(self, cx, item) + } +} - if let Const(.., Some(expr)) | Static(.., Some(expr)) = &item.kind { - self.check_unused_parens_expr(cx, expr, "assigned value", false, None, None); +declare_lint! { + pub(super) UNUSED_BRACES, + Warn, + "unnecessary braces around an expression" +} + +declare_lint_pass!(UnusedBraces => [UNUSED_BRACES]); + +impl UnusedDelimLint for UnusedBraces { + const DELIM_STR: &'static str = "braces"; + + fn lint(&self) -> &'static Lint { + UNUSED_BRACES + } + + fn check_unused_delims_expr( + &self, + cx: &EarlyContext<'_>, + value: &ast::Expr, + ctx: UnusedDelimsCtx, + followed_by_block: bool, + left_pos: Option, + right_pos: Option, + ) { + match value.kind { + ast::ExprKind::Block(ref inner, None) + if inner.rules == ast::BlockCheckMode::Default => + { + // emit a warning under the following conditions: + // + // - the block does not have a label + // - the block is not `unsafe` + // - the block contains exactly one expression (do not lint `{ expr; }`) + // - `followed_by_block` is true and the internal expr may contain a `{` + // - the block is not multiline (do not lint multiline match arms) + // ``` + // match expr { + // Pattern => { + // somewhat_long_expression + // } + // // ... + // } + // ``` + // - the block has no attribute and was not created inside a macro + // - if the block is an `anon_const`, the inner expr must be a literal + // (do not lint `struct A; let _: A<{ 2 + 3 }>;`) + // + // FIXME(const_generics): handle paths when #67075 is fixed. + if let [stmt] = inner.stmts.as_slice() { + if let ast::StmtKind::Expr(ref expr) = stmt.kind { + if !Self::is_expr_delims_necessary(expr, followed_by_block) + && (ctx != UnusedDelimsCtx::AnonConst + || matches!(expr.kind, ast::ExprKind::Lit(_))) + // array length expressions are checked during `check_anon_const` and `check_ty`, + // once as `ArrayLenExpr` and once as `AnonConst`. + // + // As we do not want to lint this twice, we do not emit an error for + // `ArrayLenExpr` if `AnonConst` would do the same. + && (ctx != UnusedDelimsCtx::ArrayLenExpr + || !matches!(expr.kind, ast::ExprKind::Lit(_))) + && !cx.sess().source_map().is_multiline(value.span) + && value.attrs.is_empty() + && !value.span.from_expansion() + { + self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos) + } + } + } + } + ast::ExprKind::Let(_, ref expr) => { + // FIXME(#60336): Properly handle `let true = (false && true)` + // actually needing the parenthesis. + self.check_unused_delims_expr( + cx, + expr, + UnusedDelimsCtx::LetScrutineeExpr, + followed_by_block, + None, + None, + ); + } + _ => {} + } + } +} + +impl EarlyLintPass for UnusedBraces { + fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { + ::check_expr(self, cx, e) + } + + fn check_anon_const(&mut self, cx: &EarlyContext<'_>, c: &ast::AnonConst) { + self.check_unused_delims_expr(cx, &c.value, UnusedDelimsCtx::AnonConst, false, None, None); + } + + fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) { + ::check_stmt(self, cx, s) + } + + fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) { + if let &ast::TyKind::Paren(ref r) = &ty.kind { + if let ast::TyKind::Array(_, ref len) = r.kind { + self.check_unused_delims_expr( + cx, + &len.value, + UnusedDelimsCtx::ArrayLenExpr, + false, + None, + None, + ); + } } } + + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { + ::check_item(self, cx, item) + } } declare_lint! { diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs index 08dc854e9ff59..7ed77304a90e1 100644 --- a/src/librustc_macros/src/query.rs +++ b/src/librustc_macros/src/query.rs @@ -356,9 +356,11 @@ fn add_query_description_impl( quote! { #t } }) .unwrap_or(quote! { _ }); + // expr is a `Block`, meaning that `{ #expr }` gets expanded + // to `{ { stmts... } }`, which triggers the `unused_braces` lint. quote! { #[inline] - #[allow(unused_variables)] + #[allow(unused_variables, unused_braces)] fn cache_on_disk( #tcx: TyCtxt<'tcx>, #key: Self::Key, 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]; 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..21f43b6fd4f64 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}; @@ -2807,7 +2808,7 @@ impl<'a> Resolver<'a> { ast::Path { span, segments: iter::once(Ident::with_dummy_span(kw::PathRoot)) - .chain({ path_str.split("::").skip(1).map(Ident::from_str) }) + .chain(path_str.split("::").skip(1).map(Ident::from_str)) .map(|i| self.new_ast_path_segment(i)) .collect(), } diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index fc91142dd7da3..b3cace8298a92 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 { + ) -> (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/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 } } diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs index f2ad057b6b624..0fefb1f6aa0fb 100644 --- a/src/libstd/sys/windows/handle.rs +++ b/src/libstd/sys/windows/handle.rs @@ -115,8 +115,7 @@ impl RawHandle { ) -> io::Result> { let len = cmp::min(buf.len(), ::max_value() as usize) as c::DWORD; let mut amt = 0; - let res = - cvt({ c::ReadFile(self.0, buf.as_ptr() as c::LPVOID, len, &mut amt, overlapped) }); + let res = cvt(c::ReadFile(self.0, buf.as_ptr() as c::LPVOID, len, &mut amt, overlapped)); match res { Ok(_) => Ok(Some(amt as usize)), Err(e) => { diff --git a/src/test/incremental/const-generics/issue-61516.rs b/src/test/incremental/const-generics/issue-61516.rs index a7465b77267a5..a193bf998dc73 100644 --- a/src/test/incremental/const-generics/issue-61516.rs +++ b/src/test/incremental/const-generics/issue-61516.rs @@ -4,7 +4,7 @@ struct FakeArray(T); -impl FakeArray { +impl FakeArray { fn len(&self) -> usize { N } 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`. 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/array-slice-vec/vec-fixed-length.rs b/src/test/ui/array-slice-vec/vec-fixed-length.rs index 5db02ee066bbe..908c39c7951c0 100644 --- a/src/test/ui/array-slice-vec/vec-fixed-length.rs +++ b/src/test/ui/array-slice-vec/vec-fixed-length.rs @@ -9,7 +9,7 @@ fn test_big_vec() {} #[cfg(target_pointer_width = "64")] fn test_big_vec() { - assert_eq!(size_of::<[u8; (1 << 32)]>(), (1 << 32)); + assert_eq!(size_of::<[u8; 1 << 32]>(), (1 << 32)); } fn main() { diff --git a/src/test/ui/block-fn-coerce.rs b/src/test/ui/block-fn-coerce.rs index fc5f51d46b255..d993ad9945974 100644 --- a/src/test/ui/block-fn-coerce.rs +++ b/src/test/ui/block-fn-coerce.rs @@ -1,4 +1,5 @@ // run-pass +#![allow(unused_braces)] fn force(f: F) -> isize where F: FnOnce() -> isize { return f(); } diff --git a/src/test/ui/cleanup-rvalue-scopes.rs b/src/test/ui/cleanup-rvalue-scopes.rs index f51f13abf792f..c5dd87c0f5a1f 100644 --- a/src/test/ui/cleanup-rvalue-scopes.rs +++ b/src/test/ui/cleanup-rvalue-scopes.rs @@ -1,5 +1,5 @@ // run-pass - +#![allow(unused_braces)] #![allow(non_snake_case)] #![allow(unused_variables)] // Test that destructors for rvalue temporaries run either at end of diff --git a/src/test/ui/coerce/coerce-expect-unsized.rs b/src/test/ui/coerce/coerce-expect-unsized.rs index b44aa6ab37760..d486fdf73aba8 100644 --- a/src/test/ui/coerce/coerce-expect-unsized.rs +++ b/src/test/ui/coerce/coerce-expect-unsized.rs @@ -1,4 +1,5 @@ // run-pass +#![allow(unused_braces)] #![feature(box_syntax)] use std::cell::RefCell; diff --git a/src/test/ui/coerce/coerce-overloaded-autoderef.rs b/src/test/ui/coerce/coerce-overloaded-autoderef.rs index 3fe18103ef8c3..d5484607c8b52 100644 --- a/src/test/ui/coerce/coerce-overloaded-autoderef.rs +++ b/src/test/ui/coerce/coerce-overloaded-autoderef.rs @@ -1,4 +1,5 @@ // run-pass +#![allow(unused_braces)] #![allow(dead_code)] // pretty-expanded FIXME #23616 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/const-generics/issues/issue-62504.rs b/src/test/ui/const-generics/issues/issue-62504.rs index cd3cfaac3b95b..212e16253f6b8 100644 --- a/src/test/ui/const-generics/issues/issue-62504.rs +++ b/src/test/ui/const-generics/issues/issue-62504.rs @@ -7,13 +7,13 @@ trait HasSize { const SIZE: usize; } -impl HasSize for ArrayHolder<{ X }> { +impl HasSize for ArrayHolder { const SIZE: usize = X; } struct ArrayHolder([u32; X]); -impl ArrayHolder<{ X }> { +impl ArrayHolder { pub const fn new() -> Self { ArrayHolder([0; Self::SIZE]) //~^ ERROR: mismatched types diff --git a/src/test/ui/const-generics/issues/issue-70125-2.rs b/src/test/ui/const-generics/issues/issue-70125-2.rs index ea7a68c2f93d9..a3eca0dd7d965 100644 --- a/src/test/ui/const-generics/issues/issue-70125-2.rs +++ b/src/test/ui/const-generics/issues/issue-70125-2.rs @@ -13,4 +13,4 @@ trait Foo { } } -impl Foo<{3}> for () {} +impl Foo<3> for () {} diff --git a/src/test/ui/const-generics/unused_braces.rs b/src/test/ui/const-generics/unused_braces.rs new file mode 100644 index 0000000000000..05234faf71420 --- /dev/null +++ b/src/test/ui/const-generics/unused_braces.rs @@ -0,0 +1,13 @@ +// check-pass +#![warn(unused_braces)] + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +struct A; + +fn main() { + let _: A<7>; // ok + let _: A<{ 7 }>; //~ WARN unnecessary braces + let _: A<{ 3 + 5 }>; // ok +} diff --git a/src/test/ui/const-generics/unused_braces.stderr b/src/test/ui/const-generics/unused_braces.stderr new file mode 100644 index 0000000000000..fc3da6096e7d4 --- /dev/null +++ b/src/test/ui/const-generics/unused_braces.stderr @@ -0,0 +1,20 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/unused_braces.rs:4:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +warning: unnecessary braces around const expression + --> $DIR/unused_braces.rs:11:14 + | +LL | let _: A<{ 7 }>; + | ^^^^^ help: remove these braces + | +note: the lint level is defined here + --> $DIR/unused_braces.rs:2:9 + | +LL | #![warn(unused_braces)] + | ^^^^^^^^^^^^^ + diff --git a/src/test/ui/consts/const-block.rs b/src/test/ui/consts/const-block.rs index 7172a34c8cfeb..ec99c70f6e0b9 100644 --- a/src/test/ui/consts/const-block.rs +++ b/src/test/ui/consts/const-block.rs @@ -1,5 +1,5 @@ // run-pass - +#![allow(unused_braces)] #![allow(dead_code)] #![allow(unused_unsafe)] diff --git a/src/test/ui/error-codes/E0730.rs b/src/test/ui/error-codes/E0730.rs index e5048d6e6e320..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 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 9309ee99064c9..fb53ae31c0b42 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/expr-block-generic-unique1.rs b/src/test/ui/expr-block-generic-unique1.rs index c14191f2ffcb5..d081cb2be7ee3 100644 --- a/src/test/ui/expr-block-generic-unique1.rs +++ b/src/test/ui/expr-block-generic-unique1.rs @@ -1,5 +1,5 @@ // run-pass - +#![allow(unused_braces)] #![feature(box_syntax)] fn test_generic(expected: Box, eq: F) where T: Clone, F: FnOnce(Box, Box) -> bool { diff --git a/src/test/ui/expr-block-generic-unique2.rs b/src/test/ui/expr-block-generic-unique2.rs index 90ebc02931ad1..9362eb86fc309 100644 --- a/src/test/ui/expr-block-generic-unique2.rs +++ b/src/test/ui/expr-block-generic-unique2.rs @@ -1,5 +1,5 @@ // run-pass - +#![allow(unused_braces)] #![feature(box_syntax)] fn test_generic(expected: T, eq: F) where T: Clone, F: FnOnce(T, T) -> bool { diff --git a/src/test/ui/expr-block-generic.rs b/src/test/ui/expr-block-generic.rs index ec93f59722d0c..29c7c42219c73 100644 --- a/src/test/ui/expr-block-generic.rs +++ b/src/test/ui/expr-block-generic.rs @@ -1,4 +1,5 @@ // run-pass +#![allow(unused_braces)] fn test_generic(expected: T, eq: F) where F: FnOnce(T, T) -> bool { let actual: T = { expected.clone() }; diff --git a/src/test/ui/expr-block-unique.rs b/src/test/ui/expr-block-unique.rs index fe1a7d9f1fb31..eff3fd3a15152 100644 --- a/src/test/ui/expr-block-unique.rs +++ b/src/test/ui/expr-block-unique.rs @@ -1,5 +1,5 @@ // run-pass - +#![allow(unused_braces)] #![feature(box_syntax)] pub fn main() { let x: Box<_> = { box 100 }; assert_eq!(*x, 100); } diff --git a/src/test/ui/expr-block.rs b/src/test/ui/expr-block.rs index 549ccf9774f43..ff87595c934e9 100644 --- a/src/test/ui/expr-block.rs +++ b/src/test/ui/expr-block.rs @@ -1,10 +1,7 @@ // run-pass - +#![allow(unused_braces)] #![allow(dead_code)] - - - // Tests for standalone blocks as expressions fn test_basic() { let rs: bool = { true }; assert!((rs)); } diff --git a/src/test/ui/expr-fn.rs b/src/test/ui/expr-fn.rs index af809f563fc04..253cbfd5d38fa 100644 --- a/src/test/ui/expr-fn.rs +++ b/src/test/ui/expr-fn.rs @@ -1,4 +1,5 @@ // run-pass +#![allow(unused_braces)] fn test_int() { fn f() -> isize { 10 } diff --git a/src/test/ui/functions-closures/closure-inference.rs b/src/test/ui/functions-closures/closure-inference.rs index 96878445245bc..1877414f09942 100644 --- a/src/test/ui/functions-closures/closure-inference.rs +++ b/src/test/ui/functions-closures/closure-inference.rs @@ -1,5 +1,5 @@ // run-pass - +#![allow(unused_braces)] fn foo(i: isize) -> isize { i + 1 } diff --git a/src/test/ui/functions-closures/closure-inference2.rs b/src/test/ui/functions-closures/closure-inference2.rs index f2dfa5888aac5..4ce132e86caa4 100644 --- a/src/test/ui/functions-closures/closure-inference2.rs +++ b/src/test/ui/functions-closures/closure-inference2.rs @@ -1,6 +1,6 @@ // run-pass // Test a rather underspecified example: - +#![allow(unused_braces)] pub fn main() { let f = {|i| i}; diff --git a/src/test/ui/intrinsics/intrinsic-move-val-cleanups.rs b/src/test/ui/intrinsics/intrinsic-move-val-cleanups.rs index a2068429af5ea..9804c421db081 100644 --- a/src/test/ui/intrinsics/intrinsic-move-val-cleanups.rs +++ b/src/test/ui/intrinsics/intrinsic-move-val-cleanups.rs @@ -1,4 +1,5 @@ // run-pass +#![allow(unused_braces)] #![allow(unused_unsafe)] #![allow(unreachable_code)] // ignore-emscripten no threads support diff --git a/src/test/ui/issues/issue-23898.rs b/src/test/ui/issues/issue-23898.rs index a8787f279b71b..3de365675ad22 100644 --- a/src/test/ui/issues/issue-23898.rs +++ b/src/test/ui/issues/issue-23898.rs @@ -1,4 +1,5 @@ // run-pass +#![allow(unused_parens)] #![allow(non_camel_case_types)] // Note: This test was used to demonstrate #5873 (now #23898). diff --git a/src/test/ui/issues/issue-28777.rs b/src/test/ui/issues/issue-28777.rs index 74de00adadbda..1f426b7185e8f 100644 --- a/src/test/ui/issues/issue-28777.rs +++ b/src/test/ui/issues/issue-28777.rs @@ -1,4 +1,5 @@ // run-pass +#![allow(unused_braces)] fn main() { let v1 = { 1 + {2} * {3} }; let v2 = 1 + {2} * {3} ; diff --git a/src/test/ui/lint/lint-unnecessary-parens.rs b/src/test/ui/lint/lint-unnecessary-parens.rs index 5ce1f57608132..623cd04d9bce3 100644 --- a/src/test/ui/lint/lint-unnecessary-parens.rs +++ b/src/test/ui/lint/lint-unnecessary-parens.rs @@ -48,11 +48,11 @@ fn main() { if (true) {} //~ ERROR unnecessary parentheses around `if` condition while (true) {} //~ ERROR unnecessary parentheses around `while` condition //~^ WARN denote infinite loops with - match (true) { //~ ERROR unnecessary parentheses around `match` head expression + match (true) { //~ ERROR unnecessary parentheses around `match` scrutinee expression _ => {} } - if let 1 = (1) {} //~ ERROR unnecessary parentheses around `let` head expression - while let 1 = (2) {} //~ ERROR unnecessary parentheses around `let` head expression + if let 1 = (1) {} //~ ERROR unnecessary parentheses around `let` scrutinee expression + while let 1 = (2) {} //~ ERROR unnecessary parentheses around `let` scrutinee expression let v = X { y: false }; // struct lits needs parens, so these shouldn't warn. if (v == X { y: true }) {} diff --git a/src/test/ui/lint/lint-unnecessary-parens.stderr b/src/test/ui/lint/lint-unnecessary-parens.stderr index 8858c95327322..15184ba36ae85 100644 --- a/src/test/ui/lint/lint-unnecessary-parens.stderr +++ b/src/test/ui/lint/lint-unnecessary-parens.stderr @@ -72,19 +72,19 @@ LL | while (true) {} | = note: `#[warn(while_true)]` on by default -error: unnecessary parentheses around `match` head expression +error: unnecessary parentheses around `match` scrutinee expression --> $DIR/lint-unnecessary-parens.rs:51:11 | LL | match (true) { | ^^^^^^ help: remove these parentheses -error: unnecessary parentheses around `let` head expression +error: unnecessary parentheses around `let` scrutinee expression --> $DIR/lint-unnecessary-parens.rs:54:16 | LL | if let 1 = (1) {} | ^^^ help: remove these parentheses -error: unnecessary parentheses around `let` head expression +error: unnecessary parentheses around `let` scrutinee expression --> $DIR/lint-unnecessary-parens.rs:55:19 | LL | while let 1 = (2) {} diff --git a/src/test/ui/lint/unused_braces.rs b/src/test/ui/lint/unused_braces.rs new file mode 100644 index 0000000000000..de456ee6c230c --- /dev/null +++ b/src/test/ui/lint/unused_braces.rs @@ -0,0 +1,31 @@ +// check-pass +#![warn(unused_braces, unused_parens)] + +fn main() { + let _ = (7); + //~^WARN unnecessary parentheses + + let _ = { 7 }; + //~^ WARN unnecessary braces + + if let 7 = { 7 } { + //~^ WARN unnecessary braces + } + + let _: [u8; { 3 }]; + //~^ WARN unnecessary braces + + // do not emit error for multiline blocks. + let _ = { + 7 + }; + + // do not emit error for unsafe blocks. + let _ = unsafe { 7 }; + + // do not emit error, as the `{` would then + // be parsed as part of the `return`. + if { return } { + + } +} diff --git a/src/test/ui/lint/unused_braces.stderr b/src/test/ui/lint/unused_braces.stderr new file mode 100644 index 0000000000000..72f425ffc3e01 --- /dev/null +++ b/src/test/ui/lint/unused_braces.stderr @@ -0,0 +1,36 @@ +warning: unnecessary parentheses around assigned value + --> $DIR/unused_braces.rs:5:13 + | +LL | let _ = (7); + | ^^^ help: remove these parentheses + | +note: the lint level is defined here + --> $DIR/unused_braces.rs:2:24 + | +LL | #![warn(unused_braces, unused_parens)] + | ^^^^^^^^^^^^^ + +warning: unnecessary braces around assigned value + --> $DIR/unused_braces.rs:8:13 + | +LL | let _ = { 7 }; + | ^^^^^ help: remove these braces + | +note: the lint level is defined here + --> $DIR/unused_braces.rs:2:9 + | +LL | #![warn(unused_braces, unused_parens)] + | ^^^^^^^^^^^^^ + +warning: unnecessary braces around `let` scrutinee expression + --> $DIR/unused_braces.rs:11:16 + | +LL | if let 7 = { 7 } { + | ^^^^^ help: remove these braces + +warning: unnecessary braces around const expression + --> $DIR/unused_braces.rs:15:17 + | +LL | let _: [u8; { 3 }]; + | ^^^^^ help: remove these braces + diff --git a/src/test/ui/lint/unused_parens_borrow.rs b/src/test/ui/lint/unused_parens_borrow.rs new file mode 100644 index 0000000000000..98dbbecfedde6 --- /dev/null +++ b/src/test/ui/lint/unused_parens_borrow.rs @@ -0,0 +1,22 @@ +// check-pass +#![warn(unused_braces)] + +// changing `&{ expr }` to `&expr` changes the semantic of the program +// so we should not warn this case + +#[repr(packed)] +struct A { + a: u8, + b: u32, +} + +fn main() { + let a = A { + a: 42, + b: 1729, + }; + + let _ = &{ a.b }; + let _ = { a.b }; + //~^ WARN unnecessary braces +} diff --git a/src/test/ui/lint/unused_parens_borrow.stderr b/src/test/ui/lint/unused_parens_borrow.stderr new file mode 100644 index 0000000000000..7e3839ae4e014 --- /dev/null +++ b/src/test/ui/lint/unused_parens_borrow.stderr @@ -0,0 +1,12 @@ +warning: unnecessary braces around assigned value + --> $DIR/unused_parens_borrow.rs:20:13 + | +LL | let _ = { a.b }; + | ^^^^^^^ help: remove these braces + | +note: the lint level is defined here + --> $DIR/unused_parens_borrow.rs:2:9 + | +LL | #![warn(unused_braces)] + | ^^^^^^^^^^^^^ + diff --git a/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr b/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr index c3bf77a3a6f2d..5fb67fd7c95a3 100644 --- a/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr +++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr @@ -46,14 +46,14 @@ LL | while(true && false) { | ^^^^^^^^^^^^^^^ help: remove these parentheses "} -{"message":"unnecessary parentheses around `for` head expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":995,"line_start":44,"line_end":44,"column_start":18,"column_end":26,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){ +{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":995,"line_start":44,"line_end":44,"column_start":18,"column_end":26,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){ --> $DIR/unused_parens_remove_json_suggestion.rs:44:18 | LL | for _ in (0 .. 3){ | ^^^^^^^^ help: remove these parentheses "} -{"message":"unnecessary parentheses around `for` head expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1096,"line_start":49,"line_end":49,"column_start":14,"column_end":22,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) { +{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1096,"line_start":49,"line_end":49,"column_start":14,"column_end":22,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) { --> $DIR/unused_parens_remove_json_suggestion.rs:49:14 | LL | for _ in (0 .. 3) { 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 + diff --git a/src/test/ui/range.rs b/src/test/ui/range.rs index 82983e37ea18e..f3f7508d12434 100644 --- a/src/test/ui/range.rs +++ b/src/test/ui/range.rs @@ -1,5 +1,5 @@ // run-pass - +#![allow(unused_braces)] #![allow(unused_comparisons)] #![allow(dead_code)] #![allow(unused_mut)] diff --git a/src/test/ui/range_inclusive.rs b/src/test/ui/range_inclusive.rs index 68d9bf7d26b69..540b35e0392de 100644 --- a/src/test/ui/range_inclusive.rs +++ b/src/test/ui/range_inclusive.rs @@ -1,7 +1,7 @@ // run-pass // Test inclusive range syntax. - #![feature(range_is_empty)] +#![allow(unused_braces)] #![allow(unused_comparisons)] use std::ops::RangeToInclusive; 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`. diff --git a/src/test/ui/structs-enums/empty-tag.rs b/src/test/ui/structs-enums/empty-tag.rs index 56a438200c00b..271ab72c74fc1 100644 --- a/src/test/ui/structs-enums/empty-tag.rs +++ b/src/test/ui/structs-enums/empty-tag.rs @@ -1,4 +1,5 @@ // run-pass +#![allow(unused_braces)] #![allow(non_camel_case_types)] #[derive(Copy, Clone, Debug)] diff --git a/src/test/ui/type-alias-impl-trait/assoc-type-const.rs b/src/test/ui/type-alias-impl-trait/assoc-type-const.rs index 2907c21c6203c..7f3f86e4df009 100644 --- a/src/test/ui/type-alias-impl-trait/assoc-type-const.rs +++ b/src/test/ui/type-alias-impl-trait/assoc-type-const.rs @@ -18,16 +18,16 @@ trait MyTrait<'a, const C: usize> { const MY_CONST: usize; } -impl<'a, const C: usize> MyTrait<'a, { C }> for MyStruct<{ C }> { +impl<'a, const C: usize> MyTrait<'a, C> for MyStruct { type MyItem = u8; const MY_CONST: usize = C; } -impl<'a, I, const C: usize> UnwrapItemsExt<'a, { C }> for I { - type Iter = impl MyTrait<'a, { C }>; +impl<'a, I, const C: usize> UnwrapItemsExt<'a, C> for I { + type Iter = impl MyTrait<'a, C>; fn unwrap_items(self) -> Self::Iter { - MyStruct::<{ C }> {} + MyStruct:: {} } } diff --git a/src/test/ui/unsized-locals/unsized-exprs-rpass.rs b/src/test/ui/unsized-locals/unsized-exprs-rpass.rs index bc64fcdec2e39..24c2758a0a255 100644 --- a/src/test/ui/unsized-locals/unsized-exprs-rpass.rs +++ b/src/test/ui/unsized-locals/unsized-exprs-rpass.rs @@ -1,5 +1,5 @@ // run-pass - +#![allow(unused_braces, unused_parens)] #![feature(unsized_tuple_coercion, unsized_locals)] struct A(X); @@ -30,7 +30,6 @@ fn main() { *foo() }); udrop::<[u8]>({*foo()}); - #[allow(unused_parens)] udrop::<[u8]>((*foo())); udrop::<[u8]>((*tfoo()).1); *afoo() + 42; diff --git a/src/test/ui/weird-exprs.rs b/src/test/ui/weird-exprs.rs index ca68a5af0ddca..d812bbd011e0e 100644 --- a/src/test/ui/weird-exprs.rs +++ b/src/test/ui/weird-exprs.rs @@ -5,7 +5,7 @@ #![allow(non_camel_case_types)] #![allow(dead_code)] #![allow(unreachable_code)] -#![allow(unused_parens)] +#![allow(unused_braces, unused_parens)] #![recursion_limit = "256"] diff --git a/src/test/ui/zero-sized/zero-sized-tuple-struct.rs b/src/test/ui/zero-sized/zero-sized-tuple-struct.rs index 6c438720e5d86..2208590f7d61b 100644 --- a/src/test/ui/zero-sized/zero-sized-tuple-struct.rs +++ b/src/test/ui/zero-sized/zero-sized-tuple-struct.rs @@ -1,4 +1,5 @@ // run-pass +#![allow(unused_braces)] #![allow(unused_assignments)] // Make sure that the constructor args are codegened for zero-sized tuple structs