diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index f2643d61fc8c9..e5b61d7000a32 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1278,6 +1278,22 @@ impl Expr { }, ) } + + // To a first-order approximation, is this a pattern + pub fn is_approximately_pattern(&self) -> bool { + match &self.peel_parens().kind { + ExprKind::Box(_) + | ExprKind::Array(_) + | ExprKind::Call(_, _) + | ExprKind::Tup(_) + | ExprKind::Lit(_) + | ExprKind::Range(_, _, _) + | ExprKind::Underscore + | ExprKind::Path(_, _) + | ExprKind::Struct(_) => true, + _ => false, + } + } } /// Limit types of a range (inclusive or exclusive) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 9c314f6765150..2f5f271dc50ef 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1813,6 +1813,20 @@ impl Expr<'_> { | ExprKind::Err => true, } } + + // To a first-order approximation, is this a pattern + pub fn is_approximately_pattern(&self) -> bool { + match &self.kind { + ExprKind::Box(_) + | ExprKind::Array(_) + | ExprKind::Call(..) + | ExprKind::Tup(_) + | ExprKind::Lit(_) + | ExprKind::Path(_) + | ExprKind::Struct(..) => true, + _ => false, + } + } } /// Checks if the specified expression is a built-in range literal. diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 2ad3f3ec19d57..ca7915ed17a50 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -360,10 +360,7 @@ impl<'a> Parser<'a> { let mutbl = self.parse_mutability(); self.parse_pat_ident(BindingMode::ByRef(mutbl))? } else if self.eat_keyword(kw::Box) { - // Parse `box pat` - let pat = self.parse_pat_with_range_pat(false, None)?; - self.sess.gated_spans.gate(sym::box_patterns, lo.to(self.prev_token.span)); - PatKind::Box(pat) + self.parse_pat_box()? } else if self.check_inline_const(0) { // Parse `const pat` let const_expr = self.parse_const_block(lo.to(self.token.span), true)?; @@ -915,6 +912,62 @@ impl<'a> Parser<'a> { Ok(PatKind::TupleStruct(qself, path, fields)) } + /// Are we sure this could not possibly be the start of a pattern? + /// + /// Currently, this only accounts for tokens that can follow identifiers + /// in patterns, but this can be extended as necessary. + fn isnt_pattern_start(&self) -> bool { + [ + token::Eq, + token::Colon, + token::Comma, + token::Semi, + token::At, + token::OpenDelim(Delimiter::Brace), + token::CloseDelim(Delimiter::Brace), + token::CloseDelim(Delimiter::Parenthesis), + ] + .contains(&self.token.kind) + } + + /// Parses `box pat` + fn parse_pat_box(&mut self) -> PResult<'a, PatKind> { + let box_span = self.prev_token.span; + + if self.isnt_pattern_start() { + self.struct_span_err( + self.token.span, + format!("expected pattern, found {}", super::token_descr(&self.token)), + ) + .span_note(box_span, "`box` is a reserved keyword") + .span_suggestion_verbose( + box_span.shrink_to_lo(), + "escape `box` to use it as an identifier", + "r#", + Applicability::MaybeIncorrect, + ) + .emit(); + + // We cannot use `parse_pat_ident()` since it will complain `box` + // is not an identifier. + let sub = if self.eat(&token::At) { + Some(self.parse_pat_no_top_alt(Some("binding pattern"))?) + } else { + None + }; + + Ok(PatKind::Ident( + BindingMode::ByValue(Mutability::Not), + Ident::new(kw::Box, box_span), + sub, + )) + } else { + let pat = self.parse_pat_with_range_pat(false, None)?; + self.sess.gated_spans.gate(sym::box_patterns, box_span.to(self.prev_token.span)); + Ok(PatKind::Box(pat)) + } + } + /// Parses the fields of a struct-like pattern. fn parse_pat_fields(&mut self) -> PResult<'a, (Vec, bool)> { let mut fields = Vec::new(); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index cb39eb5416ba2..5e52e9b40f044 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -265,13 +265,21 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { ); } match (source, self.diagnostic_metadata.in_if_condition) { - (PathSource::Expr(_), Some(Expr { span, kind: ExprKind::Assign(..), .. })) => { - err.span_suggestion_verbose( - span.shrink_to_lo(), - "you might have meant to use pattern matching", - "let ".to_string(), - Applicability::MaybeIncorrect, - ); + ( + PathSource::Expr(_), + Some(Expr { span: expr_span, kind: ExprKind::Assign(lhs, _, _), .. }), + ) => { + // Icky heuristic so we don't suggest: + // `if (i + 2) = 2` => `if let (i + 2) = 2` (approximately pattern) + // `if 2 = i` => `if let 2 = i` (lhs needs to contain error span) + if lhs.is_approximately_pattern() && lhs.span.contains(span) { + err.span_suggestion_verbose( + expr_span.shrink_to_lo(), + "you might have meant to use pattern matching", + "let ".to_string(), + Applicability::MaybeIncorrect, + ); + } } _ => {} } diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index e3e0063c4ec6a..9f82bb67bd03d 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1035,7 +1035,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { (Applicability::MaybeIncorrect, false) }; - if !lhs.is_syntactic_place_expr() && !matches!(lhs.kind, hir::ExprKind::Lit(_)) { + if !lhs.is_syntactic_place_expr() + && lhs.is_approximately_pattern() + && !matches!(lhs.kind, hir::ExprKind::Lit(_)) + { // Do not suggest `if let x = y` as `==` is way more likely to be the intention. let hir = self.tcx.hir(); if let hir::Node::Expr(hir::Expr { kind: ExprKind::If { .. }, .. }) = diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 83afbfa54b1dd..0d0cc9298394e 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -445,16 +445,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let found_errors = !errors.is_empty(); errors.drain_filter(|error| { - let Error::Invalid(input_idx, arg_idx, Compatibility::Incompatible(error)) = error else { return false }; + let Error::Invalid(input_idx, arg_idx, Compatibility::Incompatible(Some(e))) = error else { return false }; let expected_ty = expected_input_tys[*arg_idx]; - let provided_ty = final_arg_types[*input_idx].map(|ty| ty.0).unwrap(); + let provided_ty = final_arg_types[*input_idx].map(|ty| ty.0).unwrap_or_else(|| tcx.ty_error()); let cause = &self.misc(provided_args[*input_idx].span); let trace = TypeTrace::types(cause, true, expected_ty, provided_ty); - if let Some(e) = error { - if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) { - self.report_and_explain_type_error(trace, e).emit(); - return true; - } + if !matches!(trace.cause.as_failure_code(e), FailureCode::Error0308(_)) { + self.report_and_explain_type_error(trace, e).emit(); + return true; } false }); @@ -585,7 +583,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )) = errors.iter().next() { let expected_ty = expected_input_tys[*arg_idx]; - let provided_ty = final_arg_types[*arg_idx].map(|ty| ty.0).unwrap(); + let provided_ty = final_arg_types[*input_idx] + .map(|ty| ty.0) + .unwrap_or_else(|| tcx.ty_error()); let expected_ty = self.resolve_vars_if_possible(expected_ty); let provided_ty = self.resolve_vars_if_possible(provided_ty); let cause = &self.misc(provided_args[*input_idx].span); @@ -595,7 +595,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &mut err, &provided_args[*input_idx], provided_ty, - final_arg_types[*input_idx].map(|ty| ty.1).unwrap(), + final_arg_types[*input_idx] + .map(|ty| ty.1) + .unwrap_or_else(|| tcx.ty_error()), None, None, ); @@ -652,7 +654,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match error { Error::Invalid(input_idx, arg_idx, compatibility) => { let expected_ty = expected_input_tys[arg_idx]; - let provided_ty = final_arg_types[input_idx].map(|ty| ty.0).unwrap(); + let provided_ty = final_arg_types[input_idx] + .map(|ty| ty.0) + .unwrap_or_else(|| tcx.ty_error()); let expected_ty = self.resolve_vars_if_possible(expected_ty); let provided_ty = self.resolve_vars_if_possible(provided_ty); if let Compatibility::Incompatible(error) = &compatibility { @@ -674,8 +678,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.emit_coerce_suggestions( &mut err, &provided_args[input_idx], - final_arg_types[input_idx].map(|ty| ty.0).unwrap(), - final_arg_types[input_idx].map(|ty| ty.1).unwrap(), + provided_ty, + // FIXME(compiler-errors): expected_ty? + final_arg_types[input_idx] + .map(|ty| ty.1) + .unwrap_or_else(|| tcx.ty_error()), None, None, ); @@ -860,7 +867,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let first_expected_ty = self.resolve_vars_if_possible(expected_input_tys[arg_idx]); let first_provided_ty = if let Some((ty, _)) = final_arg_types[input_idx] { - format!(",found `{}`", ty) + format!(", found `{}`", ty) } else { String::new() }; @@ -872,7 +879,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.resolve_vars_if_possible(expected_input_tys[other_arg_idx]); let other_provided_ty = if let Some((ty, _)) = final_arg_types[other_input_idx] { - format!(",found `{}`", ty) + format!(", found `{}`", ty) } else { String::new() }; @@ -888,14 +895,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Error::Permutation(args) => { for (dst_arg, dest_input) in args { let expected_ty = - self.resolve_vars_if_possible(expected_input_tys[dest_input]); - let provided_ty = if let Some((ty, _)) = final_arg_types[dst_arg] { - format!(",found `{}`", ty) + self.resolve_vars_if_possible(expected_input_tys[dst_arg]); + let provided_ty = if let Some((ty, _)) = final_arg_types[dest_input] { + format!(", found `{}`", ty) } else { String::new() }; labels.push(( - provided_args[dst_arg].span, + provided_args[dest_input].span, format!("expected `{}`{}", expected_ty, provided_ty), )); } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 69f06fb06ef5d..1cc9133fc3dc4 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -40,6 +40,10 @@ fn _assert_is_object_safe(_: &dyn Iterator) {} label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`" ), on(_Self = "&[]", label = "`{Self}` is not an iterator; try calling `.iter()`"), + on( + _Self = "std::vec::Vec", + label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`" + ), on( _Self = "&str", label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`" diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index 63c527b64da48..d3879273f5b03 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -296,6 +296,20 @@ static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); /// about the allocation that failed. /// /// The allocation error hook is a global resource. +/// +/// # Examples +/// +/// ``` +/// #![feature(alloc_error_hook)] +/// +/// use std::alloc::{Layout, set_alloc_error_hook}; +/// +/// fn custom_alloc_error_hook(layout: Layout) { +/// panic!("memory allocation of {} bytes failed", layout.size()); +/// } +/// +/// set_alloc_error_hook(custom_alloc_error_hook); +/// ``` #[unstable(feature = "alloc_error_hook", issue = "51245")] pub fn set_alloc_error_hook(hook: fn(Layout)) { HOOK.store(hook as *mut (), Ordering::SeqCst); diff --git a/src/doc/book b/src/doc/book index b4dd5f00b8719..396fdb69de7fb 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit b4dd5f00b87190ad5ef42cbc2a88a783c6ae57ef +Subproject commit 396fdb69de7fb18f24b15c7ad13491b1c1fa7231 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index f7cefbb995eec..cbb494f96da32 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit f7cefbb995eec8c6148f213235e9e2e03268e775 +Subproject commit cbb494f96da3268c2925bdadc65ca83d42f2d4ef diff --git a/src/doc/nomicon b/src/doc/nomicon index 10d40c59a581c..3a43983b76174 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 10d40c59a581c66d8ecd29ad18d410bf97ed524d +Subproject commit 3a43983b76174342b7dbd3e12ea2c49f762e52be diff --git a/src/doc/reference b/src/doc/reference index b74825d8f88b6..683bfe5cd64d5 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit b74825d8f88b685e239ade00f00de68ba4cd63d4 +Subproject commit 683bfe5cd64d589c6a1645312ab5f93b6385ccbb diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 2ed26865e8c29..dbb7e5e2345ee 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 2ed26865e8c29ef939dc913a97bd321cadd72a9a +Subproject commit dbb7e5e2345ee26199ffba218156b6009016a20c diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 554c00e4805df..6e4d6435db89b 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 554c00e4805df7f7bffac7db408437d62d6dfb9a +Subproject commit 6e4d6435db89bcc027b1bba9742e4f59666f5412 diff --git a/src/test/ui/argument-suggestions/basic.stderr b/src/test/ui/argument-suggestions/basic.stderr index 8300a22c5483d..b44e77b43f8bf 100644 --- a/src/test/ui/argument-suggestions/basic.stderr +++ b/src/test/ui/argument-suggestions/basic.stderr @@ -48,9 +48,9 @@ error[E0308]: arguments to this function are incorrect --> $DIR/basic.rs:23:5 | LL | swapped("", 1); - | ^^^^^^^ -- - expected `&str`,found `{integer}` + | ^^^^^^^ -- - expected `&str`, found `{integer}` | | - | expected `u32`,found `&'static str` + | expected `u32`, found `&'static str` | note: function defined here --> $DIR/basic.rs:16:4 @@ -66,10 +66,10 @@ error[E0308]: arguments to this function are incorrect --> $DIR/basic.rs:24:5 | LL | permuted(Y {}, Z {}, X {}); - | ^^^^^^^^ ---- ---- ---- expected `Z`,found `X` + | ^^^^^^^^ ---- ---- ---- expected `Z`, found `X` | | | - | | expected `Y`,found `Z` - | expected `X`,found `Y` + | | expected `Y`, found `Z` + | expected `X`, found `Y` | note: function defined here --> $DIR/basic.rs:17:4 diff --git a/src/test/ui/argument-suggestions/issue-97484.rs b/src/test/ui/argument-suggestions/issue-97484.rs new file mode 100644 index 0000000000000..bb383ab1f8b9e --- /dev/null +++ b/src/test/ui/argument-suggestions/issue-97484.rs @@ -0,0 +1,14 @@ +struct A; +struct B; +struct C; +struct D; +struct E; +struct F; +struct G; + +fn foo(a: &A, d: D, e: &E, g: G) {} + +fn main() { + foo(&&A, B, C, D, E, F, G); + //~^ ERROR this function takes 4 arguments but 7 arguments were supplied +} diff --git a/src/test/ui/argument-suggestions/issue-97484.stderr b/src/test/ui/argument-suggestions/issue-97484.stderr new file mode 100644 index 0000000000000..4c461633121bf --- /dev/null +++ b/src/test/ui/argument-suggestions/issue-97484.stderr @@ -0,0 +1,27 @@ +error[E0061]: this function takes 4 arguments but 7 arguments were supplied + --> $DIR/issue-97484.rs:12:5 + | +LL | foo(&&A, B, C, D, E, F, G); + | ^^^ - - - argument unexpected + | | | + | | argument of type `&E` unexpected + | argument of type `D` unexpected + | +note: function defined here + --> $DIR/issue-97484.rs:9:4 + | +LL | fn foo(a: &A, d: D, e: &E, g: G) {} + | ^^^ ----- ---- ----- ---- +help: consider removing the `` + | +LL - foo(&&A, B, C, D, E, F, G); +LL + foo(&&A, B, C, D, E, F, G); + | +help: remove the extra arguments + | +LL | foo(&&A, D, {&E}, G); + | ~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/src/test/ui/argument-suggestions/mixed_cases.stderr b/src/test/ui/argument-suggestions/mixed_cases.stderr index 61da02f583789..78765335c0218 100644 --- a/src/test/ui/argument-suggestions/mixed_cases.stderr +++ b/src/test/ui/argument-suggestions/mixed_cases.stderr @@ -76,10 +76,10 @@ error[E0308]: arguments to this function are incorrect --> $DIR/mixed_cases.rs:20:3 | LL | three_args("", X {}, 1); - | ^^^^^^^^^^ -- ---- - expected `&str`,found `{integer}` + | ^^^^^^^^^^ -- ---- - expected `&str`, found `{integer}` | | | | | expected `f32`, found struct `X` - | expected `i32`,found `&'static str` + | expected `i32`, found `&'static str` | note: function defined here --> $DIR/mixed_cases.rs:6:4 @@ -98,8 +98,8 @@ LL | three_args("", 1); | ^^^^^^^^^^ -- - | | | | | an argument of type `f32` is missing - | | expected `&str`,found `{integer}` - | expected `i32`,found `&'static str` + | | expected `&str`, found `{integer}` + | expected `i32`, found `&'static str` | note: function defined here --> $DIR/mixed_cases.rs:6:4 diff --git a/src/test/ui/argument-suggestions/permuted_arguments.stderr b/src/test/ui/argument-suggestions/permuted_arguments.stderr index 52890f4e6a50e..f16d22860d807 100644 --- a/src/test/ui/argument-suggestions/permuted_arguments.stderr +++ b/src/test/ui/argument-suggestions/permuted_arguments.stderr @@ -2,10 +2,10 @@ error[E0308]: arguments to this function are incorrect --> $DIR/permuted_arguments.rs:10:3 | LL | three_args(1.0, "", 1); - | ^^^^^^^^^^ --- -- - expected `&str`,found `{integer}` + | ^^^^^^^^^^ --- -- - expected `&str`, found `{integer}` | | | - | | expected `f32`,found `&'static str` - | expected `i32`,found `{float}` + | | expected `f32`, found `&'static str` + | expected `i32`, found `{float}` | note: function defined here --> $DIR/permuted_arguments.rs:5:4 @@ -21,12 +21,12 @@ error[E0308]: arguments to this function are incorrect --> $DIR/permuted_arguments.rs:12:3 | LL | many_args(X {}, Y {}, 1, 1.0, ""); - | ^^^^^^^^^ ---- ---- - --- -- expected `Y`,found `&'static str` + | ^^^^^^^^^ ---- ---- - --- -- expected `Y`, found `&'static str` | | | | | - | | | | expected `X`,found `{float}` - | | | expected `&str`,found `{integer}` - | | expected `f32`,found `Y` - | expected `i32`,found `X` + | | | | expected `X`, found `{float}` + | | | expected `&str`, found `{integer}` + | | expected `f32`, found `Y` + | expected `i32`, found `X` | note: function defined here --> $DIR/permuted_arguments.rs:6:4 diff --git a/src/test/ui/argument-suggestions/swapped_arguments.stderr b/src/test/ui/argument-suggestions/swapped_arguments.stderr index 672f0d5bb56a6..a90792d0c5340 100644 --- a/src/test/ui/argument-suggestions/swapped_arguments.stderr +++ b/src/test/ui/argument-suggestions/swapped_arguments.stderr @@ -2,9 +2,9 @@ error[E0308]: arguments to this function are incorrect --> $DIR/swapped_arguments.rs:8:3 | LL | two_args(1.0, 1); - | ^^^^^^^^ --- - expected `f32`,found `{integer}` + | ^^^^^^^^ --- - expected `f32`, found `{integer}` | | - | expected `i32`,found `{float}` + | expected `i32`, found `{float}` | note: function defined here --> $DIR/swapped_arguments.rs:3:4 @@ -20,9 +20,9 @@ error[E0308]: arguments to this function are incorrect --> $DIR/swapped_arguments.rs:9:3 | LL | three_args(1.0, 1, ""); - | ^^^^^^^^^^ --- - expected `f32`,found `{integer}` + | ^^^^^^^^^^ --- - expected `f32`, found `{integer}` | | - | expected `i32`,found `{float}` + | expected `i32`, found `{float}` | note: function defined here --> $DIR/swapped_arguments.rs:4:4 @@ -38,9 +38,9 @@ error[E0308]: arguments to this function are incorrect --> $DIR/swapped_arguments.rs:10:3 | LL | three_args( 1, "", 1.0); - | ^^^^^^^^^^ -- --- expected `&str`,found `{float}` + | ^^^^^^^^^^ -- --- expected `&str`, found `{float}` | | - | expected `f32`,found `&'static str` + | expected `f32`, found `&'static str` | note: function defined here --> $DIR/swapped_arguments.rs:4:4 @@ -56,9 +56,9 @@ error[E0308]: arguments to this function are incorrect --> $DIR/swapped_arguments.rs:11:3 | LL | three_args( "", 1.0, 1); - | ^^^^^^^^^^ -- - expected `&str`,found `{integer}` + | ^^^^^^^^^^ -- - expected `&str`, found `{integer}` | | - | expected `i32`,found `&'static str` + | expected `i32`, found `&'static str` | note: function defined here --> $DIR/swapped_arguments.rs:4:4 @@ -74,11 +74,11 @@ error[E0308]: arguments to this function are incorrect --> $DIR/swapped_arguments.rs:13:3 | LL | four_args(1.0, 1, X {}, ""); - | ^^^^^^^^^ --- - ---- -- expected `X`,found `&'static str` + | ^^^^^^^^^ --- - ---- -- expected `X`, found `&'static str` | | | | - | | | expected `&str`,found `X` - | | expected `f32`,found `{integer}` - | expected `i32`,found `{float}` + | | | expected `&str`, found `X` + | | expected `f32`, found `{integer}` + | expected `i32`, found `{float}` | note: function defined here --> $DIR/swapped_arguments.rs:5:4 diff --git a/src/test/ui/expr/if/bad-if-let-suggestion.rs b/src/test/ui/expr/if/bad-if-let-suggestion.rs new file mode 100644 index 0000000000000..a8b2a283039fd --- /dev/null +++ b/src/test/ui/expr/if/bad-if-let-suggestion.rs @@ -0,0 +1,24 @@ +// FIXME(compiler-errors): This really should suggest `let` on the RHS of the +// `&&` operator, but that's kinda hard to do because of precedence. +// Instead, for now we just make sure not to suggest `if let let`. +fn a() { + if let x = 1 && i = 2 {} + //~^ ERROR cannot find value `i` in this scope + //~| ERROR `let` expressions in this position are unstable + //~| ERROR mismatched types + //~| ERROR `let` expressions are not supported here +} + +fn b() { + if (i + j) = i {} + //~^ ERROR cannot find value `i` in this scope + //~| ERROR cannot find value `i` in this scope + //~| ERROR cannot find value `j` in this scope +} + +fn c() { + if x[0] = 1 {} + //~^ ERROR cannot find value `x` in this scope +} + +fn main() {} diff --git a/src/test/ui/expr/if/bad-if-let-suggestion.stderr b/src/test/ui/expr/if/bad-if-let-suggestion.stderr new file mode 100644 index 0000000000000..60d286fedf58a --- /dev/null +++ b/src/test/ui/expr/if/bad-if-let-suggestion.stderr @@ -0,0 +1,69 @@ +error: `let` expressions are not supported here + --> $DIR/bad-if-let-suggestion.rs:5:8 + | +LL | if let x = 1 && i = 2 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error[E0425]: cannot find value `i` in this scope + --> $DIR/bad-if-let-suggestion.rs:5:21 + | +LL | if let x = 1 && i = 2 {} + | ^ not found in this scope + +error[E0425]: cannot find value `i` in this scope + --> $DIR/bad-if-let-suggestion.rs:13:9 + | +LL | fn a() { + | ------ similarly named function `a` defined here +... +LL | if (i + j) = i {} + | ^ help: a function with a similar name exists: `a` + +error[E0425]: cannot find value `j` in this scope + --> $DIR/bad-if-let-suggestion.rs:13:13 + | +LL | fn a() { + | ------ similarly named function `a` defined here +... +LL | if (i + j) = i {} + | ^ help: a function with a similar name exists: `a` + +error[E0425]: cannot find value `i` in this scope + --> $DIR/bad-if-let-suggestion.rs:13:18 + | +LL | fn a() { + | ------ similarly named function `a` defined here +... +LL | if (i + j) = i {} + | ^ help: a function with a similar name exists: `a` + +error[E0425]: cannot find value `x` in this scope + --> $DIR/bad-if-let-suggestion.rs:20:8 + | +LL | fn a() { + | ------ similarly named function `a` defined here +... +LL | if x[0] = 1 {} + | ^ help: a function with a similar name exists: `a` + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/bad-if-let-suggestion.rs:5:8 + | +LL | if let x = 1 && i = 2 {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/bad-if-let-suggestion.rs:5:8 + | +LL | if let x = 1 && i = 2 {} + | ^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0308, E0425, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/iterators/vec-on-unimplemented.rs b/src/test/ui/iterators/vec-on-unimplemented.rs new file mode 100644 index 0000000000000..42b5d36bfad4a --- /dev/null +++ b/src/test/ui/iterators/vec-on-unimplemented.rs @@ -0,0 +1,4 @@ +fn main() { + vec![true, false].map(|v| !v).collect::>(); + //~^ ERROR `Vec` is not an iterator +} diff --git a/src/test/ui/iterators/vec-on-unimplemented.stderr b/src/test/ui/iterators/vec-on-unimplemented.stderr new file mode 100644 index 0000000000000..afcce5c30ca02 --- /dev/null +++ b/src/test/ui/iterators/vec-on-unimplemented.stderr @@ -0,0 +1,20 @@ +error[E0599]: `Vec` is not an iterator + --> $DIR/vec-on-unimplemented.rs:2:23 + | +LL | vec![true, false].map(|v| !v).collect::>(); + | ^^^ `Vec` is not an iterator; try calling `.into_iter()` or `.iter()` + | + ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + | +LL | pub struct Vec { + | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec: Iterator` + | + = note: the following trait bounds were not satisfied: + `Vec: Iterator` + which is required by `&mut Vec: Iterator` + `[bool]: Iterator` + which is required by `&mut [bool]: Iterator` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/json-multiple.rs b/src/test/ui/json-multiple.rs index 4c37e20d94dda..fb126339dc216 100644 --- a/src/test/ui/json-multiple.rs +++ b/src/test/ui/json-multiple.rs @@ -1,6 +1,5 @@ // build-pass // ignore-pass (different metadata emitted in different modes) // compile-flags: --json=diagnostic-short --json artifacts --error-format=json -// ignore-compare-mode-nll #![crate_type = "lib"] diff --git a/src/test/ui/json-options.rs b/src/test/ui/json-options.rs index fea07cc9e3e54..8b6ba131eb002 100644 --- a/src/test/ui/json-options.rs +++ b/src/test/ui/json-options.rs @@ -1,6 +1,5 @@ // build-pass // ignore-pass (different metadata emitted in different modes) // compile-flags: --json=diagnostic-short,artifacts --error-format=json -// ignore-compare-mode-nll #![crate_type = "lib"] diff --git a/src/test/ui/lifetimes/issue-67498.rs b/src/test/ui/lifetimes/issue-67498.rs new file mode 100644 index 0000000000000..8d88264353a72 --- /dev/null +++ b/src/test/ui/lifetimes/issue-67498.rs @@ -0,0 +1,21 @@ +// check-pass + +// Regression test for #67498. + +pub fn f<'a, 'b, 'd, 'e> ( + x: for<'c> fn( + fn(&'c fn(&'c ())), + fn(&'c fn(&'c ())), + fn(&'c fn(&'c ())), + fn(&'c fn(&'c ())), + ) +) -> fn( + fn(&'a fn(&'d ())), + fn(&'b fn(&'d ())), + fn(&'a fn(&'e ())), + fn(&'b fn(&'e ())), +) { + x +} + +fn main() {} diff --git a/src/test/ui/parser/keyword-box-as-identifier.rs b/src/test/ui/parser/keyword-box-as-identifier.rs index 33961bb308467..2cf49b66be61c 100644 --- a/src/test/ui/parser/keyword-box-as-identifier.rs +++ b/src/test/ui/parser/keyword-box-as-identifier.rs @@ -1,3 +1,10 @@ fn main() { - let box = "foo"; //~ error: expected pattern, found `=` + let box = 0; + //~^ ERROR expected pattern, found `=` + let box: bool; + //~^ ERROR expected pattern, found `:` + let mut box = 0; + //~^ ERROR expected pattern, found `=` + let (box,) = (0,); + //~^ ERROR expected pattern, found `,` } diff --git a/src/test/ui/parser/keyword-box-as-identifier.stderr b/src/test/ui/parser/keyword-box-as-identifier.stderr index 8b185948498d8..eaa1f8003c53a 100644 --- a/src/test/ui/parser/keyword-box-as-identifier.stderr +++ b/src/test/ui/parser/keyword-box-as-identifier.stderr @@ -1,8 +1,66 @@ error: expected pattern, found `=` --> $DIR/keyword-box-as-identifier.rs:2:13 | -LL | let box = "foo"; - | ^ expected pattern +LL | let box = 0; + | ^ + | +note: `box` is a reserved keyword + --> $DIR/keyword-box-as-identifier.rs:2:9 + | +LL | let box = 0; + | ^^^ +help: escape `box` to use it as an identifier + | +LL | let r#box = 0; + | ++ + +error: expected pattern, found `:` + --> $DIR/keyword-box-as-identifier.rs:4:12 + | +LL | let box: bool; + | ^ + | +note: `box` is a reserved keyword + --> $DIR/keyword-box-as-identifier.rs:4:9 + | +LL | let box: bool; + | ^^^ +help: escape `box` to use it as an identifier + | +LL | let r#box: bool; + | ++ + +error: expected pattern, found `=` + --> $DIR/keyword-box-as-identifier.rs:6:17 + | +LL | let mut box = 0; + | ^ + | +note: `box` is a reserved keyword + --> $DIR/keyword-box-as-identifier.rs:6:13 + | +LL | let mut box = 0; + | ^^^ +help: escape `box` to use it as an identifier + | +LL | let mut r#box = 0; + | ++ + +error: expected pattern, found `,` + --> $DIR/keyword-box-as-identifier.rs:8:13 + | +LL | let (box,) = (0,); + | ^ + | +note: `box` is a reserved keyword + --> $DIR/keyword-box-as-identifier.rs:8:10 + | +LL | let (box,) = (0,); + | ^^^ +help: escape `box` to use it as an identifier + | +LL | let (r#box,) = (0,); + | ++ -error: aborting due to previous error +error: aborting due to 4 previous errors diff --git a/src/test/ui/rmeta/emit-artifact-notifications.rs b/src/test/ui/rmeta/emit-artifact-notifications.rs index be38fb4c3a69a..984a7fabb6633 100644 --- a/src/test/ui/rmeta/emit-artifact-notifications.rs +++ b/src/test/ui/rmeta/emit-artifact-notifications.rs @@ -2,7 +2,6 @@ // build-pass // ignore-pass // ^-- needed because `--pass check` does not emit the output needed. -// ignore-compare-mode-nll // A very basic test for the emission of artifact notifications in JSON output. diff --git a/src/test/ui/save-analysis/emit-notifications.rs b/src/test/ui/save-analysis/emit-notifications.rs index 8a696695ec0a2..9179944a6201d 100644 --- a/src/test/ui/save-analysis/emit-notifications.rs +++ b/src/test/ui/save-analysis/emit-notifications.rs @@ -3,6 +3,5 @@ // compile-flags: --crate-type rlib --error-format=json // ignore-pass // ^-- needed because otherwise, the .stderr file changes with --pass check -// ignore-compare-mode-nll pub fn foo() {} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 49c8248b80d1e..b758bb9cf6790 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1939,7 +1939,7 @@ impl<'test> TestCx<'test> { match self.config.compare_mode { Some(CompareMode::Polonius) => { - rustc.args(&["-Zpolonius", "-Zborrowck=mir"]); + rustc.args(&["-Zpolonius"]); } Some(CompareMode::Chalk) => { rustc.args(&["-Zchalk"]);