summaryrefslogtreecommitdiffstats
path: root/library/core/tests/any.rs
blob: 8ed0c88808fe27fc47d36b4734dae75a0401e11b (plain)
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
use core::any::*;

#[derive(PartialEq, Debug)]
struct Test;

static TEST: &'static str = "Test";

#[test]
fn any_referenced() {
    let (a, b, c) = (&5 as &dyn Any, &TEST as &dyn Any, &Test as &dyn Any);

    assert!(a.is::<i32>());
    assert!(!b.is::<i32>());
    assert!(!c.is::<i32>());

    assert!(!a.is::<&'static str>());
    assert!(b.is::<&'static str>());
    assert!(!c.is::<&'static str>());

    assert!(!a.is::<Test>());
    assert!(!b.is::<Test>());
    assert!(c.is::<Test>());
}

#[test]
fn any_owning() {
    let (a, b, c) = (
        Box::new(5_usize) as Box<dyn Any>,
        Box::new(TEST) as Box<dyn Any>,
        Box::new(Test) as Box<dyn Any>,
    );

    assert!(a.is::<usize>());
    assert!(!b.is::<usize>());
    assert!(!c.is::<usize>());

    assert!(!a.is::<&'static str>());
    assert!(b.is::<&'static str>());
    assert!(!c.is::<&'static str>());

    assert!(!a.is::<Test>());
    assert!(!b.is::<Test>());
    assert!(c.is::<Test>());
}

#[test]
fn any_downcast_ref() {
    let a = &5_usize as &dyn Any;

    match a.downcast_ref::<usize>() {
        Some(&5) => {}
        x => panic!("Unexpected value {x:?}"),
    }

    match a.downcast_ref::<Test>() {
        None => {}
        x => panic!("Unexpected value {x:?}"),
    }
}

#[test]
fn any_downcast_mut() {
    let mut a = 5_usize;
    let mut b: Box<_> = Box::new(7_usize);

    let a_r = &mut a as &mut dyn Any;
    let tmp: &mut usize = &mut *b;
    let b_r = tmp as &mut dyn Any;

    match a_r.downcast_mut::<usize>() {
        Some(x) => {
            assert_eq!(*x, 5);
            *x = 612;
        }
        x => panic!("Unexpected value {x:?}"),
    }

    match b_r.downcast_mut::<usize>() {
        Some(x) => {
            assert_eq!(*x, 7);
            *x = 413;
        }
        x => panic!("Unexpected value {x:?}"),
    }

    match a_r.downcast_mut::<Test>() {
        None => (),
        x => panic!("Unexpected value {x:?}"),
    }

    match b_r.downcast_mut::<Test>() {
        None => (),
        x => panic!("Unexpected value {x:?}"),
    }

    match a_r.downcast_mut::<usize>() {
        Some(&mut 612) => {}
        x => panic!("Unexpected value {x:?}"),
    }

    match b_r.downcast_mut::<usize>() {
        Some(&mut 413) => {}
        x => panic!("Unexpected value {x:?}"),
    }
}

#[test]
fn any_fixed_vec() {
    let test = [0_usize; 8];
    let test = &test as &dyn Any;
    assert!(test.is::<[usize; 8]>());
    assert!(!test.is::<[usize; 10]>());
}

#[test]
fn any_unsized() {
    fn is_any<T: Any + ?Sized>() {}
    is_any::<[i32]>();
}

#[test]
fn distinct_type_names() {
    // https://github.com/rust-lang/rust/issues/84666

    struct Velocity(f32, f32);

    fn type_name_of_val<T>(_: T) -> &'static str {
        type_name::<T>()
    }

    assert_ne!(type_name_of_val(Velocity), type_name_of_val(Velocity(0.0, -9.8)),);
}

// Test the `Provider` API.

struct SomeConcreteType {
    some_string: String,
}

impl Provider for SomeConcreteType {
    fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
        demand
            .provide_ref::<String>(&self.some_string)
            .provide_ref::<str>(&self.some_string)
            .provide_value::<String>(|| "bye".to_owned());
    }
}

// Test the provide and request mechanisms with a by-reference trait object.
#[test]
fn test_provider() {
    let obj: &dyn Provider = &SomeConcreteType { some_string: "hello".to_owned() };

    assert_eq!(&**request_ref::<String>(obj).unwrap(), "hello");
    assert_eq!(&*request_value::<String>(obj).unwrap(), "bye");
    assert_eq!(request_value::<u8>(obj), None);
}

// Test the provide and request mechanisms with a boxed trait object.
#[test]
fn test_provider_boxed() {
    let obj: Box<dyn Provider> = Box::new(SomeConcreteType { some_string: "hello".to_owned() });

    assert_eq!(&**request_ref::<String>(&*obj).unwrap(), "hello");
    assert_eq!(&*request_value::<String>(&*obj).unwrap(), "bye");
    assert_eq!(request_value::<u8>(&*obj), None);
}

// Test the provide and request mechanisms with a concrete object.
#[test]
fn test_provider_concrete() {
    let obj = SomeConcreteType { some_string: "hello".to_owned() };

    assert_eq!(&**request_ref::<String>(&obj).unwrap(), "hello");
    assert_eq!(&*request_value::<String>(&obj).unwrap(), "bye");
    assert_eq!(request_value::<u8>(&obj), None);
}

trait OtherTrait: Provider {}

impl OtherTrait for SomeConcreteType {}

impl dyn OtherTrait {
    fn get_ref<T: 'static + ?Sized>(&self) -> Option<&T> {
        request_ref::<T>(self)
    }
}

// Test the provide and request mechanisms via an intermediate trait.
#[test]
fn test_provider_intermediate() {
    let obj: &dyn OtherTrait = &SomeConcreteType { some_string: "hello".to_owned() };
    assert_eq!(obj.get_ref::<str>().unwrap(), "hello");
}