From a12788a0d77f1ad906bc1d51c4684dd8723278e0 Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Thu, 22 Aug 2019 19:57:48 +0200 Subject: [PATCH 01/33] make is_power_of_two a const function --- src/libcore/num/mod.rs | 4 ++-- src/test/ui/consts/const-int-pow-rpass.rs | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/consts/const-int-pow-rpass.rs diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index ebde82de83457..82c1943b7d057 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -3749,8 +3749,8 @@ assert!(!10", stringify!($SelfT), ".is_power_of_two());", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn is_power_of_two(self) -> bool { - (self.wrapping_sub(1)) & self == 0 && !(self == 0) + pub const fn is_power_of_two(self) -> bool { + ((self.wrapping_sub(1)) & self == 0) & !(self == 0) } } diff --git a/src/test/ui/consts/const-int-pow-rpass.rs b/src/test/ui/consts/const-int-pow-rpass.rs new file mode 100644 index 0000000000000..8e84a900605f5 --- /dev/null +++ b/src/test/ui/consts/const-int-pow-rpass.rs @@ -0,0 +1,11 @@ +// run-pass + +const IS_POWER_OF_TWO_A: bool = 0u32.is_power_of_two(); +const IS_POWER_OF_TWO_B: bool = 32u32.is_power_of_two(); +const IS_POWER_OF_TWO_C: bool = 33u32.is_power_of_two(); + +fn main() { + assert!(!IS_POWER_OF_TWO_A); + assert!(IS_POWER_OF_TWO_B); + assert!(!IS_POWER_OF_TWO_C); +} From 0a08841bb075959874e2e29c538150c826a1401a Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 3 Jul 2019 12:23:26 +0200 Subject: [PATCH 02/33] Remove uses of `allow(unions_with_drop_fields)` in the standard library --- src/libstd/panicking.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 638ce1679b8e9..296f2a59bb82e 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -12,7 +12,7 @@ use core::panic::{BoxMeUp, PanicInfo, Location}; use crate::any::Any; use crate::fmt; use crate::intrinsics; -use crate::mem; +use crate::mem::{self, ManuallyDrop}; use crate::ptr; use crate::raw; use crate::sync::atomic::{AtomicBool, Ordering}; @@ -227,10 +227,9 @@ pub use realstd::rt::update_panic_count; /// Invoke a closure, capturing the cause of an unwinding panic if one occurs. pub unsafe fn r#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 @@ -261,7 +260,7 @@ pub unsafe fn r#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::, @@ -271,7 +270,7 @@ pub unsafe fn r#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); @@ -284,8 +283,8 @@ pub unsafe fn r#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()); } } } From 84ca0a1cb47f71a43ee16da2f6bc173577b35cb9 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 3 Jul 2019 12:35:02 +0200 Subject: [PATCH 03/33] Remove most uses of `allow(unions_with_drop_fields)` in tests --- .../ui/associated-type-bounds/union-bounds.rs | 15 ++--- src/test/ui/drop/dynamic-drop.rs | 12 ++-- .../rfc-2093-infer-outlives/explicit-union.rs | 5 +- .../rfc-2093-infer-outlives/nested-union.rs | 5 +- src/test/ui/self/self-in-typedefs.rs | 11 +++- .../union/union-borrow-move-parent-sibling.rs | 61 +++++++++++++++---- .../union-borrow-move-parent-sibling.stderr | 34 ++++------- src/test/ui/union/union-derive-rpass.rs | 5 +- src/test/ui/union/union-drop-assign.rs | 11 ++-- src/test/ui/union/union-drop.rs | 11 +--- src/test/ui/union/union-generic-rpass.rs | 12 +--- src/test/ui/union/union-nodrop.rs | 11 ++-- src/test/ui/union/union-overwrite.rs | 14 +++-- .../union-with-drop-fields-lint-rpass.rs | 32 ---------- 14 files changed, 118 insertions(+), 121 deletions(-) delete mode 100644 src/test/ui/union/union-with-drop-fields-lint-rpass.rs diff --git a/src/test/ui/associated-type-bounds/union-bounds.rs b/src/test/ui/associated-type-bounds/union-bounds.rs index ce482fff401c8..97c5acf1f72ca 100644 --- a/src/test/ui/associated-type-bounds/union-bounds.rs +++ b/src/test/ui/associated-type-bounds/union-bounds.rs @@ -3,13 +3,13 @@ #![feature(associated_type_bounds)] #![feature(untagged_unions)] -#![allow(unions_with_drop_fields, unused_assignments)] +#![allow(unused_assignments)] -trait Tr1 { type As1; } -trait Tr2 { type As2; } -trait Tr3 { type As3; } -trait Tr4<'a> { type As4; } -trait Tr5 { type As5; } +trait Tr1: Copy { type As1: Copy; } +trait Tr2: Copy { type As2: Copy; } +trait Tr3: Copy { type As3: Copy; } +trait Tr4<'a>: Copy { type As4: Copy; } +trait Tr5: Copy { type As5: Copy; } impl Tr1 for &str { type As1 = bool; } impl Tr2 for bool { type As2 = u8; } @@ -71,7 +71,8 @@ where let _: &'a T = &x.f0; } -union UnSelf where Self: Tr1 { +#[derive(Copy, Clone)] +union UnSelf where Self: Tr1, T: Copy { f0: T, f1: ::As1, f2: <::As1 as Tr2>::As2, diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs index 8516bc3d96424..29dcbfe9609a0 100644 --- a/src/test/ui/drop/dynamic-drop.rs +++ b/src/test/ui/drop/dynamic-drop.rs @@ -8,6 +8,7 @@ #![feature(slice_patterns)] use std::cell::{Cell, RefCell}; +use std::mem::ManuallyDrop; use std::ops::Generator; use std::panic; use std::pin::Pin; @@ -152,17 +153,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/ui/rfc-2093-infer-outlives/explicit-union.rs b/src/test/ui/rfc-2093-infer-outlives/explicit-union.rs index a16fb7670a603..ea8a3c177e9d7 100644 --- a/src/test/ui/rfc-2093-infer-outlives/explicit-union.rs +++ b/src/test/ui/rfc-2093-infer-outlives/explicit-union.rs @@ -1,13 +1,12 @@ #![feature(rustc_attrs)] #![feature(untagged_unions)] -#![allow(unions_with_drop_fields)] #[rustc_outlives] -union Foo<'b, U> { //~ ERROR rustc_outlives +union Foo<'b, U: Copy> { //~ ERROR rustc_outlives bar: Bar<'b, U> } -union Bar<'a, T> where T: 'a { +union Bar<'a, T: Copy> where T: 'a { x: &'a (), y: T, } diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-union.rs b/src/test/ui/rfc-2093-infer-outlives/nested-union.rs index 0ff667fbeba64..0da3cc2ba1b04 100644 --- a/src/test/ui/rfc-2093-infer-outlives/nested-union.rs +++ b/src/test/ui/rfc-2093-infer-outlives/nested-union.rs @@ -1,14 +1,13 @@ #![feature(rustc_attrs)] #![feature(untagged_unions)] -#![allow(unions_with_drop_fields)] #[rustc_outlives] -union Foo<'a, T> { //~ ERROR rustc_outlives +union Foo<'a, T: Copy> { //~ ERROR rustc_outlives field1: Bar<'a, T> } // Type U needs to outlive lifetime 'b -union Bar<'b, U> { +union Bar<'b, U: Copy> { field2: &'b U } diff --git a/src/test/ui/self/self-in-typedefs.rs b/src/test/ui/self/self-in-typedefs.rs index 73f23a9cc17cf..3b1eb9e1dfa16 100644 --- a/src/test/ui/self/self-in-typedefs.rs +++ b/src/test/ui/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/ui/union/union-borrow-move-parent-sibling.rs b/src/test/ui/union/union-borrow-move-parent-sibling.rs index 1b6052f10ba4a..edf08e6ca678f 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,90 @@ #![feature(untagged_unions)] #![allow(unused)] -#[allow(unions_with_drop_fields)] +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 } +} + + 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` (via `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` } 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` (via `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` } 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` + 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` } 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 2f4c921ea08f9..1a7a02690d3ea 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` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0`) - --> $DIR/union-borrow-move-parent-sibling.rs:15:13 + --> $DIR/union-borrow-move-parent-sibling.rs:54:13 | LL | let a = &mut u.x.0; | ---------- mutable borrow occurs here (via `u.x.0`) @@ -11,9 +11,9 @@ LL | use_borrow(a); = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0` error[E0382]: use of moved value: `u` - --> $DIR/union-borrow-move-parent-sibling.rs:22:13 + --> $DIR/union-borrow-move-parent-sibling.rs:61:13 | -LL | let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; +LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; | - move occurs because `u` has type `U`, which does not implement the `Copy` trait LL | let a = u.x.0; | ----- value moved here @@ -21,7 +21,7 @@ LL | let b = u.y; | ^^^ value used here after move error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`) - --> $DIR/union-borrow-move-parent-sibling.rs:28:13 + --> $DIR/union-borrow-move-parent-sibling.rs:67:13 | LL | let a = &mut (u.x.0).0; | -------------- mutable borrow occurs here (via `u.x.0.0`) @@ -33,38 +33,28 @@ LL | use_borrow(a); = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0.0` error[E0382]: use of moved value: `u` - --> $DIR/union-borrow-move-parent-sibling.rs:35:13 + --> $DIR/union-borrow-move-parent-sibling.rs:74:13 | -LL | let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; +LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; | - move occurs because `u` has type `U`, which does not implement the `Copy` trait LL | let a = (u.x.0).0; | --------- value moved here LL | let b = u.y; | ^^^ value used here after move -error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `*u.y`) - --> $DIR/union-borrow-move-parent-sibling.rs:41:13 +error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `u.y`) + --> $DIR/union-borrow-move-parent-sibling.rs:80:13 | 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; - | ^^^^ immutable borrow of `u.x` -- which overlaps with `*u.y` -- occurs here + | ^^^^ immutable borrow of `u.x` -- which overlaps with `u.y` -- occurs here LL | use_borrow(a); | - mutable borrow later used here | - = note: `u.x` is a field of the union `U`, so it overlaps the field `*u.y` + = note: `u.x` is a field of the union `U`, so it overlaps the field `u.y` -error[E0382]: use of moved value: `u` - --> $DIR/union-borrow-move-parent-sibling.rs:48:13 - | -LL | let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) }; - | - move occurs because `u` has type `U`, which does not implement the `Copy` trait -LL | let a = *u.y; - | ---- value moved here -LL | let b = u.x; - | ^^^ value used here after move - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0382, E0502. For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/union/union-derive-rpass.rs b/src/test/ui/union/union-derive-rpass.rs index d4b82cdb250b1..b2f7ae679fd68 100644 --- a/src/test/ui/union/union-derive-rpass.rs +++ b/src/test/ui/union/union-derive-rpass.rs @@ -1,7 +1,6 @@ // run-pass #![allow(dead_code)] #![allow(unused_variables)] -#![allow(unions_with_drop_fields)] // Some traits can be derived for unions. @@ -24,11 +23,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/ui/union/union-drop-assign.rs b/src/test/ui/union/union-drop-assign.rs index c4349c454641b..f1511b0a60180 100644 --- a/src/test/ui/union/union-drop-assign.rs +++ b/src/test/ui/union/union-drop-assign.rs @@ -1,15 +1,16 @@ // run-pass #![allow(unused_assignments)] -#![allow(unions_with_drop_fields)] // Drop works for union itself. #![feature(untagged_unions)] +use std::mem::ManuallyDrop; + struct S; union U { - a: S + a: ManuallyDrop } impl Drop for S { @@ -28,11 +29,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/ui/union/union-drop.rs b/src/test/ui/union/union-drop.rs index 2060950dda951..daa03ce6b6fd8 100644 --- a/src/test/ui/union/union-drop.rs +++ b/src/test/ui/union/union-drop.rs @@ -1,7 +1,6 @@ // run-pass #![allow(dead_code)] #![allow(unused_variables)] -#![allow(unions_with_drop_fields)] // Drop works for union itself. @@ -21,12 +20,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 +44,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/ui/union/union-generic-rpass.rs b/src/test/ui/union/union-generic-rpass.rs index 6f2caf8dc5b1e..5ca3bc0f722c3 100644 --- a/src/test/ui/union/union-generic-rpass.rs +++ b/src/test/ui/union/union-generic-rpass.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/ui/union/union-nodrop.rs b/src/test/ui/union/union-nodrop.rs index 4cd64ddb5d67f..330f6f9593b13 100644 --- a/src/test/ui/union/union-nodrop.rs +++ b/src/test/ui/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/ui/union/union-overwrite.rs b/src/test/ui/union/union-overwrite.rs index 64c60604ba9f0..8234beb74a826 100644 --- a/src/test/ui/union/union-overwrite.rs +++ b/src/test/ui/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/ui/union/union-with-drop-fields-lint-rpass.rs b/src/test/ui/union/union-with-drop-fields-lint-rpass.rs deleted file mode 100644 index 4dbeb7c1e7e97..0000000000000 --- a/src/test/ui/union/union-with-drop-fields-lint-rpass.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() {} From 2f0c821be9ba9cdf52a45c327b7d3f2831626225 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Wed, 19 Dec 2018 20:58:20 +0100 Subject: [PATCH 04/33] Change untagged_unions to not allow union fields with drop Union fields may now never have a type with attached destructor. This for example allows unions to use arbitrary field types only by wrapping them in ManuallyDrop. The stable rule remains, that union fields must be Copy. We use the new rule for the `untagged_union` feature. See RFC 2514. Note for ui tests: We can't test move out through Box's deref-move since we can't have a Box in a union anymore. --- src/librustc/Cargo.toml | 2 +- src/librustc/ty/util.rs | 2 + src/librustc_typeck/check/mod.rs | 29 ++++++++ src/librustc_typeck/error_codes.rs | 4 ++ src/test/run-pass/union/union-manuallydrop.rs | 42 ++++++++++++ .../feature-gate-associated_type_bounds.rs | 6 +- .../explicit-union.stderr | 4 +- .../nested-union.stderr | 4 +- .../union-borrow-move-parent-sibling.stderr | 10 +-- src/test/ui/union/union-derive-clone.rs | 13 +++- src/test/ui/union/union-derive-clone.stderr | 10 +-- src/test/ui/union/union-unsafe.rs | 34 ++++++---- src/test/ui/union/union-unsafe.stderr | 66 +++++++++++++++---- .../union/union-with-drop-fields-lint.stderr | 26 -------- ...elds-lint.rs => union-with-drop-fields.rs} | 7 +- .../ui/union/union-with-drop-fields.stderr | 39 +++++++++++ 16 files changed, 222 insertions(+), 76 deletions(-) create mode 100644 src/test/run-pass/union/union-manuallydrop.rs delete mode 100644 src/test/ui/union/union-with-drop-fields-lint.stderr rename src/test/ui/union/{union-with-drop-fields-lint.rs => union-with-drop-fields.rs} (60%) create mode 100644 src/test/ui/union/union-with-drop-fields.stderr diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 9b3609eca3e62..8f191961fdd04 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -35,5 +35,5 @@ parking_lot = "0.9" byteorder = { version = "1.3" } 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"] } measureme = "0.3" diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index d0e95a18c59fc..bd0d5846d9585 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -805,6 +805,8 @@ impl<'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<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { tcx.needs_drop_raw(param_env.and(self)).0 diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7475b9cc3b327..2f122e5edb1cb 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1387,9 +1387,38 @@ fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) { def.destructor(tcx); // force the destructor to be evaluated check_representable(tcx, span, def_id); check_transparent(tcx, span, def_id); + check_union_fields(tcx, span, def_id); check_packed(tcx, span, def_id); } +fn check_union_fields<'tcx>(tcx: TyCtxt<'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, E0740, + "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; +} + /// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo` /// projections that would result in "inheriting lifetimes". fn check_opaque<'tcx>( diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index ef08e8d4f0b7a..a92a2c9600391 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -4863,6 +4863,10 @@ assert_eq!(1, discriminant(&Enum::Struct{a: 7, b: 11})); ``` "##, +E0740: r##" +A `union` can not have fields with destructors. +"##, + E0733: r##" Recursion in an `async fn` requires boxing. For example, this will not compile: 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..a43a505086569 --- /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/ui/feature-gates/feature-gate-associated_type_bounds.rs b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs index 3d75251e15616..0faa9090f4ebc 100644 --- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs +++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs @@ -1,7 +1,7 @@ #![feature(untagged_unions)] -trait Tr1 { type As1; } -trait Tr2 { type As2; } +trait Tr1 { type As1: Copy; } +trait Tr2 { type As2: Copy; } struct S1; #[derive(Copy, Clone)] @@ -32,7 +32,7 @@ enum _En1> { union _Un1> { //~^ ERROR associated type bounds are unstable - outest: T, + outest: std::mem::ManuallyDrop, outer: T::As1, inner: ::As2, } diff --git a/src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr b/src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr index adf62651cacb1..8aa246e8bfeb3 100644 --- a/src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr @@ -1,7 +1,7 @@ error: rustc_outlives - --> $DIR/explicit-union.rs:6:1 + --> $DIR/explicit-union.rs:5:1 | -LL | / union Foo<'b, U> { +LL | / union Foo<'b, U: Copy> { LL | | bar: Bar<'b, U> LL | | } | |_^ diff --git a/src/test/ui/rfc-2093-infer-outlives/nested-union.stderr b/src/test/ui/rfc-2093-infer-outlives/nested-union.stderr index fc4b1a223294d..a42285a56d089 100644 --- a/src/test/ui/rfc-2093-infer-outlives/nested-union.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/nested-union.stderr @@ -1,7 +1,7 @@ error: rustc_outlives - --> $DIR/nested-union.rs:6:1 + --> $DIR/nested-union.rs:5:1 | -LL | / union Foo<'a, T> { +LL | / union Foo<'a, T: Copy> { LL | | field1: Bar<'a, T> LL | | } | |_^ 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 1a7a02690d3ea..8ba155bafb0b9 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` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0`) - --> $DIR/union-borrow-move-parent-sibling.rs:54:13 + --> $DIR/union-borrow-move-parent-sibling.rs:53:13 | LL | let a = &mut u.x.0; | ---------- mutable borrow occurs here (via `u.x.0`) @@ -11,7 +11,7 @@ LL | use_borrow(a); = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0` error[E0382]: use of moved value: `u` - --> $DIR/union-borrow-move-parent-sibling.rs:61:13 + --> $DIR/union-borrow-move-parent-sibling.rs:60:13 | LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; | - move occurs because `u` has type `U`, which does not implement the `Copy` trait @@ -21,7 +21,7 @@ LL | let b = u.y; | ^^^ value used here after move error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`) - --> $DIR/union-borrow-move-parent-sibling.rs:67:13 + --> $DIR/union-borrow-move-parent-sibling.rs:66:13 | LL | let a = &mut (u.x.0).0; | -------------- mutable borrow occurs here (via `u.x.0.0`) @@ -33,7 +33,7 @@ LL | use_borrow(a); = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0.0` error[E0382]: use of moved value: `u` - --> $DIR/union-borrow-move-parent-sibling.rs:74:13 + --> $DIR/union-borrow-move-parent-sibling.rs:73:13 | LL | let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) }; | - move occurs because `u` has type `U`, which does not implement the `Copy` trait @@ -43,7 +43,7 @@ LL | let b = u.y; | ^^^ value used here after move error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `u.y`) - --> $DIR/union-borrow-move-parent-sibling.rs:80:13 + --> $DIR/union-borrow-move-parent-sibling.rs:79:13 | LL | let a = &mut *u.y; | --- mutable borrow occurs here (via `u.y`) 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 4f4c779b12bb3..a6dcd556a1fee 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)] | ^^^^^ 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(); | ^^^^^ method not found in `U4` | = 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 ab62508fcf666..e020dab63f8f4 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(); - | ^^^^ assignment to non-`Copy` union field +LL | u3.a = ManuallyDrop::new(T::default()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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(); + | ^^^^ 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(); + | ^^^^ 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; | ^^^^ access to union field @@ -15,7 +31,7 @@ LL | let a = u1.a; = 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; | ^ access to union field @@ -23,7 +39,7 @@ LL | let U1 { a } = u1; = 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 {} | ^^ access to union field @@ -31,21 +47,45 @@ LL | if let U1 { a: 12 } = u1 {} = 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"); - | ^^^^ assignment to non-`Copy` union field +LL | u2.a = ManuallyDrop::new(String::from("new")); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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"); + | ^^^^ 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; + | ^^^^ 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"); - | ^^^^ assignment to non-`Copy` union field +LL | u3.a = ManuallyDrop::new(String::from("new")); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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"); + | ^^^^ 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 2f90f240d2e19..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, - | ^^^^^^^^^ - | -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, drop code of union fields is ignored when dropping the union - --> $DIR/union-with-drop-fields-lint.rs:23:5 - | -LL | a: T, - | ^^^^ - -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..0e77279be616a --- /dev/null +++ b/src/test/ui/union/union-with-drop-fields.stderr @@ -0,0 +1,39 @@ +error[E0740]: unions may not contain fields that need dropping + --> $DIR/union-with-drop-fields.rs:9:5 + | +LL | a: String, + | ^^^^^^^^^ + | +note: `std::mem::ManuallyDrop` can be used to wrap the type + --> $DIR/union-with-drop-fields.rs:9:5 + | +LL | a: String, + | ^^^^^^^^^ + +error[E0740]: unions may not contain fields that need dropping + --> $DIR/union-with-drop-fields.rs:17:5 + | +LL | a: S, + | ^^^^ + | +note: `std::mem::ManuallyDrop` can be used to wrap the type + --> $DIR/union-with-drop-fields.rs:17:5 + | +LL | a: S, + | ^^^^ + +error[E0740]: unions may not contain fields that need dropping + --> $DIR/union-with-drop-fields.rs:22:5 + | +LL | a: T, + | ^^^^ + | +note: `std::mem::ManuallyDrop` can be used to wrap the type + --> $DIR/union-with-drop-fields.rs:22:5 + | +LL | a: T, + | ^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0740`. From fe13bbd0648c4f7ad8f7cdfe540ca13bc93ade60 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 3 Jul 2019 11:56:59 +0200 Subject: [PATCH 05/33] Remove unions_with_drop_fields lint Cases where it would trigger are now hard errors. --- .../src/lints/listing/warn-by-default.md | 24 --------------- src/librustc_lint/builtin.rs | 30 ------------------- src/librustc_lint/lib.rs | 3 -- 3 files changed, 57 deletions(-) diff --git a/src/doc/rustc/src/lints/listing/warn-by-default.md b/src/doc/rustc/src/lints/listing/warn-by-default.md index e486240fda896..813d7c4bafef8 100644 --- a/src/doc/rustc/src/lints/listing/warn-by-default.md +++ b/src/doc/rustc/src/lints/listing/warn-by-default.md @@ -596,30 +596,6 @@ warning: function cannot return without recursing | ``` -## unions-with-drop-fields - -This lint detects use of unions that contain fields with possibly non-trivial drop code. Some -example code that triggers this lint: - -```rust -#![feature(untagged_unions)] - -union U { - s: String, -} -``` - -This will produce: - -```text -warning: union contains a field with possibly non-trivial drop code, drop code of union fields is ignored when dropping the union - --> src/main.rs:4:5 - | -4 | s: String, - | ^^^^^^^^^ - | -``` - ## unknown-lints This lint detects unrecognized lint attribute. Some diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index d0a7eab071c31..f00bcd41b601e 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -979,35 +979,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnstableFeatures { } } -declare_lint! { - UNIONS_WITH_DROP_FIELDS, - Warn, - "use of unions that contain fields with possibly non-trivial drop code" -} - -declare_lint_pass!( - /// Lint for unions that contain fields with possibly non-trivial destructors. - UnionsWithDropFields => [UNIONS_WITH_DROP_FIELDS] -); - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields { - fn check_item(&mut self, ctx: &LateContext<'_, '_>, item: &hir::Item) { - if let hir::ItemKind::Union(ref vdata, _) = item.kind { - for field in vdata.fields() { - let field_ty = ctx.tcx.type_of( - ctx.tcx.hir().local_def_id(field.hir_id)); - if field_ty.needs_drop(ctx.tcx, ctx.param_env) { - ctx.span_lint(UNIONS_WITH_DROP_FIELDS, - field.span, - "union contains a field with possibly non-trivial drop code, \ - drop code of union fields is ignored when dropping the union"); - return; - } - } - } - } -} - declare_lint! { pub UNREACHABLE_PUB, Allow, @@ -1287,7 +1258,6 @@ declare_lint_pass!( NO_MANGLE_GENERIC_ITEMS, MUTABLE_TRANSMUTES, UNSTABLE_FEATURES, - UNIONS_WITH_DROP_FIELDS, UNREACHABLE_PUB, TYPE_ALIAS_BOUNDS, TRIVIAL_BOUNDS diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 0e054013cd779..a898e1a3dcfa1 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -164,9 +164,6 @@ macro_rules! late_lint_mod_passes { // Depends on referenced function signatures in expressions MutableTransmutes: MutableTransmutes, - // Depends on types of fields, checks if they implement Drop - UnionsWithDropFields: UnionsWithDropFields, - TypeAliasBounds: TypeAliasBounds, TrivialConstraints: TrivialConstraints, From e247a40a1c5f37cf76ca41d5bbee09985a809529 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 3 Jul 2019 13:02:47 +0200 Subject: [PATCH 06/33] Fixes #41073, it is no longer an ICE --- src/test/ui/union/issue-41073.rs | 24 ++++++++++++++++++++++++ src/test/ui/union/issue-41073.stderr | 15 +++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/test/ui/union/issue-41073.rs create mode 100644 src/test/ui/union/issue-41073.stderr diff --git a/src/test/ui/union/issue-41073.rs b/src/test/ui/union/issue-41073.rs new file mode 100644 index 0000000000000..91e9a0d0b659c --- /dev/null +++ b/src/test/ui/union/issue-41073.rs @@ -0,0 +1,24 @@ +#![feature(untagged_unions)] + +union Test { + a: A, //~ ERROR unions may not contain fields that need dropping + b: B +} + +#[derive(Debug)] +struct A(i32); +impl Drop for A { + fn drop(&mut self) { println!("A"); } +} + +#[derive(Debug)] +struct B(f32); +impl Drop for B { + fn drop(&mut self) { println!("B"); } +} + +fn main() { + let mut test = Test { a: A(3) }; + println!("{:?}", unsafe { test.b }); + unsafe { test.b = B(0.5); } +} diff --git a/src/test/ui/union/issue-41073.stderr b/src/test/ui/union/issue-41073.stderr new file mode 100644 index 0000000000000..2e9598b227124 --- /dev/null +++ b/src/test/ui/union/issue-41073.stderr @@ -0,0 +1,15 @@ +error[E0740]: unions may not contain fields that need dropping + --> $DIR/issue-41073.rs:4:5 + | +LL | a: A, + | ^^^^ + | +note: `std::mem::ManuallyDrop` can be used to wrap the type + --> $DIR/issue-41073.rs:4:5 + | +LL | a: A, + | ^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0740`. From 05a644e8257b20c3372f27420d28bef5fd6d6d73 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 4 Jul 2019 15:51:55 +0200 Subject: [PATCH 07/33] Update src/librustc_typeck/check/mod.rs Co-Authored-By: Mazdak Farrokhzad --- src/librustc_typeck/check/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2f122e5edb1cb..294d1992b9d9d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1402,7 +1402,7 @@ fn check_union_fields<'tcx>(tcx: TyCtxt<'tcx>, _sp: Span, item_def_id: DefId) -> 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 + // 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) { From 8c5ae86496d25ddd9df3486df46bcb671ce619ad Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 4 Jul 2019 15:52:37 +0200 Subject: [PATCH 08/33] Update src/librustc_typeck/check/mod.rs Co-Authored-By: Mazdak Farrokhzad --- src/librustc_typeck/check/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 294d1992b9d9d..a8b3a0483899c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1391,7 +1391,9 @@ fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) { check_packed(tcx, span, def_id); } -fn check_union_fields<'tcx>(tcx: TyCtxt<'tcx>, _sp: Span, item_def_id: DefId) -> bool { +/// When the `#![feature(untagged_unions)]` gate is active, +/// check that the fields of the `union` does not contain fields that need dropping. +fn check_union_fields(tcx: TyCtxt<'_>, _: Span, item_def_id: DefId) -> bool { // Without the feature we check Copy types only later if !tcx.features().untagged_unions { return true; From 0301eafd32a128b31cc7c551d5844f6fce965caa Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 4 Jul 2019 15:52:48 +0200 Subject: [PATCH 09/33] Update src/librustc_typeck/error_codes.rs Co-Authored-By: Mazdak Farrokhzad --- src/librustc_typeck/error_codes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index a92a2c9600391..78dedca8027f7 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -4864,7 +4864,7 @@ assert_eq!(1, discriminant(&Enum::Struct{a: 7, b: 11})); "##, E0740: r##" -A `union` can not have fields with destructors. +A `union` cannot have fields with destructors. "##, E0733: r##" From bf25a9c82fb9d78447da885eb70d7234d135ecd5 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 4 Jul 2019 15:54:16 +0200 Subject: [PATCH 10/33] Update src/test/run-pass/union/union-nodrop.rs Co-Authored-By: Mazdak Farrokhzad --- src/test/ui/union/union-nodrop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/union/union-nodrop.rs b/src/test/ui/union/union-nodrop.rs index 330f6f9593b13..c99228d7d3439 100644 --- a/src/test/ui/union/union-nodrop.rs +++ b/src/test/ui/union/union-nodrop.rs @@ -13,7 +13,7 @@ impl Drop for NeedDrop { fn drop(&mut self) {} } -// Constant expressios allow `NoDrop` to go out of scope, +// Constant expressions allow `NoDrop` to go out of scope, // unlike a value of the interior type implementing `Drop`. static X: () = (NoDrop { inner: ManuallyDrop::new(NeedDrop) }, ()).1; From fc512d2cdf5ab654e55e25725b7243812f4630d1 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 4 Jul 2019 18:21:06 +0200 Subject: [PATCH 11/33] More descriptive variable name --- src/librustc_typeck/check/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a8b3a0483899c..ea27efcd0fbcd 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1398,8 +1398,8 @@ fn check_union_fields(tcx: TyCtxt<'_>, _: Span, item_def_id: DefId) -> bool { if !tcx.features().untagged_unions { return true; } - let t = tcx.type_of(item_def_id); - if let ty::Adt(def, substs) = t.sty { + let item_type = tcx.type_of(item_def_id); + if let ty::Adt(def, substs) = item_type.sty { if def.is_union() { let fields = &def.non_enum_variant().fields; for field in fields { From 616cf52358a66f0d546aac67a58958e2b50c5f0b Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 4 Jul 2019 18:30:41 +0200 Subject: [PATCH 12/33] Extend union-nodrop.rs test --- src/test/ui/union/union-nodrop.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/test/ui/union/union-nodrop.rs b/src/test/ui/union/union-nodrop.rs index c99228d7d3439..59282bec59b84 100644 --- a/src/test/ui/union/union-nodrop.rs +++ b/src/test/ui/union/union-nodrop.rs @@ -13,10 +13,14 @@ impl Drop for NeedDrop { fn drop(&mut self) {} } -// Constant expressions allow `NoDrop` to go out of scope, +// Constant expressios allow `NoDrop` to go out of scope, // unlike a value of the interior type implementing `Drop`. static X: () = (NoDrop { inner: ManuallyDrop::new(NeedDrop) }, ()).1; +const Y: () = (NoDrop { inner: ManuallyDrop::new(NeedDrop) }, ()).1; + +const fn _f() { (NoDrop { inner: ManuallyDrop::new(NeedDrop) }, ()).1 } + // A union that scrubs the drop glue from its inner type union NoDrop { inner: ManuallyDrop } From 50ec10e6059f923204c573b4004612e99aa6cdad Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 20 Sep 2019 10:59:29 +0200 Subject: [PATCH 13/33] rpass tests are now part of `ui` tests --- src/test/ui/union/union-derive-clone.stderr | 2 +- .../union/union-manuallydrop-rpass.rs} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/test/{run-pass/union/union-manuallydrop.rs => ui/union/union-manuallydrop-rpass.rs} (100%) diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index a6dcd556a1fee..6893f9176f2db 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -13,7 +13,7 @@ LL | union U5 { | ----------- method `clone` not found for this ... LL | let w = u.clone(); - | ^^^^^ method not found in `U4` + | ^^^^^ method not found in `U5` | = note: the method `clone` exists but the following trait bounds were not satisfied: `U5 : std::clone::Clone` diff --git a/src/test/run-pass/union/union-manuallydrop.rs b/src/test/ui/union/union-manuallydrop-rpass.rs similarity index 100% rename from src/test/run-pass/union/union-manuallydrop.rs rename to src/test/ui/union/union-manuallydrop-rpass.rs From 9c1ad0ff2fe64c02a91c1daf0ce6670b1eaf75f6 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 20 Sep 2019 12:22:06 +0200 Subject: [PATCH 14/33] Preserve originally intended test semantics --- src/test/ui/union/union-generic-rpass.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/test/ui/union/union-generic-rpass.rs b/src/test/ui/union/union-generic-rpass.rs index 5ca3bc0f722c3..eb169c516d2a8 100644 --- a/src/test/ui/union/union-generic-rpass.rs +++ b/src/test/ui/union/union-generic-rpass.rs @@ -3,8 +3,10 @@ #![feature(untagged_unions)] -union MaybeItem where T::Item: Copy { - elem: T::Item, +use std::mem::ManuallyDrop; + +union MaybeItem { + elem: ManuallyDrop, none: (), } @@ -25,7 +27,7 @@ fn main() { let v: Vec = vec![1, 2, 3]; let mut i = v.iter(); i.next(); - let mi = MaybeItem::> { elem: i.next().unwrap() }; - assert_eq!(*mi.elem, 2); + let mi = MaybeItem::> { elem: ManuallyDrop::new(i.next().unwrap()) }; + assert_eq!(**mi.elem, 2); } } From 2fc257ca8144ad6a41b053a01f977afce7a23c95 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 20 Sep 2019 12:40:57 +0200 Subject: [PATCH 15/33] Prefer `ManuallyDrop::{take,new}` over `ptr::{read,write}` --- src/libstd/lib.rs | 1 + src/libstd/panicking.rs | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 5ff32d7adafc2..8e3e02586a625 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -275,6 +275,7 @@ #![feature(link_args)] #![feature(linkage)] #![feature(log_syntax)] +#![feature(manually_drop_take)] #![feature(maybe_uninit_ref)] #![feature(maybe_uninit_slice)] #![feature(mem_take)] diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 296f2a59bb82e..2dde81bb0ecd4 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -13,7 +13,6 @@ use crate::any::Any; use crate::fmt; use crate::intrinsics; use crate::mem::{self, ManuallyDrop}; -use crate::ptr; use crate::raw; use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sys::stdio::panic_output; @@ -283,8 +282,9 @@ pub unsafe fn r#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 data = &mut (*data); + let f = ManuallyDrop::take(&mut data.f); + data.r = ManuallyDrop::new(f()); } } } From fb23a5cf3bda8d4d5ee89be4c1777d28a1061f9b Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 20 Sep 2019 12:46:41 +0200 Subject: [PATCH 16/33] Clarify a vague comment --- src/librustc_typeck/check/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index ea27efcd0fbcd..d2a4b824439d3 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1394,7 +1394,8 @@ fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) { /// When the `#![feature(untagged_unions)]` gate is active, /// check that the fields of the `union` does not contain fields that need dropping. fn check_union_fields(tcx: TyCtxt<'_>, _: Span, item_def_id: DefId) -> bool { - // Without the feature we check Copy types only later + // Without the feature we check that all fields are `Copy` in our stability checking + // infrastructure. if !tcx.features().untagged_unions { return true; } From 7e1a65dce1d13d02de8e0ffafad15538556cb7b9 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 20 Sep 2019 13:53:46 +0200 Subject: [PATCH 17/33] Ensure we do not treat all unions as not having any drop glue. --- src/test/ui/union/union-custom-drop.rs | 19 +++++++++++++++ src/test/ui/union/union-custom-drop.stderr | 28 ++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 src/test/ui/union/union-custom-drop.rs create mode 100644 src/test/ui/union/union-custom-drop.stderr diff --git a/src/test/ui/union/union-custom-drop.rs b/src/test/ui/union/union-custom-drop.rs new file mode 100644 index 0000000000000..8f816cc1b737c --- /dev/null +++ b/src/test/ui/union/union-custom-drop.rs @@ -0,0 +1,19 @@ +// test for a union with a field that's a union with a manual impl Drop +// Ensures we do not treat all unions as not having any drop glue. + +#![feature(untagged_unions)] + +union Foo { + bar: Bar, //~ ERROR unions may not contain fields that need dropping +} + +union Bar { + a: i32, + b: u32, +} + +impl Drop for Bar { + fn drop(&mut self) {} +} + +fn main() {} diff --git a/src/test/ui/union/union-custom-drop.stderr b/src/test/ui/union/union-custom-drop.stderr new file mode 100644 index 0000000000000..8e4e5dd40fd3f --- /dev/null +++ b/src/test/ui/union/union-custom-drop.stderr @@ -0,0 +1,28 @@ +error[E0601]: `main` function not found in crate `union_custom_drop` + --> $DIR/union-custom-drop.rs:4:1 + | +LL | / #![feature(untagged_unions)] +LL | | +LL | | union Foo { +LL | | bar: Bar, +... | +LL | | } +LL | | } + | |_^ consider adding a `main` function to `$DIR/union-custom-drop.rs` + +error[E0740]: unions may not contain fields that need dropping + --> $DIR/union-custom-drop.rs:7:5 + | +LL | bar: Bar, + | ^^^^^^^^ + | +note: `std::mem::ManuallyDrop` can be used to wrap the type + --> $DIR/union-custom-drop.rs:7:5 + | +LL | bar: Bar, + | ^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0601, E0740. +For more information about an error, try `rustc --explain E0601`. From f5669ebb45353bfb828650472af783331b7b90fe Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 20 Sep 2019 15:23:10 +0200 Subject: [PATCH 18/33] Update ui stderr --- src/test/ui/union/union-custom-drop.stderr | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/src/test/ui/union/union-custom-drop.stderr b/src/test/ui/union/union-custom-drop.stderr index 8e4e5dd40fd3f..ee2333f905fb4 100644 --- a/src/test/ui/union/union-custom-drop.stderr +++ b/src/test/ui/union/union-custom-drop.stderr @@ -1,15 +1,3 @@ -error[E0601]: `main` function not found in crate `union_custom_drop` - --> $DIR/union-custom-drop.rs:4:1 - | -LL | / #![feature(untagged_unions)] -LL | | -LL | | union Foo { -LL | | bar: Bar, -... | -LL | | } -LL | | } - | |_^ consider adding a `main` function to `$DIR/union-custom-drop.rs` - error[E0740]: unions may not contain fields that need dropping --> $DIR/union-custom-drop.rs:7:5 | @@ -22,7 +10,6 @@ note: `std::mem::ManuallyDrop` can be used to wrap the type LL | bar: Bar, | ^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0601, E0740. -For more information about an error, try `rustc --explain E0601`. +For more information about this error, try `rustc --explain E0740`. From bb5a652361bb416e38fa4f41784dd5d08b232f59 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 17 Oct 2019 13:28:14 +0200 Subject: [PATCH 19/33] Rebase fallout --- src/librustc_typeck/check/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d2a4b824439d3..3e0527393cd12 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1400,7 +1400,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, _: Span, item_def_id: DefId) -> bool { return true; } let item_type = tcx.type_of(item_def_id); - if let ty::Adt(def, substs) = item_type.sty { + if let ty::Adt(def, substs) = item_type.kind { if def.is_union() { let fields = &def.non_enum_variant().fields; for field in fields { From 5719f57fb1628e33765393d886f1638bfa0da059 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 20 Oct 2019 12:02:35 +0200 Subject: [PATCH 20/33] miri add write_bytes method to Memory doing bounds-checks and supporting iterators --- src/librustc/mir/interpret/allocation.rs | 9 +++++++-- src/librustc_mir/interpret/memory.rs | 21 ++++++++++++++++++++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 15e6cb6bcabae..3bcde8defdfac 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -346,11 +346,16 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { &mut self, cx: &impl HasDataLayout, ptr: Pointer, - src: &[u8], + src: impl IntoIterator, ) -> InterpResult<'tcx> { + let mut src = src.into_iter(); let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(src.len() as u64))?; - bytes.clone_from_slice(src); + // `zip` would stop when the first iterator ends; we want to definitely + // cover all of `bytes`. + for dest in bytes { + *dest = src.next().expect("iterator was shorter than it said it would be"); + } Ok(()) } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 924474c53175c..0b65e9742b6a5 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -7,7 +7,7 @@ //! short-circuiting the empty case! use std::collections::VecDeque; -use std::ptr; +use std::{ptr, iter}; use std::borrow::Cow; use rustc::ty::{self, Instance, ParamEnv, query::TyCtxtAt}; @@ -785,6 +785,25 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { self.get(ptr.alloc_id)?.read_c_str(self, ptr) } + /// Writes the given stream of bytes into memory. + /// + /// Performs appropriate bounds checks. + pub fn write_bytes( + &mut self, + ptr: Scalar, + src: impl IntoIterator, + ) -> InterpResult<'tcx> + { + let src = src.into_iter(); + let size = Size::from_bytes(src.len() as u64); + let ptr = match self.check_ptr_access(ptr, size, Align::from_bytes(1).unwrap())? { + Some(ptr) => ptr, + None => return Ok(()), // zero-sized access + }; + let tcx = self.tcx.tcx; + self.get_mut(ptr.alloc_id)?.write_bytes(&tcx, ptr, src) + } + /// Expects the caller to have checked bounds and alignment. pub fn copy( &mut self, From 50ddcbb2f5004da5b2d805c079e7c9699b6b7bea Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 20 Oct 2019 12:06:03 +0200 Subject: [PATCH 21/33] also check the iterator is not too long --- src/librustc/lib.rs | 1 + src/librustc/mir/interpret/allocation.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 8943fc342c023..3b0ac9ada8f65 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -43,6 +43,7 @@ #![feature(nll)] #![feature(non_exhaustive)] #![feature(optin_builtin_traits)] +#![feature(option_expect_none)] #![feature(range_is_empty)] #![feature(slice_patterns)] #![feature(specialization)] diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 3bcde8defdfac..87e9b91a86c74 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -356,6 +356,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { for dest in bytes { *dest = src.next().expect("iterator was shorter than it said it would be"); } + src.next().expect_none("iterator was longer than it said it would be"); Ok(()) } From 77c50dc508b8a0ea4277db6860c8d86288fd8538 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 20 Oct 2019 10:35:51 +1100 Subject: [PATCH 22/33] Remove unnecessary trait bounds from `keys::Keys`. --- src/librustc/ty/query/keys.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/librustc/ty/query/keys.rs b/src/librustc/ty/query/keys.rs index 30a3e53dddfbb..f61801cd23276 100644 --- a/src/librustc/ty/query/keys.rs +++ b/src/librustc/ty/query/keys.rs @@ -8,14 +8,12 @@ use crate::ty::subst::SubstsRef; use crate::ty::fast_reject::SimplifiedType; use crate::mir; -use std::fmt::Debug; -use std::hash::Hash; use syntax_pos::{Span, DUMMY_SP}; use syntax_pos::symbol::InternedString; /// The `Key` trait controls what types can legally be used as the key /// for a query. -pub(super) trait Key: Clone + Hash + Eq + Debug { +pub(super) trait Key { /// Given an instance of this key, what crate is it referring to? /// This is used to find the provider. fn query_crate(&self) -> CrateNum; @@ -201,10 +199,7 @@ impl Key for InternedString { /// Canonical query goals correspond to abstract trait operations that /// are not tied to any crate in particular. -impl<'tcx, T> Key for Canonical<'tcx, T> -where - T: Debug + Hash + Clone + Eq, -{ +impl<'tcx, T> Key for Canonical<'tcx, T> { fn query_crate(&self) -> CrateNum { LOCAL_CRATE } From c3b3a861244f5e61d5912ba507e229d978ec1c1c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 20 Oct 2019 10:29:11 +1100 Subject: [PATCH 23/33] Remove unnecessary `Hash` bounds from various types. --- src/bootstrap/cache.rs | 2 +- src/librustc/ty/fast_reject.rs | 8 ++++---- src/librustc_data_structures/sharded.rs | 2 +- src/librustc_data_structures/snapshot_map/mod.rs | 2 +- src/librustc_data_structures/stable_hasher.rs | 6 +++--- src/librustc_mir/borrow_check/nll/member_constraints.rs | 4 ++-- src/libserialize/collection_impls.rs | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs index 53071df855297..4310f2c6fa140 100644 --- a/src/bootstrap/cache.rs +++ b/src/bootstrap/cache.rs @@ -161,7 +161,7 @@ impl Ord for Interned { } } -struct TyIntern { +struct TyIntern { items: Vec, set: HashMap>, } diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 038b54f1f26dd..27a09b394b8fa 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -19,7 +19,7 @@ pub type SimplifiedType = SimplifiedTypeGen; /// the non-stable but fast to construct DefId-version is the better choice. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, RustcEncodable, RustcDecodable)] pub enum SimplifiedTypeGen - where D: Copy + Debug + Ord + Eq + Hash + where D: Copy + Debug + Ord + Eq { BoolSimplifiedType, CharSimplifiedType, @@ -123,10 +123,10 @@ pub fn simplify_type( } } -impl SimplifiedTypeGen { +impl SimplifiedTypeGen { pub fn map_def(self, map: F) -> SimplifiedTypeGen where F: Fn(D) -> U, - U: Copy + Debug + Ord + Eq + Hash, + U: Copy + Debug + Ord + Eq, { match self { BoolSimplifiedType => BoolSimplifiedType, @@ -155,7 +155,7 @@ impl SimplifiedTypeGen { impl<'a, D> HashStable> for SimplifiedTypeGen where - D: Copy + Debug + Ord + Eq + Hash + HashStable>, + D: Copy + Debug + Ord + Eq + HashStable>, { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); diff --git a/src/librustc_data_structures/sharded.rs b/src/librustc_data_structures/sharded.rs index d0ff6108d6ea6..2f972eeccdcbd 100644 --- a/src/librustc_data_structures/sharded.rs +++ b/src/librustc_data_structures/sharded.rs @@ -90,7 +90,7 @@ impl Sharded { pub type ShardedHashMap = Sharded>; -impl ShardedHashMap { +impl ShardedHashMap { pub fn len(&self) -> usize { self.lock_shards().iter().map(|shard| shard.len()).sum() } diff --git a/src/librustc_data_structures/snapshot_map/mod.rs b/src/librustc_data_structures/snapshot_map/mod.rs index ce0aa07cc282c..bdd3dc9665629 100644 --- a/src/librustc_data_structures/snapshot_map/mod.rs +++ b/src/librustc_data_structures/snapshot_map/mod.rs @@ -7,7 +7,7 @@ use std::mem; mod tests; pub struct SnapshotMap - where K: Hash + Clone + Eq + where K: Clone + Eq { map: FxHashMap, undo_log: Vec>, diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index ee4f6a5e785e4..78494401c0baf 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -460,7 +460,7 @@ impl_stable_hash_via_hash!(::std::path::Path); impl_stable_hash_via_hash!(::std::path::PathBuf); impl HashStable for ::std::collections::HashMap - where K: ToStableHashKey + Eq + Hash, + where K: ToStableHashKey + Eq, V: HashStable, R: BuildHasher, { @@ -471,7 +471,7 @@ impl HashStable for ::std::collections::HashMap } impl HashStable for ::std::collections::HashSet - where K: ToStableHashKey + Eq + Hash, + where K: ToStableHashKey + Eq, R: BuildHasher, { fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { @@ -513,7 +513,7 @@ pub fn hash_stable_hashmap( hasher: &mut StableHasher, map: &::std::collections::HashMap, to_stable_hash_key: F) - where K: Eq + Hash, + where K: Eq, V: HashStable, R: BuildHasher, SK: HashStable + Ord + Clone, diff --git a/src/librustc_mir/borrow_check/nll/member_constraints.rs b/src/librustc_mir/borrow_check/nll/member_constraints.rs index fd195873a55e4..75213d30982f9 100644 --- a/src/librustc_mir/borrow_check/nll/member_constraints.rs +++ b/src/librustc_mir/borrow_check/nll/member_constraints.rs @@ -11,7 +11,7 @@ use syntax_pos::Span; /// indexed by the region `R0`. crate struct MemberConstraintSet<'tcx, R> where - R: Copy + Hash + Eq, + R: Copy + Eq, { /// Stores the first "member" constraint for a given `R0`. This is an /// index into the `constraints` vector below. @@ -191,7 +191,7 @@ where impl<'tcx, R> Index for MemberConstraintSet<'tcx, R> where - R: Copy + Hash + Eq, + R: Copy + Eq, { type Output = NllMemberConstraint<'tcx>; diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs index d981740780e6f..f2e9be14c8d12 100644 --- a/src/libserialize/collection_impls.rs +++ b/src/libserialize/collection_impls.rs @@ -143,7 +143,7 @@ impl Decodable for BTreeSet } impl Encodable for HashMap - where K: Encodable + Hash + Eq, + where K: Encodable + Eq, V: Encodable, S: BuildHasher, { @@ -180,7 +180,7 @@ impl Decodable for HashMap } impl Encodable for HashSet - where T: Encodable + Hash + Eq, + where T: Encodable + Eq, S: BuildHasher, { fn encode(&self, s: &mut E) -> Result<(), E::Error> { From 0653694fdc46a2bca119b9790d1dfd62e1b4901e Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 21 Oct 2019 09:08:05 +0200 Subject: [PATCH 24/33] Don't silently do nothing on mis_use of `check_union_fields` --- src/librustc_typeck/check/mod.rs | 33 ++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 3e0527393cd12..d5182d69c3e70 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1393,7 +1393,7 @@ fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) { /// When the `#![feature(untagged_unions)]` gate is active, /// check that the fields of the `union` does not contain fields that need dropping. -fn check_union_fields(tcx: TyCtxt<'_>, _: Span, item_def_id: DefId) -> bool { +fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: DefId) -> bool { // Without the feature we check that all fields are `Copy` in our stability checking // infrastructure. if !tcx.features().untagged_unions { @@ -1401,23 +1401,24 @@ fn check_union_fields(tcx: TyCtxt<'_>, _: Span, item_def_id: DefId) -> bool { } let item_type = tcx.type_of(item_def_id); if let ty::Adt(def, substs) = item_type.kind { - 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, E0740, - "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; - } + assert!(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, E0740, + "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; } } + } else { + span_bug!(span, "unions must be ty::Adt, but got {:?}", item_type.kind); } return true; } From 875bdd5dbe663a6dafd785b86c8964a90653eeb7 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 21 Oct 2019 10:12:09 +0200 Subject: [PATCH 25/33] Report even duplilcate errors in case the feature gat is not active --- src/librustc_typeck/check/mod.rs | 5 ---- .../feature-gate-untagged_unions.rs | 4 +-- .../feature-gate-untagged_unions.stderr | 29 +++++++++++++++++-- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d5182d69c3e70..c5b809ad380f7 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1394,11 +1394,6 @@ fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) { /// When the `#![feature(untagged_unions)]` gate is active, /// check that the fields of the `union` does not contain fields that need dropping. fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: DefId) -> bool { - // Without the feature we check that all fields are `Copy` in our stability checking - // infrastructure. - if !tcx.features().untagged_unions { - return true; - } let item_type = tcx.type_of(item_def_id); if let ty::Adt(def, substs) = item_type.kind { assert!(def.is_union()); diff --git a/src/test/ui/feature-gates/feature-gate-untagged_unions.rs b/src/test/ui/feature-gates/feature-gate-untagged_unions.rs index 3bac3d853e907..9ee0e6f681dcc 100644 --- a/src/test/ui/feature-gates/feature-gate-untagged_unions.rs +++ b/src/test/ui/feature-gates/feature-gate-untagged_unions.rs @@ -7,11 +7,11 @@ union U2 { // OK } union U3 { //~ ERROR unions with non-`Copy` fields are unstable - a: String, + a: String, //~ ERROR unions may not contain fields that need dropping } union U4 { //~ ERROR unions with non-`Copy` fields are unstable - a: T, + a: T, //~ ERROR unions may not contain fields that need dropping } union U5 { //~ ERROR unions with `Drop` implementations are unstable diff --git a/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr b/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr index f59a34e2c81f6..1885518a4585c 100644 --- a/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr +++ b/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr @@ -31,6 +31,31 @@ LL | | } = note: for more information, see https://github.com/rust-lang/rust/issues/32836 = help: add `#![feature(untagged_unions)]` to the crate attributes to enable -error: aborting due to 3 previous errors +error[E0740]: unions may not contain fields that need dropping + --> $DIR/feature-gate-untagged_unions.rs:10:5 + | +LL | a: String, + | ^^^^^^^^^ + | +note: `std::mem::ManuallyDrop` can be used to wrap the type + --> $DIR/feature-gate-untagged_unions.rs:10:5 + | +LL | a: String, + | ^^^^^^^^^ + +error[E0740]: unions may not contain fields that need dropping + --> $DIR/feature-gate-untagged_unions.rs:14:5 + | +LL | a: T, + | ^^^^ + | +note: `std::mem::ManuallyDrop` can be used to wrap the type + --> $DIR/feature-gate-untagged_unions.rs:14:5 + | +LL | a: T, + | ^^^^ + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0658, E0740. +For more information about an error, try `rustc --explain E0658`. From 55b787e675e26a3b0e7513ec17936210abc42fa1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Oct 2019 10:30:35 +0200 Subject: [PATCH 26/33] keep the root dir clean from debugging --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index 1c47ed4c02482..81a472451d777 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,3 @@ config.stamp Session.vim .cargo no_llvm_build -# Generated when dumping Graphviz output for debugging: -/mir_dump/ -/*.dot From d4b365429ddaeb18b42ff47456bd9865fd1d732e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 20 Oct 2019 14:57:21 +0200 Subject: [PATCH 27/33] points the user away from the Allocation type and towards the Memory type --- src/librustc/mir/interpret/allocation.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 87e9b91a86c74..33c53323d96a7 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -245,6 +245,8 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// as a slice. /// /// It is the caller's responsibility to check bounds and alignment beforehand. + /// Most likely, you want to use the `PlaceTy` and `OperandTy`-based methods + /// on `InterpCx` instead. #[inline] pub fn get_bytes( &self, @@ -275,6 +277,8 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// so be sure to actually put data there! /// /// It is the caller's responsibility to check bounds and alignment beforehand. + /// Most likely, you want to use the `PlaceTy` and `OperandTy`-based methods + /// on `InterpCx` instead. pub fn get_bytes_mut( &mut self, cx: &impl HasDataLayout, @@ -297,6 +301,8 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Reads bytes until a `0` is encountered. Will error if the end of the allocation is reached /// before a `0` is found. + /// + /// Most likely, you want to call `Memory::read_c_str` instead of this method. pub fn read_c_str( &self, cx: &impl HasDataLayout, @@ -342,6 +348,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Writes `src` to the memory starting at `ptr.offset`. /// /// It is the caller's responsibility to check bounds and alignment beforehand. + /// Most likely, you want to call `Memory::write_bytes` instead of this method. pub fn write_bytes( &mut self, cx: &impl HasDataLayout, @@ -363,6 +370,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Sets `count` bytes starting at `ptr.offset` with `val`. Basically `memset`. /// /// It is the caller's responsibility to check bounds and alignment beforehand. + /// Most likely, you want to call `Memory::write_bytes` instead of this method. pub fn write_repeat( &mut self, cx: &impl HasDataLayout, @@ -386,6 +394,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// pointers being valid for ZSTs. /// /// It is the caller's responsibility to check bounds and alignment beforehand. + /// Most likely, you want to call `InterpCx::read_scalar` instead of this method. pub fn read_scalar( &self, cx: &impl HasDataLayout, @@ -424,6 +433,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Reads a pointer-sized scalar. /// /// It is the caller's responsibility to check bounds and alignment beforehand. + /// Most likely, you want to call `InterpCx::read_scalar` instead of this method. pub fn read_ptr_sized( &self, cx: &impl HasDataLayout, @@ -441,6 +451,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// pointers being valid for ZSTs. /// /// It is the caller's responsibility to check bounds and alignment beforehand. + /// Most likely, you want to call `InterpCx::write_scalar` instead of this method. pub fn write_scalar( &mut self, cx: &impl HasDataLayout, @@ -483,6 +494,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Writes a pointer-sized scalar. /// /// It is the caller's responsibility to check bounds and alignment beforehand. + /// Most likely, you want to call `InterpCx::write_scalar` instead of this method. pub fn write_ptr_sized( &mut self, cx: &impl HasDataLayout, From f6d70b42b8d6d299fe5621ac9170f69c511c8ddc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Oct 2019 11:08:37 +0200 Subject: [PATCH 28/33] remove write_repeat; it is subsumed by the new write_bytes --- src/librustc/mir/interpret/allocation.rs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 33c53323d96a7..796d293e2c63c 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -367,25 +367,6 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { Ok(()) } - /// Sets `count` bytes starting at `ptr.offset` with `val`. Basically `memset`. - /// - /// It is the caller's responsibility to check bounds and alignment beforehand. - /// Most likely, you want to call `Memory::write_bytes` instead of this method. - pub fn write_repeat( - &mut self, - cx: &impl HasDataLayout, - ptr: Pointer, - val: u8, - count: Size - ) -> InterpResult<'tcx> - { - let bytes = self.get_bytes_mut(cx, ptr, count)?; - for b in bytes { - *b = val; - } - Ok(()) - } - /// Reads a *non-ZST* scalar. /// /// ZSTs can't be read for two reasons: From ac6daed384d17abd31f84fc8205c21eee6a248be Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 20 Oct 2019 15:54:53 +1100 Subject: [PATCH 29/33] Remove many unnecessary trait derivations. --- src/librustc/dep_graph/graph.rs | 2 +- src/librustc/hir/map/definitions.rs | 1 - src/librustc/hir/mod.rs | 10 ++++------ src/librustc/hir/ptr.rs | 2 +- src/librustc/infer/canonical/mod.rs | 2 +- src/librustc/infer/combine.rs | 2 +- src/librustc/infer/mod.rs | 2 +- src/librustc/infer/nll_relate/mod.rs | 2 +- src/librustc/infer/region_constraints/mod.rs | 2 +- src/librustc/middle/cstore.rs | 2 +- src/librustc/middle/mem_categorization.rs | 8 ++++---- src/librustc/middle/stability.rs | 2 +- src/librustc/mir/interpret/value.rs | 4 ++-- src/librustc/mir/mod.rs | 20 +++++++++---------- src/librustc/mir/mono.rs | 6 +++--- src/librustc/mir/visit.rs | 2 +- src/librustc/session/config.rs | 8 ++++---- src/librustc/session/search_paths.rs | 3 +-- src/librustc/traits/query/mod.rs | 2 +- .../query/type_op/implied_outlives_bounds.rs | 2 +- src/librustc/ty/binding.rs | 2 +- src/librustc/ty/context.rs | 4 ++-- src/librustc/ty/error.rs | 1 - src/librustc/ty/fold.rs | 1 - src/librustc/ty/mod.rs | 8 ++++---- src/librustc/ty/query/plumbing.rs | 4 ++-- src/librustc/ty/sty.rs | 8 +++----- src/librustc_codegen_llvm/llvm/ffi.rs | 3 +-- .../graph/implementation/mod.rs | 4 ++-- src/librustc_data_structures/stable_hasher.rs | 4 ++-- src/librustc_data_structures/sync.rs | 2 +- src/librustc_data_structures/thin_vec.rs | 2 +- src/librustc_data_structures/tiny_list.rs | 4 ++-- .../transitive_relation.rs | 6 +++--- .../borrow_check/nll/constraints/mod.rs | 2 +- .../borrow_check/nll/region_infer/values.rs | 2 +- .../borrow_check/nll/universal_regions.rs | 2 +- src/librustc_mir/interpret/eval_context.rs | 4 ++-- src/librustc_mir/interpret/memory.rs | 2 +- src/librustc_mir/interpret/operand.rs | 6 +++--- src/librustc_mir/monomorphize/collector.rs | 2 +- src/librustc_target/spec/mod.rs | 6 ++---- src/librustdoc/clean/mod.rs | 7 +++---- src/libsyntax/ast.rs | 6 +++--- src/libsyntax/attr/builtin.rs | 9 ++++----- src/libsyntax/ptr.rs | 1 - src/libsyntax/source_map.rs | 2 +- src/libsyntax_expand/mbe.rs | 2 +- src/libsyntax_pos/lib.rs | 2 +- 49 files changed, 89 insertions(+), 103 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 337cdddc432c4..0104507f7020f 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -35,7 +35,7 @@ impl DepNodeIndex { pub const INVALID: DepNodeIndex = DepNodeIndex::MAX; } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(PartialEq)] pub enum DepNodeColor { Red, Green(DepNodeIndex) diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index d2732c92d2688..d95637c3b9868 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -599,7 +599,6 @@ macro_rules! define_global_metadata_kind { (pub enum GlobalMetaDataKind { $($variant:ident),* }) => ( - #[derive(Clone, Copy, Debug, Hash, RustcEncodable, RustcDecodable)] pub enum GlobalMetaDataKind { $($variant),* } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 568e051aaf08f..364a8ace1aac4 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1077,7 +1077,7 @@ impl Mutability { } } -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Hash, HashStable)] +#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum BinOpKind { /// The `+` operator (addition). Add, @@ -1211,7 +1211,7 @@ impl Into for BinOpKind { pub type BinOp = Spanned; -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Hash, HashStable)] +#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum UnOp { /// The `*` operator (deferencing). UnDeref, @@ -1388,8 +1388,7 @@ impl Body { } /// The type of source expression that caused this generator to be created. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, HashStable, - RustcEncodable, RustcDecodable, Hash, Debug, Copy)] +#[derive(Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable, Debug, Copy)] pub enum GeneratorKind { /// An explicit `async` block or the body of an async function. Async(AsyncGeneratorKind), @@ -1412,8 +1411,7 @@ impl fmt::Display for GeneratorKind { /// /// This helps error messages but is also used to drive coercions in /// type-checking (see #60424). -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, HashStable, - RustcEncodable, RustcDecodable, Hash, Debug, Copy)] +#[derive(Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable, Debug, Copy)] pub enum AsyncGeneratorKind { /// An explicit `async` block written by the user. Block, diff --git a/src/librustc/hir/ptr.rs b/src/librustc/hir/ptr.rs index 8cdcf5202fcda..7ee461a859bd6 100644 --- a/src/librustc/hir/ptr.rs +++ b/src/librustc/hir/ptr.rs @@ -11,7 +11,7 @@ use rustc_serialize::{Encodable, Decodable, Encoder, Decoder}; use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; /// An owned smart pointer. -#[derive(Hash, PartialEq, Eq)] +#[derive(PartialEq, Eq)] pub struct P { ptr: Box } diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs index 562a463ded86a..de1867596c8cb 100644 --- a/src/librustc/infer/canonical/mod.rs +++ b/src/librustc/infer/canonical/mod.rs @@ -73,7 +73,7 @@ pub struct CanonicalVarValues<'tcx> { /// various parts of it with canonical variables. This struct stores /// those replaced bits to remember for when we process the query /// result. -#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)] +#[derive(Clone, Debug)] pub struct OriginalQueryValues<'tcx> { /// Map from the universes that appear in the query to the /// universes in the caller context. For the time being, we only diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 6f73275d455f5..f06dbc72cd961 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -53,7 +53,7 @@ pub struct CombineFields<'infcx, 'tcx> { pub obligations: PredicateObligations<'tcx>, } -#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +#[derive(Copy, Clone, Debug)] pub enum RelationDir { SubtypeOf, SupertypeOf, EqTo } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index af74d13572431..f4ed7dac1f7c4 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -407,7 +407,7 @@ pub enum RegionVariableOrigin { NLL(NLLRegionVariableOrigin), } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, Debug)] pub enum NLLRegionVariableOrigin { /// During NLL region processing, we create variables for free /// regions that we encounter in the function signature and diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs index 4649f3f9567e7..9a835cf5c0938 100644 --- a/src/librustc/infer/nll_relate/mod.rs +++ b/src/librustc/infer/nll_relate/mod.rs @@ -32,7 +32,7 @@ use crate::mir::interpret::ConstValue; use rustc_data_structures::fx::FxHashMap; use std::fmt::Debug; -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(PartialEq)] pub enum NormalizationStrategy { Lazy, Eager, diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index b4b4d1fe3e1f6..8c6a7c9a376a7 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -116,7 +116,7 @@ pub struct RegionConstraintData<'tcx> { } /// Represents a constraint that influences the inference process. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, PartialOrd, Ord)] pub enum Constraint<'tcx> { /// A region variable is a subregion of another. VarSubVar(RegionVid, RegionVid), diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 2170a288c922b..ec1e32988a607 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -117,7 +117,7 @@ pub struct NativeLibrary { pub wasm_import_module: Option, } -#[derive(Clone, Hash, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] pub struct ForeignModule { pub foreign_items: Vec, pub def_id: DefId, diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 8f79b8aa29529..cbf336fdbe2f3 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -102,7 +102,7 @@ pub struct Upvar { } // different kinds of pointers: -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum PointerKind<'tcx> { /// `Box` Unique, @@ -116,7 +116,7 @@ pub enum PointerKind<'tcx> { // We use the term "interior" to mean "something reachable from the // base without a pointer dereference", e.g., a field -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq)] pub enum InteriorKind { InteriorField(FieldIndex), InteriorElement(InteriorOffsetKind), @@ -139,13 +139,13 @@ impl Hash for FieldIndex { } } -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, PartialEq)] pub enum InteriorOffsetKind { Index, // e.g., `array_expr[index_expr]` Pattern, // e.g., `fn foo([_, a, _, _]: [A; 4]) { ... }` } -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Debug)] pub enum MutabilityCategory { McImmutable, // Immutable. McDeclared, // Directly declared as mutable. diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 302c11f309d90..0095f89337c4e 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -25,7 +25,7 @@ use crate::util::nodemap::{FxHashSet, FxHashMap}; use std::mem::replace; use std::cmp::Ordering; -#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Copy, Debug, Eq, Hash)] +#[derive(PartialEq, Clone, Copy, Debug)] pub enum StabilityLevel { Unstable, Stable, diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index bbf00cc23ae88..04b1a86d4d02e 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -9,7 +9,7 @@ use crate::hir::def_id::DefId; use super::{InterpResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate}; /// Represents the result of a raw const operation, pre-validation. -#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash, HashStable)] +#[derive(Clone, HashStable)] pub struct RawConst<'tcx> { // the value lives here, at offset 0, and that allocation definitely is a `AllocKind::Memory` // (so you can use `AllocMap::unwrap_memory`). @@ -487,7 +487,7 @@ impl From> for Scalar { } } -#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, RustcEncodable, RustcDecodable)] +#[derive(Clone, Copy, Eq, PartialEq, RustcEncodable, RustcDecodable)] pub enum ScalarMaybeUndef { Scalar(Scalar), Undef, diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 9ac1465cb0ba9..ccf64c51e1330 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -468,7 +468,7 @@ impl rustc_serialize::UseSpecializedDecodable for ClearCrossCrate< /// Grouped information about the source code origin of a MIR entity. /// Intended to be inspected by diagnostics and debuginfo. /// Most passes can work with it as a whole, within a single function. -#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable)] pub struct SourceInfo { /// The source span for the AST pertaining to this MIR entity. pub span: Span, @@ -608,7 +608,7 @@ pub enum LocalKind { ReturnPointer, } -#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub struct VarBindingForm<'tcx> { /// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`? pub binding_mode: ty::BindingMode, @@ -630,7 +630,7 @@ pub struct VarBindingForm<'tcx> { pub pat_span: Span, } -#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub enum BindingForm<'tcx> { /// This is a binding for a non-`self` binding, or a `self` that has an explicit type. Var(VarBindingForm<'tcx>), @@ -641,7 +641,7 @@ pub enum BindingForm<'tcx> { } /// Represents what type of implicit self a function has, if any. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable)] pub enum ImplicitSelfKind { /// Represents a `fn x(self);`. Imm, @@ -2392,7 +2392,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { /// this does not necessarily mean that they are "==" in Rust -- in /// particular one must be wary of `NaN`! -#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)] pub struct Constant<'tcx> { pub span: Span, @@ -2438,7 +2438,7 @@ pub struct Constant<'tcx> { /// The first will lead to the constraint `w: &'1 str` (for some /// inferred region `'1`). The second will lead to the constraint `w: /// &'static str`. -#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct UserTypeProjections { pub(crate) contents: Vec<(UserTypeProjection, Span)>, } @@ -2515,7 +2515,7 @@ impl<'tcx> UserTypeProjections { /// * `let (x, _): T = ...` -- here, the `projs` vector would contain /// `field[0]` (aka `.0`), indicating that the type of `s` is /// determined by finding the type of the `.0` field from `T`. -#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct UserTypeProjection { pub base: UserTypeAnnotationIndex, pub projs: Vec, @@ -2724,7 +2724,7 @@ impl Location { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)] pub enum UnsafetyViolationKind { General, /// Permitted both in `const fn`s and regular `fn`s. @@ -2733,7 +2733,7 @@ pub enum UnsafetyViolationKind { BorrowPacked(hir::HirId), } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)] pub struct UnsafetyViolation { pub source_info: SourceInfo, pub description: InternedString, @@ -2741,7 +2741,7 @@ pub struct UnsafetyViolation { pub kind: UnsafetyViolationKind, } -#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] pub struct UnsafetyCheckResult { /// Violations that are propagated *upwards* from this function. pub violations: Lrc<[UnsafetyViolation]>, diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index 265ac975ed7a2..eeb997d75ca55 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -15,7 +15,7 @@ use std::fmt; use std::hash::Hash; /// Describes how a monomorphization will be instantiated in object files. -#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)] +#[derive(PartialEq)] pub enum InstantiationMode { /// There will be exactly one instance of the given MonoItem. It will have /// external linkage so that it can be linked to from other codegen units. @@ -251,7 +251,7 @@ pub struct CodegenUnit<'tcx> { size_estimate: Option, } -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)] pub enum Linkage { External, AvailableExternally, @@ -280,7 +280,7 @@ impl_stable_hash_for!(enum self::Linkage { Common }); -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum Visibility { Default, Hidden, diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index fef406e898783..427540d72758e 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -947,7 +947,7 @@ impl<'tcx> MirVisitable<'tcx> for Option> { /// Extra information passed to `visit_ty` and friends to give context /// about where the type etc appears. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Debug)] pub enum TyContext { LocalDecl { /// The index of the local variable we are visiting. diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 675e3bbd002b0..491c636374bca 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -67,7 +67,7 @@ impl_stable_hash_via_hash!(OptLevel); /// This is what the `LtoCli` values get mapped to after resolving defaults and /// and taking other command line options into account. -#[derive(Clone, Copy, PartialEq, Hash, Debug)] +#[derive(Clone, PartialEq)] pub enum Lto { /// Don't do any LTO whatsoever No, @@ -301,10 +301,10 @@ impl OutputTypes { /// Use tree-based collections to cheaply get a deterministic `Hash` implementation. /// *Do not* switch `BTreeMap` or `BTreeSet` out for an unsorted container type! That /// would break dependency tracking for command-line arguments. -#[derive(Clone, Hash)] +#[derive(Clone)] pub struct Externs(BTreeMap); -#[derive(Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug, Default)] +#[derive(Clone, Debug, Default)] pub struct ExternEntry { pub locations: BTreeSet>, pub is_private_dep: bool @@ -464,7 +464,7 @@ pub enum PrintRequest { NativeStaticLibs, } -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone)] pub enum BorrowckMode { Mir, Migrate, diff --git a/src/librustc/session/search_paths.rs b/src/librustc/session/search_paths.rs index 3695f0a82f4b0..949dad751a101 100644 --- a/src/librustc/session/search_paths.rs +++ b/src/librustc/session/search_paths.rs @@ -1,5 +1,4 @@ use std::path::{Path, PathBuf}; -use rustc_macros::HashStable; use crate::session::{early_error, config}; use crate::session::filesearch::make_target_lib_path; @@ -10,7 +9,7 @@ pub struct SearchPath { pub files: Vec, } -#[derive(Eq, PartialEq, Clone, Copy, Debug, PartialOrd, Ord, Hash, HashStable)] +#[derive(PartialEq, Clone, Copy, Debug, HashStable)] pub enum PathKind { Native, Crate, diff --git a/src/librustc/traits/query/mod.rs b/src/librustc/traits/query/mod.rs index 112a1d0e09c94..f6ea77dc5cc68 100644 --- a/src/librustc/traits/query/mod.rs +++ b/src/librustc/traits/query/mod.rs @@ -40,7 +40,7 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> = pub type CanonicalTypeOpNormalizeGoal<'tcx, T> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::normalize::Normalize>>; -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug)] pub struct NoSolution; pub type Fallible = Result; diff --git a/src/librustc/traits/query/type_op/implied_outlives_bounds.rs b/src/librustc/traits/query/type_op/implied_outlives_bounds.rs index 12a834fbda6bd..7aa98703411b2 100644 --- a/src/librustc/traits/query/type_op/implied_outlives_bounds.rs +++ b/src/librustc/traits/query/type_op/implied_outlives_bounds.rs @@ -3,7 +3,7 @@ use crate::traits::query::outlives_bounds::OutlivesBound; use crate::traits::query::Fallible; use crate::ty::{ParamEnvAnd, Ty, TyCtxt}; -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Clone, Debug)] pub struct ImpliedOutlivesBounds<'tcx> { pub ty: Ty<'tcx>, } diff --git a/src/librustc/ty/binding.rs b/src/librustc/ty/binding.rs index 1290141b0a6b0..5570144489cdf 100644 --- a/src/librustc/ty/binding.rs +++ b/src/librustc/ty/binding.rs @@ -2,7 +2,7 @@ use crate::hir::BindingAnnotation::*; use crate::hir::BindingAnnotation; use crate::hir::Mutability; -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] pub enum BindingMode { BindByReference(Mutability), BindByValue(Mutability), diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 665d4c2d0696a..1027cbd8322bb 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -827,7 +827,7 @@ rustc_index::newtype_index! { pub type CanonicalUserTypeAnnotations<'tcx> = IndexVec>; -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct CanonicalUserTypeAnnotation<'tcx> { pub user_ty: CanonicalUserType<'tcx>, pub span: Span, @@ -899,7 +899,7 @@ impl CanonicalUserType<'tcx> { /// A user-given type annotation attached to a constant. These arise /// from constants that are named via paths, like `Foo::::new` and /// so forth. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable)] pub enum UserType<'tcx> { Ty(Ty<'tcx>), diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 5851a48a8d377..3395715f67ff9 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -51,7 +51,6 @@ pub enum TypeError<'tcx> { IntrinsicCast, } -#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] pub enum UnconstrainedNumeric { UnconstrainedFloat, UnconstrainedInt, diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 5192075c26e98..0f8061ef3dd48 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -718,7 +718,6 @@ impl<'tcx> TyCtxt<'tcx> { // vars. See comment on `shift_vars_through_binders` method in // `subst.rs` for more details. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] enum Direction { In, Out, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index d46ab3769ad55..d377b7328e80b 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -159,7 +159,7 @@ impl AssocItemContainer { /// The "header" of an impl is everything outside the body: a Self type, a trait /// ref (in the case of a trait impl), and a set of predicates (from the /// bounds / where-clauses). -#[derive(Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Debug)] pub struct ImplHeader<'tcx> { pub impl_def_id: DefId, pub self_ty: Ty<'tcx>, @@ -195,7 +195,7 @@ pub struct AssocItem { pub method_has_self_argument: bool, } -#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, PartialEq, Debug, HashStable)] pub enum AssocKind { Const, Method, @@ -331,7 +331,7 @@ impl Visibility { } } -#[derive(Copy, Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Hash, HashStable)] +#[derive(Copy, Clone, PartialEq, RustcDecodable, RustcEncodable, HashStable)] pub enum Variance { Covariant, // T <: T iff A <: B -- e.g., function return type Invariant, // T <: T iff B == A -- e.g., type of mutable cell @@ -752,7 +752,7 @@ pub struct UpvarId { pub closure_expr_id: LocalDefId, } -#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, Copy, HashStable)] +#[derive(Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, HashStable)] pub enum BorrowKind { /// Data must be immutable and is aliasable. ImmBorrow, diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 7f05e553bc976..41b4883793b54 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -801,7 +801,7 @@ macro_rules! define_queries_inner { } #[allow(nonstandard_style)] - #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] + #[derive(Clone, Copy)] pub enum QueryName { $($name),* } @@ -819,7 +819,7 @@ macro_rules! define_queries_inner { } #[allow(nonstandard_style)] - #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] + #[derive(Clone, Debug)] pub enum Query<$tcx> { $($(#[$attr])* $name($K)),* } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 4af73fa389a7d..1e872eb8e4561 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -304,8 +304,7 @@ static_assert_size!(TyKind<'_>, 24); /// type parameters is similar, but the role of CK and CS are /// different. CK represents the "yield type" and CS represents the /// "return type" of the generator. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, - RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, Debug)] pub struct ClosureSubsts<'tcx> { /// Lifetime and type parameters from the enclosing function, /// concatenated with the types of the upvars. @@ -392,8 +391,7 @@ impl<'tcx> ClosureSubsts<'tcx> { } /// Similar to `ClosureSubsts`; see the above documentation for more. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, - RustcEncodable, RustcDecodable, HashStable)] +#[derive(Copy, Clone, Debug)] pub struct GeneratorSubsts<'tcx> { pub substs: SubstsRef<'tcx>, } @@ -1035,7 +1033,7 @@ impl<'tcx> ProjectionTy<'tcx> { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Debug)] pub struct GenSig<'tcx> { pub yield_ty: Ty<'tcx>, pub return_ty: Ty<'tcx>, diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index a2313b933a6c9..c69942ef3f2d5 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -50,7 +50,7 @@ pub enum CallConv { } /// LLVMRustLinkage -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(PartialEq)] #[repr(C)] pub enum Linkage { ExternalLinkage = 0, @@ -67,7 +67,6 @@ pub enum Linkage { } // LLVMRustVisibility -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[repr(C)] pub enum Visibility { Default = 0, diff --git a/src/librustc_data_structures/graph/implementation/mod.rs b/src/librustc_data_structures/graph/implementation/mod.rs index c438a8558a704..9fdcea6df88c5 100644 --- a/src/librustc_data_structures/graph/implementation/mod.rs +++ b/src/librustc_data_structures/graph/implementation/mod.rs @@ -60,10 +60,10 @@ impl SnapshotVecDelegate for Edge { fn reverse(_: &mut Vec>, _: ()) {} } -#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] +#[derive(Copy, Clone, PartialEq, Debug)] pub struct NodeIndex(pub usize); -#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] +#[derive(Copy, Clone, PartialEq, Debug)] pub struct EdgeIndex(pub usize); pub const INVALID_EDGE_INDEX: EdgeIndex = EdgeIndex(usize::MAX); diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index 78494401c0baf..092208cfe1db7 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -169,7 +169,7 @@ pub trait HashStable { /// example, for DefId that can be converted to a DefPathHash. This is used for /// bringing maps into a predictable order before hashing them. pub trait ToStableHashKey { - type KeyType: Ord + Clone + Sized + HashStable; + type KeyType: Ord + Sized + HashStable; fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType; } @@ -516,7 +516,7 @@ pub fn hash_stable_hashmap( where K: Eq, V: HashStable, R: BuildHasher, - SK: HashStable + Ord + Clone, + SK: HashStable + Ord, F: Fn(&K, &HCX) -> SK, { let mut entries: Vec<_> = map.iter() diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index 9622c290039d5..f09474ff4d344 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -738,7 +738,7 @@ impl Clone for RwLock { /// A type which only allows its inner value to be used in one thread. /// It will panic if it is used on multiple threads. -#[derive(Copy, Clone, Hash, Debug, Eq, PartialEq)] +#[derive(Debug)] pub struct OneThread { #[cfg(parallel_compiler)] thread: thread::ThreadId, diff --git a/src/librustc_data_structures/thin_vec.rs b/src/librustc_data_structures/thin_vec.rs index 93a8b7f525fff..d97da489db8df 100644 --- a/src/librustc_data_structures/thin_vec.rs +++ b/src/librustc_data_structures/thin_vec.rs @@ -3,7 +3,7 @@ use crate::stable_hasher::{StableHasher, HashStable}; /// A vector type optimized for cases where this size is usually 0 (cf. `SmallVector`). /// The `Option>` wrapping allows us to represent a zero sized vector with `None`, /// which uses only a single (null) pointer. -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct ThinVec(Option>>); impl ThinVec { diff --git a/src/librustc_data_structures/tiny_list.rs b/src/librustc_data_structures/tiny_list.rs index ea771d9f20f8b..371f0f6fa0b44 100644 --- a/src/librustc_data_structures/tiny_list.rs +++ b/src/librustc_data_structures/tiny_list.rs @@ -14,7 +14,7 @@ #[cfg(test)] mod tests; -#[derive(Clone, Hash, Debug, PartialEq)] +#[derive(Clone)] pub struct TinyList { head: Option> } @@ -80,7 +80,7 @@ impl TinyList { } } -#[derive(Clone, Hash, Debug, PartialEq)] +#[derive(Clone)] struct Element { data: T, next: Option>>, diff --git a/src/librustc_data_structures/transitive_relation.rs b/src/librustc_data_structures/transitive_relation.rs index f0a9c3afc68b0..a3926c1555172 100644 --- a/src/librustc_data_structures/transitive_relation.rs +++ b/src/librustc_data_structures/transitive_relation.rs @@ -11,7 +11,7 @@ use std::mem; mod tests; #[derive(Clone, Debug)] -pub struct TransitiveRelation { +pub struct TransitiveRelation { // List of elements. This is used to map from a T to a usize. elements: Vec, @@ -35,7 +35,7 @@ pub struct TransitiveRelation { } // HACK(eddyb) manual impl avoids `Default` bound on `T`. -impl Default for TransitiveRelation { +impl Default for TransitiveRelation { fn default() -> Self { TransitiveRelation { elements: Default::default(), @@ -46,7 +46,7 @@ impl Default for TransitiveRelation { } } -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, RustcEncodable, RustcDecodable, Debug)] struct Index(usize); #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)] diff --git a/src/librustc_mir/borrow_check/nll/constraints/mod.rs b/src/librustc_mir/borrow_check/nll/constraints/mod.rs index 93113753c630b..8a242b7ee25ba 100644 --- a/src/librustc_mir/borrow_check/nll/constraints/mod.rs +++ b/src/librustc_mir/borrow_check/nll/constraints/mod.rs @@ -71,7 +71,7 @@ impl Index for OutlivesConstraintSet { } } -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct OutlivesConstraint { // NB. The ordering here is not significant for correctness, but // it is for convenience. Before we dump the constraints in the diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs index 6acbff76bdc90..7a86536573dcf 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs @@ -129,7 +129,7 @@ rustc_index::newtype_index! { /// An individual element in a region value -- the value of a /// particular region variable consists of a set of these elements. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Debug)] crate enum RegionElement { /// A point in the control-flow graph. Location(Location), diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs index 5f6951856434e..fd1f333010adc 100644 --- a/src/librustc_mir/borrow_check/nll/universal_regions.rs +++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs @@ -146,7 +146,7 @@ struct UniversalRegionIndices<'tcx> { indices: FxHashMap, RegionVid>, } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Debug, PartialEq)] pub enum RegionClassification { /// A **global** region is one that can be named from /// anywhere. There is only one, `'static`. diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 06fdd407951c1..2ab7c41bb787e 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -91,7 +91,7 @@ pub struct Frame<'mir, 'tcx, Tag=(), Extra=()> { pub extra: Extra, } -#[derive(Clone, Debug, Eq, PartialEq, Hash)] +#[derive(Clone, Eq, PartialEq)] pub enum StackPopCleanup { /// Jump to the next block in the caller, or cause UB if None (that's a function /// that may never return). Also store layout of return place so @@ -113,7 +113,7 @@ pub struct LocalState<'tcx, Tag=(), Id=AllocId> { } /// Current value of a local variable -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, PartialEq, Eq)] pub enum LocalValue { /// This local is not currently alive, and cannot be used at all. Dead, diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 924474c53175c..269e7a5d6efe3 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -22,7 +22,7 @@ use super::{ Machine, AllocMap, MayLeak, ErrorHandled, CheckInAllocMsg, }; -#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] +#[derive(Debug, PartialEq, Copy, Clone)] pub enum MemoryKind { /// Error if deallocated except during a stack pop Stack, diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 4d9be55945e02..a0f50f21352b1 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -26,7 +26,7 @@ pub use rustc::mir::interpret::ScalarMaybeUndef; /// operations and fat pointers. This idea was taken from rustc's codegen. /// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely /// defined on `Immediate`, and do not have to work with a `Place`. -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Immediate { Scalar(ScalarMaybeUndef), ScalarPair(ScalarMaybeUndef, ScalarMaybeUndef), @@ -123,7 +123,7 @@ impl<'tcx, Tag> ::std::ops::Deref for ImmTy<'tcx, Tag> { /// An `Operand` is the result of computing a `mir::Operand`. It can be immediate, /// or still in memory. The latter is an optimization, to delay reading that chunk of /// memory and to avoid having to store arbitrary-sized data here. -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Operand { Immediate(Immediate), Indirect(MemPlace), @@ -153,7 +153,7 @@ impl Operand { } } -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub struct OpTy<'tcx, Tag=()> { op: Operand, // Keep this private, it helps enforce invariants pub layout: TyLayout<'tcx>, diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index ee7452d3e8b46..5e31b80bec6d3 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -199,7 +199,7 @@ use rustc_data_structures::sync::{MTRef, MTLock, ParallelIterator, par_iter}; use std::iter; -#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)] +#[derive(PartialEq)] pub enum MonoItemCollectionMode { Eager, Lazy diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index c5277c4f90e7a..d91588db1834f 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -71,8 +71,7 @@ mod riscv_base; mod wasm32_base; mod vxworks_base; -#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash, - RustcEncodable, RustcDecodable)] +#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] pub enum LinkerFlavor { Em, Gcc, @@ -82,8 +81,7 @@ pub enum LinkerFlavor { PtxLinker, } -#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash, - RustcEncodable, RustcDecodable)] +#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] pub enum LldFlavor { Wasm, Ld64, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c355f661410e5..09c9757dc4d07 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1307,7 +1307,7 @@ impl Clean> for ty::RegionKind { } } -#[derive(Clone, PartialEq, Eq, Debug, Hash)] +#[derive(Clone, Debug)] pub enum WherePredicate { BoundPredicate { ty: Type, bounds: Vec }, RegionPredicate { lifetime: Lifetime, bounds: Vec }, @@ -1589,7 +1589,7 @@ impl Clean for hir::GenericParam { } // maybe use a Generic enum and use Vec? -#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)] +#[derive(Clone, Debug, Default)] pub struct Generics { pub params: Vec, pub where_predicates: Vec, @@ -3847,7 +3847,7 @@ impl Clean for hir::Mutability { } } -#[derive(Clone, PartialEq, Eq, Copy, Debug, Hash)] +#[derive(Clone, PartialEq, Debug)] pub enum ImplPolarity { Positive, Negative, @@ -4506,7 +4506,6 @@ struct RegionDeps<'tcx> { smaller: FxHashSet> } -#[derive(Eq, PartialEq, Hash, Debug)] enum SimpleBound { TraitBound(Vec, Vec, Vec, hir::TraitBoundModifier), Outlives(Lifetime), diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 0408d7d1bc2aa..8be7f4478fa09 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1305,7 +1305,7 @@ impl MacroDef { } } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)] pub enum StrStyle { /// A regular string, like `"foo"`. Cooked, @@ -1327,7 +1327,7 @@ pub struct Lit { pub span: Span, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)] pub enum LitIntType { Signed(IntTy), Unsigned(UintTy), @@ -1337,7 +1337,7 @@ pub enum LitIntType { /// Literal kind. /// /// E.g., `"foo"`, `42`, `12.34`, or `bool`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum LitKind { /// A string literal (`"foo"`). Str(Symbol, StrStyle), diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index 28b61c5aa77cc..84c86c9651fcf 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -84,7 +84,7 @@ fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) { } } -#[derive(Copy, Clone, Hash, PartialEq, RustcEncodable, RustcDecodable)] +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)] pub enum InlineAttr { None, Hint, @@ -92,7 +92,7 @@ pub enum InlineAttr { Never, } -#[derive(Copy, Clone, Hash, PartialEq, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable)] pub enum OptimizeAttr { None, Speed, @@ -624,8 +624,7 @@ pub fn eval_condition(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F) } } - -#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)] +#[derive(RustcEncodable, RustcDecodable, Clone)] pub struct Deprecation { pub since: Option, pub note: Option, @@ -749,7 +748,7 @@ pub enum ReprAttr { ReprAlign(u32), } -#[derive(Eq, Hash, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)] +#[derive(Eq, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)] pub enum IntType { SignedInt(ast::IntTy), UnsignedInt(ast::UintTy) diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index 7300ce249548b..d987dc855b615 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -35,7 +35,6 @@ use rustc_serialize::{Encodable, Decodable, Encoder, Decoder}; use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; /// An owned smart pointer. -#[derive(Hash, PartialEq, Eq)] pub struct P { ptr: Box } diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs index 1501adc597104..a1d147637e27e 100644 --- a/src/libsyntax/source_map.rs +++ b/src/libsyntax/source_map.rs @@ -41,7 +41,7 @@ pub fn original_sp(sp: Span, enclosing_sp: Span) -> Span { } } -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)] pub struct Spanned { pub node: T, pub span: Span, diff --git a/src/libsyntax_expand/mbe.rs b/src/libsyntax_expand/mbe.rs index 453fe94f1de19..d0f790638efa3 100644 --- a/src/libsyntax_expand/mbe.rs +++ b/src/libsyntax_expand/mbe.rs @@ -73,7 +73,7 @@ impl KleeneToken { /// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star) /// for token sequences. -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] enum KleeneOp { /// Kleene star (`*`) for zero or more repetitions ZeroOrMore, diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 7f7c5cb2e4548..7e42b931961f8 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -1311,7 +1311,7 @@ pub struct BytePos(pub u32); /// A character offset. Because of multibyte UTF-8 characters, a byte offset /// is not equivalent to a character offset. The `SourceMap` will convert `BytePos` /// values to `CharPos` values as necessary. -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct CharPos(pub usize); // FIXME: lots of boilerplate in these impls, but so far my attempts to fix From 3de7698e124f5fc2bbde48fdfce41410747bcc00 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 21 Oct 2019 13:13:43 +0100 Subject: [PATCH 30/33] Fix typo from #65214 --- src/libstd/panic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index 24c693790e84b..577673b7e405b 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -264,7 +264,7 @@ impl RefUnwindSafe for atomic::AtomicI128 {} #[cfg(target_has_atomic_load_store = "ptr")] #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] impl RefUnwindSafe for atomic::AtomicUsize {} -#[cfg(target_hastarget_has_atomic_load_store_atomic = "8")] +#[cfg(target_has_atomic_load_store = "8")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicU8 {} #[cfg(target_has_atomic_load_store = "16")] From d689c709ea6e942de1687d918eaee541610aa86d Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Mon, 21 Oct 2019 15:35:54 +0200 Subject: [PATCH 31/33] improve readability of is_power_of_two --- src/libcore/num/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 82c1943b7d057..e14c886aec391 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -3750,7 +3750,7 @@ assert!(!10", stringify!($SelfT), ".is_power_of_two());", $EndFeature, " #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub const fn is_power_of_two(self) -> bool { - ((self.wrapping_sub(1)) & self == 0) & !(self == 0) + self.count_ones() == 1 } } From ebc9a1ab10ff813664778e572eaeef4a9c6fcf4f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Oct 2019 10:36:49 +0200 Subject: [PATCH 32/33] expand comment --- .gitignore | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 81a472451d777..487867c375d45 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,10 @@ -# This file should only ignore things that are generated during a build, -# generated by common IDEs, and optional files controlled by the user -# that affect the build (such as config.toml). +# This file should only ignore things that are generated during a `x.py` build, +# generated by common IDEs, and optional files controlled by the user that +# affect the build (such as config.toml). +# In particular, things like `mir_dump` should not be listed here; they are only +# created during manual debugging and many people like to clean up instead of +# having git ignore such leftovers. You can use `.git/info/exclude` to +# configure your local ignore list. # FIXME: This needs cleanup. *~ .#* @@ -52,3 +56,4 @@ config.stamp Session.vim .cargo no_llvm_build +# Before adding new lines, see the comment at the top. From e9c2685167c4d0f207714d436de8bb95538b7254 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 21 Oct 2019 11:22:45 +0100 Subject: [PATCH 33/33] Rename `ConstValue::Infer(InferConst::Canonical(..))` to `ConstValue::Bound(..)` --- src/librustc/infer/canonical/canonicalizer.rs | 4 ++-- src/librustc/infer/canonical/mod.rs | 6 ++--- .../infer/canonical/query_response.rs | 7 ++---- src/librustc/infer/freshen.rs | 2 +- src/librustc/infer/nll_relate/mod.rs | 6 ++--- src/librustc/mir/interpret/value.rs | 7 +++++- src/librustc/ty/context.rs | 2 +- src/librustc/ty/flags.rs | 2 +- src/librustc/ty/fold.rs | 23 +++++++++---------- src/librustc/ty/structural_impls.rs | 14 ++++------- src/librustc/ty/sty.rs | 2 -- src/librustc/ty/subst.rs | 6 ++--- src/librustc_codegen_ssa/mir/operand.rs | 1 + src/librustc_mir/interpret/operand.rs | 4 ++-- src/librustc_traits/chalk_context/mod.rs | 4 ++-- .../chalk_context/resolvent_ops.rs | 17 ++++---------- src/test/ui/symbol-names/impl1.legacy.stderr | 4 ++-- 17 files changed, 47 insertions(+), 64 deletions(-) diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index e69719806a81d..49a2c90bdbf60 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -468,7 +468,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { ConstValue::Infer(InferConst::Fresh(_)) => { bug!("encountered a fresh const during canonicalization") } - ConstValue::Infer(InferConst::Canonical(debruijn, _)) => { + ConstValue::Bound(debruijn, _) => { if debruijn >= self.binder_index { bug!("escaping bound type during canonicalization") } else { @@ -700,7 +700,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { let var = self.canonical_var(info, const_var.into()); self.tcx().mk_const( ty::Const { - val: ConstValue::Infer(InferConst::Canonical(self.binder_index, var.into())), + val: ConstValue::Bound(self.binder_index, var.into()), ty: self.fold_ty(const_var.ty), } ) diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs index 562a463ded86a..ef53fc12eed7b 100644 --- a/src/librustc/infer/canonical/mod.rs +++ b/src/librustc/infer/canonical/mod.rs @@ -33,7 +33,7 @@ use std::ops::Index; use syntax::source_map::Span; use crate::ty::fold::TypeFoldable; use crate::ty::subst::GenericArg; -use crate::ty::{self, BoundVar, InferConst, Lift, List, Region, TyCtxt}; +use crate::ty::{self, BoundVar, Lift, List, Region, TyCtxt}; mod canonicalizer; @@ -510,9 +510,7 @@ impl<'tcx> CanonicalVarValues<'tcx> { GenericArgKind::Const(ct) => { tcx.mk_const(ty::Const { ty: ct.ty, - val: ConstValue::Infer( - InferConst::Canonical(ty::INNERMOST, ty::BoundVar::from_u32(i)) - ), + val: ConstValue::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i)), }).into() } }) diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index 95b6a8bc84342..7ad6006012f49 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -26,7 +26,7 @@ use crate::traits::TraitEngine; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use crate::ty::fold::TypeFoldable; use crate::ty::subst::{GenericArg, GenericArgKind}; -use crate::ty::{self, BoundVar, InferConst, Ty, TyCtxt}; +use crate::ty::{self, BoundVar, Ty, TyCtxt}; use crate::util::captures::Captures; impl<'tcx> InferCtxtBuilder<'tcx> { @@ -493,10 +493,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { } } GenericArgKind::Const(result_value) => { - if let ty::Const { - val: ConstValue::Infer(InferConst::Canonical(debrujin, b)), - .. - } = result_value { + if let ty::Const { val: ConstValue::Bound(debrujin, b), .. } = result_value { // ...in which case we would set `canonical_vars[0]` to `Some(const X)`. // We only allow a `ty::INNERMOST` index in substitutions. diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index 9e9220cc3d8cc..1841bd9ea6423 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -252,7 +252,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { return ct; } - ConstValue::Infer(ty::InferConst::Canonical(..)) | + ConstValue::Bound(..) | ConstValue::Placeholder(_) => { bug!("unexpected const {:?}", ct) } diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs index 4649f3f9567e7..a032d0df028d1 100644 --- a/src/librustc/infer/nll_relate/mod.rs +++ b/src/librustc/infer/nll_relate/mod.rs @@ -27,7 +27,7 @@ use crate::ty::error::TypeError; use crate::ty::fold::{TypeFoldable, TypeVisitor}; use crate::ty::relate::{self, Relate, RelateResult, TypeRelation}; use crate::ty::subst::GenericArg; -use crate::ty::{self, Ty, TyCtxt, InferConst}; +use crate::ty::{self, Ty, TyCtxt}; use crate::mir::interpret::ConstValue; use rustc_data_structures::fx::FxHashMap; use std::fmt::Debug; @@ -618,7 +618,7 @@ where a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - if let ty::Const { val: ConstValue::Infer(InferConst::Canonical(_, _)), .. } = a { + if let ty::Const { val: ConstValue::Bound(..), .. } = a { // FIXME(const_generics): I'm unsure how this branch should actually be handled, // so this is probably not correct. self.infcx.super_combine_consts(self, a, b) @@ -993,7 +993,7 @@ where ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { debug!("TypeGeneralizer::consts(a={:?})", a); - if let ty::Const { val: ConstValue::Infer(InferConst::Canonical(_, _)), .. } = a { + if let ty::Const { val: ConstValue::Bound(..), .. } = a { bug!( "unexpected inference variable encountered in NLL generalization: {:?}", a diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index bbf00cc23ae88..377f9448941f2 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -5,6 +5,7 @@ use rustc_apfloat::{Float, ieee::{Double, Single}}; use crate::ty::{Ty, InferConst, ParamConst, layout::{HasDataLayout, Size}, subst::SubstsRef}; use crate::ty::PlaceholderConst; use crate::hir::def_id::DefId; +use crate::ty::{BoundVar, DebruijnIndex}; use super::{InterpResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate}; @@ -28,6 +29,9 @@ pub enum ConstValue<'tcx> { /// Infer the value of the const. Infer(InferConst<'tcx>), + /// Bound const variable, used only when preparing a trait query. + Bound(DebruijnIndex, BoundVar), + /// A placeholder const - universally quantified higher-ranked const. Placeholder(PlaceholderConst), @@ -66,8 +70,9 @@ impl<'tcx> ConstValue<'tcx> { match *self { ConstValue::Param(_) | ConstValue::Infer(_) | + ConstValue::Bound(..) | ConstValue::Placeholder(_) | - ConstValue::ByRef{ .. } | + ConstValue::ByRef { .. } | ConstValue::Unevaluated(..) | ConstValue::Slice { .. } => None, ConstValue::Scalar(val) => Some(val), diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 665d4c2d0696a..2674d0bcdb45d 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -882,7 +882,7 @@ impl CanonicalUserType<'tcx> { }, GenericArgKind::Const(ct) => match ct.val { - ConstValue::Infer(InferConst::Canonical(debruijn, b)) => { + ConstValue::Bound(debruijn, b) => { // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(debruijn, ty::INNERMOST); cvar == b diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index d3a3f51cfa47b..cb1fb4f685de5 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -240,10 +240,10 @@ impl FlagComputation { self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_CT_INFER); match infer { InferConst::Fresh(_) => {} - InferConst::Canonical(debruijn, _) => self.add_binder(debruijn), InferConst::Var(_) => self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX), } } + ConstValue::Bound(debruijn, _) => self.add_binder(debruijn), ConstValue::Param(_) => { self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_PARAMS); } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index a95ed589c3e2a..a69f1a623b69b 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -521,10 +521,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> { } fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if let ty::Const { - val: ConstValue::Infer(ty::InferConst::Canonical(debruijn, bound_const)), - ty, - } = *ct { + if let ty::Const { val: ConstValue::Bound(debruijn, bound_const), ty } = *ct { if debruijn == self.current_index { let fld_c = &mut self.fld_c; let ct = fld_c(bound_const, ty); @@ -570,7 +567,10 @@ impl<'tcx> TyCtxt<'tcx> { // identity for bound types and consts let fld_t = |bound_ty| self.mk_ty(ty::Bound(ty::INNERMOST, bound_ty)); let fld_c = |bound_ct, ty| { - self.mk_const_infer(ty::InferConst::Canonical(ty::INNERMOST, bound_ct), ty) + self.mk_const(ty::Const { + val: ConstValue::Bound(ty::INNERMOST, bound_ct), + ty, + }) }; self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t, fld_c) } @@ -802,10 +802,7 @@ impl TypeFolder<'tcx> for Shifter<'tcx> { } fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if let ty::Const { - val: ConstValue::Infer(ty::InferConst::Canonical(debruijn, bound_const)), - ty, - } = *ct { + if let ty::Const { val: ConstValue::Bound(debruijn, bound_ct), ty } = *ct { if self.amount == 0 || debruijn < self.current_index { ct } else { @@ -816,7 +813,10 @@ impl TypeFolder<'tcx> for Shifter<'tcx> { debruijn.shifted_out(self.amount) } }; - self.tcx.mk_const_infer(ty::InferConst::Canonical(debruijn, bound_const), ty) + self.tcx.mk_const(ty::Const { + val: ConstValue::Bound(debruijn, bound_ct), + ty, + }) } } else { ct.super_fold_with(self) @@ -920,8 +920,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { // const, as it has types/regions embedded in a lot of other // places. match ct.val { - ConstValue::Infer(ty::InferConst::Canonical(debruijn, _)) - if debruijn >= self.outer_index => true, + ConstValue::Bound(debruijn, _) if debruijn >= self.outer_index => true, _ => ct.super_visit_with(self), } } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 83ec98f9ddd2f..6b1f10bdb21c4 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -1379,27 +1379,23 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> { impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> { fn super_fold_with>(&self, folder: &mut F) -> Self { match *self { - ConstValue::ByRef { alloc, offset } => - ConstValue::ByRef { alloc, offset }, ConstValue::Infer(ic) => ConstValue::Infer(ic.fold_with(folder)), ConstValue::Param(p) => ConstValue::Param(p.fold_with(folder)), - ConstValue::Placeholder(p) => ConstValue::Placeholder(p), - ConstValue::Scalar(a) => ConstValue::Scalar(a), - ConstValue::Slice { data, start, end } => ConstValue::Slice { data, start, end }, ConstValue::Unevaluated(did, substs) => ConstValue::Unevaluated(did, substs.fold_with(folder)), + ConstValue::ByRef { .. } | ConstValue::Bound(..) | ConstValue::Placeholder(..) + | ConstValue::Scalar(..) | ConstValue::Slice { .. } => *self, + } } fn super_visit_with>(&self, visitor: &mut V) -> bool { match *self { - ConstValue::ByRef { .. } => false, ConstValue::Infer(ic) => ic.visit_with(visitor), ConstValue::Param(p) => p.visit_with(visitor), - ConstValue::Placeholder(_) => false, - ConstValue::Scalar(_) => false, - ConstValue::Slice { .. } => false, ConstValue::Unevaluated(_, substs) => substs.visit_with(visitor), + ConstValue::ByRef { .. } | ConstValue::Bound(..) | ConstValue::Placeholder(_) + | ConstValue::Scalar(_) | ConstValue::Slice { .. } => false, } } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 4af73fa389a7d..618d7d0b78014 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2373,6 +2373,4 @@ pub enum InferConst<'tcx> { Var(ConstVid<'tcx>), /// A fresh const variable. See `infer::freshen` for more details. Fresh(u32), - /// Canonicalized const variable, used only when preparing a trait query. - Canonical(DebruijnIndex, BoundVar), } diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 4081c02a33ca4..29721979099d5 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -2,7 +2,7 @@ use crate::hir::def_id::DefId; use crate::infer::canonical::Canonical; -use crate::ty::{self, Lift, List, Ty, TyCtxt, InferConst, ParamConst}; +use crate::ty::{self, Lift, List, Ty, TyCtxt, ParamConst}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::mir::interpret::ConstValue; use crate::ty::sty::{ClosureSubsts, GeneratorSubsts}; @@ -234,9 +234,7 @@ impl<'a, 'tcx> InternalSubsts<'tcx> { ty::GenericParamDefKind::Const => { tcx.mk_const(ty::Const { - val: ConstValue::Infer( - InferConst::Canonical(ty::INNERMOST, ty::BoundVar::from(param.index)) - ), + val: ConstValue::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)), ty: tcx.type_of(def_id), }).into() } diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index daa25b2ea0591..ba5e47aeede1b 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -79,6 +79,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { ConstValue::Unevaluated(..) => bug!("unevaluated constant in `OperandRef::from_const`"), ConstValue::Param(_) => bug!("encountered a ConstValue::Param in codegen"), ConstValue::Infer(_) => bug!("encountered a ConstValue::Infer in codegen"), + ConstValue::Bound(..) => bug!("encountered a ConstValue::Bound in codegen"), ConstValue::Placeholder(_) => bug!("encountered a ConstValue::Placeholder in codegen"), ConstValue::Scalar(x) => { let scalar = match layout.abi { diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 4d9be55945e02..b225d66aec568 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -589,8 +589,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let ptr = self.tag_static_base_pointer(Pointer::new(id, offset)); Operand::Indirect(MemPlace::from_ptr(ptr, layout.align.abi)) }, - ConstValue::Scalar(x) => - Operand::Immediate(tag_scalar(x).into()), + ConstValue::Scalar(x) => Operand::Immediate(tag_scalar(x).into()), ConstValue::Slice { data, start, end } => { // We rely on mutability being set correctly in `data` to prevent writes // where none should happen. @@ -606,6 +605,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } ConstValue::Param(..) | ConstValue::Infer(..) | + ConstValue::Bound(..) | ConstValue::Placeholder(..) | ConstValue::Unevaluated(..) => bug!("eval_const_to_op: Unexpected ConstValue {:?}", val), diff --git a/src/librustc_traits/chalk_context/mod.rs b/src/librustc_traits/chalk_context/mod.rs index 54d580ec05d71..8d136a1b65c79 100644 --- a/src/librustc_traits/chalk_context/mod.rs +++ b/src/librustc_traits/chalk_context/mod.rs @@ -33,7 +33,7 @@ use rustc::traits::{ InEnvironment, ChalkCanonicalGoal, }; -use rustc::ty::{self, TyCtxt, InferConst}; +use rustc::ty::{self, TyCtxt}; use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use rustc::ty::query::Providers; use rustc::ty::subst::{GenericArg, GenericArgKind}; @@ -286,7 +286,7 @@ impl context::ContextOps> for ChalkContext<'tcx> { _ => false, }, GenericArgKind::Const(ct) => match ct.val { - ConstValue::Infer(InferConst::Canonical(debruijn, bound_ct)) => { + ConstValue::Bound(debruijn, bound_ct) => { debug_assert_eq!(debruijn, ty::INNERMOST); cvar == bound_ct } diff --git a/src/librustc_traits/chalk_context/resolvent_ops.rs b/src/librustc_traits/chalk_context/resolvent_ops.rs index 8facec1e9e35f..49d76681196af 100644 --- a/src/librustc_traits/chalk_context/resolvent_ops.rs +++ b/src/librustc_traits/chalk_context/resolvent_ops.rs @@ -16,7 +16,7 @@ use rustc::traits::{ Environment, InEnvironment, }; -use rustc::ty::{self, Ty, TyCtxt, InferConst}; +use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::GenericArg; use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc::mir::interpret::ConstValue; @@ -287,10 +287,7 @@ impl TypeRelation<'tcx> for AnswerSubstitutor<'cx, 'tcx> { a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - if let ty::Const { - val: ConstValue::Infer(InferConst::Canonical(debruijn, bound_ct)), - .. - } = a { + if let ty::Const { val: ConstValue::Bound(debruijn, bound_ct), .. } = a { if *debruijn == self.binder_index { self.unify_free_answer_var(*bound_ct, b.into())?; return Ok(b); @@ -299,14 +296,8 @@ impl TypeRelation<'tcx> for AnswerSubstitutor<'cx, 'tcx> { match (a, b) { ( - ty::Const { - val: ConstValue::Infer(InferConst::Canonical(a_debruijn, a_bound)), - .. - }, - ty::Const { - val: ConstValue::Infer(InferConst::Canonical(b_debruijn, b_bound)), - .. - }, + ty::Const { val: ConstValue::Bound(a_debruijn, a_bound), .. }, + ty::Const { val: ConstValue::Bound(b_debruijn, b_bound), .. }, ) => { assert_eq!(a_debruijn, b_debruijn); assert_eq!(a_bound, b_bound); diff --git a/src/test/ui/symbol-names/impl1.legacy.stderr b/src/test/ui/symbol-names/impl1.legacy.stderr index a3d966bb0b035..610937739c194 100644 --- a/src/test/ui/symbol-names/impl1.legacy.stderr +++ b/src/test/ui/symbol-names/impl1.legacy.stderr @@ -46,13 +46,13 @@ error: def-path(bar::::baz) LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ -error: symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$_$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method17h059bf53000885489E) +error: symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$_$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method17h636bc933fc62ee2fE) --> $DIR/impl1.rs:61:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method::h059bf53000885489) +error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method::h636bc933fc62ee2f) --> $DIR/impl1.rs:61:13 | LL | #[rustc_symbol_name]