From f6e4c742f41c5505c9a371ce8ef2c7aed55c35e4 Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Mon, 11 Oct 2021 16:40:16 -0700 Subject: [PATCH 01/11] Make split_inclusive() on an empty slice yield an empty output `[].split_inclusive()` currently yields a single, empty slice. That's different from `"".split_inslusive()`, which yields no output at all. I think that makes the slice version harder to use. The case where I ran into this bug was when writing code for generating a diff between two slices of bytes. I wanted to prefix removed lines with "-" and a added lines with "+". Due to `split_inclusive()`'s current behavior, that means that my code prints just a "-" or "+" for empty files. I suspect most existing callers have similar "bugs" (which would be fixed by this patch). Closes #89716. --- library/alloc/tests/slice.rs | 8 ++++---- library/core/src/slice/iter.rs | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/library/alloc/tests/slice.rs b/library/alloc/tests/slice.rs index 13b8c059e37ae..18ea6a2141377 100644 --- a/library/alloc/tests/slice.rs +++ b/library/alloc/tests/slice.rs @@ -863,7 +863,7 @@ fn test_splitator_inclusive() { assert_eq!(xs.split_inclusive(|_| true).collect::>(), splits); let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; + let splits: &[&[i32]] = &[]; assert_eq!(xs.split_inclusive(|x| *x == 5).collect::>(), splits); } @@ -883,7 +883,7 @@ fn test_splitator_inclusive_reverse() { assert_eq!(xs.split_inclusive(|_| true).rev().collect::>(), splits); let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; + let splits: &[&[i32]] = &[]; assert_eq!(xs.split_inclusive(|x| *x == 5).rev().collect::>(), splits); } @@ -903,7 +903,7 @@ fn test_splitator_mut_inclusive() { assert_eq!(xs.split_inclusive_mut(|_| true).collect::>(), splits); let xs: &mut [i32] = &mut []; - let splits: &[&[i32]] = &[&[]]; + let splits: &[&[i32]] = &[]; assert_eq!(xs.split_inclusive_mut(|x| *x == 5).collect::>(), splits); } @@ -923,7 +923,7 @@ fn test_splitator_mut_inclusive_reverse() { assert_eq!(xs.split_inclusive_mut(|_| true).rev().collect::>(), splits); let xs: &mut [i32] = &mut []; - let splits: &[&[i32]] = &[&[]]; + let splits: &[&[i32]] = &[]; assert_eq!(xs.split_inclusive_mut(|x| *x == 5).rev().collect::>(), splits); } diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 70e59cda63f26..d88c85613a900 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -479,7 +479,8 @@ where impl<'a, T: 'a, P: FnMut(&T) -> bool> SplitInclusive<'a, T, P> { #[inline] pub(super) fn new(slice: &'a [T], pred: P) -> Self { - Self { v: slice, pred, finished: false } + let finished = slice.is_empty(); + Self { v: slice, pred, finished } } } @@ -727,7 +728,8 @@ where impl<'a, T: 'a, P: FnMut(&T) -> bool> SplitInclusiveMut<'a, T, P> { #[inline] pub(super) fn new(slice: &'a mut [T], pred: P) -> Self { - Self { v: slice, pred, finished: false } + let finished = slice.is_empty(); + Self { v: slice, pred, finished } } } From c983c0a46ae0d496a64ae7553921a904c5a92d16 Mon Sep 17 00:00:00 2001 From: cameron Date: Fri, 26 Nov 2021 00:03:52 +0000 Subject: [PATCH 02/11] regression test for issue 87490 --- src/test/ui/issues/issue-87490.rs | 10 ++++++++++ src/test/ui/issues/issue-87490.stderr | 14 ++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 src/test/ui/issues/issue-87490.rs create mode 100644 src/test/ui/issues/issue-87490.stderr diff --git a/src/test/ui/issues/issue-87490.rs b/src/test/ui/issues/issue-87490.rs new file mode 100644 index 0000000000000..998f61a6bd32d --- /dev/null +++ b/src/test/ui/issues/issue-87490.rs @@ -0,0 +1,10 @@ +fn main() {} +trait StreamOnce { + type Position; +} +impl StreamOnce for &str { + type Position = usize; +} +fn follow(_: &str) -> <&str as StreamOnce>::Position { + String::new //~ ERROR mismatched types +} diff --git a/src/test/ui/issues/issue-87490.stderr b/src/test/ui/issues/issue-87490.stderr new file mode 100644 index 0000000000000..f359dd638ad93 --- /dev/null +++ b/src/test/ui/issues/issue-87490.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-87490.rs:9:5 + | +LL | fn follow(_: &str) -> <&str as StreamOnce>::Position { + | ------------------------------ expected `usize` because of return type +LL | String::new + | ^^^^^^^^^^^ expected `usize`, found fn item + | + = note: expected type `usize` + found fn item `fn() -> String {String::new}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From dfdc60fc99847af6df0867f2d1b27adf24bfe30e Mon Sep 17 00:00:00 2001 From: surechen Date: Sat, 11 Dec 2021 14:55:13 +0800 Subject: [PATCH 03/11] fix typo --- compiler/rustc_ast/src/mut_visit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 205625573a6d9..6bf23af81bf6b 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1,5 +1,5 @@ //! A `MutVisitor` represents an AST modification; it accepts an AST piece and -//! and mutates it in place. So, for instance, macro expansion is a `MutVisitor` +//! mutates it in place. So, for instance, macro expansion is a `MutVisitor` //! that walks over an AST and modifies it. //! //! Note: using a `MutVisitor` (other than the `MacroExpander` `MutVisitor`) on From f3a08fd8e78b567342d1f42cc17315eddea9b1e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Sat, 11 Dec 2021 17:32:15 +0100 Subject: [PATCH 04/11] Avoid suggesting self in visibility spec Co-authored-by: Esteban Kuber --- .../rustc_resolve/src/late/diagnostics.rs | 7 ++++- src/test/ui/suggestions/suggest-add-self.rs | 15 ++++++++++ .../ui/suggestions/suggest-add-self.stderr | 29 +++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/suggestions/suggest-add-self.rs create mode 100644 src/test/ui/suggestions/suggest-add-self.stderr diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 72ba3f7b980cb..f3891723e97b7 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -298,11 +298,16 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { .get(0) .map(|p| (p.span.shrink_to_lo(), "&self, ")) .unwrap_or_else(|| { + // Try to look for the "(" after the function name, if possible. + // This avoids placing the suggestion into the visibility specifier. + let span = fn_kind + .ident() + .map_or(*span, |ident| span.with_lo(ident.span.hi())); ( self.r .session .source_map() - .span_through_char(*span, '(') + .span_through_char(span, '(') .shrink_to_hi(), "&self", ) diff --git a/src/test/ui/suggestions/suggest-add-self.rs b/src/test/ui/suggestions/suggest-add-self.rs new file mode 100644 index 0000000000000..40692c8df2053 --- /dev/null +++ b/src/test/ui/suggestions/suggest-add-self.rs @@ -0,0 +1,15 @@ +struct X(i32); + +impl X { + pub(crate) fn f() { + self.0 + //~^ ERROR expected value, found module `self` + } + + pub fn g() { + self.0 + //~^ ERROR expected value, found module `self` + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/suggest-add-self.stderr b/src/test/ui/suggestions/suggest-add-self.stderr new file mode 100644 index 0000000000000..a5e8f93deb64a --- /dev/null +++ b/src/test/ui/suggestions/suggest-add-self.stderr @@ -0,0 +1,29 @@ +error[E0424]: expected value, found module `self` + --> $DIR/suggest-add-self.rs:5:9 + | +LL | pub(crate) fn f() { + | - this function doesn't have a `self` parameter +LL | self.0 + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + | +help: add a `self` receiver parameter to make the associated `fn` a method + | +LL | pub(crate) fn f(&self) { + | +++++ + +error[E0424]: expected value, found module `self` + --> $DIR/suggest-add-self.rs:10:9 + | +LL | pub fn g() { + | - this function doesn't have a `self` parameter +LL | self.0 + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + | +help: add a `self` receiver parameter to make the associated `fn` a method + | +LL | pub fn g(&self) { + | +++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0424`. From 01948e2f45acefc336501b9b9f836845fc566774 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Mon, 13 Dec 2021 12:35:55 +0300 Subject: [PATCH 05/11] Looser check for binary_op_overflow --- compiler/rustc_const_eval/src/interpret/operator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index a90582fc33820..a3094c8991c7d 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -330,7 +330,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { _ if left.layout.ty.is_any_ptr() => { // The RHS type must be the same *or an integer type* (for `Offset`). assert!( - right.layout.ty == left.layout.ty || right.layout.ty.is_integral(), + right.layout.ty.is_any_ptr()|| right.layout.ty.is_integral(), "Unexpected types for BinOp: {:?} {:?} {:?}", left.layout.ty, bin_op, From a01b13dede8f4197520ac136d87a831ddfadc9c4 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Mon, 13 Dec 2021 12:59:31 +0300 Subject: [PATCH 06/11] formatting --- compiler/rustc_const_eval/src/interpret/operator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index a3094c8991c7d..58a51b15faa6c 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -330,7 +330,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { _ if left.layout.ty.is_any_ptr() => { // The RHS type must be the same *or an integer type* (for `Offset`). assert!( - right.layout.ty.is_any_ptr()|| right.layout.ty.is_integral(), + right.layout.ty.is_any_ptr() || right.layout.ty.is_integral(), "Unexpected types for BinOp: {:?} {:?} {:?}", left.layout.ty, bin_op, From b6c80985bd5c63ebf5f720450c4208fabc20af73 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Tue, 14 Dec 2021 00:15:50 +0300 Subject: [PATCH 07/11] Add regression test and comment --- compiler/rustc_const_eval/src/interpret/operator.rs | 3 ++- src/test/ui/binop/binary-op-on-fn-ptr-eq.rs | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/binop/binary-op-on-fn-ptr-eq.rs diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 58a51b15faa6c..3b8b65a50d21f 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -328,7 +328,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.binary_int_op(bin_op, l, left.layout, r, right.layout) } _ if left.layout.ty.is_any_ptr() => { - // The RHS type must be the same *or an integer type* (for `Offset`). + // The RHS type must be a `pointer` *or an integer type* (for `Offset`). + // (This is workaround for the issue #91636) assert!( right.layout.ty.is_any_ptr() || right.layout.ty.is_integral(), "Unexpected types for BinOp: {:?} {:?} {:?}", diff --git a/src/test/ui/binop/binary-op-on-fn-ptr-eq.rs b/src/test/ui/binop/binary-op-on-fn-ptr-eq.rs new file mode 100644 index 0000000000000..188a27a1dcd45 --- /dev/null +++ b/src/test/ui/binop/binary-op-on-fn-ptr-eq.rs @@ -0,0 +1,8 @@ +// Tests equality between supertype and subtype of a function +// See the issue #91636 +fn foo(_a: &str) {} + +fn main() { + let x = foo as fn(&'static str); + let _ = x == foo; +} From b85762f436a2ef12e2a0a36ac3a61d680871b3cc Mon Sep 17 00:00:00 2001 From: ouz-a Date: Tue, 14 Dec 2021 01:19:10 +0300 Subject: [PATCH 08/11] test should pass :sweat_smile: --- src/test/ui/binop/binary-op-on-fn-ptr-eq.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/binop/binary-op-on-fn-ptr-eq.rs b/src/test/ui/binop/binary-op-on-fn-ptr-eq.rs index 188a27a1dcd45..8e20640b58d94 100644 --- a/src/test/ui/binop/binary-op-on-fn-ptr-eq.rs +++ b/src/test/ui/binop/binary-op-on-fn-ptr-eq.rs @@ -1,3 +1,4 @@ +// run-pass // Tests equality between supertype and subtype of a function // See the issue #91636 fn foo(_a: &str) {} From ffe067cdfcedd34989fb6ece769eb34a24eb4f9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 11 Dec 2021 00:00:00 +0000 Subject: [PATCH 09/11] Return an error when `eval_rvalue_with_identities` fails Previously some code paths would fail to evaluate the rvalue, while incorrectly indicating success with `Ok`. As a result the previous value of lhs could have been incorrectly const propagated. --- .../rustc_mir_transform/src/const_prop.rs | 86 ++++++++----------- src/test/ui/mir/mir_const_prop_identity.rs | 12 +++ 2 files changed, 46 insertions(+), 52 deletions(-) create mode 100644 src/test/ui/mir/mir_const_prop_identity.rs diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index e897e89982c0d..84bdb8eece654 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -752,62 +752,44 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { rvalue: &Rvalue<'tcx>, place: Place<'tcx>, ) -> Option<()> { - self.use_ecx(|this| { - match rvalue { - Rvalue::BinaryOp(op, box (left, right)) - | Rvalue::CheckedBinaryOp(op, box (left, right)) => { - let l = this.ecx.eval_operand(left, None); - let r = this.ecx.eval_operand(right, None); - - let const_arg = match (l, r) { - (Ok(ref x), Err(_)) | (Err(_), Ok(ref x)) => this.ecx.read_immediate(x)?, - (Err(e), Err(_)) => return Err(e), - (Ok(_), Ok(_)) => { - this.ecx.eval_rvalue_into_place(rvalue, place)?; - return Ok(()); - } - }; - - let arg_value = const_arg.to_scalar()?.to_bits(const_arg.layout.size)?; - let dest = this.ecx.eval_place(place)?; - - match op { - BinOp::BitAnd => { - if arg_value == 0 { - this.ecx.write_immediate(*const_arg, &dest)?; - } - } - BinOp::BitOr => { - if arg_value == const_arg.layout.size.truncate(u128::MAX) - || (const_arg.layout.ty.is_bool() && arg_value == 1) - { - this.ecx.write_immediate(*const_arg, &dest)?; - } - } - BinOp::Mul => { - if const_arg.layout.ty.is_integral() && arg_value == 0 { - if let Rvalue::CheckedBinaryOp(_, _) = rvalue { - let val = Immediate::ScalarPair( - const_arg.to_scalar()?.into(), - Scalar::from_bool(false).into(), - ); - this.ecx.write_immediate(val, &dest)?; - } else { - this.ecx.write_immediate(*const_arg, &dest)?; - } - } - } - _ => { - this.ecx.eval_rvalue_into_place(rvalue, place)?; + self.use_ecx(|this| match rvalue { + Rvalue::BinaryOp(op, box (left, right)) + | Rvalue::CheckedBinaryOp(op, box (left, right)) => { + let l = this.ecx.eval_operand(left, None); + let r = this.ecx.eval_operand(right, None); + + let const_arg = match (l, r) { + (Ok(ref x), Err(_)) | (Err(_), Ok(ref x)) => this.ecx.read_immediate(x)?, + (Err(e), Err(_)) => return Err(e), + (Ok(_), Ok(_)) => return this.ecx.eval_rvalue_into_place(rvalue, place), + }; + + let arg_value = const_arg.to_scalar()?.to_bits(const_arg.layout.size)?; + let dest = this.ecx.eval_place(place)?; + + match op { + BinOp::BitAnd if arg_value == 0 => this.ecx.write_immediate(*const_arg, &dest), + BinOp::BitOr + if arg_value == const_arg.layout.size.truncate(u128::MAX) + || (const_arg.layout.ty.is_bool() && arg_value == 1) => + { + this.ecx.write_immediate(*const_arg, &dest) + } + BinOp::Mul if const_arg.layout.ty.is_integral() && arg_value == 0 => { + if let Rvalue::CheckedBinaryOp(_, _) = rvalue { + let val = Immediate::ScalarPair( + const_arg.to_scalar()?.into(), + Scalar::from_bool(false).into(), + ); + this.ecx.write_immediate(val, &dest) + } else { + this.ecx.write_immediate(*const_arg, &dest) } } - } - _ => { - this.ecx.eval_rvalue_into_place(rvalue, place)?; + _ => this.ecx.eval_rvalue_into_place(rvalue, place), } } - - Ok(()) + _ => this.ecx.eval_rvalue_into_place(rvalue, place), }) } diff --git a/src/test/ui/mir/mir_const_prop_identity.rs b/src/test/ui/mir/mir_const_prop_identity.rs new file mode 100644 index 0000000000000..25d2202b909d9 --- /dev/null +++ b/src/test/ui/mir/mir_const_prop_identity.rs @@ -0,0 +1,12 @@ +// Regression test for issue #91725. +// +// run-pass +// compile-flags: -Zmir-opt-level=4 + +fn main() { + let a = true; + let _ = &a; + let mut b = false; + b |= a; + assert!(b); +} From a5054e3858150384c30ce71afc76ca9c57c8cec2 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Tue, 14 Dec 2021 19:29:29 +0300 Subject: [PATCH 10/11] comment update --- compiler/rustc_const_eval/src/interpret/operator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 3b8b65a50d21f..48c90e1881a9a 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -329,7 +329,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } _ if left.layout.ty.is_any_ptr() => { // The RHS type must be a `pointer` *or an integer type* (for `Offset`). - // (This is workaround for the issue #91636) + // (Even when both sides are pointers, their type might differ, see issue #91636) assert!( right.layout.ty.is_any_ptr() || right.layout.ty.is_integral(), "Unexpected types for BinOp: {:?} {:?} {:?}", From f194c9b26af5d280ab2d0e01fd85e23b3c303771 Mon Sep 17 00:00:00 2001 From: r00ster91 Date: Mon, 6 Dec 2021 18:55:58 +0100 Subject: [PATCH 11/11] Recover on invalid operators <> and <=> --- compiler/rustc_parse/src/parser/expr.rs | 34 ++++++++++++++++++- .../less-than-greater-than.rs | 4 +++ .../less-than-greater-than.stderr | 8 +++++ src/test/ui/operator-recovery/spaceship.rs | 4 +++ .../ui/operator-recovery/spaceship.stderr | 8 +++++ 5 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/operator-recovery/less-than-greater-than.rs create mode 100644 src/test/ui/operator-recovery/less-than-greater-than.stderr create mode 100644 src/test/ui/operator-recovery/spaceship.rs create mode 100644 src/test/ui/operator-recovery/spaceship.stderr diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 1dbd7bad0f023..1c31c84b8bfec 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -213,11 +213,11 @@ impl<'a> Parser<'a> { } } + // Look for JS' `===` and `!==` and recover if (op.node == AssocOp::Equal || op.node == AssocOp::NotEqual) && self.token.kind == token::Eq && self.prev_token.span.hi() == self.token.span.lo() { - // Look for JS' `===` and `!==` and recover 😇 let sp = op.span.to(self.token.span); let sugg = match op.node { AssocOp::Equal => "==", @@ -235,6 +235,38 @@ impl<'a> Parser<'a> { self.bump(); } + // Look for PHP's `<>` and recover + if op.node == AssocOp::Less + && self.token.kind == token::Gt + && self.prev_token.span.hi() == self.token.span.lo() + { + let sp = op.span.to(self.token.span); + self.struct_span_err(sp, "invalid comparison operator `<>`") + .span_suggestion_short( + sp, + "`<>` is not a valid comparison operator, use `!=`", + "!=".to_string(), + Applicability::MachineApplicable, + ) + .emit(); + self.bump(); + } + + // Look for C++'s `<=>` and recover + if op.node == AssocOp::LessEqual + && self.token.kind == token::Gt + && self.prev_token.span.hi() == self.token.span.lo() + { + let sp = op.span.to(self.token.span); + self.struct_span_err(sp, "invalid comparison operator `<=>`") + .span_label( + sp, + "`<=>` is not a valid comparison operator, use `std::cmp::Ordering`", + ) + .emit(); + self.bump(); + } + let op = op.node; // Special cases: if op == AssocOp::As { diff --git a/src/test/ui/operator-recovery/less-than-greater-than.rs b/src/test/ui/operator-recovery/less-than-greater-than.rs new file mode 100644 index 0000000000000..2beed528ff1c1 --- /dev/null +++ b/src/test/ui/operator-recovery/less-than-greater-than.rs @@ -0,0 +1,4 @@ +fn main() { + println!("{}", 1 <> 2); + //~^ERROR invalid comparison operator `<>` +} diff --git a/src/test/ui/operator-recovery/less-than-greater-than.stderr b/src/test/ui/operator-recovery/less-than-greater-than.stderr new file mode 100644 index 0000000000000..80c921535bd08 --- /dev/null +++ b/src/test/ui/operator-recovery/less-than-greater-than.stderr @@ -0,0 +1,8 @@ +error: invalid comparison operator `<>` + --> $DIR/less-than-greater-than.rs:2:22 + | +LL | println!("{}", 1 <> 2); + | ^^ help: `<>` is not a valid comparison operator, use `!=` + +error: aborting due to previous error + diff --git a/src/test/ui/operator-recovery/spaceship.rs b/src/test/ui/operator-recovery/spaceship.rs new file mode 100644 index 0000000000000..a65f9389625fc --- /dev/null +++ b/src/test/ui/operator-recovery/spaceship.rs @@ -0,0 +1,4 @@ +fn main() { + println!("{}", 1 <=> 2); + //~^ERROR invalid comparison operator `<=>` +} diff --git a/src/test/ui/operator-recovery/spaceship.stderr b/src/test/ui/operator-recovery/spaceship.stderr new file mode 100644 index 0000000000000..ed6bd74c9b92e --- /dev/null +++ b/src/test/ui/operator-recovery/spaceship.stderr @@ -0,0 +1,8 @@ +error: invalid comparison operator `<=>` + --> $DIR/spaceship.rs:2:22 + | +LL | println!("{}", 1 <=> 2); + | ^^^ `<=>` is not a valid comparison operator, use `std::cmp::Ordering` + +error: aborting due to previous error +