From 8facdcf2ef11b7638dc63c265eaaf3975d39e27c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 17 Mar 2024 20:46:36 +0000 Subject: [PATCH] Change the desugaring of `assert!` for better error output In the desugaring of `assert!`, we now expand to a `match` expression instead of `if !cond {..}`. The span of incorrect conditions will point only at the expression, and not the whole `assert!` invocation. ``` error[E0308]: mismatched types --> $DIR/issue-14091.rs:2:13 | LL | assert!(1,1); | ^ expected `bool`, found integer ``` We no longer mention the expression needing to implement the `Not` trait. ``` error[E0308]: mismatched types --> $DIR/issue-14091-2.rs:15:13 | LL | assert!(x, x); | ^ expected `bool`, found `BytePos` ``` `assert!(val)` now desugars to: ```rust match val { true => {}, _ => $crate::panic::panic_2021!(), } ``` Fix #122159. We make some minor changes to some diagnostics to avoid span overlap on type mismatch or inverted "expected"/"found" on type errors. We remove some unnecessary parens from core, alloc and miri. --- compiler/rustc_builtin_macros/src/assert.rs | 34 +++++++++++-------- compiler/rustc_hir_typeck/src/demand.rs | 2 +- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/parser/pat.rs | 1 + compiler/rustc_parse/src/parser/stmt.rs | 9 ++--- .../src/error_reporting/infer/mod.rs | 30 +++++++++++++--- library/coretests/tests/tuple.rs | 2 +- library/std/tests/env.rs | 2 +- .../src/bool_assert_comparison.rs | 24 ++++++++++--- .../src/missing_asserts_for_indexing.rs | 18 +++++----- .../tests/ui/bool_assert_comparison.fixed | 6 ++-- .../tests/ui/bool_assert_comparison.stderr | 6 ++-- .../clippy/tests/ui/const_is_empty.stderr | 8 ++++- .../ui/missing_asserts_for_indexing.stderr | 22 ++++++------ tests/coverage/assert_not.cov-map | 21 +++++++----- tests/ui/codemap_tests/issue-28308.rs | 16 +++++++-- tests/ui/codemap_tests/issue-28308.stderr | 30 +++++++++++++--- tests/ui/consts/control-flow/assert.stderr | 4 +-- tests/ui/else-if.rs | 18 +++++----- ...st_monomorphization_error_backtrace.stderr | 8 ++--- .../const-expr-generic-err.stderr | 4 +-- tests/ui/issues/issue-14091-2.rs | 2 +- tests/ui/issues/issue-14091-2.stderr | 15 +++----- tests/ui/issues/issue-14091.stderr | 6 ++-- tests/ui/lazy-and-or.rs | 6 ++-- .../ui/simd/const-err-trumps-simd-err.stderr | 4 +-- tests/ui/tag-type-args.rs | 2 +- tests/ui/tag-type-args.stderr | 4 +-- tests/ui/transmutability/uninhabited.stderr | 12 +++---- 29 files changed, 195 insertions(+), 123 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs index c659b1cff59b8..adff64bb69b05 100644 --- a/compiler/rustc_builtin_macros/src/assert.rs +++ b/compiler/rustc_builtin_macros/src/assert.rs @@ -1,9 +1,9 @@ mod context; use rustc_ast::ptr::P; -use rustc_ast::token::Delimiter; +use rustc_ast::token::{self, Delimiter}; use rustc_ast::tokenstream::{DelimSpan, TokenStream}; -use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, Path, PathSegment, UnOp, token}; +use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, Path, PathSegment}; use rustc_ast_pretty::pprust; use rustc_errors::PResult; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; @@ -30,7 +30,7 @@ pub(crate) fn expand_assert<'cx>( // `core::panic` and `std::panic` are different macros, so we use call-site // context to pick up whichever is currently in scope. - let call_site_span = cx.with_call_site_ctxt(span); + let call_site_span = cx.with_call_site_ctxt(cond_expr.span); let panic_path = || { if use_panic_2021(span) { @@ -64,12 +64,14 @@ pub(crate) fn expand_assert<'cx>( }), })), ); - expr_if_not(cx, call_site_span, cond_expr, then, None) + expr_if_not(cx, call_site_span, cond_expr, then) } // If `generic_assert` is enabled, generates rich captured outputs // // FIXME(c410-f3r) See https://github.com/rust-lang/rust/issues/96949 else if cx.ecfg.features.generic_assert() { + // FIXME(estebank): we use the condition the user passed without coercing to `bool` when + // `generic_assert` is enabled, but we could use `cond_expr` instead. context::Context::new(cx, call_site_span).build(cond_expr, panic_path()) } // If `generic_assert` is not enabled, only outputs a literal "assertion failed: ..." @@ -89,26 +91,30 @@ pub(crate) fn expand_assert<'cx>( )), )], ); - expr_if_not(cx, call_site_span, cond_expr, then, None) + expr_if_not(cx, call_site_span, cond_expr, then) }; ExpandResult::Ready(MacEager::expr(expr)) } +/// `assert!($cond_expr, $custom_message)` struct Assert { cond_expr: P, custom_message: Option, } -// if !{ ... } { ... } else { ... } -fn expr_if_not( - cx: &ExtCtxt<'_>, - span: Span, - cond: P, - then: P, - els: Option>, -) -> P { - cx.expr_if(span, cx.expr(span, ExprKind::Unary(UnOp::Not, cond)), then, els) +/// `match { true => {} _ => }` +fn expr_if_not(cx: &ExtCtxt<'_>, span: Span, cond: P, then: P) -> P { + // Instead of expanding to `if ! { }`, we expand to + // `match { true => {} _ }`. + // This allows us to always complain about mismatched types instead of "cannot apply unary + // operator `!` to type `X`" when passing an invalid ``, while also allowing `` to + // be `&true`. + let els = cx.expr_block(cx.block(span, thin_vec![])); + let mut arms = thin_vec![]; + arms.push(cx.arm(span, cx.pat_lit(span, cx.expr_bool(span, true)), els)); + arms.push(cx.arm(span, cx.pat_wild(span), then)); + cx.expr_match(span, cond, arms) } fn parse_assert<'a>(cx: &ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PResult<'a, Assert> { diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 85e949952f8de..6437d10b624b2 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -697,7 +697,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { match (self.tcx.parent_hir_node(expr.hir_id), error) { (hir::Node::LetStmt(hir::LetStmt { ty: Some(ty), init: Some(init), .. }), _) - if init.hir_id == expr.hir_id => + if init.hir_id == expr.hir_id && !ty.span.source_equal(init.span) => { // Point at `let` assignment type. err.span_label(ty.span, "expected due to this"); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e0e6c2177da54..6492d862cd91a 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3859,7 +3859,7 @@ impl<'a> Parser<'a> { P(Expr { kind, span, attrs, id: DUMMY_NODE_ID, tokens: None }) } - pub(crate) fn mk_expr(&self, span: Span, kind: ExprKind) -> P { + pub fn mk_expr(&self, span: Span, kind: ExprKind) -> P { self.mk_expr_with_attrs(span, kind, AttrVec::new()) } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 64bcb1a5a36cc..30613785b4547 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1732,6 +1732,7 @@ impl<'a> Parser<'a> { }) } + // `pub` because we use it from `rustc_builtin_macros`. pub(super) fn mk_pat_ident(&self, span: Span, ann: BindingMode, ident: Ident) -> P { self.mk_pat(span, PatKind::Ident(ann, ident, None)) } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index a2699b077fcff..92afbee93d229 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -994,12 +994,7 @@ impl<'a> Parser<'a> { Ok(Some(stmt)) } - pub(super) fn mk_block( - &self, - stmts: ThinVec, - rules: BlockCheckMode, - span: Span, - ) -> P { + pub fn mk_block(&self, stmts: ThinVec, rules: BlockCheckMode, span: Span) -> P { P(Block { stmts, id: DUMMY_NODE_ID, @@ -1010,7 +1005,7 @@ impl<'a> Parser<'a> { }) } - pub(super) fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt { + pub fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt { Stmt { id: DUMMY_NODE_ID, kind, span } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 091773009e98d..762e6e00bab4d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -456,7 +456,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { span, format!("this is an iterator with items of type `{}`", args.type_at(0)), ); - } else { + } else if !span.overlaps(cause.span) { let expected_ty = self.tcx.short_string(expected_ty, err.long_ty_path()); err.span_label(span, format!("this expression has type `{expected_ty}`")); } @@ -1584,8 +1584,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { let e = self.tcx.erase_regions(e); let f = self.tcx.erase_regions(f); - let expected = with_forced_trimmed_paths!(e.sort_string(self.tcx)); - let found = with_forced_trimmed_paths!(f.sort_string(self.tcx)); + let mut expected = with_forced_trimmed_paths!(e.sort_string(self.tcx)); + let mut found = with_forced_trimmed_paths!(f.sort_string(self.tcx)); + if let Some(def_id) = cause.span.ctxt().outer_expn_data().macro_def_id + && self.tcx.is_diagnostic_item(sym::assert_macro, def_id) + { + // When the type error comes from `assert!()`, the cause and effect are reversed + // because that macro expands to `match val { false => {panic!()}, _ => {} }`, which + // would say something like "expected `Type`, found `bool`", confusing the user. + (found, expected) = (expected, found); + } if expected == found { label_or_note(span, terr.to_string(self.tcx)); } else { @@ -2108,7 +2116,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) -> Option<(DiagStyledString, DiagStyledString)> { match values { ValuePairs::Regions(exp_found) => self.expected_found_str(exp_found), - ValuePairs::Terms(exp_found) => self.expected_found_str_term(exp_found, file), + ValuePairs::Terms(exp_found) => self.expected_found_str_term(cause, exp_found, file), ValuePairs::Aliases(exp_found) => self.expected_found_str(exp_found), ValuePairs::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found), ValuePairs::ExistentialProjection(exp_found) => self.expected_found_str(exp_found), @@ -2147,6 +2155,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn expected_found_str_term( &self, + cause: &ObligationCause<'tcx>, exp_found: ty::error::ExpectedFound>, path: &mut Option, ) -> Option<(DiagStyledString, DiagStyledString)> { @@ -2154,8 +2163,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if exp_found.references_error() { return None; } + let (mut expected, mut found) = (exp_found.expected, exp_found.found); + if let Some(def_id) = cause.span.ctxt().outer_expn_data().macro_def_id + && self.tcx.is_diagnostic_item(sym::assert_macro, def_id) + { + // When the type error comes from `assert!()`, the cause and effect are reversed + // because that macro expands to `match val { false => {panic!()}, _ => {} }`, which + // would say something like + // = note: expected `Type` + // found `bool`" + (expected, found) = (found, expected); + } - Some(match (exp_found.expected.unpack(), exp_found.found.unpack()) { + Some(match (expected.unpack(), found.unpack()) { (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => { let (mut exp, mut fnd) = self.cmp(expected, found); // Use the terminal width as the basis to determine when to compress the printed diff --git a/library/coretests/tests/tuple.rs b/library/coretests/tests/tuple.rs index ea1e281425c89..5d680d1047237 100644 --- a/library/coretests/tests/tuple.rs +++ b/library/coretests/tests/tuple.rs @@ -37,7 +37,7 @@ fn test_partial_ord() { assert!(!((1.0f64, 2.0f64) <= (f64::NAN, 3.0))); assert!(!((1.0f64, 2.0f64) > (f64::NAN, 3.0))); assert!(!((1.0f64, 2.0f64) >= (f64::NAN, 3.0))); - assert!(((1.0f64, 2.0f64) < (2.0, f64::NAN))); + assert!((1.0f64, 2.0f64) < (2.0, f64::NAN)); assert!(!((2.0f64, 2.0f64) < (2.0, f64::NAN))); } diff --git a/library/std/tests/env.rs b/library/std/tests/env.rs index e754cf8263b0f..b53fd69b7070b 100644 --- a/library/std/tests/env.rs +++ b/library/std/tests/env.rs @@ -16,7 +16,7 @@ fn test_self_exe_path() { #[test] fn test() { - assert!((!Path::new("test-path").is_absolute())); + assert!(!Path::new("test-path").is_absolute()); #[cfg(not(target_env = "sgx"))] current_dir().unwrap(); diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs index adac2f27ea8cf..e6d55b9ff5162 100644 --- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs +++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs @@ -129,13 +129,27 @@ impl<'tcx> LateLintPass<'tcx> for BoolAssertComparison { let mut suggestions = vec![(name_span, non_eq_mac.to_string()), (lit_span, String::new())]; - if bool_value ^ eq_macro { - let Some(sugg) = Sugg::hir_opt(cx, non_lit_expr) else { - return; - }; - suggestions.push((non_lit_expr.span, (!sugg).to_string())); + if let ty::Bool = non_lit_ty.kind() { + if bool_value ^ eq_macro { + let Some(sugg) = Sugg::hir_opt(cx, non_lit_expr) else { + return; + }; + suggestions.push((non_lit_expr.span, (!sugg).to_string())); + } + } else { + // If we have a `value` that is *not* `bool` but that `!value` *is*, we suggest + // `!!value`. + suggestions.push(( + non_lit_expr.span.shrink_to_lo(), + if bool_value ^ eq_macro { + "!".to_string() + } else { + "!!".to_string() + }, + )); } + diag.multipart_suggestion( format!("replace it with `{non_eq_mac}!(..)`"), suggestions, diff --git a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs index d78299fe08be8..7adeed154d631 100644 --- a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs +++ b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs @@ -10,7 +10,7 @@ use rustc_ast::{LitKind, RangeLimits}; use rustc_data_structures::packed::Pu128; use rustc_data_structures::unhash::UnindexMap; use rustc_errors::{Applicability, Diag}; -use rustc_hir::{BinOp, Block, Body, Expr, ExprKind, UnOp}; +use rustc_hir::{BinOp, Body, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; @@ -134,9 +134,8 @@ fn assert_len_expr<'hir>( cx: &LateContext<'_>, expr: &'hir Expr<'hir>, ) -> Option<(LengthComparison, usize, &'hir Expr<'hir>)> { - if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr) - && let ExprKind::Unary(UnOp::Not, condition) = &cond.kind - && let ExprKind::Binary(bin_op, left, right) = &condition.kind + if let higher::IfLetOrMatch::Match(cond, [_, then], _) = higher::IfLetOrMatch::parse(cx, expr)? + && let ExprKind::Binary(bin_op, left, right) = &cond.kind && let Some((cmp, asserted_len, slice_len)) = len_comparison(*bin_op, left, right) && let ExprKind::MethodCall(method, recv, [], _) = &slice_len.kind @@ -144,8 +143,7 @@ fn assert_len_expr<'hir>( && method.ident.name == sym::len // check if `then` block has a never type expression - && let ExprKind::Block(Block { expr: Some(then_expr), .. }, _) = then.kind - && cx.typeck_results().expr_ty(then_expr).is_never() + && cx.typeck_results().expr_ty(then.body).is_never() { Some((cmp, asserted_len, recv)) } else { @@ -337,21 +335,21 @@ fn report_indexes(cx: &LateContext<'_>, map: &UnindexMap // `v.len() < 5` and `v.len() <= 5` does nothing in terms of bounds checks. // The user probably meant `v.len() > 5` LengthComparison::LengthLessThanInt | LengthComparison::LengthLessThanOrEqualInt => Some( - format!("assert!({}.len() > {highest_index})", snippet(cx, slice.span, "..")), + format!("{}.len() > {highest_index}", snippet(cx, slice.span, "..")), ), // `5 < v.len()` == `v.len() > 5` LengthComparison::IntLessThanLength if asserted_len < highest_index => Some(format!( - "assert!({}.len() > {highest_index})", + "{}.len() > {highest_index}", snippet(cx, slice.span, "..") )), // `5 <= v.len() == `v.len() >= 5` LengthComparison::IntLessThanOrEqualLength if asserted_len <= highest_index => Some(format!( - "assert!({}.len() > {highest_index})", + "{}.len() > {highest_index}", snippet(cx, slice.span, "..") )), // `highest_index` here is rather a length, so we need to add 1 to it LengthComparison::LengthEqualInt if asserted_len < highest_index + 1 => Some(format!( - "assert!({}.len() == {})", + "{}.len() == {}", snippet(cx, slice.span, ".."), highest_index + 1 )), diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.fixed b/src/tools/clippy/tests/ui/bool_assert_comparison.fixed index b05166a055ee3..a9856f39c3289 100644 --- a/src/tools/clippy/tests/ui/bool_assert_comparison.fixed +++ b/src/tools/clippy/tests/ui/bool_assert_comparison.fixed @@ -91,7 +91,7 @@ fn main() { assert_eq!(a!(), "".is_empty()); assert_eq!("".is_empty(), b!()); assert_eq!(a, true); - assert!(b); + assert!(!!b); assert_ne!("a".len(), 1); assert!("a".is_empty()); @@ -111,7 +111,7 @@ fn main() { debug_assert_eq!(a!(), "".is_empty()); debug_assert_eq!("".is_empty(), b!()); debug_assert_eq!(a, true); - debug_assert!(b); + debug_assert!(!!b); debug_assert_ne!("a".len(), 1); debug_assert!("a".is_empty()); @@ -143,7 +143,7 @@ fn main() { use debug_assert_eq as renamed; renamed!(a, true); - debug_assert!(b); + debug_assert!(!!b); let non_copy = NonCopy; assert_eq!(non_copy, true); diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.stderr b/src/tools/clippy/tests/ui/bool_assert_comparison.stderr index 41183c61ee01d..80530f11ef7df 100644 --- a/src/tools/clippy/tests/ui/bool_assert_comparison.stderr +++ b/src/tools/clippy/tests/ui/bool_assert_comparison.stderr @@ -45,7 +45,7 @@ LL | assert_eq!(b, true); help: replace it with `assert!(..)` | LL - assert_eq!(b, true); -LL + assert!(b); +LL + assert!(!!b); | error: used `assert_ne!` with a literal bool @@ -141,7 +141,7 @@ LL | debug_assert_eq!(b, true); help: replace it with `debug_assert!(..)` | LL - debug_assert_eq!(b, true); -LL + debug_assert!(b); +LL + debug_assert!(!!b); | error: used `debug_assert_ne!` with a literal bool @@ -297,7 +297,7 @@ LL | renamed!(b, true); help: replace it with `debug_assert!(..)` | LL - renamed!(b, true); -LL + debug_assert!(b); +LL + debug_assert!(!!b); | error: used `assert_eq!` with a literal bool diff --git a/src/tools/clippy/tests/ui/const_is_empty.stderr b/src/tools/clippy/tests/ui/const_is_empty.stderr index 0afba940d8b4b..1a417b0e7ac4a 100644 --- a/src/tools/clippy/tests/ui/const_is_empty.stderr +++ b/src/tools/clippy/tests/ui/const_is_empty.stderr @@ -157,11 +157,17 @@ error: this expression always evaluates to true LL | let _ = val.is_empty(); | ^^^^^^^^^^^^^^ +error: this expression always evaluates to true + --> tests/ui/const_is_empty.rs:181:17 + | +LL | assert!(EMPTY_STR.is_empty()); + | ^^^^^^^^^^^^^^^^^^^^ + error: this expression always evaluates to true --> tests/ui/const_is_empty.rs:185:9 | LL | EMPTY_STR.is_empty(); | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 27 previous errors +error: aborting due to 28 previous errors diff --git a/src/tools/clippy/tests/ui/missing_asserts_for_indexing.stderr b/src/tools/clippy/tests/ui/missing_asserts_for_indexing.stderr index 2e63cd4a0e503..4987f06d6becc 100644 --- a/src/tools/clippy/tests/ui/missing_asserts_for_indexing.stderr +++ b/src/tools/clippy/tests/ui/missing_asserts_for_indexing.stderr @@ -2,7 +2,7 @@ error: indexing into a slice multiple times with an `assert` that does not cover --> tests/ui/missing_asserts_for_indexing.rs:30:5 | LL | assert!(v.len() < 5); - | -------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 4)` + | ----------- help: provide the highest index that is indexed with: `v.len() > 4` LL | v[0] + v[1] + v[2] + v[3] + v[4] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -39,7 +39,7 @@ error: indexing into a slice multiple times with an `assert` that does not cover --> tests/ui/missing_asserts_for_indexing.rs:36:5 | LL | assert!(v.len() <= 5); - | --------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 4)` + | ------------ help: provide the highest index that is indexed with: `v.len() > 4` LL | v[0] + v[1] + v[2] + v[3] + v[4] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -74,7 +74,7 @@ error: indexing into a slice multiple times with an `assert` that does not cover --> tests/ui/missing_asserts_for_indexing.rs:42:5 | LL | assert!(v.len() > 3); - | -------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 4)` + | ----------- help: provide the highest index that is indexed with: `v.len() > 4` LL | v[0] + v[1] + v[2] + v[3] + v[4] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -109,7 +109,7 @@ error: indexing into a slice multiple times with an `assert` that does not cover --> tests/ui/missing_asserts_for_indexing.rs:48:5 | LL | assert!(v.len() >= 4); - | --------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 4)` + | ------------ help: provide the highest index that is indexed with: `v.len() > 4` LL | v[0] + v[1] + v[2] + v[3] + v[4] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -144,7 +144,7 @@ error: indexing into a slice multiple times with an `assert` that does not cover --> tests/ui/missing_asserts_for_indexing.rs:66:13 | LL | assert!(v.len() >= 3); - | --------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 3)` + | ------------ help: provide the highest index that is indexed with: `v.len() > 3` LL | let _ = v[0]; | _____________^ LL | | @@ -167,7 +167,7 @@ error: indexing into a slice multiple times with an `assert` that does not cover --> tests/ui/missing_asserts_for_indexing.rs:80:13 | LL | assert!(v.len() >= 4); - | --------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 4)` + | ------------ help: provide the highest index that is indexed with: `v.len() > 4` LL | let _ = v[0]; | _____________^ LL | | @@ -190,7 +190,7 @@ error: indexing into a slice multiple times with an `assert` that does not cover --> tests/ui/missing_asserts_for_indexing.rs:95:13 | LL | assert!(v1.len() >= 12); - | ----------------------- help: provide the highest index that is indexed with: `assert!(v1.len() > 12)` + | -------------- help: provide the highest index that is indexed with: `v1.len() > 12` LL | assert!(v2.len() >= 15); LL | let _ = v1[0] + v1[12]; | ^^^^^^^^^^^^^^ @@ -211,7 +211,7 @@ error: indexing into a slice multiple times with an `assert` that does not cover --> tests/ui/missing_asserts_for_indexing.rs:97:13 | LL | assert!(v2.len() >= 15); - | ----------------------- help: provide the highest index that is indexed with: `assert!(v2.len() > 15)` + | -------------- help: provide the highest index that is indexed with: `v2.len() > 15` ... LL | let _ = v2[5] + v2[15]; | ^^^^^^^^^^^^^^ @@ -232,7 +232,7 @@ error: indexing into a slice multiple times with an `assert` that does not cover --> tests/ui/missing_asserts_for_indexing.rs:103:13 | LL | assert!(v1.len() >= 12); - | ----------------------- help: provide the highest index that is indexed with: `assert!(v1.len() > 12)` + | -------------- help: provide the highest index that is indexed with: `v1.len() > 12` LL | assert!(v2.len() > 15); LL | let _ = v1[0] + v1[12]; | ^^^^^^^^^^^^^^ @@ -253,7 +253,7 @@ error: indexing into a slice multiple times with an `assert` that does not cover --> tests/ui/missing_asserts_for_indexing.rs:127:13 | LL | assert!(v1.len() == 2); - | ---------------------- help: provide the highest index that is indexed with: `assert!(v1.len() == 3)` + | ------------- help: provide the highest index that is indexed with: `v1.len() == 3` ... LL | let _ = v1[0] + v1[1] + v1[2]; | ^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +279,7 @@ error: indexing into a slice multiple times with an `assert` that does not cover --> tests/ui/missing_asserts_for_indexing.rs:131:13 | LL | assert!(2 == v3.len()); - | ---------------------- help: provide the highest index that is indexed with: `assert!(v3.len() == 3)` + | ------------- help: provide the highest index that is indexed with: `v3.len() == 3` ... LL | let _ = v3[0] + v3[1] + v3[2]; | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/coverage/assert_not.cov-map b/tests/coverage/assert_not.cov-map index 35568a98af444..4fd86e1404118 100644 --- a/tests/coverage/assert_not.cov-map +++ b/tests/coverage/assert_not.cov-map @@ -1,13 +1,18 @@ Function name: assert_not::main -Raw bytes (29): 0x[01, 01, 00, 05, 01, 06, 01, 01, 12, 05, 02, 05, 00, 14, 09, 01, 05, 00, 14, 0d, 01, 05, 00, 16, 0d, 01, 01, 00, 02] +Raw bytes (54): 0x[01, 01, 00, 0a, 01, 06, 01, 00, 0b, 05, 01, 05, 00, 0c, 01, 00, 0d, 00, 11, 09, 01, 05, 00, 0c, 05, 00, 0d, 00, 13, 0d, 01, 05, 00, 0c, 09, 00, 0d, 00, 13, 11, 01, 05, 00, 0c, 0d, 00, 0d, 00, 15, 11, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 -Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 18) -- Code(Counter(1)) at (prev + 2, 5) to (start + 0, 20) -- Code(Counter(2)) at (prev + 1, 5) to (start + 0, 20) -- Code(Counter(3)) at (prev + 1, 5) to (start + 0, 22) -- Code(Counter(3)) at (prev + 1, 1) to (start + 0, 2) -Highest counter ID seen: c3 +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 6, 1) to (start + 0, 11) +- Code(Counter(1)) at (prev + 1, 5) to (start + 0, 12) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 17) +- Code(Counter(2)) at (prev + 1, 5) to (start + 0, 12) +- Code(Counter(1)) at (prev + 0, 13) to (start + 0, 19) +- Code(Counter(3)) at (prev + 1, 5) to (start + 0, 12) +- Code(Counter(2)) at (prev + 0, 13) to (start + 0, 19) +- Code(Counter(4)) at (prev + 1, 5) to (start + 0, 12) +- Code(Counter(3)) at (prev + 0, 13) to (start + 0, 21) +- Code(Counter(4)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c4 diff --git a/tests/ui/codemap_tests/issue-28308.rs b/tests/ui/codemap_tests/issue-28308.rs index 81493f8c45311..b0e04d0f1f6b1 100644 --- a/tests/ui/codemap_tests/issue-28308.rs +++ b/tests/ui/codemap_tests/issue-28308.rs @@ -1,4 +1,16 @@ fn main() { - assert!("foo"); - //~^ ERROR cannot apply unary operator `!` + assert!("foo"); //~ ERROR mismatched types + //~^ NOTE expected `bool`, found `str` + //~| NOTE in this expansion of assert! + let x = Some(&1); + assert!(x); //~ ERROR mismatched types + //~^ NOTE expected `bool`, found `Option<&{integer}>` + //~| NOTE expected enum `bool` + //~| NOTE in this expansion of assert! + //~| NOTE in this expansion of assert! + assert!(x, ""); //~ ERROR mismatched types + //~^ NOTE expected `bool`, found `Option<&{integer}>` + //~| NOTE expected enum `bool` + //~| NOTE in this expansion of assert! + //~| NOTE in this expansion of assert! } diff --git a/tests/ui/codemap_tests/issue-28308.stderr b/tests/ui/codemap_tests/issue-28308.stderr index efd8fa22fa5ce..bdafad7ccd7a5 100644 --- a/tests/ui/codemap_tests/issue-28308.stderr +++ b/tests/ui/codemap_tests/issue-28308.stderr @@ -1,11 +1,31 @@ -error[E0600]: cannot apply unary operator `!` to type `&'static str` - --> $DIR/issue-28308.rs:2:5 +error[E0308]: mismatched types + --> $DIR/issue-28308.rs:2:13 | LL | assert!("foo"); - | ^^^^^^^^^^^^^^ cannot apply unary operator `!` + | ^^^^^ expected `bool`, found `str` | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 1 previous error +error[E0308]: mismatched types + --> $DIR/issue-28308.rs:6:13 + | +LL | assert!(x); + | ^ expected `bool`, found `Option<&{integer}>` + | + = note: expected enum `bool` + found type `Option<&{integer}>` + = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/issue-28308.rs:11:13 + | +LL | assert!(x, ""); + | ^ expected `bool`, found `Option<&{integer}>` + | + = note: expected enum `bool` + found type `Option<&{integer}>` + = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0600`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/control-flow/assert.stderr b/tests/ui/consts/control-flow/assert.stderr index 2f863daf760da..e0ae949b13c44 100644 --- a/tests/ui/consts/control-flow/assert.stderr +++ b/tests/ui/consts/control-flow/assert.stderr @@ -1,8 +1,8 @@ error[E0080]: evaluation of constant value failed - --> $DIR/assert.rs:5:15 + --> $DIR/assert.rs:5:23 | LL | const _: () = assert!(false); - | ^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: false', $DIR/assert.rs:5:15 + | ^^^^^ the evaluated program panicked at 'assertion failed: false', $DIR/assert.rs:5:15 | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/else-if.rs b/tests/ui/else-if.rs index 2161b28c58c93..26db3ec50306e 100644 --- a/tests/ui/else-if.rs +++ b/tests/ui/else-if.rs @@ -2,19 +2,19 @@ pub fn main() { if 1 == 2 { - assert!((false)); + assert!(false); } else if 2 == 3 { - assert!((false)); - } else if 3 == 4 { assert!((false)); } else { assert!((true)); } - if 1 == 2 { assert!((false)); } else if 2 == 2 { assert!((true)); } + assert!(false); + } else if 3 == 4 { assert!(false); } else { assert!(true); } + if 1 == 2 { assert!(false); } else if 2 == 2 { assert!(true); } if 1 == 2 { - assert!((false)); + assert!(false); } else if 2 == 2 { if 1 == 1 { - assert!((true)); - } else { if 2 == 1 { assert!((false)); } else { assert!((false)); } } + assert!(true); + } else { if 2 == 1 { assert!(false); } else { assert!(false); } } } if 1 == 2 { - assert!((false)); - } else { if 1 == 2 { assert!((false)); } else { assert!((true)); } } + assert!(false); + } else { if 1 == 2 { assert!(false); } else { assert!(true); } } } diff --git a/tests/ui/generics/post_monomorphization_error_backtrace.stderr b/tests/ui/generics/post_monomorphization_error_backtrace.stderr index 8a57979bca7d4..3921c32a9c892 100644 --- a/tests/ui/generics/post_monomorphization_error_backtrace.stderr +++ b/tests/ui/generics/post_monomorphization_error_backtrace.stderr @@ -1,8 +1,8 @@ error[E0080]: evaluation of `assert_zst::F::::V` failed - --> $DIR/post_monomorphization_error_backtrace.rs:6:23 + --> $DIR/post_monomorphization_error_backtrace.rs:6:31 | LL | const V: () = assert!(std::mem::size_of::() == 0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::() == 0', $DIR/post_monomorphization_error_backtrace.rs:6:23 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::() == 0', $DIR/post_monomorphization_error_backtrace.rs:6:23 | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -19,10 +19,10 @@ LL | assert_zst::() | ^^^^^^^^^^^^^^^^^ error[E0080]: evaluation of `assert_zst::F::::V` failed - --> $DIR/post_monomorphization_error_backtrace.rs:6:23 + --> $DIR/post_monomorphization_error_backtrace.rs:6:31 | LL | const V: () = assert!(std::mem::size_of::() == 0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::() == 0', $DIR/post_monomorphization_error_backtrace.rs:6:23 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::() == 0', $DIR/post_monomorphization_error_backtrace.rs:6:23 | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/inline-const/const-expr-generic-err.stderr b/tests/ui/inline-const/const-expr-generic-err.stderr index dcd6b62bbfc1d..10d8d0191c0ff 100644 --- a/tests/ui/inline-const/const-expr-generic-err.stderr +++ b/tests/ui/inline-const/const-expr-generic-err.stderr @@ -1,8 +1,8 @@ error[E0080]: evaluation of `foo::::{constant#0}` failed - --> $DIR/const-expr-generic-err.rs:4:13 + --> $DIR/const-expr-generic-err.rs:4:21 | LL | const { assert!(std::mem::size_of::() == 0); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::() == 0', $DIR/const-expr-generic-err.rs:4:13 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::() == 0', $DIR/const-expr-generic-err.rs:4:13 | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/issues/issue-14091-2.rs b/tests/ui/issues/issue-14091-2.rs index e2f6b18337266..23163b8cf481a 100644 --- a/tests/ui/issues/issue-14091-2.rs +++ b/tests/ui/issues/issue-14091-2.rs @@ -13,5 +13,5 @@ fn main() { let x = BytePos(1); assert!(x, x); - //~^ ERROR cannot apply unary operator `!` to type `BytePos` + //~^ ERROR mismatched types } diff --git a/tests/ui/issues/issue-14091-2.stderr b/tests/ui/issues/issue-14091-2.stderr index ac8947670592a..29e63cd35aaf7 100644 --- a/tests/ui/issues/issue-14091-2.stderr +++ b/tests/ui/issues/issue-14091-2.stderr @@ -1,18 +1,11 @@ -error[E0600]: cannot apply unary operator `!` to type `BytePos` - --> $DIR/issue-14091-2.rs:15:5 +error[E0308]: mismatched types + --> $DIR/issue-14091-2.rs:15:13 | LL | assert!(x, x); - | ^^^^^^^^^^^^^ cannot apply unary operator `!` + | ^ expected `bool`, found `BytePos` | -note: an implementation of `Not` might be missing for `BytePos` - --> $DIR/issue-14091-2.rs:6:1 - | -LL | pub struct BytePos(pub u32); - | ^^^^^^^^^^^^^^^^^^ must implement `Not` -note: the trait `Not` must be implemented - --> $SRC_DIR/core/src/ops/bit.rs:LL:COL = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0600`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-14091.stderr b/tests/ui/issues/issue-14091.stderr index 83879583b1f29..53251699eb404 100644 --- a/tests/ui/issues/issue-14091.stderr +++ b/tests/ui/issues/issue-14091.stderr @@ -1,8 +1,10 @@ error[E0308]: mismatched types - --> $DIR/issue-14091.rs:2:5 + --> $DIR/issue-14091.rs:2:13 | LL | assert!(1,1); - | ^^^^^^^^^^^^ expected `bool`, found integer + | ^ expected `bool`, found integer + | + = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/lazy-and-or.rs b/tests/ui/lazy-and-or.rs index f9dbeb68959a3..4691f9f27497b 100644 --- a/tests/ui/lazy-and-or.rs +++ b/tests/ui/lazy-and-or.rs @@ -1,12 +1,12 @@ //@ run-pass -fn incr(x: &mut isize) -> bool { *x += 1; assert!((false)); return false; } +fn incr(x: &mut isize) -> bool { *x += 1; assert!(false); return false; } pub fn main() { let x = 1 == 2 || 3 == 3; - assert!((x)); + assert!(x); let mut y: isize = 10; println!("{}", x || incr(&mut y)); assert_eq!(y, 10); - if true && x { assert!((true)); } else { assert!((false)); } + if true && x { assert!(true); } else { assert!(false); } } diff --git a/tests/ui/simd/const-err-trumps-simd-err.stderr b/tests/ui/simd/const-err-trumps-simd-err.stderr index 11cbcad227ff8..19606aeb50189 100644 --- a/tests/ui/simd/const-err-trumps-simd-err.stderr +++ b/tests/ui/simd/const-err-trumps-simd-err.stderr @@ -1,8 +1,8 @@ error[E0080]: evaluation of `get_elem::<4>::{constant#0}` failed - --> $DIR/const-err-trumps-simd-err.rs:16:13 + --> $DIR/const-err-trumps-simd-err.rs:16:21 | LL | const { assert!(LANE < 4); } // the error should be here... - | ^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: LANE < 4', $DIR/const-err-trumps-simd-err.rs:16:13 + | ^^^^^^^^ the evaluated program panicked at 'assertion failed: LANE < 4', $DIR/const-err-trumps-simd-err.rs:16:13 | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/tag-type-args.rs b/tests/ui/tag-type-args.rs index 75a54927443f2..e3bc89b759c8a 100644 --- a/tests/ui/tag-type-args.rs +++ b/tests/ui/tag-type-args.rs @@ -1,6 +1,6 @@ enum Quux { Bar } //~^ ERROR: parameter `T` is never used -fn foo(c: Quux) { assert!((false)); } //~ ERROR missing generics for enum `Quux` +fn foo(c: Quux) { assert!(false); } //~ ERROR missing generics for enum `Quux` fn main() { panic!(); } diff --git a/tests/ui/tag-type-args.stderr b/tests/ui/tag-type-args.stderr index def13832e1ae0..b56b13de6b11c 100644 --- a/tests/ui/tag-type-args.stderr +++ b/tests/ui/tag-type-args.stderr @@ -10,7 +10,7 @@ LL | enum Quux { Bar } error[E0107]: missing generics for enum `Quux` --> $DIR/tag-type-args.rs:4:11 | -LL | fn foo(c: Quux) { assert!((false)); } +LL | fn foo(c: Quux) { assert!(false); } | ^^^^ expected 1 generic argument | note: enum defined here, with 1 generic parameter: `T` @@ -20,7 +20,7 @@ LL | enum Quux { Bar } | ^^^^ - help: add missing generic argument | -LL | fn foo(c: Quux) { assert!((false)); } +LL | fn foo(c: Quux) { assert!(false); } | +++ error: aborting due to 2 previous errors diff --git a/tests/ui/transmutability/uninhabited.stderr b/tests/ui/transmutability/uninhabited.stderr index b8b7b67f78160..619ab79de8b9b 100644 --- a/tests/ui/transmutability/uninhabited.stderr +++ b/tests/ui/transmutability/uninhabited.stderr @@ -1,24 +1,24 @@ error[E0080]: evaluation of constant value failed - --> $DIR/uninhabited.rs:41:9 + --> $DIR/uninhabited.rs:41:17 | LL | assert!(false); - | ^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: false', $DIR/uninhabited.rs:41:9 + | ^^^^^ the evaluated program panicked at 'assertion failed: false', $DIR/uninhabited.rs:41:9 | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/uninhabited.rs:63:9 + --> $DIR/uninhabited.rs:63:17 | LL | assert!(false); - | ^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: false', $DIR/uninhabited.rs:63:9 + | ^^^^^ the evaluated program panicked at 'assertion failed: false', $DIR/uninhabited.rs:63:9 | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed - --> $DIR/uninhabited.rs:87:9 + --> $DIR/uninhabited.rs:87:17 | LL | assert!(false); - | ^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: false', $DIR/uninhabited.rs:87:9 + | ^^^^^ the evaluated program panicked at 'assertion failed: false', $DIR/uninhabited.rs:87:9 | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)