Allow const patterns of matches to contain pattern types
This commit is contained in:
parent
b9856b6e40
commit
7ad16974b9
9 changed files with 233 additions and 9 deletions
|
@ -1568,11 +1568,15 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
CastKind::Transmute => {
|
||||
span_mirbug!(
|
||||
self,
|
||||
rvalue,
|
||||
"Unexpected CastKind::Transmute, which is not permitted in Analysis MIR",
|
||||
);
|
||||
let ty_from = op.ty(self.body, tcx);
|
||||
match ty_from.kind() {
|
||||
ty::Pat(base, _) if base == ty => {}
|
||||
_ => span_mirbug!(
|
||||
self,
|
||||
rvalue,
|
||||
"Unexpected CastKind::Transmute {ty_from:?} -> {ty:?}, which is not permitted in Analysis MIR",
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,8 +140,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
let success_block = target_block(TestBranch::Success);
|
||||
let fail_block = target_block(TestBranch::Failure);
|
||||
|
||||
let expect_ty = value.ty();
|
||||
let expect = self.literal_operand(test.span, value);
|
||||
let mut expect_ty = value.ty();
|
||||
let mut expect = self.literal_operand(test.span, value);
|
||||
|
||||
let mut place = place;
|
||||
let mut block = block;
|
||||
|
@ -174,6 +174,31 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
place = ref_str;
|
||||
ty = ref_str_ty;
|
||||
}
|
||||
&ty::Pat(base, _) => {
|
||||
assert_eq!(ty, value.ty());
|
||||
assert!(base.is_trivially_pure_clone_copy());
|
||||
|
||||
let transmuted_place = self.temp(base, test.span);
|
||||
self.cfg.push_assign(
|
||||
block,
|
||||
self.source_info(scrutinee_span),
|
||||
transmuted_place,
|
||||
Rvalue::Cast(CastKind::Transmute, Operand::Copy(place), base),
|
||||
);
|
||||
|
||||
let transmuted_expect = self.temp(base, test.span);
|
||||
self.cfg.push_assign(
|
||||
block,
|
||||
self.source_info(test.span),
|
||||
transmuted_expect,
|
||||
Rvalue::Cast(CastKind::Transmute, expect, base),
|
||||
);
|
||||
|
||||
place = transmuted_place;
|
||||
expect = Operand::Copy(transmuted_expect);
|
||||
ty = base;
|
||||
expect_ty = base;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//! Check that pattern types don't implement traits of their base automatically
|
||||
//! Check that pattern types don't implement traits of their base automatically.
|
||||
//! Exceptions are `Clone` and `Copy`, which have builtin impls for pattern types.
|
||||
|
||||
#![feature(pattern_types)]
|
||||
#![feature(pattern_type_macro)]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0369]: binary operation `==` cannot be applied to type `(i32) is 0..=999999999`
|
||||
--> $DIR/derives.rs:10:20
|
||||
--> $DIR/derives.rs:11:20
|
||||
|
|
||||
LL | #[derive(Clone, Copy, PartialEq)]
|
||||
| --------- in this derive macro expansion
|
||||
|
|
26
tests/ui/type/pattern_types/derives_fail.rs
Normal file
26
tests/ui/type/pattern_types/derives_fail.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
//! Check that pattern types don't implement traits of their base automatically.
|
||||
//! Exceptions are `Clone` and `Copy`, which have bultin impls for pattern types.
|
||||
|
||||
#![feature(pattern_types)]
|
||||
#![feature(pattern_type_macro)]
|
||||
|
||||
use std::pat::pattern_type;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)]
|
||||
#[repr(transparent)]
|
||||
struct Nanoseconds(NanoI32);
|
||||
//~^ ERROR: the trait bound `(i32) is 0..=999999999: Eq` is not satisfied
|
||||
//~| ERROR: `(i32) is 0..=999999999` doesn't implement `Debug`
|
||||
//~| ERROR: the trait bound `(i32) is 0..=999999999: Ord` is not satisfied
|
||||
//~| ERROR: the trait bound `(i32) is 0..=999999999: Hash` is not satisfied
|
||||
//~| ERROR: the trait bound `(i32) is 0..=999999999: Default` is not satisfied
|
||||
//~| ERROR: can't compare `(i32) is 0..=999999999` with `_`
|
||||
//~| ERROR: `==` cannot be applied
|
||||
|
||||
type NanoI32 = crate::pattern_type!(i32 is 0..=999_999_999);
|
||||
|
||||
fn main() {
|
||||
let x = Nanoseconds(unsafe { std::mem::transmute(42) });
|
||||
let y = x.clone();
|
||||
if y == x {}
|
||||
}
|
74
tests/ui/type/pattern_types/derives_fail.stderr
Normal file
74
tests/ui/type/pattern_types/derives_fail.stderr
Normal file
|
@ -0,0 +1,74 @@
|
|||
error[E0369]: binary operation `==` cannot be applied to type `(i32) is 0..=999999999`
|
||||
--> $DIR/derives_fail.rs:11:20
|
||||
|
|
||||
LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)]
|
||||
| --------- in this derive macro expansion
|
||||
LL | #[repr(transparent)]
|
||||
LL | struct Nanoseconds(NanoI32);
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0277]: the trait bound `(i32) is 0..=999999999: Eq` is not satisfied
|
||||
--> $DIR/derives_fail.rs:11:20
|
||||
|
|
||||
LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)]
|
||||
| -- in this derive macro expansion
|
||||
LL | #[repr(transparent)]
|
||||
LL | struct Nanoseconds(NanoI32);
|
||||
| ^^^^^^^ the trait `Eq` is not implemented for `(i32) is 0..=999999999`
|
||||
|
|
||||
note: required by a bound in `AssertParamIsEq`
|
||||
--> $SRC_DIR/core/src/cmp.rs:LL:COL
|
||||
|
||||
error[E0277]: `(i32) is 0..=999999999` doesn't implement `Debug`
|
||||
--> $DIR/derives_fail.rs:11:20
|
||||
|
|
||||
LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)]
|
||||
| ----- in this derive macro expansion
|
||||
LL | #[repr(transparent)]
|
||||
LL | struct Nanoseconds(NanoI32);
|
||||
| ^^^^^^^ `(i32) is 0..=999999999` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
||||
|
|
||||
= help: the trait `Debug` is not implemented for `(i32) is 0..=999999999`
|
||||
|
||||
error[E0277]: the trait bound `(i32) is 0..=999999999: Ord` is not satisfied
|
||||
--> $DIR/derives_fail.rs:11:20
|
||||
|
|
||||
LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)]
|
||||
| --- in this derive macro expansion
|
||||
LL | #[repr(transparent)]
|
||||
LL | struct Nanoseconds(NanoI32);
|
||||
| ^^^^^^^ the trait `Ord` is not implemented for `(i32) is 0..=999999999`
|
||||
|
||||
error[E0277]: can't compare `(i32) is 0..=999999999` with `_`
|
||||
--> $DIR/derives_fail.rs:11:20
|
||||
|
|
||||
LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)]
|
||||
| ---------- in this derive macro expansion
|
||||
LL | #[repr(transparent)]
|
||||
LL | struct Nanoseconds(NanoI32);
|
||||
| ^^^^^^^ no implementation for `(i32) is 0..=999999999 < _` and `(i32) is 0..=999999999 > _`
|
||||
|
|
||||
= help: the trait `PartialOrd<_>` is not implemented for `(i32) is 0..=999999999`
|
||||
|
||||
error[E0277]: the trait bound `(i32) is 0..=999999999: Hash` is not satisfied
|
||||
--> $DIR/derives_fail.rs:11:20
|
||||
|
|
||||
LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)]
|
||||
| ---- in this derive macro expansion
|
||||
LL | #[repr(transparent)]
|
||||
LL | struct Nanoseconds(NanoI32);
|
||||
| ^^^^^^^ the trait `Hash` is not implemented for `(i32) is 0..=999999999`
|
||||
|
||||
error[E0277]: the trait bound `(i32) is 0..=999999999: Default` is not satisfied
|
||||
--> $DIR/derives_fail.rs:11:20
|
||||
|
|
||||
LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)]
|
||||
| ------- in this derive macro expansion
|
||||
LL | #[repr(transparent)]
|
||||
LL | struct Nanoseconds(NanoI32);
|
||||
| ^^^^^^^ the trait `Default` is not implemented for `(i32) is 0..=999999999`
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0369.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
26
tests/ui/type/pattern_types/matching.rs
Normal file
26
tests/ui/type/pattern_types/matching.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
#![feature(pattern_types, pattern_type_macro, structural_match)]
|
||||
|
||||
//@ check-pass
|
||||
|
||||
use std::marker::StructuralPartialEq;
|
||||
use std::pat::pattern_type;
|
||||
|
||||
struct Thing(pattern_type!(u32 is 1..));
|
||||
|
||||
impl StructuralPartialEq for Thing {}
|
||||
impl PartialEq for Thing {
|
||||
fn eq(&self, other: &Thing) -> bool {
|
||||
unsafe { std::mem::transmute::<_, u32>(self.0) == std::mem::transmute::<_, u32>(other.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Thing {}
|
||||
|
||||
const TWO: Thing = Thing(2);
|
||||
|
||||
const _: () = match TWO {
|
||||
TWO => {}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
fn main() {}
|
25
tests/ui/type/pattern_types/matching_fail.rs
Normal file
25
tests/ui/type/pattern_types/matching_fail.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
#![feature(pattern_types, pattern_type_macro, structural_match)]
|
||||
|
||||
use std::pat::pattern_type;
|
||||
|
||||
const THREE: pattern_type!(u32 is 1..) = 3;
|
||||
|
||||
const _: () = match THREE {
|
||||
THREE => {}
|
||||
//~^ ERROR non-structural type
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
const _: () = match THREE {
|
||||
3 => {}
|
||||
//~^ ERROR mismatched types
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
const _: () = match 3 {
|
||||
THREE => {}
|
||||
//~^ ERROR mismatched types
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
fn main() {}
|
43
tests/ui/type/pattern_types/matching_fail.stderr
Normal file
43
tests/ui/type/pattern_types/matching_fail.stderr
Normal file
|
@ -0,0 +1,43 @@
|
|||
error: constant of non-structural type `(u32) is 1..` in a pattern
|
||||
--> $DIR/matching_fail.rs:8:5
|
||||
|
|
||||
LL | const THREE: pattern_type!(u32 is 1..) = 3;
|
||||
| -------------------------------------- constant defined here
|
||||
...
|
||||
LL | THREE => {}
|
||||
| ^^^^^ constant of non-structural type
|
||||
|
|
||||
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/matching_fail.rs:14:5
|
||||
|
|
||||
LL | const _: () = match THREE {
|
||||
| ----- this expression has type `(u32) is 1..`
|
||||
LL | 3 => {}
|
||||
| ^ expected `(u32) is 1..`, found integer
|
||||
|
|
||||
= note: expected pattern type `(u32) is 1..`
|
||||
found type `{integer}`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/matching_fail.rs:20:5
|
||||
|
|
||||
LL | const THREE: pattern_type!(u32 is 1..) = 3;
|
||||
| -------------------------------------- constant defined here
|
||||
...
|
||||
LL | const _: () = match 3 {
|
||||
| - this expression has type `{integer}`
|
||||
LL | THREE => {}
|
||||
| ^^^^^
|
||||
| |
|
||||
| expected integer, found `(u32) is 1..`
|
||||
| `THREE` is interpreted as a constant, not a new binding
|
||||
| help: introduce a new binding instead: `other_three`
|
||||
|
|
||||
= note: expected type `{integer}`
|
||||
found pattern type `(u32) is 1..`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Add table
Add a link
Reference in a new issue