diff --git a/.gitignore b/.gitignore index 1c47ed4c02482..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,6 +56,4 @@ config.stamp Session.vim .cargo no_llvm_build -# Generated when dumping Graphviz output for debugging: -/mir_dump/ -/*.dot +# Before adding new lines, see the comment at the top. 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/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/libcore/num/mod.rs b/src/libcore/num/mod.rs index 8f4ade377e312..b4ade70414462 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -3757,8 +3757,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.count_ones() == 1 } } diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index cf9f36ca37c90..93274ef0c927c 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -36,5 +36,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/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/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..d833feeeb09d6 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; @@ -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 @@ -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/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/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/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..64ef0421808f4 100644 --- a/src/librustc/infer/nll_relate/mod.rs +++ b/src/librustc/infer/nll_relate/mod.rs @@ -27,12 +27,12 @@ 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; -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(PartialEq)] pub enum NormalizationStrategy { Lazy, Eager, @@ -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/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/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/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 b8d1a549ecda3..e65f17c79497e 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/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 15e6cb6bcabae..796d293e2c63c 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,33 +348,22 @@ 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, 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); - Ok(()) - } - - /// Sets `count` bytes starting at `ptr.offset` with `val`. Basically `memset`. - /// - /// It is the caller's responsibility to check bounds and alignment beforehand. - 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; + // `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"); } + src.next().expect_none("iterator was longer than it said it would be"); Ok(()) } @@ -380,6 +375,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, @@ -418,6 +414,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, @@ -435,6 +432,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, @@ -477,6 +475,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, diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index bbf00cc23ae88..ac16b8b884c45 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -5,11 +5,12 @@ 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}; /// 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`). @@ -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), @@ -487,7 +492,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 651f9393a31ba..2446d4f4788df 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -62,7 +62,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, @@ -296,10 +296,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 @@ -459,7 +459,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..d118bef37fc11 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, @@ -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 @@ -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/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/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..bacf3d42f0431 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) } @@ -721,7 +721,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, @@ -802,10 +801,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 +812,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 +919,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/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/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 } 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/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..298e798959635 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>, @@ -2373,6 +2371,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/ty/util.rs b/src/librustc/ty/util.rs index e1eab2c6579e1..5555dace45bfa 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -818,6 +818,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_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_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_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/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..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; } @@ -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,10 +513,10 @@ 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, + 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_lint/builtin.rs b/src/librustc_lint/builtin.rs index 08f6f43ab0cff..5d9a97cc21eef 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -980,35 +980,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, @@ -1288,7 +1259,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 e3860e229d6b5..f83755181f82e 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, 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/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/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..eef1868ec65b6 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}; @@ -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, @@ -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, diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 4d9be55945e02..4fd5e6a543551 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>, @@ -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_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/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/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 73f35dde4f6eb..73a025182a7e3 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1387,9 +1387,37 @@ 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); } +/// 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 { + let item_type = tcx.type_of(item_def_id); + if let ty::Adt(def, substs) = item_type.kind { + 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; +} + /// 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 8321fdd400fec..3ecbf620cbc7b 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` cannot have fields with destructors. +"##, + E0733: r##" Recursion in an `async fn` requires boxing. For example, this will not compile: 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/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> { diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 50a1226cc1d07..93d3e4ea3df22 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(needs_panic_runtime)] 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")] diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 638ce1679b8e9..2dde81bb0ecd4 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -12,8 +12,7 @@ use core::panic::{BoxMeUp, PanicInfo, Location}; use crate::any::Any; use crate::fmt; use crate::intrinsics; -use crate::mem; -use crate::ptr; +use crate::mem::{self, ManuallyDrop}; use crate::raw; use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sys::stdio::panic_output; @@ -227,10 +226,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 +259,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 +269,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 +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()); } } } 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 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/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); +} diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs index 7fd3f420a6d5b..5a7568fe2cd50 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/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/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`. 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/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.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/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/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/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] 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`. 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..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:15: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,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:60: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:66: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:73: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:79: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-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..ee2333f905fb4 --- /dev/null +++ b/src/test/ui/union/union-custom-drop.stderr @@ -0,0 +1,15 @@ +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 previous error + +For more information about this error, try `rustc --explain E0740`. 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..6893f9176f2db 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` + | ^^^^^ method not found in `U5` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `U4 : std::clone::Clone` + `U5 : std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/union/union-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..eb169c516d2a8 100644 --- a/src/test/ui/union/union-generic-rpass.rs +++ b/src/test/ui/union/union-generic-rpass.rs @@ -1,37 +1,33 @@ // run-pass #![allow(dead_code)] -#![allow(unions_with_drop_fields)] #![feature(untagged_unions)] +use std::mem::ManuallyDrop; + union MaybeItem { - elem: T::Item, + elem: ManuallyDrop, 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); 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); } } diff --git a/src/test/ui/union/union-manuallydrop-rpass.rs b/src/test/ui/union/union-manuallydrop-rpass.rs new file mode 100644 index 0000000000000..a43a505086569 --- /dev/null +++ b/src/test/ui/union/union-manuallydrop-rpass.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/union/union-nodrop.rs b/src/test/ui/union/union-nodrop.rs index 4cd64ddb5d67f..59282bec59b84 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,14 @@ 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; + +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: T} +union NoDrop { inner: ManuallyDrop } // Copy currently can't be implemented on drop-containing unions, // this may change later @@ -40,7 +43,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-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-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() {} 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`.