File: const-pats-do-not-mislead-inference.rs

package info (click to toggle)
rustc 1.88.0%2Bdfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 934,128 kB
  • sloc: xml: 158,127; python: 36,062; javascript: 19,855; sh: 19,700; cpp: 18,947; ansic: 12,993; asm: 4,792; makefile: 690; lisp: 29; perl: 29; ruby: 19; sql: 11
file content (54 lines) | stat: -rw-r--r-- 2,144 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//@ revisions: stable deref_patterns
//@[deref_patterns] check-pass
//! `deref_patterns` allows string and byte string literal patterns to implicitly peel references
//! and smart pointers from the scrutinee before matching. Since strings and byte strings themselves
//! have reference types, we need to make sure we don't peel too much. By leaving the type of the
//! match scrutinee partially uninferred, these tests make sure we only peel as much as needed in
//! order to match. In particular, when peeling isn't needed, the results should be the same was
//! we'd get without `deref_patterns` enabled.

#![cfg_attr(deref_patterns, feature(deref_patterns))]
#![cfg_attr(deref_patterns, expect(incomplete_features))]

fn uninferred<T>() -> T { unimplemented!() }

// Assert type equality without allowing coercions.
trait Is<T> {}
impl<T> Is<T> for T {}
fn has_type<T>(_: impl Is<T>) {}

fn main() {
    // We don't need to peel anything to unify the type of `x` with `&str`, so `x: &str`.
    let x = uninferred();
    if let "..." = x {}
    has_type::<&str>(x);

    // We don't need to peel anything to unify the type of `&x` with `&[u8; 3]`, so `x: [u8; 3]`.
    let x = uninferred();
    if let b"..." = &x {}
    has_type::<[u8; 3]>(x);

    // Peeling a single `&` lets us unify the type of `&x` with `&[u8; 3]`, giving `x: [u8; 3]`.
    let x = uninferred();
    if let b"..." = &&x {}
    //[stable]~^ ERROR: mismatched types
    has_type::<[u8; 3]>(x);

    // We have to peel both the `&` and the box before unifying the type of `x` with `&str`.
    let x = uninferred();
    if let "..." = &Box::new(x) {}
    //[stable]~^ ERROR mismatched types
    has_type::<&str>(x);

    // After peeling the box, we can unify the type of `&x` with `&[u8; 3]`, giving `x: [u8; 3]`.
    let x = uninferred();
    if let b"..." = Box::new(&x) {}
    //[stable]~^ ERROR mismatched types
    has_type::<[u8; 3]>(x);

    // `&` and `&mut` aren't interchangeable: `&mut`s need to be peeled before unifying, like boxes:
    let mut x = uninferred();
    if let "..." = &mut x {}
    //[stable]~^ ERROR mismatched types
    has_type::<&str>(x);
}