From 24d94b2db9c18a30e8564ac8144a30b52dd31577 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 30 Jan 2025 09:15:33 +0000 Subject: [PATCH 1/2] Add regression test for negative unsigned literals in patterns --- tests/ui/type/pattern_types/signed_ranges.rs | 22 +++++++++++++++++++ .../type/pattern_types/signed_ranges.stderr | 17 ++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 tests/ui/type/pattern_types/signed_ranges.rs create mode 100644 tests/ui/type/pattern_types/signed_ranges.stderr diff --git a/tests/ui/type/pattern_types/signed_ranges.rs b/tests/ui/type/pattern_types/signed_ranges.rs new file mode 100644 index 0000000000000..73ae89ac813e5 --- /dev/null +++ b/tests/ui/type/pattern_types/signed_ranges.rs @@ -0,0 +1,22 @@ +#![feature(pattern_types)] +#![feature(pattern_type_macro)] + +use std::pat::pattern_type; + +type Sign = pattern_type!(u32 is -10..); +//~^ ERROR: cannot apply unary operator `-` + +type SignedChar = pattern_type!(char is -'A'..); +//~^ ERROR: cannot apply unary operator `-` + +fn main() { + match 42_u8 { + -10..253 => {} + _ => {} + } + + match 'A' { + -'\0'..'a' => {} + _ => {} + } +} diff --git a/tests/ui/type/pattern_types/signed_ranges.stderr b/tests/ui/type/pattern_types/signed_ranges.stderr new file mode 100644 index 0000000000000..63e346927f785 --- /dev/null +++ b/tests/ui/type/pattern_types/signed_ranges.stderr @@ -0,0 +1,17 @@ +error[E0600]: cannot apply unary operator `-` to type `u32` + --> $DIR/signed_ranges.rs:6:34 + | +LL | type Sign = pattern_type!(u32 is -10..); + | ^^^ cannot apply unary operator `-` + | + = note: unsigned values cannot be negated + +error[E0600]: cannot apply unary operator `-` to type `char` + --> $DIR/signed_ranges.rs:9:41 + | +LL | type SignedChar = pattern_type!(char is -'A'..); + | ^^^^ cannot apply unary operator `-` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0600`. From f44794f45506df2499083e66e5d225c7437ed158 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 30 Jan 2025 17:14:35 +0000 Subject: [PATCH 2/2] Only allow negation on literals in patterns if it's on integers or floats --- compiler/rustc_hir_typeck/src/pat.rs | 12 ++++++-- tests/ui/type/pattern_types/signed_ranges.rs | 2 ++ .../type/pattern_types/signed_ranges.stderr | 28 +++++++++++++++++-- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index c947ecde65605..2e7415cec5d35 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -570,8 +570,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_expr_unadjusted(&self, lt: &'tcx hir::PatExpr<'tcx>) -> Ty<'tcx> { let ty = match <.kind { - rustc_hir::PatExprKind::Lit { lit, .. } => { - self.check_expr_lit(lit, Expectation::NoExpectation) + rustc_hir::PatExprKind::Lit { lit, negated } => { + let ty = self.check_expr_lit(lit, Expectation::NoExpectation); + if *negated { + self.register_bound( + ty, + self.tcx.require_lang_item(LangItem::Neg, Some(lt.span)), + ObligationCause::dummy_with_span(lt.span), + ); + } + ty } rustc_hir::PatExprKind::ConstBlock(c) => { self.check_expr_const_block(c, Expectation::NoExpectation) diff --git a/tests/ui/type/pattern_types/signed_ranges.rs b/tests/ui/type/pattern_types/signed_ranges.rs index 73ae89ac813e5..3725fbda7292a 100644 --- a/tests/ui/type/pattern_types/signed_ranges.rs +++ b/tests/ui/type/pattern_types/signed_ranges.rs @@ -12,11 +12,13 @@ type SignedChar = pattern_type!(char is -'A'..); fn main() { match 42_u8 { -10..253 => {} + //~^ ERROR `u8: Neg` is not satisfied _ => {} } match 'A' { -'\0'..'a' => {} + //~^ ERROR `char: Neg` is not satisfied _ => {} } } diff --git a/tests/ui/type/pattern_types/signed_ranges.stderr b/tests/ui/type/pattern_types/signed_ranges.stderr index 63e346927f785..79bf8501b639f 100644 --- a/tests/ui/type/pattern_types/signed_ranges.stderr +++ b/tests/ui/type/pattern_types/signed_ranges.stderr @@ -1,3 +1,26 @@ +error[E0277]: the trait bound `u8: Neg` is not satisfied + --> $DIR/signed_ranges.rs:14:9 + | +LL | -10..253 => {} + | ^^^ the trait `Neg` is not implemented for `u8` + | + = help: the following other types implement trait `Neg`: + &f128 + &f16 + &f32 + &f64 + &i128 + &i16 + &i32 + &i64 + and 12 others + +error[E0277]: the trait bound `char: Neg` is not satisfied + --> $DIR/signed_ranges.rs:20:9 + | +LL | -'\0'..'a' => {} + | ^^^^^ the trait `Neg` is not implemented for `char` + error[E0600]: cannot apply unary operator `-` to type `u32` --> $DIR/signed_ranges.rs:6:34 | @@ -12,6 +35,7 @@ error[E0600]: cannot apply unary operator `-` to type `char` LL | type SignedChar = pattern_type!(char is -'A'..); | ^^^^ cannot apply unary operator `-` -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0600`. +Some errors have detailed explanations: E0277, E0600. +For more information about an error, try `rustc --explain E0277`.