summaryrefslogtreecommitdiffstats
path: root/src/test/ui/lint/uninitialized-zeroed.rs
blob: dae258407ebb0801cbf888343495196370ff1ca4 (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
// This test checks that calling `mem::{uninitialized,zeroed}` with certain types results
// in a lint.

#![feature(never_type, rustc_attrs)]
#![allow(deprecated)]
#![deny(invalid_value)]

use std::mem::{self, MaybeUninit};
use std::ptr::NonNull;
use std::num::NonZeroU32;

enum Void {}

struct Ref(&'static i32);
struct RefPair((&'static i32, i32));

struct Wrap<T> { wrapped: T }
enum WrapEnum<T> { Wrapped(T) }

#[rustc_layout_scalar_valid_range_start(0)]
#[rustc_layout_scalar_valid_range_end(128)]
#[repr(transparent)]
pub(crate) struct NonBig(u64);

/// A two-variant enum, thus needs a tag and may not remain uninitialized.
enum Fruit {
    Apple,
    Banana,
}

/// Looks like two variants but really only has one.
enum OneFruit {
    Apple(!),
    Banana,
}

#[allow(unused)]
fn generic<T: 'static>() {
    unsafe {
        let _val: &'static T = mem::zeroed(); //~ ERROR: does not permit zero-initialization
        let _val: &'static T = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: Wrap<&'static T> = mem::zeroed(); //~ ERROR: does not permit zero-initialization
        let _val: Wrap<&'static T> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
    }
}

fn main() {
    unsafe {
        // Things that cannot even be zero.
        let _val: ! = mem::zeroed(); //~ ERROR: does not permit zero-initialization
        let _val: ! = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: (i32, !) = mem::zeroed(); //~ ERROR: does not permit zero-initialization
        let _val: (i32, !) = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: Void = mem::zeroed(); //~ ERROR: does not permit zero-initialization
        let _val: Void = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: &'static i32 = mem::zeroed(); //~ ERROR: does not permit zero-initialization
        let _val: &'static i32 = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: Ref = mem::zeroed(); //~ ERROR: does not permit zero-initialization
        let _val: Ref = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: fn() = mem::zeroed(); //~ ERROR: does not permit zero-initialization
        let _val: fn() = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: Wrap<fn()> = mem::zeroed(); //~ ERROR: does not permit zero-initialization
        let _val: Wrap<fn()> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: WrapEnum<fn()> = mem::zeroed(); //~ ERROR: does not permit zero-initialization
        let _val: WrapEnum<fn()> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: Wrap<(RefPair, i32)> = mem::zeroed(); //~ ERROR: does not permit zero-initialization
        let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: NonNull<i32> = mem::zeroed(); //~ ERROR: does not permit zero-initialization
        let _val: NonNull<i32> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: *const dyn Send = mem::zeroed(); //~ ERROR: does not permit zero-initialization
        let _val: *const dyn Send = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: [fn(); 2] = mem::zeroed(); //~ ERROR: does not permit zero-initialization
        let _val: [fn(); 2] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        // Things that can be zero, but not uninit.
        let _val: bool = mem::zeroed();
        let _val: bool = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: Wrap<char> = mem::zeroed();
        let _val: Wrap<char> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: NonBig = mem::zeroed();
        let _val: NonBig = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: Fruit = mem::zeroed();
        let _val: Fruit = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: [bool; 2] = mem::zeroed();
        let _val: [bool; 2] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: i32 = mem::zeroed();
        let _val: i32 = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: f32 = mem::zeroed();
        let _val: f32 = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: *const () = mem::zeroed();
        let _val: *const () = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        let _val: *const [()] = mem::zeroed();
        let _val: *const [()] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

        // Transmute-from-0
        let _val: &'static i32 = mem::transmute(0usize); //~ ERROR: does not permit zero-initialization
        let _val: &'static [i32] = mem::transmute((0usize, 0usize)); //~ ERROR: does not permit zero-initialization
        let _val: NonZeroU32 = mem::transmute(0); //~ ERROR: does not permit zero-initialization

        // `MaybeUninit` cases
        let _val: NonNull<i32> = MaybeUninit::zeroed().assume_init(); //~ ERROR: does not permit zero-initialization
        let _val: NonNull<i32> = MaybeUninit::uninit().assume_init(); //~ ERROR: does not permit being left uninitialized
        let _val: bool = MaybeUninit::uninit().assume_init(); //~ ERROR: does not permit being left uninitialized

        // Some more types that should work just fine.
        let _val: Option<&'static i32> = mem::zeroed();
        let _val: Option<fn()> = mem::zeroed();
        let _val: MaybeUninit<&'static i32> = mem::zeroed();
        let _val: bool = MaybeUninit::zeroed().assume_init();
        let _val: [bool; 0] = MaybeUninit::uninit().assume_init();
        let _val: [!; 0] = MaybeUninit::zeroed().assume_init();

        // Some things that happen to work due to rustc implementation details,
        // but are not guaranteed to keep working.
        let _val: OneFruit = mem::uninitialized();
    }
}