diff --git a/Cargo.lock b/Cargo.lock index 1fde5ac8cb15a..2a8eef6227682 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -363,7 +363,7 @@ dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -517,7 +517,7 @@ dependencies = [ "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1551,7 +1551,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2084,7 +2084,7 @@ dependencies = [ "rustc_target 0.0.0", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2128,7 +2128,7 @@ dependencies = [ "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2164,7 +2164,7 @@ name = "rustc-ap-serialize" version = "306.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2180,7 +2180,7 @@ dependencies = [ "rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2266,7 +2266,7 @@ dependencies = [ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2280,7 +2280,7 @@ dependencies = [ "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_target 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -2291,7 +2291,7 @@ version = "0.0.0" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_cratesio_shim 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2396,7 +2396,7 @@ dependencies = [ "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_cratesio_shim 0.0.0", "serialize 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2429,7 +2429,7 @@ dependencies = [ "rustc_typeck 0.0.0", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_ext 0.0.0", "syntax_pos 0.0.0", @@ -2535,7 +2535,7 @@ dependencies = [ "rustc_errors 0.0.0", "rustc_target 0.0.0", "serialize 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -2653,7 +2653,7 @@ dependencies = [ "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_target 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -2680,7 +2680,7 @@ dependencies = [ "rustc_errors 0.0.0", "rustc_platform_intrinsics 0.0.0", "rustc_target 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -2852,7 +2852,7 @@ dependencies = [ name = "serialize" version = "0.0.0" dependencies = [ - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2872,7 +2872,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3020,7 +3020,7 @@ dependencies = [ "rustc_target 0.0.0", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syntax_pos 0.0.0", ] @@ -3033,7 +3033,7 @@ dependencies = [ "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_target 0.0.0", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -3619,7 +3619,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "170a13e64f2a51b77a45702ba77287f5c6829375b04a69cf2222acd17d0cfab9" "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" -"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" +"checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" "checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7" "checksum stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa" "checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423" diff --git a/src/libcore/slice/rotate.rs b/src/libcore/slice/rotate.rs index 52677713f5ac4..e1ca457989179 100644 --- a/src/libcore/slice/rotate.rs +++ b/src/libcore/slice/rotate.rs @@ -8,7 +8,7 @@ use ptr; union RawArray { /// Ensure this is appropriately aligned for T, and is big /// enough for two elements even if T is enormous. - typed: [T; 2], + typed: [MaybeUninit; 2], /// For normally-sized types, especially things like u8, having more /// than 2 in the buffer is necessary for usefulness, so pad it out /// enough to be helpful, but not so big as to risk overflow. @@ -73,7 +73,8 @@ pub unsafe fn ptr_rotate(mut left: usize, mid: *mut T, mut right: usize) { } let mut rawarray = MaybeUninit::>::uninitialized(); - let buf = &mut (*rawarray.as_mut_ptr()).typed as *mut [T; 2] as *mut T; + let buf = &mut (*rawarray.as_mut_ptr()).typed as *mut [MaybeUninit; 2] + as *mut [T; 2] as *mut T; let dim = mid.sub(left).add(right); if left <= right { diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 504e016e5b803..ecba1da3e5a62 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -32,7 +32,7 @@ parking_lot = "0.6" byteorder = { version = "1.1", features = ["i128"]} chalk-engine = { version = "0.9.0", default-features=false } rustc_fs_util = { path = "../librustc_fs_util" } -smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } +smallvec = { version = "0.6.8", features = ["union", "may_dangle"] } # Note that these dependencies are a lie, they're just here to get linkage to # work. diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index e989ef823e979..3fbf5a757c6ff 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -740,6 +740,8 @@ impl<'a, 'tcx> ty::TyS<'tcx> { /// /// (Note that this implies that if `ty` has a destructor attached, /// then `needs_drop` will definitely return `true` for `ty`.) + /// + /// Note that this method is used to check eligible types in unions. #[inline] pub fn needs_drop(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_allocator/Cargo.toml b/src/librustc_allocator/Cargo.toml index 03d33f413c807..df738ec1f7b89 100644 --- a/src/librustc_allocator/Cargo.toml +++ b/src/librustc_allocator/Cargo.toml @@ -16,4 +16,4 @@ rustc_target = { path = "../librustc_target" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } log = "0.4" -smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } +smallvec = { version = "0.6.8", features = ["union", "may_dangle"] } diff --git a/src/librustc_apfloat/Cargo.toml b/src/librustc_apfloat/Cargo.toml index 248f2d71f41e5..8a15ac715c717 100644 --- a/src/librustc_apfloat/Cargo.toml +++ b/src/librustc_apfloat/Cargo.toml @@ -10,4 +10,4 @@ path = "lib.rs" [dependencies] bitflags = "1.0" rustc_cratesio_shim = { path = "../librustc_cratesio_shim" } -smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } +smallvec = { version = "0.6.8", features = ["union", "may_dangle"] } diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index 1754376a5d7f9..765a2162826ad 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -19,7 +19,7 @@ stable_deref_trait = "1.0.0" rustc-rayon = "0.1.1" rustc-rayon-core = "0.1.1" rustc-hash = "1.0.1" -smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } +smallvec = { version = "0.6.8", features = ["union", "may_dangle"] } [dependencies.parking_lot] version = "0.6" diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 8bcda409e6663..aa9fece23f161 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -35,6 +35,6 @@ rustc_codegen_utils = { path = "../librustc_codegen_utils" } rustc_typeck = { path = "../librustc_typeck" } serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } -smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } +smallvec = { version = "0.6.8", features = ["union", "may_dangle"] } syntax_ext = { path = "../libsyntax_ext" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index f0234c48c3eca..229dbec3bec72 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -25,4 +25,4 @@ syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } byteorder = { version = "1.1", features = ["i128"] } rustc_apfloat = { path = "../librustc_apfloat" } -smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } +smallvec = { version = "0.6.8", features = ["union", "may_dangle"] } diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml index bf946d39806ec..b6ddd9d642b22 100644 --- a/src/librustc_traits/Cargo.toml +++ b/src/librustc_traits/Cargo.toml @@ -18,4 +18,4 @@ rustc_target = { path = "../librustc_target" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } chalk-engine = { version = "0.9.0", default-features=false } -smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } +smallvec = { version = "0.6.8", features = ["union", "may_dangle"] } diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml index 87f11b01a1d94..f880ae7aadb2b 100644 --- a/src/librustc_typeck/Cargo.toml +++ b/src/librustc_typeck/Cargo.toml @@ -17,6 +17,6 @@ rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" } rustc_target = { path = "../librustc_target" } -smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } +smallvec = { version = "0.6.8", features = ["union", "may_dangle"] } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 870c6dd8bc1f6..6367b40ff2d4f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1302,9 +1302,41 @@ fn check_union<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def.destructor(tcx); // force the destructor to be evaluated check_representable(tcx, span, def_id); + check_union_fields(tcx, span, def_id); check_packed(tcx, span, def_id); } +fn check_union_fields<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + _sp: Span, + item_def_id: DefId) + -> bool { + // Without the feature we check Copy types only later + if !tcx.features().untagged_unions { + return true; + } + let t = tcx.type_of(item_def_id); + if let ty::Adt(def, substs) = t.sty { + if def.is_union() { + let fields = &def.non_enum_variant().fields; + for field in fields { + let field_ty = field.ty(tcx, substs); + // We are currently checking the type this field came from, so it must be local + let field_span = tcx.hir().span_if_local(field.did).unwrap(); + let param_env = tcx.param_env(field.did); + if field_ty.needs_drop(tcx, param_env) { + struct_span_err!(tcx.sess, field_span, E0730, + "unions may not contain fields that need dropping") + .span_note(field_span, + "`std::mem::ManuallyDrop` can be used to wrap the type") + .emit(); + return false; + } + } + } + } + return true; +} + fn check_opaque<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 387dabe747ab8..620823945d4ec 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4831,6 +4831,10 @@ fn make_recursive_type() -> impl Sized { ``` "##, +E0730: r##" +A `union` can not have fields with destructors. +"##, + } register_diagnostics! { diff --git a/src/libserialize/Cargo.toml b/src/libserialize/Cargo.toml index 3e040818d3777..92307072e5639 100644 --- a/src/libserialize/Cargo.toml +++ b/src/libserialize/Cargo.toml @@ -9,4 +9,4 @@ path = "lib.rs" crate-type = ["dylib", "rlib"] [dependencies] -smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } +smallvec = { version = "0.6.8", features = ["union", "may_dangle"] } diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index aaffc9bad4547..15bc2599c1b8b 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -16,7 +16,7 @@ use cell::RefCell; use core::panic::{PanicInfo, Location}; use fmt; use intrinsics; -use mem; +use mem::{self, ManuallyDrop}; use ptr; use raw; use sys::stdio::panic_output; @@ -238,8 +238,8 @@ pub use realstd::rt::update_panic_count; pub unsafe fn try R>(f: F) -> Result> { #[allow(unions_with_drop_fields)] union Data { - f: F, - r: R, + f: ManuallyDrop, + r: ManuallyDrop, } // We do some sketchy operations with ownership here for the sake of @@ -270,7 +270,7 @@ pub unsafe fn try R>(f: F) -> Result> { let mut any_data = 0; let mut any_vtable = 0; let mut data = Data { - f, + f: ManuallyDrop::new(f) }; let r = __rust_maybe_catch_panic(do_call::, @@ -280,7 +280,7 @@ pub unsafe fn try R>(f: F) -> Result> { return if r == 0 { debug_assert!(update_panic_count(0) == 0); - Ok(data.r) + Ok(ManuallyDrop::into_inner(data.r)) } else { update_panic_count(-1); debug_assert!(update_panic_count(0) == 0); @@ -293,8 +293,8 @@ pub unsafe fn try R>(f: F) -> Result> { fn do_call R, R>(data: *mut u8) { unsafe { let data = data as *mut Data; - let f = ptr::read(&mut (*data).f); - ptr::write(&mut (*data).r, f()); + let f = ptr::read(&mut *(*data).f); + ptr::write(&mut *(*data).r, f()); } } } diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml index fba2623e005d0..96af94eca5834 100644 --- a/src/libsyntax/Cargo.toml +++ b/src/libsyntax/Cargo.toml @@ -17,4 +17,4 @@ syntax_pos = { path = "../libsyntax_pos" } rustc_errors = { path = "../librustc_errors" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_target = { path = "../librustc_target" } -smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } +smallvec = { version = "0.6.8", features = ["union", "may_dangle"] } diff --git a/src/libsyntax_ext/Cargo.toml b/src/libsyntax_ext/Cargo.toml index 7ad08f75e8bdd..bcf10b2e77dbc 100644 --- a/src/libsyntax_ext/Cargo.toml +++ b/src/libsyntax_ext/Cargo.toml @@ -15,5 +15,5 @@ syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_target = { path = "../librustc_target" } -smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } +smallvec = { version = "0.6.8", features = ["union", "may_dangle"] } log = "0.4" diff --git a/src/test/run-pass/drop/dynamic-drop.rs b/src/test/run-pass/drop/dynamic-drop.rs index 41814f2af16b4..7aa2b0efc7f25 100644 --- a/src/test/run-pass/drop/dynamic-drop.rs +++ b/src/test/run-pass/drop/dynamic-drop.rs @@ -10,6 +10,7 @@ #![feature(slice_patterns)] use std::cell::{Cell, RefCell}; +use std::mem::ManuallyDrop; use std::ops::Generator; use std::panic; use std::usize; @@ -139,17 +140,16 @@ fn assignment1(a: &Allocator, c0: bool) { _v = _w; } -#[allow(unions_with_drop_fields)] union Boxy { - a: T, - b: T, + a: ManuallyDrop, + b: ManuallyDrop, } fn union1(a: &Allocator) { unsafe { - let mut u = Boxy { a: a.alloc() }; - u.b = a.alloc(); - drop(u.a); + let mut u = Boxy { a: ManuallyDrop::new(a.alloc()) }; + *u.b = a.alloc(); // drops first alloc + drop(ManuallyDrop::into_inner(u.a)); } } diff --git a/src/test/run-pass/self/self-in-typedefs.rs b/src/test/run-pass/self/self-in-typedefs.rs index 9c0906013fafc..cd7a68ec06146 100644 --- a/src/test/run-pass/self/self-in-typedefs.rs +++ b/src/test/run-pass/self/self-in-typedefs.rs @@ -3,7 +3,8 @@ #![feature(untagged_unions)] #![allow(dead_code)] -#![allow(unions_with_drop_fields)] + +use std::mem::ManuallyDrop; enum A<'a, T: 'a> where @@ -24,6 +25,14 @@ where union C<'a, T: 'a> where Self: Send, T: PartialEq +{ + foo: &'a Self, + bar: ManuallyDrop, +} + +union D<'a, T: 'a> +where + Self: Send, T: PartialEq + Copy { foo: &'a Self, bar: T, diff --git a/src/test/run-pass/union/union-derive.rs b/src/test/run-pass/union/union-derive.rs index d4b82cdb250b1..30c5dc8e35f0e 100644 --- a/src/test/run-pass/union/union-derive.rs +++ b/src/test/run-pass/union/union-derive.rs @@ -24,11 +24,11 @@ impl PartialEq for U { fn eq(&self, rhs: &Self) -> bool { true } } Copy, Eq )] -union W { +union W { a: T, } -impl PartialEq for W { fn eq(&self, rhs: &Self) -> bool { true } } +impl PartialEq for W { fn eq(&self, rhs: &Self) -> bool { true } } fn main() { let u = U { b: 0 }; diff --git a/src/test/run-pass/union/union-drop-assign.rs b/src/test/run-pass/union/union-drop-assign.rs index c4349c454641b..0650740c1fce2 100644 --- a/src/test/run-pass/union/union-drop-assign.rs +++ b/src/test/run-pass/union/union-drop-assign.rs @@ -6,10 +6,12 @@ #![feature(untagged_unions)] +use std::mem::ManuallyDrop; + struct S; union U { - a: S + a: ManuallyDrop } impl Drop for S { @@ -28,11 +30,11 @@ static mut CHECK: u8 = 0; fn main() { unsafe { - let mut u = U { a: S }; + let mut u = U { a: ManuallyDrop::new(S) }; assert_eq!(CHECK, 0); - u = U { a: S }; + u = U { a: ManuallyDrop::new(S) }; assert_eq!(CHECK, 1); // union itself is assigned, union is dropped, field is not dropped - u.a = S; + *u.a = S; assert_eq!(CHECK, 11); // union field is assigned, field is dropped } } diff --git a/src/test/run-pass/union/union-drop.rs b/src/test/run-pass/union/union-drop.rs index 2060950dda951..0d9fafc1e87c0 100644 --- a/src/test/run-pass/union/union-drop.rs +++ b/src/test/run-pass/union/union-drop.rs @@ -21,12 +21,6 @@ union Y { a: S, } -impl Drop for S { - fn drop(&mut self) { - unsafe { CHECK += 10; } - } -} - impl Drop for U { fn drop(&mut self) { unsafe { CHECK += 1; } @@ -51,10 +45,10 @@ fn main() { { let w = W { a: S }; } - assert_eq!(CHECK, 2); // 2, not 11, dtor of S is not called + assert_eq!(CHECK, 2); // 2, dtor of W is called { let y = Y { a: S }; } - assert_eq!(CHECK, 2); // 2, not 12, dtor of S is not called + assert_eq!(CHECK, 2); // 2, dtor of Y is called } } diff --git a/src/test/run-pass/union/union-generic.rs b/src/test/run-pass/union/union-generic.rs index 6f2caf8dc5b1e..5ca3bc0f722c3 100644 --- a/src/test/run-pass/union/union-generic.rs +++ b/src/test/run-pass/union/union-generic.rs @@ -1,30 +1,24 @@ // run-pass #![allow(dead_code)] -#![allow(unions_with_drop_fields)] #![feature(untagged_unions)] -union MaybeItem { +union MaybeItem where T::Item: Copy { elem: T::Item, none: (), } -union U { +union U where A: Copy, B: Copy { a: A, b: B, } -unsafe fn union_transmute(a: A) -> B { +unsafe fn union_transmute(a: A) -> B where A: Copy, B: Copy { U { a: a }.b } fn main() { unsafe { - let u = U::> { a: String::from("abcd") }; - - assert_eq!(u.b.len(), 4); - assert_eq!(u.b[0], b'a'); - let b = union_transmute::<(u8, u8), u16>((1, 1)); assert_eq!(b, (1 << 8) + 1); diff --git a/src/test/run-pass/union/union-manuallydrop.rs b/src/test/run-pass/union/union-manuallydrop.rs new file mode 100644 index 0000000000000..317fb727e6239 --- /dev/null +++ b/src/test/run-pass/union/union-manuallydrop.rs @@ -0,0 +1,42 @@ +#![feature(untagged_unions)] +#![allow(dead_code)] +// run-pass + +use std::mem::needs_drop; +use std::mem::ManuallyDrop; + +struct NeedDrop; + +impl Drop for NeedDrop { + fn drop(&mut self) {} +} + +union UnionOk1 { + empty: (), + value: ManuallyDrop, +} + +union UnionOk2 { + value: ManuallyDrop, +} + +#[allow(dead_code)] +union UnionOk3 { + empty: (), + value: T, +} + +trait Foo { } + +trait ImpliesCopy : Copy { } + +#[allow(dead_code)] +union UnionOk4 { + value: T, +} + +fn main() { + // NeedDrop should not make needs_drop true + assert!(!needs_drop::>()); + assert!(!needs_drop::>()); +} diff --git a/src/test/run-pass/union/union-nodrop.rs b/src/test/run-pass/union/union-nodrop.rs index 4cd64ddb5d67f..330f6f9593b13 100644 --- a/src/test/run-pass/union/union-nodrop.rs +++ b/src/test/run-pass/union/union-nodrop.rs @@ -1,12 +1,11 @@ // run-pass -#![feature(core_intrinsics)] #![feature(untagged_unions)] -#![allow(unions_with_drop_fields)] #![allow(dead_code)] -use std::intrinsics::needs_drop; +use std::mem::needs_drop; +use std::mem::ManuallyDrop; struct NeedDrop; @@ -16,10 +15,10 @@ impl Drop for NeedDrop { // Constant expressios allow `NoDrop` to go out of scope, // unlike a value of the interior type implementing `Drop`. -static X: () = (NoDrop { inner: NeedDrop }, ()).1; +static X: () = (NoDrop { inner: ManuallyDrop::new(NeedDrop) }, ()).1; // A union that scrubs the drop glue from its inner type -union NoDrop {inner: T} +union NoDrop { inner: ManuallyDrop } // Copy currently can't be implemented on drop-containing unions, // this may change later @@ -40,7 +39,7 @@ struct Baz { y: Box, } -union ActuallyDrop {inner: T} +union ActuallyDrop { inner: ManuallyDrop } impl Drop for ActuallyDrop { fn drop(&mut self) {} diff --git a/src/test/run-pass/union/union-overwrite.rs b/src/test/run-pass/union/union-overwrite.rs index 64c60604ba9f0..8234beb74a826 100644 --- a/src/test/run-pass/union/union-overwrite.rs +++ b/src/test/run-pass/union/union-overwrite.rs @@ -1,21 +1,27 @@ // run-pass -#![allow(unions_with_drop_fields)] - #![feature(untagged_unions)] #[repr(C)] +#[derive(Copy, Clone)] struct Pair(T, U); #[repr(C)] +#[derive(Copy, Clone)] struct Triple(T, T, T); #[repr(C)] -union U { +union U +where + A: Copy, B: Copy +{ a: Pair, b: B, } #[repr(C)] -union W { +union W +where + A: Copy, B: Copy +{ a: A, b: B, } diff --git a/src/test/run-pass/union/union-with-drop-fields-lint.rs b/src/test/run-pass/union/union-with-drop-fields-lint.rs deleted file mode 100644 index 4dbeb7c1e7e97..0000000000000 --- a/src/test/run-pass/union/union-with-drop-fields-lint.rs +++ /dev/null @@ -1,32 +0,0 @@ -// run-pass - -#![feature(untagged_unions)] -#![allow(dead_code)] -#![allow(unions_with_drop_fields)] - -union U { - a: u8, // OK -} - -union W { - a: String, // OK - b: String, // OK -} - -struct S(String); - -// `S` doesn't implement `Drop` trait, but still has non-trivial destructor -union Y { - a: S, // OK -} - -// We don't know if `T` is trivially-destructable or not until trans -union J { - a: T, // OK -} - -union H { - a: T, // OK -} - -fn main() {} diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.rs b/src/test/ui/union/union-borrow-move-parent-sibling.rs index 43abbd374fcf1..8f045262130c7 100644 --- a/src/test/ui/union/union-borrow-move-parent-sibling.rs +++ b/src/test/ui/union/union-borrow-move-parent-sibling.rs @@ -1,51 +1,91 @@ #![feature(untagged_unions)] #![allow(unused)] +use std::ops::{Deref, DerefMut}; + +#[derive(Default)] +struct MockBox { + value: [T; 1], +} + +impl MockBox { + fn new(value: T) -> Self { MockBox { value: [value] } } +} + +impl Deref for MockBox { + type Target = T; + fn deref(&self) -> &T { &self.value[0] } +} + +impl DerefMut for MockBox { + fn deref_mut(&mut self) -> &mut T { &mut self.value[0] } +} + +#[derive(Default)] +struct MockVec { + value: [T; 0], +} + +impl MockVec { + fn new() -> Self { MockVec { value: [] } } +} + +impl Deref for MockVec { + type Target = [T]; + fn deref(&self) -> &[T] { &self.value } +} + +impl DerefMut for MockVec { + fn deref_mut(&mut self) -> &mut [T] { &mut self.value } +} + + #[allow(unions_with_drop_fields)] union U { - x: ((Vec, Vec), Vec), - y: Box>, + x: ((MockVec, MockVec), MockVec), + y: MockBox>, } fn use_borrow(_: &T) {} unsafe fn parent_sibling_borrow() { - let mut u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; + let mut u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; let a = &mut u.x.0; let b = &u.y; //~ ERROR cannot borrow `u.y` use_borrow(a); } unsafe fn parent_sibling_move() { - let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; + let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; let a = u.x.0; let b = u.y; //~ ERROR use of moved value: `u.y` } unsafe fn grandparent_sibling_borrow() { - let mut u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; + let mut u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; let a = &mut (u.x.0).0; let b = &u.y; //~ ERROR cannot borrow `u.y` use_borrow(a); } unsafe fn grandparent_sibling_move() { - let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; + let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; let a = (u.x.0).0; let b = u.y; //~ ERROR use of moved value: `u.y` } unsafe fn deref_sibling_borrow() { - let mut u = U { y: Box::default() }; + let mut u = U { y: MockBox::default() }; let a = &mut *u.y; let b = &u.x; //~ ERROR cannot borrow `u` (via `u.x`) use_borrow(a); } unsafe fn deref_sibling_move() { - let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; - let a = *u.y; - let b = u.x; //~ ERROR use of moved value: `u.x` + let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; + // No way to test deref-move without Box in union + // let a = *u.y; + // let b = u.x; ERROR use of moved value: `u.x` } diff --git a/src/test/ui/union/union-borrow-move-parent-sibling.stderr b/src/test/ui/union/union-borrow-move-parent-sibling.stderr index c5baf82c74584..8a3401895cb30 100644 --- a/src/test/ui/union/union-borrow-move-parent-sibling.stderr +++ b/src/test/ui/union/union-borrow-move-parent-sibling.stderr @@ -1,5 +1,5 @@ error[E0502]: cannot borrow `u.y` as immutable because `u.x.0` is also borrowed as mutable - --> $DIR/union-borrow-move-parent-sibling.rs:15:14 + --> $DIR/union-borrow-move-parent-sibling.rs:54:14 | LL | let a = &mut u.x.0; | ----- mutable borrow occurs here @@ -10,7 +10,7 @@ LL | } | - mutable borrow ends here error[E0382]: use of moved value: `u.y` - --> $DIR/union-borrow-move-parent-sibling.rs:22:9 + --> $DIR/union-borrow-move-parent-sibling.rs:61:9 | LL | let a = u.x.0; | - value moved here @@ -20,7 +20,7 @@ LL | let b = u.y; //~ ERROR use of moved value: `u.y` = note: move occurs because `u.y` has type `[type error]`, which does not implement the `Copy` trait error[E0502]: cannot borrow `u.y` as immutable because `u.x.0.0` is also borrowed as mutable - --> $DIR/union-borrow-move-parent-sibling.rs:28:14 + --> $DIR/union-borrow-move-parent-sibling.rs:67:14 | LL | let a = &mut (u.x.0).0; | --------- mutable borrow occurs here @@ -31,7 +31,7 @@ LL | } | - mutable borrow ends here error[E0382]: use of moved value: `u.y` - --> $DIR/union-borrow-move-parent-sibling.rs:35:9 + --> $DIR/union-borrow-move-parent-sibling.rs:74:9 | LL | let a = (u.x.0).0; | - value moved here @@ -40,28 +40,18 @@ LL | let b = u.y; //~ ERROR use of moved value: `u.y` | = note: move occurs because `u.y` has type `[type error]`, which does not implement the `Copy` trait -error[E0502]: cannot borrow `u` (via `u.x`) as immutable because `u` is also borrowed as mutable (via `*u.y`) - --> $DIR/union-borrow-move-parent-sibling.rs:41:14 +error[E0502]: cannot borrow `u` (via `u.x`) as immutable because `u` is also borrowed as mutable (via `u.y`) + --> $DIR/union-borrow-move-parent-sibling.rs:80:14 | LL | let a = &mut *u.y; - | ---- mutable borrow occurs here (via `*u.y`) + | --- mutable borrow occurs here (via `u.y`) LL | let b = &u.x; //~ ERROR cannot borrow `u` (via `u.x`) | ^^^ immutable borrow occurs here (via `u.x`) LL | use_borrow(a); LL | } | - mutable borrow ends here -error[E0382]: use of moved value: `u.x` - --> $DIR/union-borrow-move-parent-sibling.rs:48:9 - | -LL | let a = *u.y; - | - value moved here -LL | let b = u.x; //~ ERROR use of moved value: `u.x` - | ^ value used here after move - | - = note: move occurs because `u.x` has type `[type error]`, which does not implement the `Copy` trait - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors Some errors occurred: E0382, E0502. For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/union/union-derive-clone.rs b/src/test/ui/union/union-derive-clone.rs index 64c3caef44906..60e280f53f52c 100644 --- a/src/test/ui/union/union-derive-clone.rs +++ b/src/test/ui/union/union-derive-clone.rs @@ -1,5 +1,7 @@ #![feature(untagged_unions)] +use std::mem::ManuallyDrop; + #[derive(Clone)] //~ ERROR the trait bound `U1: std::marker::Copy` is not satisfied union U1 { a: u8, @@ -18,14 +20,19 @@ union U3 { } #[derive(Clone, Copy)] -union U4 { +union U4 { a: T, // OK } +#[derive(Clone, Copy)] +union U5 { + a: ManuallyDrop, // OK +} + #[derive(Clone)] struct CloneNoCopy; fn main() { - let u = U4 { a: CloneNoCopy }; - let w = u.clone(); //~ ERROR no method named `clone` found for type `U4` + let u = U5 { a: ManuallyDrop::new(CloneNoCopy) }; + let w = u.clone(); //~ ERROR no method named `clone` found for type `U5` } diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index 9580a9710e1f9..eef3c5a5841f1 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -1,22 +1,22 @@ error[E0277]: the trait bound `U1: std::marker::Copy` is not satisfied - --> $DIR/union-derive-clone.rs:3:10 + --> $DIR/union-derive-clone.rs:5:10 | LL | #[derive(Clone)] //~ ERROR the trait bound `U1: std::marker::Copy` is not satisfied | ^^^^^ the trait `std::marker::Copy` is not implemented for `U1` | = note: required by `std::clone::AssertParamIsCopy` -error[E0599]: no method named `clone` found for type `U4` in the current scope - --> $DIR/union-derive-clone.rs:30:15 +error[E0599]: no method named `clone` found for type `U5` in the current scope + --> $DIR/union-derive-clone.rs:37:15 | -LL | union U4 { +LL | union U5 { | ----------- method `clone` not found for this ... -LL | let w = u.clone(); //~ ERROR no method named `clone` found for type `U4` +LL | let w = u.clone(); //~ ERROR no method named `clone` found for type `U5` | ^^^^^ | = note: the method `clone` exists but the following trait bounds were not satisfied: - `U4 : std::clone::Clone` + `U5 : std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/union/union-unsafe.rs b/src/test/ui/union/union-unsafe.rs index 6cfde35fe4c34..8535cbd019ce8 100644 --- a/src/test/ui/union/union-unsafe.rs +++ b/src/test/ui/union/union-unsafe.rs @@ -1,15 +1,16 @@ #![feature(untagged_unions)] +use std::mem::ManuallyDrop; union U1 { a: u8 } union U2 { - a: String + a: ManuallyDrop } union U3 { - a: T + a: ManuallyDrop } union U4 { @@ -17,13 +18,16 @@ union U4 { } fn generic_noncopy() { - let mut u3 = U3 { a: T::default() }; - u3.a = T::default(); //~ ERROR assignment to non-`Copy` union field is unsafe + let mut u3 = U3 { a: ManuallyDrop::new(T::default()) }; + u3.a = ManuallyDrop::new(T::default()); //~ ERROR assignment to non-`Copy` union field is unsafe + *u3.a = T::default(); //~ ERROR access to union field is unsafe } fn generic_copy() { - let mut u3 = U3 { a: T::default() }; - u3.a = T::default(); // OK + let mut u3 = U3 { a: ManuallyDrop::new(T::default()) }; + u3.a = ManuallyDrop::new(T::default()); // OK + *u3.a = T::default(); //~ ERROR access to union field is unsafe + let mut u4 = U4 { a: T::default() }; u4.a = T::default(); // OK } @@ -32,14 +36,20 @@ fn main() { let mut u1 = U1 { a: 10 }; // OK let a = u1.a; //~ ERROR access to union field is unsafe u1.a = 11; // OK + let U1 { a } = u1; //~ ERROR access to union field is unsafe if let U1 { a: 12 } = u1 {} //~ ERROR access to union field is unsafe // let U1 { .. } = u1; // OK - let mut u2 = U2 { a: String::from("old") }; // OK - u2.a = String::from("new"); //~ ERROR assignment to non-`Copy` union field is unsafe - let mut u3 = U3 { a: 0 }; // OK - u3.a = 1; // OK - let mut u3 = U3 { a: String::from("old") }; // OK - u3.a = String::from("new"); //~ ERROR assignment to non-`Copy` union field is unsafe + let mut u2 = U2 { a: ManuallyDrop::new(String::from("old")) }; // OK + u2.a = ManuallyDrop::new(String::from("new")); //~ ERROR assignment to non-`Copy` union + *u2.a = String::from("new"); //~ ERROR access to union field is unsafe + + let mut u3 = U3 { a: ManuallyDrop::new(0) }; // OK + u3.a = ManuallyDrop::new(1); // OK + *u3.a = 1; //~ ERROR access to union field is unsafe + + let mut u3 = U3 { a: ManuallyDrop::new(String::from("old")) }; // OK + u3.a = ManuallyDrop::new(String::from("new")); //~ ERROR assignment to non-`Copy` union + *u3.a = String::from("new"); //~ ERROR access to union field is unsafe } diff --git a/src/test/ui/union/union-unsafe.stderr b/src/test/ui/union/union-unsafe.stderr index 35051485f6ad0..6c1bdb6f5b59b 100644 --- a/src/test/ui/union/union-unsafe.stderr +++ b/src/test/ui/union/union-unsafe.stderr @@ -1,13 +1,29 @@ error[E0133]: assignment to non-`Copy` union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:21:5 + --> $DIR/union-unsafe.rs:22:5 | -LL | u3.a = T::default(); //~ ERROR assignment to non-`Copy` union field is unsafe - | ^^^^ assignment to non-`Copy` union field +LL | u3.a = ManuallyDrop::new(T::default()); //~ ERROR assignment to non-`Copy` union field is unsafe + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to non-`Copy` union field | = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:33:13 + --> $DIR/union-unsafe.rs:23:6 + | +LL | *u3.a = T::default(); //~ ERROR access to union field is unsafe + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:29:6 + | +LL | *u3.a = T::default(); //~ ERROR access to union field is unsafe + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:37:13 | LL | let a = u1.a; //~ ERROR access to union field is unsafe | ^^^^ access to union field @@ -15,7 +31,7 @@ LL | let a = u1.a; //~ ERROR access to union field is unsafe = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:35:14 + --> $DIR/union-unsafe.rs:40:14 | LL | let U1 { a } = u1; //~ ERROR access to union field is unsafe | ^ access to union field @@ -23,7 +39,7 @@ LL | let U1 { a } = u1; //~ ERROR access to union field is unsafe = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:36:20 + --> $DIR/union-unsafe.rs:41:20 | LL | if let U1 { a: 12 } = u1 {} //~ ERROR access to union field is unsafe | ^^ access to union field @@ -31,21 +47,45 @@ LL | if let U1 { a: 12 } = u1 {} //~ ERROR access to union field is unsafe = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: assignment to non-`Copy` union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:40:5 + --> $DIR/union-unsafe.rs:45:5 | -LL | u2.a = String::from("new"); //~ ERROR assignment to non-`Copy` union field is unsafe - | ^^^^ assignment to non-`Copy` union field +LL | u2.a = ManuallyDrop::new(String::from("new")); //~ ERROR assignment to non-`Copy` union + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to non-`Copy` union field | = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:46:6 + | +LL | *u2.a = String::from("new"); //~ ERROR access to union field is unsafe + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:50:6 + | +LL | *u3.a = 1; //~ ERROR access to union field is unsafe + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + error[E0133]: assignment to non-`Copy` union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:44:5 + --> $DIR/union-unsafe.rs:53:5 | -LL | u3.a = String::from("new"); //~ ERROR assignment to non-`Copy` union field is unsafe - | ^^^^ assignment to non-`Copy` union field +LL | u3.a = ManuallyDrop::new(String::from("new")); //~ ERROR assignment to non-`Copy` union + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to non-`Copy` union field | = note: the previous content of the field will be dropped, which causes undefined behavior if the field was not properly initialized -error: aborting due to 6 previous errors +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:54:6 + | +LL | *u3.a = String::from("new"); //~ ERROR access to union field is unsafe + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error: aborting due to 11 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/union/union-with-drop-fields-lint.stderr b/src/test/ui/union/union-with-drop-fields-lint.stderr deleted file mode 100644 index d8f456f2aefbc..0000000000000 --- a/src/test/ui/union/union-with-drop-fields-lint.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error: union contains a field with possibly non-trivial drop code, drop code of union fields is ignored when dropping the union - --> $DIR/union-with-drop-fields-lint.rs:10:5 - | -LL | a: String, //~ ERROR union contains a field with possibly non-trivial drop code - | ^^^^^^^^^ - | -note: lint level defined here - --> $DIR/union-with-drop-fields-lint.rs:3:9 - | -LL | #![deny(unions_with_drop_fields)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: union contains a field with possibly non-trivial drop code, drop code of union fields is ignored when dropping the union - --> $DIR/union-with-drop-fields-lint.rs:18:5 - | -LL | a: S, //~ ERROR union contains a field with possibly non-trivial drop code - | ^^^^ - -error: union contains a field with possibly non-trivial drop code, drop code of union fields is ignored when dropping the union - --> $DIR/union-with-drop-fields-lint.rs:23:5 - | -LL | a: T, //~ ERROR union contains a field with possibly non-trivial drop code - | ^^^^ - -error: aborting due to 3 previous errors - diff --git a/src/test/ui/union/union-with-drop-fields-lint.rs b/src/test/ui/union/union-with-drop-fields.rs similarity index 60% rename from src/test/ui/union/union-with-drop-fields-lint.rs rename to src/test/ui/union/union-with-drop-fields.rs index 8e502aa55f952..e3c63a6d5b5a2 100644 --- a/src/test/ui/union/union-with-drop-fields-lint.rs +++ b/src/test/ui/union/union-with-drop-fields.rs @@ -1,13 +1,12 @@ #![feature(untagged_unions)] #![allow(dead_code)] -#![deny(unions_with_drop_fields)] union U { a: u8, // OK } union W { - a: String, //~ ERROR union contains a field with possibly non-trivial drop code + a: String, //~ ERROR unions may not contain fields that need dropping b: String, // OK, only one field is reported } @@ -15,12 +14,12 @@ struct S(String); // `S` doesn't implement `Drop` trait, but still has non-trivial destructor union Y { - a: S, //~ ERROR union contains a field with possibly non-trivial drop code + a: S, //~ ERROR unions may not contain fields that need dropping } // We don't know if `T` is trivially-destructable or not until trans union J { - a: T, //~ ERROR union contains a field with possibly non-trivial drop code + a: T, //~ ERROR unions may not contain fields that need dropping } union H { diff --git a/src/test/ui/union/union-with-drop-fields.stderr b/src/test/ui/union/union-with-drop-fields.stderr new file mode 100644 index 0000000000000..f07f783b773f8 --- /dev/null +++ b/src/test/ui/union/union-with-drop-fields.stderr @@ -0,0 +1,39 @@ +error[E0730]: unions may not contain fields that need dropping + --> $DIR/union-with-drop-fields.rs:9:5 + | +LL | a: String, //~ ERROR unions may not contain fields that need dropping + | ^^^^^^^^^ + | +note: `std::mem::ManuallyDrop` can be used to wrap the type + --> $DIR/union-with-drop-fields.rs:9:5 + | +LL | a: String, //~ ERROR unions may not contain fields that need dropping + | ^^^^^^^^^ + +error[E0730]: unions may not contain fields that need dropping + --> $DIR/union-with-drop-fields.rs:17:5 + | +LL | a: S, //~ ERROR unions may not contain fields that need dropping + | ^^^^ + | +note: `std::mem::ManuallyDrop` can be used to wrap the type + --> $DIR/union-with-drop-fields.rs:17:5 + | +LL | a: S, //~ ERROR unions may not contain fields that need dropping + | ^^^^ + +error[E0730]: unions may not contain fields that need dropping + --> $DIR/union-with-drop-fields.rs:22:5 + | +LL | a: T, //~ ERROR unions may not contain fields that need dropping + | ^^^^ + | +note: `std::mem::ManuallyDrop` can be used to wrap the type + --> $DIR/union-with-drop-fields.rs:22:5 + | +LL | a: T, //~ ERROR unions may not contain fields that need dropping + | ^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0730`.