1
Fork 0

Auto merge of #65671 - Centril:rollup-00glhmb, r=Centril

Rollup of 7 pull requests

Successful merges:

 - #62330 (Change untagged_unions to not allow union fields with drop)
 - #65092 (make is_power_of_two a const function)
 - #65621 (miri: add write_bytes method to Memory doing bounds-checks and supporting iterators)
 - #65647 (Remove unnecessary trait bounds and derivations)
 - #65653 (keep the root dir clean from debugging)
 - #65660 (Rename `ConstValue::Infer(InferConst::Canonical(..))` to `ConstValue::Bound(..)`)
 - #65663 (Fix typo from #65214)

Failed merges:

r? @ghost
This commit is contained in:
bors 2019-10-22 00:20:12 +00:00
commit 6576f4be5a
112 changed files with 667 additions and 482 deletions

14
.gitignore vendored
View file

@ -1,6 +1,10 @@
# This file should only ignore things that are generated during a build, # 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 # generated by common IDEs, and optional files controlled by the user that
# that affect the build (such as config.toml). # 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. # FIXME: This needs cleanup.
*~ *~
.#* .#*
@ -52,6 +56,4 @@ config.stamp
Session.vim Session.vim
.cargo .cargo
no_llvm_build no_llvm_build
# Generated when dumping Graphviz output for debugging: # Before adding new lines, see the comment at the top.
/mir_dump/
/*.dot

View file

@ -161,7 +161,7 @@ impl Ord for Interned<String> {
} }
} }
struct TyIntern<T: Hash + Clone + Eq> { struct TyIntern<T: Clone + Eq> {
items: Vec<T>, items: Vec<T>,
set: HashMap<T, Interned<T>>, set: HashMap<T, Interned<T>>,
} }

View file

@ -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 ## unknown-lints
This lint detects unrecognized lint attribute. Some This lint detects unrecognized lint attribute. Some

View file

@ -3757,8 +3757,8 @@ assert!(!10", stringify!($SelfT), ".is_power_of_two());", $EndFeature, "
```"), ```"),
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn is_power_of_two(self) -> bool { pub const fn is_power_of_two(self) -> bool {
(self.wrapping_sub(1)) & self == 0 && !(self == 0) self.count_ones() == 1
} }
} }

View file

@ -36,5 +36,5 @@ parking_lot = "0.9"
byteorder = { version = "1.3" } byteorder = { version = "1.3" }
chalk-engine = { version = "0.9.0", default-features=false } chalk-engine = { version = "0.9.0", default-features=false }
rustc_fs_util = { path = "../librustc_fs_util" } 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" measureme = "0.3"

View file

@ -35,7 +35,7 @@ impl DepNodeIndex {
pub const INVALID: DepNodeIndex = DepNodeIndex::MAX; pub const INVALID: DepNodeIndex = DepNodeIndex::MAX;
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(PartialEq)]
pub enum DepNodeColor { pub enum DepNodeColor {
Red, Red,
Green(DepNodeIndex) Green(DepNodeIndex)

View file

@ -599,7 +599,6 @@ macro_rules! define_global_metadata_kind {
(pub enum GlobalMetaDataKind { (pub enum GlobalMetaDataKind {
$($variant:ident),* $($variant:ident),*
}) => ( }) => (
#[derive(Clone, Copy, Debug, Hash, RustcEncodable, RustcDecodable)]
pub enum GlobalMetaDataKind { pub enum GlobalMetaDataKind {
$($variant),* $($variant),*
} }

View file

@ -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 { pub enum BinOpKind {
/// The `+` operator (addition). /// The `+` operator (addition).
Add, Add,
@ -1211,7 +1211,7 @@ impl Into<ast::BinOpKind> for BinOpKind {
pub type BinOp = Spanned<BinOpKind>; pub type BinOp = Spanned<BinOpKind>;
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Hash, HashStable)] #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)]
pub enum UnOp { pub enum UnOp {
/// The `*` operator (deferencing). /// The `*` operator (deferencing).
UnDeref, UnDeref,
@ -1388,8 +1388,7 @@ impl Body {
} }
/// The type of source expression that caused this generator to be created. /// The type of source expression that caused this generator to be created.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, HashStable, #[derive(Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable, Debug, Copy)]
RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
pub enum GeneratorKind { pub enum GeneratorKind {
/// An explicit `async` block or the body of an async function. /// An explicit `async` block or the body of an async function.
Async(AsyncGeneratorKind), Async(AsyncGeneratorKind),
@ -1412,8 +1411,7 @@ impl fmt::Display for GeneratorKind {
/// ///
/// This helps error messages but is also used to drive coercions in /// This helps error messages but is also used to drive coercions in
/// type-checking (see #60424). /// type-checking (see #60424).
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, HashStable, #[derive(Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable, Debug, Copy)]
RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
pub enum AsyncGeneratorKind { pub enum AsyncGeneratorKind {
/// An explicit `async` block written by the user. /// An explicit `async` block written by the user.
Block, Block,

View file

@ -11,7 +11,7 @@ use rustc_serialize::{Encodable, Decodable, Encoder, Decoder};
use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
/// An owned smart pointer. /// An owned smart pointer.
#[derive(Hash, PartialEq, Eq)] #[derive(PartialEq, Eq)]
pub struct P<T: ?Sized> { pub struct P<T: ?Sized> {
ptr: Box<T> ptr: Box<T>
} }

View file

@ -468,7 +468,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
ConstValue::Infer(InferConst::Fresh(_)) => { ConstValue::Infer(InferConst::Fresh(_)) => {
bug!("encountered a fresh const during canonicalization") bug!("encountered a fresh const during canonicalization")
} }
ConstValue::Infer(InferConst::Canonical(debruijn, _)) => { ConstValue::Bound(debruijn, _) => {
if debruijn >= self.binder_index { if debruijn >= self.binder_index {
bug!("escaping bound type during canonicalization") bug!("escaping bound type during canonicalization")
} else { } else {
@ -700,7 +700,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
let var = self.canonical_var(info, const_var.into()); let var = self.canonical_var(info, const_var.into());
self.tcx().mk_const( self.tcx().mk_const(
ty::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), ty: self.fold_ty(const_var.ty),
} }
) )

View file

@ -33,7 +33,7 @@ use std::ops::Index;
use syntax::source_map::Span; use syntax::source_map::Span;
use crate::ty::fold::TypeFoldable; use crate::ty::fold::TypeFoldable;
use crate::ty::subst::GenericArg; 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; mod canonicalizer;
@ -73,7 +73,7 @@ pub struct CanonicalVarValues<'tcx> {
/// various parts of it with canonical variables. This struct stores /// various parts of it with canonical variables. This struct stores
/// those replaced bits to remember for when we process the query /// those replaced bits to remember for when we process the query
/// result. /// result.
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)] #[derive(Clone, Debug)]
pub struct OriginalQueryValues<'tcx> { pub struct OriginalQueryValues<'tcx> {
/// Map from the universes that appear in the query to the /// Map from the universes that appear in the query to the
/// universes in the caller context. For the time being, we only /// universes in the caller context. For the time being, we only
@ -510,9 +510,7 @@ impl<'tcx> CanonicalVarValues<'tcx> {
GenericArgKind::Const(ct) => { GenericArgKind::Const(ct) => {
tcx.mk_const(ty::Const { tcx.mk_const(ty::Const {
ty: ct.ty, ty: ct.ty,
val: ConstValue::Infer( val: ConstValue::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i)),
InferConst::Canonical(ty::INNERMOST, ty::BoundVar::from_u32(i))
),
}).into() }).into()
} }
}) })

View file

@ -26,7 +26,7 @@ use crate::traits::TraitEngine;
use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use crate::traits::{Obligation, ObligationCause, PredicateObligation};
use crate::ty::fold::TypeFoldable; use crate::ty::fold::TypeFoldable;
use crate::ty::subst::{GenericArg, GenericArgKind}; 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; use crate::util::captures::Captures;
impl<'tcx> InferCtxtBuilder<'tcx> { impl<'tcx> InferCtxtBuilder<'tcx> {
@ -493,10 +493,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
} }
} }
GenericArgKind::Const(result_value) => { GenericArgKind::Const(result_value) => {
if let ty::Const { if let ty::Const { val: ConstValue::Bound(debrujin, b), .. } = result_value {
val: ConstValue::Infer(InferConst::Canonical(debrujin, b)),
..
} = result_value {
// ...in which case we would set `canonical_vars[0]` to `Some(const X)`. // ...in which case we would set `canonical_vars[0]` to `Some(const X)`.
// We only allow a `ty::INNERMOST` index in substitutions. // We only allow a `ty::INNERMOST` index in substitutions.

View file

@ -53,7 +53,7 @@ pub struct CombineFields<'infcx, 'tcx> {
pub obligations: PredicateObligations<'tcx>, pub obligations: PredicateObligations<'tcx>,
} }
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] #[derive(Copy, Clone, Debug)]
pub enum RelationDir { pub enum RelationDir {
SubtypeOf, SupertypeOf, EqTo SubtypeOf, SupertypeOf, EqTo
} }

View file

@ -252,7 +252,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
return ct; return ct;
} }
ConstValue::Infer(ty::InferConst::Canonical(..)) | ConstValue::Bound(..) |
ConstValue::Placeholder(_) => { ConstValue::Placeholder(_) => {
bug!("unexpected const {:?}", ct) bug!("unexpected const {:?}", ct)
} }

View file

@ -407,7 +407,7 @@ pub enum RegionVariableOrigin {
NLL(NLLRegionVariableOrigin), NLL(NLLRegionVariableOrigin),
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Copy, Clone, Debug)]
pub enum NLLRegionVariableOrigin { pub enum NLLRegionVariableOrigin {
/// During NLL region processing, we create variables for free /// During NLL region processing, we create variables for free
/// regions that we encounter in the function signature and /// regions that we encounter in the function signature and

View file

@ -27,12 +27,12 @@ use crate::ty::error::TypeError;
use crate::ty::fold::{TypeFoldable, TypeVisitor}; use crate::ty::fold::{TypeFoldable, TypeVisitor};
use crate::ty::relate::{self, Relate, RelateResult, TypeRelation}; use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
use crate::ty::subst::GenericArg; use crate::ty::subst::GenericArg;
use crate::ty::{self, Ty, TyCtxt, InferConst}; use crate::ty::{self, Ty, TyCtxt};
use crate::mir::interpret::ConstValue; use crate::mir::interpret::ConstValue;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use std::fmt::Debug; use std::fmt::Debug;
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[derive(PartialEq)]
pub enum NormalizationStrategy { pub enum NormalizationStrategy {
Lazy, Lazy,
Eager, Eager,
@ -618,7 +618,7 @@ where
a: &'tcx ty::Const<'tcx>, a: &'tcx ty::Const<'tcx>,
b: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>,
) -> RelateResult<'tcx, &'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, // FIXME(const_generics): I'm unsure how this branch should actually be handled,
// so this is probably not correct. // so this is probably not correct.
self.infcx.super_combine_consts(self, a, b) self.infcx.super_combine_consts(self, a, b)
@ -993,7 +993,7 @@ where
) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
debug!("TypeGeneralizer::consts(a={:?})", a); debug!("TypeGeneralizer::consts(a={:?})", a);
if let ty::Const { val: ConstValue::Infer(InferConst::Canonical(_, _)), .. } = a { if let ty::Const { val: ConstValue::Bound(..), .. } = a {
bug!( bug!(
"unexpected inference variable encountered in NLL generalization: {:?}", "unexpected inference variable encountered in NLL generalization: {:?}",
a a

View file

@ -116,7 +116,7 @@ pub struct RegionConstraintData<'tcx> {
} }
/// Represents a constraint that influences the inference process. /// 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> { pub enum Constraint<'tcx> {
/// A region variable is a subregion of another. /// A region variable is a subregion of another.
VarSubVar(RegionVid, RegionVid), VarSubVar(RegionVid, RegionVid),

View file

@ -43,6 +43,7 @@
#![feature(nll)] #![feature(nll)]
#![feature(non_exhaustive)] #![feature(non_exhaustive)]
#![feature(optin_builtin_traits)] #![feature(optin_builtin_traits)]
#![feature(option_expect_none)]
#![feature(range_is_empty)] #![feature(range_is_empty)]
#![feature(slice_patterns)] #![feature(slice_patterns)]
#![feature(specialization)] #![feature(specialization)]

View file

@ -117,7 +117,7 @@ pub struct NativeLibrary {
pub wasm_import_module: Option<Symbol>, pub wasm_import_module: Option<Symbol>,
} }
#[derive(Clone, Hash, RustcEncodable, RustcDecodable, HashStable)] #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
pub struct ForeignModule { pub struct ForeignModule {
pub foreign_items: Vec<DefId>, pub foreign_items: Vec<DefId>,
pub def_id: DefId, pub def_id: DefId,

View file

@ -102,7 +102,7 @@ pub struct Upvar {
} }
// different kinds of pointers: // different kinds of pointers:
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq)]
pub enum PointerKind<'tcx> { pub enum PointerKind<'tcx> {
/// `Box<T>` /// `Box<T>`
Unique, Unique,
@ -116,7 +116,7 @@ pub enum PointerKind<'tcx> {
// We use the term "interior" to mean "something reachable from the // We use the term "interior" to mean "something reachable from the
// base without a pointer dereference", e.g., a field // base without a pointer dereference", e.g., a field
#[derive(Clone, Copy, PartialEq, Eq, Hash)] #[derive(Clone, PartialEq)]
pub enum InteriorKind { pub enum InteriorKind {
InteriorField(FieldIndex), InteriorField(FieldIndex),
InteriorElement(InteriorOffsetKind), InteriorElement(InteriorOffsetKind),
@ -139,13 +139,13 @@ impl Hash for FieldIndex {
} }
} }
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] #[derive(Clone, PartialEq)]
pub enum InteriorOffsetKind { pub enum InteriorOffsetKind {
Index, // e.g., `array_expr[index_expr]` Index, // e.g., `array_expr[index_expr]`
Pattern, // e.g., `fn foo([_, a, _, _]: [A; 4]) { ... }` Pattern, // e.g., `fn foo([_, a, _, _]: [A; 4]) { ... }`
} }
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] #[derive(Clone, Copy, PartialEq, Debug)]
pub enum MutabilityCategory { pub enum MutabilityCategory {
McImmutable, // Immutable. McImmutable, // Immutable.
McDeclared, // Directly declared as mutable. McDeclared, // Directly declared as mutable.

View file

@ -25,7 +25,7 @@ use crate::util::nodemap::{FxHashSet, FxHashMap};
use std::mem::replace; use std::mem::replace;
use std::cmp::Ordering; use std::cmp::Ordering;
#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Copy, Debug, Eq, Hash)] #[derive(PartialEq, Clone, Copy, Debug)]
pub enum StabilityLevel { pub enum StabilityLevel {
Unstable, Unstable,
Stable, Stable,

View file

@ -245,6 +245,8 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
/// as a slice. /// as a slice.
/// ///
/// It is the caller's responsibility to check bounds and alignment beforehand. /// 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] #[inline]
pub fn get_bytes( pub fn get_bytes(
&self, &self,
@ -275,6 +277,8 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
/// so be sure to actually put data there! /// so be sure to actually put data there!
/// ///
/// It is the caller's responsibility to check bounds and alignment beforehand. /// 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( pub fn get_bytes_mut(
&mut self, &mut self,
cx: &impl HasDataLayout, cx: &impl HasDataLayout,
@ -297,6 +301,8 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> { impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
/// Reads bytes until a `0` is encountered. Will error if the end of the allocation is reached /// Reads bytes until a `0` is encountered. Will error if the end of the allocation is reached
/// before a `0` is found. /// before a `0` is found.
///
/// Most likely, you want to call `Memory::read_c_str` instead of this method.
pub fn read_c_str( pub fn read_c_str(
&self, &self,
cx: &impl HasDataLayout, cx: &impl HasDataLayout,
@ -342,33 +348,22 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
/// Writes `src` to the memory starting at `ptr.offset`. /// Writes `src` to the memory starting at `ptr.offset`.
/// ///
/// It is the caller's responsibility to check bounds and alignment beforehand. /// 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( pub fn write_bytes(
&mut self, &mut self,
cx: &impl HasDataLayout, cx: &impl HasDataLayout,
ptr: Pointer<Tag>, ptr: Pointer<Tag>,
src: &[u8], src: impl IntoIterator<Item=u8, IntoIter: iter::ExactSizeIterator>,
) -> InterpResult<'tcx> ) -> InterpResult<'tcx>
{ {
let mut src = src.into_iter();
let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(src.len() as u64))?; let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(src.len() as u64))?;
bytes.clone_from_slice(src); // `zip` would stop when the first iterator ends; we want to definitely
Ok(()) // cover all of `bytes`.
} for dest in bytes {
*dest = src.next().expect("iterator was shorter than it said it would be");
/// 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<Tag>,
val: u8,
count: Size
) -> InterpResult<'tcx>
{
let bytes = self.get_bytes_mut(cx, ptr, count)?;
for b in bytes {
*b = val;
} }
src.next().expect_none("iterator was longer than it said it would be");
Ok(()) Ok(())
} }
@ -380,6 +375,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
/// pointers being valid for ZSTs. /// pointers being valid for ZSTs.
/// ///
/// It is the caller's responsibility to check bounds and alignment beforehand. /// 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( pub fn read_scalar(
&self, &self,
cx: &impl HasDataLayout, cx: &impl HasDataLayout,
@ -418,6 +414,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
/// Reads a pointer-sized scalar. /// Reads a pointer-sized scalar.
/// ///
/// It is the caller's responsibility to check bounds and alignment beforehand. /// 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( pub fn read_ptr_sized(
&self, &self,
cx: &impl HasDataLayout, cx: &impl HasDataLayout,
@ -435,6 +432,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
/// pointers being valid for ZSTs. /// pointers being valid for ZSTs.
/// ///
/// It is the caller's responsibility to check bounds and alignment beforehand. /// 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( pub fn write_scalar(
&mut self, &mut self,
cx: &impl HasDataLayout, cx: &impl HasDataLayout,
@ -477,6 +475,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
/// Writes a pointer-sized scalar. /// Writes a pointer-sized scalar.
/// ///
/// It is the caller's responsibility to check bounds and alignment beforehand. /// 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( pub fn write_ptr_sized(
&mut self, &mut self,
cx: &impl HasDataLayout, cx: &impl HasDataLayout,

View file

@ -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::{Ty, InferConst, ParamConst, layout::{HasDataLayout, Size}, subst::SubstsRef};
use crate::ty::PlaceholderConst; use crate::ty::PlaceholderConst;
use crate::hir::def_id::DefId; use crate::hir::def_id::DefId;
use crate::ty::{BoundVar, DebruijnIndex};
use super::{InterpResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate}; use super::{InterpResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate};
/// Represents the result of a raw const operation, pre-validation. /// 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> { pub struct RawConst<'tcx> {
// the value lives here, at offset 0, and that allocation definitely is a `AllocKind::Memory` // the value lives here, at offset 0, and that allocation definitely is a `AllocKind::Memory`
// (so you can use `AllocMap::unwrap_memory`). // (so you can use `AllocMap::unwrap_memory`).
@ -28,6 +29,9 @@ pub enum ConstValue<'tcx> {
/// Infer the value of the const. /// Infer the value of the const.
Infer(InferConst<'tcx>), Infer(InferConst<'tcx>),
/// Bound const variable, used only when preparing a trait query.
Bound(DebruijnIndex, BoundVar),
/// A placeholder const - universally quantified higher-ranked const. /// A placeholder const - universally quantified higher-ranked const.
Placeholder(PlaceholderConst), Placeholder(PlaceholderConst),
@ -66,8 +70,9 @@ impl<'tcx> ConstValue<'tcx> {
match *self { match *self {
ConstValue::Param(_) | ConstValue::Param(_) |
ConstValue::Infer(_) | ConstValue::Infer(_) |
ConstValue::Bound(..) |
ConstValue::Placeholder(_) | ConstValue::Placeholder(_) |
ConstValue::ByRef{ .. } | ConstValue::ByRef { .. } |
ConstValue::Unevaluated(..) | ConstValue::Unevaluated(..) |
ConstValue::Slice { .. } => None, ConstValue::Slice { .. } => None,
ConstValue::Scalar(val) => Some(val), ConstValue::Scalar(val) => Some(val),
@ -487,7 +492,7 @@ impl<Tag> From<Pointer<Tag>> for Scalar<Tag> {
} }
} }
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, RustcEncodable, RustcDecodable)] #[derive(Clone, Copy, Eq, PartialEq, RustcEncodable, RustcDecodable)]
pub enum ScalarMaybeUndef<Tag = (), Id = AllocId> { pub enum ScalarMaybeUndef<Tag = (), Id = AllocId> {
Scalar(Scalar<Tag, Id>), Scalar(Scalar<Tag, Id>),
Undef, Undef,

View file

@ -468,7 +468,7 @@ impl<T: Decodable> rustc_serialize::UseSpecializedDecodable for ClearCrossCrate<
/// Grouped information about the source code origin of a MIR entity. /// Grouped information about the source code origin of a MIR entity.
/// Intended to be inspected by diagnostics and debuginfo. /// Intended to be inspected by diagnostics and debuginfo.
/// Most passes can work with it as a whole, within a single function. /// 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 { pub struct SourceInfo {
/// The source span for the AST pertaining to this MIR entity. /// The source span for the AST pertaining to this MIR entity.
pub span: Span, pub span: Span,
@ -608,7 +608,7 @@ pub enum LocalKind {
ReturnPointer, ReturnPointer,
} }
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct VarBindingForm<'tcx> { pub struct VarBindingForm<'tcx> {
/// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`? /// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`?
pub binding_mode: ty::BindingMode, pub binding_mode: ty::BindingMode,
@ -630,7 +630,7 @@ pub struct VarBindingForm<'tcx> {
pub pat_span: Span, pub pat_span: Span,
} }
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum BindingForm<'tcx> { pub enum BindingForm<'tcx> {
/// This is a binding for a non-`self` binding, or a `self` that has an explicit type. /// This is a binding for a non-`self` binding, or a `self` that has an explicit type.
Var(VarBindingForm<'tcx>), Var(VarBindingForm<'tcx>),
@ -641,7 +641,7 @@ pub enum BindingForm<'tcx> {
} }
/// Represents what type of implicit self a function has, if any. /// 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 { pub enum ImplicitSelfKind {
/// Represents a `fn x(self);`. /// Represents a `fn x(self);`.
Imm, Imm,
@ -2392,7 +2392,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
/// this does not necessarily mean that they are "==" in Rust -- in /// this does not necessarily mean that they are "==" in Rust -- in
/// particular one must be wary of `NaN`! /// 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 struct Constant<'tcx> {
pub span: Span, pub span: Span,
@ -2438,7 +2438,7 @@ pub struct Constant<'tcx> {
/// The first will lead to the constraint `w: &'1 str` (for some /// The first will lead to the constraint `w: &'1 str` (for some
/// inferred region `'1`). The second will lead to the constraint `w: /// inferred region `'1`). The second will lead to the constraint `w:
/// &'static str`. /// &'static str`.
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
pub struct UserTypeProjections { pub struct UserTypeProjections {
pub(crate) contents: Vec<(UserTypeProjection, Span)>, pub(crate) contents: Vec<(UserTypeProjection, Span)>,
} }
@ -2515,7 +2515,7 @@ impl<'tcx> UserTypeProjections {
/// * `let (x, _): T = ...` -- here, the `projs` vector would contain /// * `let (x, _): T = ...` -- here, the `projs` vector would contain
/// `field[0]` (aka `.0`), indicating that the type of `s` is /// `field[0]` (aka `.0`), indicating that the type of `s` is
/// determined by finding the type of the `.0` field from `T`. /// 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 struct UserTypeProjection {
pub base: UserTypeAnnotationIndex, pub base: UserTypeAnnotationIndex,
pub projs: Vec<ProjectionKind>, pub projs: Vec<ProjectionKind>,
@ -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 { pub enum UnsafetyViolationKind {
General, General,
/// Permitted both in `const fn`s and regular `fn`s. /// Permitted both in `const fn`s and regular `fn`s.
@ -2733,7 +2733,7 @@ pub enum UnsafetyViolationKind {
BorrowPacked(hir::HirId), BorrowPacked(hir::HirId),
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
pub struct UnsafetyViolation { pub struct UnsafetyViolation {
pub source_info: SourceInfo, pub source_info: SourceInfo,
pub description: InternedString, pub description: InternedString,
@ -2741,7 +2741,7 @@ pub struct UnsafetyViolation {
pub kind: UnsafetyViolationKind, pub kind: UnsafetyViolationKind,
} }
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
pub struct UnsafetyCheckResult { pub struct UnsafetyCheckResult {
/// Violations that are propagated *upwards* from this function. /// Violations that are propagated *upwards* from this function.
pub violations: Lrc<[UnsafetyViolation]>, pub violations: Lrc<[UnsafetyViolation]>,

View file

@ -15,7 +15,7 @@ use std::fmt;
use std::hash::Hash; use std::hash::Hash;
/// Describes how a monomorphization will be instantiated in object files. /// Describes how a monomorphization will be instantiated in object files.
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)] #[derive(PartialEq)]
pub enum InstantiationMode { pub enum InstantiationMode {
/// There will be exactly one instance of the given MonoItem. It will have /// 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. /// external linkage so that it can be linked to from other codegen units.
@ -251,7 +251,7 @@ pub struct CodegenUnit<'tcx> {
size_estimate: Option<usize>, size_estimate: Option<usize>,
} }
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] #[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)]
pub enum Linkage { pub enum Linkage {
External, External,
AvailableExternally, AvailableExternally,
@ -280,7 +280,7 @@ impl_stable_hash_for!(enum self::Linkage {
Common Common
}); });
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[derive(Copy, Clone, PartialEq, Debug)]
pub enum Visibility { pub enum Visibility {
Default, Default,
Hidden, Hidden,

View file

@ -947,7 +947,7 @@ impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> {
/// Extra information passed to `visit_ty` and friends to give context /// Extra information passed to `visit_ty` and friends to give context
/// about where the type etc appears. /// about where the type etc appears.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Debug)]
pub enum TyContext { pub enum TyContext {
LocalDecl { LocalDecl {
/// The index of the local variable we are visiting. /// The index of the local variable we are visiting.

View file

@ -62,7 +62,7 @@ impl_stable_hash_via_hash!(OptLevel);
/// This is what the `LtoCli` values get mapped to after resolving defaults and /// This is what the `LtoCli` values get mapped to after resolving defaults and
/// and taking other command line options into account. /// and taking other command line options into account.
#[derive(Clone, Copy, PartialEq, Hash, Debug)] #[derive(Clone, PartialEq)]
pub enum Lto { pub enum Lto {
/// Don't do any LTO whatsoever /// Don't do any LTO whatsoever
No, No,
@ -296,10 +296,10 @@ impl OutputTypes {
/// Use tree-based collections to cheaply get a deterministic `Hash` implementation. /// Use tree-based collections to cheaply get a deterministic `Hash` implementation.
/// *Do not* switch `BTreeMap` or `BTreeSet` out for an unsorted container type! That /// *Do not* switch `BTreeMap` or `BTreeSet` out for an unsorted container type! That
/// would break dependency tracking for command-line arguments. /// would break dependency tracking for command-line arguments.
#[derive(Clone, Hash)] #[derive(Clone)]
pub struct Externs(BTreeMap<String, ExternEntry>); pub struct Externs(BTreeMap<String, ExternEntry>);
#[derive(Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct ExternEntry { pub struct ExternEntry {
pub locations: BTreeSet<Option<String>>, pub locations: BTreeSet<Option<String>>,
pub is_private_dep: bool pub is_private_dep: bool
@ -459,7 +459,7 @@ pub enum PrintRequest {
NativeStaticLibs, NativeStaticLibs,
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Copy, Clone)]
pub enum BorrowckMode { pub enum BorrowckMode {
Mir, Mir,
Migrate, Migrate,

View file

@ -1,5 +1,4 @@
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use rustc_macros::HashStable;
use crate::session::{early_error, config}; use crate::session::{early_error, config};
use crate::session::filesearch::make_target_lib_path; use crate::session::filesearch::make_target_lib_path;
@ -10,7 +9,7 @@ pub struct SearchPath {
pub files: Vec<PathBuf>, pub files: Vec<PathBuf>,
} }
#[derive(Eq, PartialEq, Clone, Copy, Debug, PartialOrd, Ord, Hash, HashStable)] #[derive(PartialEq, Clone, Copy, Debug, HashStable)]
pub enum PathKind { pub enum PathKind {
Native, Native,
Crate, Crate,

View file

@ -40,7 +40,7 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
pub type CanonicalTypeOpNormalizeGoal<'tcx, T> = pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::normalize::Normalize<T>>>; Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::normalize::Normalize<T>>>;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug)]
pub struct NoSolution; pub struct NoSolution;
pub type Fallible<T> = Result<T, NoSolution>; pub type Fallible<T> = Result<T, NoSolution>;

View file

@ -3,7 +3,7 @@ use crate::traits::query::outlives_bounds::OutlivesBound;
use crate::traits::query::Fallible; use crate::traits::query::Fallible;
use crate::ty::{ParamEnvAnd, Ty, TyCtxt}; use crate::ty::{ParamEnvAnd, Ty, TyCtxt};
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] #[derive(Clone, Debug)]
pub struct ImpliedOutlivesBounds<'tcx> { pub struct ImpliedOutlivesBounds<'tcx> {
pub ty: Ty<'tcx>, pub ty: Ty<'tcx>,
} }

View file

@ -2,7 +2,7 @@ use crate::hir::BindingAnnotation::*;
use crate::hir::BindingAnnotation; use crate::hir::BindingAnnotation;
use crate::hir::Mutability; use crate::hir::Mutability;
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
pub enum BindingMode { pub enum BindingMode {
BindByReference(Mutability), BindByReference(Mutability),
BindByValue(Mutability), BindByValue(Mutability),

View file

@ -827,7 +827,7 @@ rustc_index::newtype_index! {
pub type CanonicalUserTypeAnnotations<'tcx> = pub type CanonicalUserTypeAnnotations<'tcx> =
IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>; IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
pub struct CanonicalUserTypeAnnotation<'tcx> { pub struct CanonicalUserTypeAnnotation<'tcx> {
pub user_ty: CanonicalUserType<'tcx>, pub user_ty: CanonicalUserType<'tcx>,
pub span: Span, pub span: Span,
@ -882,7 +882,7 @@ impl CanonicalUserType<'tcx> {
}, },
GenericArgKind::Const(ct) => match ct.val { 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. // We only allow a `ty::INNERMOST` index in substitutions.
assert_eq!(debruijn, ty::INNERMOST); assert_eq!(debruijn, ty::INNERMOST);
cvar == b cvar == b
@ -899,7 +899,7 @@ impl CanonicalUserType<'tcx> {
/// A user-given type annotation attached to a constant. These arise /// A user-given type annotation attached to a constant. These arise
/// from constants that are named via paths, like `Foo::<A>::new` and /// from constants that are named via paths, like `Foo::<A>::new` and
/// so forth. /// so forth.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] #[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
pub enum UserType<'tcx> { pub enum UserType<'tcx> {
Ty(Ty<'tcx>), Ty(Ty<'tcx>),

View file

@ -51,7 +51,6 @@ pub enum TypeError<'tcx> {
IntrinsicCast, IntrinsicCast,
} }
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
pub enum UnconstrainedNumeric { pub enum UnconstrainedNumeric {
UnconstrainedFloat, UnconstrainedFloat,
UnconstrainedInt, UnconstrainedInt,

View file

@ -19,7 +19,7 @@ pub type SimplifiedType = SimplifiedTypeGen<DefId>;
/// the non-stable but fast to construct DefId-version is the better choice. /// the non-stable but fast to construct DefId-version is the better choice.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, RustcEncodable, RustcDecodable)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
pub enum SimplifiedTypeGen<D> pub enum SimplifiedTypeGen<D>
where D: Copy + Debug + Ord + Eq + Hash where D: Copy + Debug + Ord + Eq
{ {
BoolSimplifiedType, BoolSimplifiedType,
CharSimplifiedType, CharSimplifiedType,
@ -123,10 +123,10 @@ pub fn simplify_type(
} }
} }
impl<D: Copy + Debug + Ord + Eq + Hash> SimplifiedTypeGen<D> { impl<D: Copy + Debug + Ord + Eq> SimplifiedTypeGen<D> {
pub fn map_def<U, F>(self, map: F) -> SimplifiedTypeGen<U> pub fn map_def<U, F>(self, map: F) -> SimplifiedTypeGen<U>
where F: Fn(D) -> U, where F: Fn(D) -> U,
U: Copy + Debug + Ord + Eq + Hash, U: Copy + Debug + Ord + Eq,
{ {
match self { match self {
BoolSimplifiedType => BoolSimplifiedType, BoolSimplifiedType => BoolSimplifiedType,
@ -155,7 +155,7 @@ impl<D: Copy + Debug + Ord + Eq + Hash> SimplifiedTypeGen<D> {
impl<'a, D> HashStable<StableHashingContext<'a>> for SimplifiedTypeGen<D> impl<'a, D> HashStable<StableHashingContext<'a>> for SimplifiedTypeGen<D>
where where
D: Copy + Debug + Ord + Eq + Hash + HashStable<StableHashingContext<'a>>, D: Copy + Debug + Ord + Eq + HashStable<StableHashingContext<'a>>,
{ {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
mem::discriminant(self).hash_stable(hcx, hasher); mem::discriminant(self).hash_stable(hcx, hasher);

View file

@ -240,10 +240,10 @@ impl FlagComputation {
self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_CT_INFER); self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_CT_INFER);
match infer { match infer {
InferConst::Fresh(_) => {} InferConst::Fresh(_) => {}
InferConst::Canonical(debruijn, _) => self.add_binder(debruijn),
InferConst::Var(_) => self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX), InferConst::Var(_) => self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX),
} }
} }
ConstValue::Bound(debruijn, _) => self.add_binder(debruijn),
ConstValue::Param(_) => { ConstValue::Param(_) => {
self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_PARAMS); self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_PARAMS);
} }

View file

@ -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> { fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
if let ty::Const { if let ty::Const { val: ConstValue::Bound(debruijn, bound_const), ty } = *ct {
val: ConstValue::Infer(ty::InferConst::Canonical(debruijn, bound_const)),
ty,
} = *ct {
if debruijn == self.current_index { if debruijn == self.current_index {
let fld_c = &mut self.fld_c; let fld_c = &mut self.fld_c;
let ct = fld_c(bound_const, ty); let ct = fld_c(bound_const, ty);
@ -570,7 +567,10 @@ impl<'tcx> TyCtxt<'tcx> {
// identity for bound types and consts // identity for bound types and consts
let fld_t = |bound_ty| self.mk_ty(ty::Bound(ty::INNERMOST, bound_ty)); let fld_t = |bound_ty| self.mk_ty(ty::Bound(ty::INNERMOST, bound_ty));
let fld_c = |bound_ct, 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) 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 // vars. See comment on `shift_vars_through_binders` method in
// `subst.rs` for more details. // `subst.rs` for more details.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
enum Direction { enum Direction {
In, In,
Out, 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> { fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
if let ty::Const { if let ty::Const { val: ConstValue::Bound(debruijn, bound_ct), ty } = *ct {
val: ConstValue::Infer(ty::InferConst::Canonical(debruijn, bound_const)),
ty,
} = *ct {
if self.amount == 0 || debruijn < self.current_index { if self.amount == 0 || debruijn < self.current_index {
ct ct
} else { } else {
@ -816,7 +812,10 @@ impl TypeFolder<'tcx> for Shifter<'tcx> {
debruijn.shifted_out(self.amount) 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 { } else {
ct.super_fold_with(self) 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 // const, as it has types/regions embedded in a lot of other
// places. // places.
match ct.val { match ct.val {
ConstValue::Infer(ty::InferConst::Canonical(debruijn, _)) ConstValue::Bound(debruijn, _) if debruijn >= self.outer_index => true,
if debruijn >= self.outer_index => true,
_ => ct.super_visit_with(self), _ => ct.super_visit_with(self),
} }
} }

View file

@ -159,7 +159,7 @@ impl AssocItemContainer {
/// The "header" of an impl is everything outside the body: a Self type, a trait /// 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 /// ref (in the case of a trait impl), and a set of predicates (from the
/// bounds / where-clauses). /// bounds / where-clauses).
#[derive(Clone, PartialEq, Eq, Hash, Debug)] #[derive(Clone, Debug)]
pub struct ImplHeader<'tcx> { pub struct ImplHeader<'tcx> {
pub impl_def_id: DefId, pub impl_def_id: DefId,
pub self_ty: Ty<'tcx>, pub self_ty: Ty<'tcx>,
@ -195,7 +195,7 @@ pub struct AssocItem {
pub method_has_self_argument: bool, 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 { pub enum AssocKind {
Const, Const,
Method, 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 { pub enum Variance {
Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type
Invariant, // T<A> <: T<B> iff B == A -- e.g., type of mutable cell Invariant, // T<A> <: T<B> iff B == A -- e.g., type of mutable cell
@ -752,7 +752,7 @@ pub struct UpvarId {
pub closure_expr_id: LocalDefId, 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 { pub enum BorrowKind {
/// Data must be immutable and is aliasable. /// Data must be immutable and is aliasable.
ImmBorrow, ImmBorrow,

View file

@ -8,14 +8,12 @@ use crate::ty::subst::SubstsRef;
use crate::ty::fast_reject::SimplifiedType; use crate::ty::fast_reject::SimplifiedType;
use crate::mir; use crate::mir;
use std::fmt::Debug;
use std::hash::Hash;
use syntax_pos::{Span, DUMMY_SP}; use syntax_pos::{Span, DUMMY_SP};
use syntax_pos::symbol::InternedString; use syntax_pos::symbol::InternedString;
/// The `Key` trait controls what types can legally be used as the key /// The `Key` trait controls what types can legally be used as the key
/// for a query. /// 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? /// Given an instance of this key, what crate is it referring to?
/// This is used to find the provider. /// This is used to find the provider.
fn query_crate(&self) -> CrateNum; fn query_crate(&self) -> CrateNum;
@ -201,10 +199,7 @@ impl Key for InternedString {
/// Canonical query goals correspond to abstract trait operations that /// Canonical query goals correspond to abstract trait operations that
/// are not tied to any crate in particular. /// are not tied to any crate in particular.
impl<'tcx, T> Key for Canonical<'tcx, T> impl<'tcx, T> Key for Canonical<'tcx, T> {
where
T: Debug + Hash + Clone + Eq,
{
fn query_crate(&self) -> CrateNum { fn query_crate(&self) -> CrateNum {
LOCAL_CRATE LOCAL_CRATE
} }

View file

@ -801,7 +801,7 @@ macro_rules! define_queries_inner {
} }
#[allow(nonstandard_style)] #[allow(nonstandard_style)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy)]
pub enum QueryName { pub enum QueryName {
$($name),* $($name),*
} }
@ -819,7 +819,7 @@ macro_rules! define_queries_inner {
} }
#[allow(nonstandard_style)] #[allow(nonstandard_style)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug)]
pub enum Query<$tcx> { pub enum Query<$tcx> {
$($(#[$attr])* $name($K)),* $($(#[$attr])* $name($K)),*
} }

View file

@ -1379,27 +1379,23 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> {
impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> { impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self { fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
match *self { match *self {
ConstValue::ByRef { alloc, offset } =>
ConstValue::ByRef { alloc, offset },
ConstValue::Infer(ic) => ConstValue::Infer(ic.fold_with(folder)), ConstValue::Infer(ic) => ConstValue::Infer(ic.fold_with(folder)),
ConstValue::Param(p) => ConstValue::Param(p.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)
=> ConstValue::Unevaluated(did, substs.fold_with(folder)), => ConstValue::Unevaluated(did, substs.fold_with(folder)),
ConstValue::ByRef { .. } | ConstValue::Bound(..) | ConstValue::Placeholder(..)
| ConstValue::Scalar(..) | ConstValue::Slice { .. } => *self,
} }
} }
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool { fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
match *self { match *self {
ConstValue::ByRef { .. } => false,
ConstValue::Infer(ic) => ic.visit_with(visitor), ConstValue::Infer(ic) => ic.visit_with(visitor),
ConstValue::Param(p) => p.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::Unevaluated(_, substs) => substs.visit_with(visitor),
ConstValue::ByRef { .. } | ConstValue::Bound(..) | ConstValue::Placeholder(_)
| ConstValue::Scalar(_) | ConstValue::Slice { .. } => false,
} }
} }
} }

View file

@ -304,8 +304,7 @@ static_assert_size!(TyKind<'_>, 24);
/// type parameters is similar, but the role of CK and CS are /// type parameters is similar, but the role of CK and CS are
/// different. CK represents the "yield type" and CS represents the /// different. CK represents the "yield type" and CS represents the
/// "return type" of the generator. /// "return type" of the generator.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, #[derive(Copy, Clone, Debug)]
RustcEncodable, RustcDecodable, HashStable)]
pub struct ClosureSubsts<'tcx> { pub struct ClosureSubsts<'tcx> {
/// Lifetime and type parameters from the enclosing function, /// Lifetime and type parameters from the enclosing function,
/// concatenated with the types of the upvars. /// concatenated with the types of the upvars.
@ -392,8 +391,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
} }
/// Similar to `ClosureSubsts`; see the above documentation for more. /// Similar to `ClosureSubsts`; see the above documentation for more.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, #[derive(Copy, Clone, Debug)]
RustcEncodable, RustcDecodable, HashStable)]
pub struct GeneratorSubsts<'tcx> { pub struct GeneratorSubsts<'tcx> {
pub substs: SubstsRef<'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 struct GenSig<'tcx> {
pub yield_ty: Ty<'tcx>, pub yield_ty: Ty<'tcx>,
pub return_ty: Ty<'tcx>, pub return_ty: Ty<'tcx>,
@ -2373,6 +2371,4 @@ pub enum InferConst<'tcx> {
Var(ConstVid<'tcx>), Var(ConstVid<'tcx>),
/// A fresh const variable. See `infer::freshen` for more details. /// A fresh const variable. See `infer::freshen` for more details.
Fresh(u32), Fresh(u32),
/// Canonicalized const variable, used only when preparing a trait query.
Canonical(DebruijnIndex, BoundVar),
} }

View file

@ -2,7 +2,7 @@
use crate::hir::def_id::DefId; use crate::hir::def_id::DefId;
use crate::infer::canonical::Canonical; 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::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use crate::mir::interpret::ConstValue; use crate::mir::interpret::ConstValue;
use crate::ty::sty::{ClosureSubsts, GeneratorSubsts}; use crate::ty::sty::{ClosureSubsts, GeneratorSubsts};
@ -234,9 +234,7 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
ty::GenericParamDefKind::Const => { ty::GenericParamDefKind::Const => {
tcx.mk_const(ty::Const { tcx.mk_const(ty::Const {
val: ConstValue::Infer( val: ConstValue::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)),
InferConst::Canonical(ty::INNERMOST, ty::BoundVar::from(param.index))
),
ty: tcx.type_of(def_id), ty: tcx.type_of(def_id),
}).into() }).into()
} }

View file

@ -818,6 +818,8 @@ impl<'tcx> ty::TyS<'tcx> {
/// ///
/// (Note that this implies that if `ty` has a destructor attached, /// (Note that this implies that if `ty` has a destructor attached,
/// then `needs_drop` will definitely return `true` for `ty`.) /// then `needs_drop` will definitely return `true` for `ty`.)
///
/// Note that this method is used to check eligible types in unions.
#[inline] #[inline]
pub fn needs_drop(&'tcx self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { pub fn needs_drop(&'tcx self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
tcx.needs_drop_raw(param_env.and(self)).0 tcx.needs_drop_raw(param_env.and(self)).0

View file

@ -50,7 +50,7 @@ pub enum CallConv {
} }
/// LLVMRustLinkage /// LLVMRustLinkage
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[derive(PartialEq)]
#[repr(C)] #[repr(C)]
pub enum Linkage { pub enum Linkage {
ExternalLinkage = 0, ExternalLinkage = 0,
@ -67,7 +67,6 @@ pub enum Linkage {
} }
// LLVMRustVisibility // LLVMRustVisibility
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
#[repr(C)] #[repr(C)]
pub enum Visibility { pub enum Visibility {
Default = 0, Default = 0,

View file

@ -79,6 +79,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
ConstValue::Unevaluated(..) => bug!("unevaluated constant in `OperandRef::from_const`"), ConstValue::Unevaluated(..) => bug!("unevaluated constant in `OperandRef::from_const`"),
ConstValue::Param(_) => bug!("encountered a ConstValue::Param in codegen"), ConstValue::Param(_) => bug!("encountered a ConstValue::Param in codegen"),
ConstValue::Infer(_) => bug!("encountered a ConstValue::Infer 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::Placeholder(_) => bug!("encountered a ConstValue::Placeholder in codegen"),
ConstValue::Scalar(x) => { ConstValue::Scalar(x) => {
let scalar = match layout.abi { let scalar = match layout.abi {

View file

@ -60,10 +60,10 @@ impl<N> SnapshotVecDelegate for Edge<N> {
fn reverse(_: &mut Vec<Edge<N>>, _: ()) {} fn reverse(_: &mut Vec<Edge<N>>, _: ()) {}
} }
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] #[derive(Copy, Clone, PartialEq, Debug)]
pub struct NodeIndex(pub usize); pub struct NodeIndex(pub usize);
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] #[derive(Copy, Clone, PartialEq, Debug)]
pub struct EdgeIndex(pub usize); pub struct EdgeIndex(pub usize);
pub const INVALID_EDGE_INDEX: EdgeIndex = EdgeIndex(usize::MAX); pub const INVALID_EDGE_INDEX: EdgeIndex = EdgeIndex(usize::MAX);

View file

@ -90,7 +90,7 @@ impl<T> Sharded<T> {
pub type ShardedHashMap<K, V> = Sharded<FxHashMap<K, V>>; pub type ShardedHashMap<K, V> = Sharded<FxHashMap<K, V>>;
impl<K: Eq + Hash, V> ShardedHashMap<K, V> { impl<K: Eq, V> ShardedHashMap<K, V> {
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.lock_shards().iter().map(|shard| shard.len()).sum() self.lock_shards().iter().map(|shard| shard.len()).sum()
} }

View file

@ -7,7 +7,7 @@ use std::mem;
mod tests; mod tests;
pub struct SnapshotMap<K, V> pub struct SnapshotMap<K, V>
where K: Hash + Clone + Eq where K: Clone + Eq
{ {
map: FxHashMap<K, V>, map: FxHashMap<K, V>,
undo_log: Vec<UndoLog<K, V>>, undo_log: Vec<UndoLog<K, V>>,

View file

@ -169,7 +169,7 @@ pub trait HashStable<CTX> {
/// example, for DefId that can be converted to a DefPathHash. This is used for /// example, for DefId that can be converted to a DefPathHash. This is used for
/// bringing maps into a predictable order before hashing them. /// bringing maps into a predictable order before hashing them.
pub trait ToStableHashKey<HCX> { pub trait ToStableHashKey<HCX> {
type KeyType: Ord + Clone + Sized + HashStable<HCX>; type KeyType: Ord + Sized + HashStable<HCX>;
fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType; 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_stable_hash_via_hash!(::std::path::PathBuf);
impl<K, V, R, HCX> HashStable<HCX> for ::std::collections::HashMap<K, V, R> impl<K, V, R, HCX> HashStable<HCX> for ::std::collections::HashMap<K, V, R>
where K: ToStableHashKey<HCX> + Eq + Hash, where K: ToStableHashKey<HCX> + Eq,
V: HashStable<HCX>, V: HashStable<HCX>,
R: BuildHasher, R: BuildHasher,
{ {
@ -471,7 +471,7 @@ impl<K, V, R, HCX> HashStable<HCX> for ::std::collections::HashMap<K, V, R>
} }
impl<K, R, HCX> HashStable<HCX> for ::std::collections::HashSet<K, R> impl<K, R, HCX> HashStable<HCX> for ::std::collections::HashSet<K, R>
where K: ToStableHashKey<HCX> + Eq + Hash, where K: ToStableHashKey<HCX> + Eq,
R: BuildHasher, R: BuildHasher,
{ {
fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
@ -513,10 +513,10 @@ pub fn hash_stable_hashmap<HCX, K, V, R, SK, F>(
hasher: &mut StableHasher, hasher: &mut StableHasher,
map: &::std::collections::HashMap<K, V, R>, map: &::std::collections::HashMap<K, V, R>,
to_stable_hash_key: F) to_stable_hash_key: F)
where K: Eq + Hash, where K: Eq,
V: HashStable<HCX>, V: HashStable<HCX>,
R: BuildHasher, R: BuildHasher,
SK: HashStable<HCX> + Ord + Clone, SK: HashStable<HCX> + Ord,
F: Fn(&K, &HCX) -> SK, F: Fn(&K, &HCX) -> SK,
{ {
let mut entries: Vec<_> = map.iter() let mut entries: Vec<_> = map.iter()

View file

@ -738,7 +738,7 @@ impl<T: Clone> Clone for RwLock<T> {
/// A type which only allows its inner value to be used in one thread. /// A type which only allows its inner value to be used in one thread.
/// It will panic if it is used on multiple threads. /// It will panic if it is used on multiple threads.
#[derive(Copy, Clone, Hash, Debug, Eq, PartialEq)] #[derive(Debug)]
pub struct OneThread<T> { pub struct OneThread<T> {
#[cfg(parallel_compiler)] #[cfg(parallel_compiler)]
thread: thread::ThreadId, thread: thread::ThreadId,

View file

@ -3,7 +3,7 @@ use crate::stable_hasher::{StableHasher, HashStable};
/// A vector type optimized for cases where this size is usually 0 (cf. `SmallVector`). /// A vector type optimized for cases where this size is usually 0 (cf. `SmallVector`).
/// The `Option<Box<..>>` wrapping allows us to represent a zero sized vector with `None`, /// The `Option<Box<..>>` wrapping allows us to represent a zero sized vector with `None`,
/// which uses only a single (null) pointer. /// which uses only a single (null) pointer.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct ThinVec<T>(Option<Box<Vec<T>>>); pub struct ThinVec<T>(Option<Box<Vec<T>>>);
impl<T> ThinVec<T> { impl<T> ThinVec<T> {

View file

@ -14,7 +14,7 @@
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
#[derive(Clone, Hash, Debug, PartialEq)] #[derive(Clone)]
pub struct TinyList<T: PartialEq> { pub struct TinyList<T: PartialEq> {
head: Option<Element<T>> head: Option<Element<T>>
} }
@ -80,7 +80,7 @@ impl<T: PartialEq> TinyList<T> {
} }
} }
#[derive(Clone, Hash, Debug, PartialEq)] #[derive(Clone)]
struct Element<T: PartialEq> { struct Element<T: PartialEq> {
data: T, data: T,
next: Option<Box<Element<T>>>, next: Option<Box<Element<T>>>,

View file

@ -11,7 +11,7 @@ use std::mem;
mod tests; mod tests;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct TransitiveRelation<T: Clone + Debug + Eq + Hash> { pub struct TransitiveRelation<T: Eq + Hash> {
// List of elements. This is used to map from a T to a usize. // List of elements. This is used to map from a T to a usize.
elements: Vec<T>, elements: Vec<T>,
@ -35,7 +35,7 @@ pub struct TransitiveRelation<T: Clone + Debug + Eq + Hash> {
} }
// HACK(eddyb) manual impl avoids `Default` bound on `T`. // HACK(eddyb) manual impl avoids `Default` bound on `T`.
impl<T: Clone + Debug + Eq + Hash> Default for TransitiveRelation<T> { impl<T: Eq + Hash> Default for TransitiveRelation<T> {
fn default() -> Self { fn default() -> Self {
TransitiveRelation { TransitiveRelation {
elements: Default::default(), elements: Default::default(),
@ -46,7 +46,7 @@ impl<T: Clone + Debug + Eq + Hash> Default for TransitiveRelation<T> {
} }
} }
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, RustcEncodable, RustcDecodable, Debug)]
struct Index(usize); struct Index(usize);
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]

View file

@ -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! { declare_lint! {
pub UNREACHABLE_PUB, pub UNREACHABLE_PUB,
Allow, Allow,
@ -1288,7 +1259,6 @@ declare_lint_pass!(
NO_MANGLE_GENERIC_ITEMS, NO_MANGLE_GENERIC_ITEMS,
MUTABLE_TRANSMUTES, MUTABLE_TRANSMUTES,
UNSTABLE_FEATURES, UNSTABLE_FEATURES,
UNIONS_WITH_DROP_FIELDS,
UNREACHABLE_PUB, UNREACHABLE_PUB,
TYPE_ALIAS_BOUNDS, TYPE_ALIAS_BOUNDS,
TRIVIAL_BOUNDS TRIVIAL_BOUNDS

View file

@ -164,9 +164,6 @@ macro_rules! late_lint_mod_passes {
// Depends on referenced function signatures in expressions // Depends on referenced function signatures in expressions
MutableTransmutes: MutableTransmutes, MutableTransmutes: MutableTransmutes,
// Depends on types of fields, checks if they implement Drop
UnionsWithDropFields: UnionsWithDropFields,
TypeAliasBounds: TypeAliasBounds, TypeAliasBounds: TypeAliasBounds,
TrivialConstraints: TrivialConstraints, TrivialConstraints: TrivialConstraints,

View file

@ -71,7 +71,7 @@ impl Index<OutlivesConstraintIndex> for OutlivesConstraintSet {
} }
} }
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct OutlivesConstraint { pub struct OutlivesConstraint {
// NB. The ordering here is not significant for correctness, but // NB. The ordering here is not significant for correctness, but
// it is for convenience. Before we dump the constraints in the // it is for convenience. Before we dump the constraints in the

View file

@ -11,7 +11,7 @@ use syntax_pos::Span;
/// indexed by the region `R0`. /// indexed by the region `R0`.
crate struct MemberConstraintSet<'tcx, R> crate struct MemberConstraintSet<'tcx, R>
where where
R: Copy + Hash + Eq, R: Copy + Eq,
{ {
/// Stores the first "member" constraint for a given `R0`. This is an /// Stores the first "member" constraint for a given `R0`. This is an
/// index into the `constraints` vector below. /// index into the `constraints` vector below.
@ -191,7 +191,7 @@ where
impl<'tcx, R> Index<NllMemberConstraintIndex> for MemberConstraintSet<'tcx, R> impl<'tcx, R> Index<NllMemberConstraintIndex> for MemberConstraintSet<'tcx, R>
where where
R: Copy + Hash + Eq, R: Copy + Eq,
{ {
type Output = NllMemberConstraint<'tcx>; type Output = NllMemberConstraint<'tcx>;

View file

@ -129,7 +129,7 @@ rustc_index::newtype_index! {
/// An individual element in a region value -- the value of a /// An individual element in a region value -- the value of a
/// particular region variable consists of a set of these elements. /// particular region variable consists of a set of these elements.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Debug)]
crate enum RegionElement { crate enum RegionElement {
/// A point in the control-flow graph. /// A point in the control-flow graph.
Location(Location), Location(Location),

View file

@ -146,7 +146,7 @@ struct UniversalRegionIndices<'tcx> {
indices: FxHashMap<ty::Region<'tcx>, RegionVid>, indices: FxHashMap<ty::Region<'tcx>, RegionVid>,
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq)]
pub enum RegionClassification { pub enum RegionClassification {
/// A **global** region is one that can be named from /// A **global** region is one that can be named from
/// anywhere. There is only one, `'static`. /// anywhere. There is only one, `'static`.

View file

@ -91,7 +91,7 @@ pub struct Frame<'mir, 'tcx, Tag=(), Extra=()> {
pub extra: Extra, pub extra: Extra,
} }
#[derive(Clone, Debug, Eq, PartialEq, Hash)] #[derive(Clone, Eq, PartialEq)]
pub enum StackPopCleanup { pub enum StackPopCleanup {
/// Jump to the next block in the caller, or cause UB if None (that's a function /// 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 /// 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 /// Current value of a local variable
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[derive(Clone, PartialEq, Eq)]
pub enum LocalValue<Tag=(), Id=AllocId> { pub enum LocalValue<Tag=(), Id=AllocId> {
/// This local is not currently alive, and cannot be used at all. /// This local is not currently alive, and cannot be used at all.
Dead, Dead,

View file

@ -7,7 +7,7 @@
//! short-circuiting the empty case! //! short-circuiting the empty case!
use std::collections::VecDeque; use std::collections::VecDeque;
use std::ptr; use std::{ptr, iter};
use std::borrow::Cow; use std::borrow::Cow;
use rustc::ty::{self, Instance, ParamEnv, query::TyCtxtAt}; use rustc::ty::{self, Instance, ParamEnv, query::TyCtxtAt};
@ -22,7 +22,7 @@ use super::{
Machine, AllocMap, MayLeak, ErrorHandled, CheckInAllocMsg, Machine, AllocMap, MayLeak, ErrorHandled, CheckInAllocMsg,
}; };
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] #[derive(Debug, PartialEq, Copy, Clone)]
pub enum MemoryKind<T> { pub enum MemoryKind<T> {
/// Error if deallocated except during a stack pop /// Error if deallocated except during a stack pop
Stack, 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) 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<M::PointerTag>,
src: impl IntoIterator<Item=u8, IntoIter: iter::ExactSizeIterator>,
) -> 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. /// Expects the caller to have checked bounds and alignment.
pub fn copy( pub fn copy(
&mut self, &mut self,

View file

@ -26,7 +26,7 @@ pub use rustc::mir::interpret::ScalarMaybeUndef;
/// operations and fat pointers. This idea was taken from rustc's codegen. /// operations and fat pointers. This idea was taken from rustc's codegen.
/// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely /// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely
/// defined on `Immediate`, and do not have to work with a `Place`. /// 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<Tag=(), Id=AllocId> { pub enum Immediate<Tag=(), Id=AllocId> {
Scalar(ScalarMaybeUndef<Tag, Id>), Scalar(ScalarMaybeUndef<Tag, Id>),
ScalarPair(ScalarMaybeUndef<Tag, Id>, ScalarMaybeUndef<Tag, Id>), ScalarPair(ScalarMaybeUndef<Tag, Id>, ScalarMaybeUndef<Tag, Id>),
@ -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, /// 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 /// 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. /// 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<Tag=(), Id=AllocId> { pub enum Operand<Tag=(), Id=AllocId> {
Immediate(Immediate<Tag, Id>), Immediate(Immediate<Tag, Id>),
Indirect(MemPlace<Tag, Id>), Indirect(MemPlace<Tag, Id>),
@ -153,7 +153,7 @@ impl<Tag> Operand<Tag> {
} }
} }
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq)]
pub struct OpTy<'tcx, Tag=()> { pub struct OpTy<'tcx, Tag=()> {
op: Operand<Tag>, // Keep this private, it helps enforce invariants op: Operand<Tag>, // Keep this private, it helps enforce invariants
pub layout: TyLayout<'tcx>, 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)); let ptr = self.tag_static_base_pointer(Pointer::new(id, offset));
Operand::Indirect(MemPlace::from_ptr(ptr, layout.align.abi)) Operand::Indirect(MemPlace::from_ptr(ptr, layout.align.abi))
}, },
ConstValue::Scalar(x) => ConstValue::Scalar(x) => Operand::Immediate(tag_scalar(x).into()),
Operand::Immediate(tag_scalar(x).into()),
ConstValue::Slice { data, start, end } => { ConstValue::Slice { data, start, end } => {
// We rely on mutability being set correctly in `data` to prevent writes // We rely on mutability being set correctly in `data` to prevent writes
// where none should happen. // where none should happen.
@ -606,6 +605,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} }
ConstValue::Param(..) | ConstValue::Param(..) |
ConstValue::Infer(..) | ConstValue::Infer(..) |
ConstValue::Bound(..) |
ConstValue::Placeholder(..) | ConstValue::Placeholder(..) |
ConstValue::Unevaluated(..) => ConstValue::Unevaluated(..) =>
bug!("eval_const_to_op: Unexpected ConstValue {:?}", val), bug!("eval_const_to_op: Unexpected ConstValue {:?}", val),

View file

@ -199,7 +199,7 @@ use rustc_data_structures::sync::{MTRef, MTLock, ParallelIterator, par_iter};
use std::iter; use std::iter;
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)] #[derive(PartialEq)]
pub enum MonoItemCollectionMode { pub enum MonoItemCollectionMode {
Eager, Eager,
Lazy Lazy

View file

@ -71,8 +71,7 @@ mod riscv_base;
mod wasm32_base; mod wasm32_base;
mod vxworks_base; mod vxworks_base;
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash, #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
RustcEncodable, RustcDecodable)]
pub enum LinkerFlavor { pub enum LinkerFlavor {
Em, Em,
Gcc, Gcc,
@ -82,8 +81,7 @@ pub enum LinkerFlavor {
PtxLinker, PtxLinker,
} }
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash, #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
RustcEncodable, RustcDecodable)]
pub enum LldFlavor { pub enum LldFlavor {
Wasm, Wasm,
Ld64, Ld64,

View file

@ -33,7 +33,7 @@ use rustc::traits::{
InEnvironment, InEnvironment,
ChalkCanonicalGoal, ChalkCanonicalGoal,
}; };
use rustc::ty::{self, TyCtxt, InferConst}; use rustc::ty::{self, TyCtxt};
use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use rustc::ty::query::Providers; use rustc::ty::query::Providers;
use rustc::ty::subst::{GenericArg, GenericArgKind}; use rustc::ty::subst::{GenericArg, GenericArgKind};
@ -286,7 +286,7 @@ impl context::ContextOps<ChalkArenas<'tcx>> for ChalkContext<'tcx> {
_ => false, _ => false,
}, },
GenericArgKind::Const(ct) => match ct.val { GenericArgKind::Const(ct) => match ct.val {
ConstValue::Infer(InferConst::Canonical(debruijn, bound_ct)) => { ConstValue::Bound(debruijn, bound_ct) => {
debug_assert_eq!(debruijn, ty::INNERMOST); debug_assert_eq!(debruijn, ty::INNERMOST);
cvar == bound_ct cvar == bound_ct
} }

View file

@ -16,7 +16,7 @@ use rustc::traits::{
Environment, Environment,
InEnvironment, InEnvironment,
}; };
use rustc::ty::{self, Ty, TyCtxt, InferConst}; use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::subst::GenericArg; use rustc::ty::subst::GenericArg;
use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc::ty::relate::{Relate, RelateResult, TypeRelation};
use rustc::mir::interpret::ConstValue; use rustc::mir::interpret::ConstValue;
@ -287,10 +287,7 @@ impl TypeRelation<'tcx> for AnswerSubstitutor<'cx, 'tcx> {
a: &'tcx ty::Const<'tcx>, a: &'tcx ty::Const<'tcx>,
b: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>,
) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
if let ty::Const { if let ty::Const { val: ConstValue::Bound(debruijn, bound_ct), .. } = a {
val: ConstValue::Infer(InferConst::Canonical(debruijn, bound_ct)),
..
} = a {
if *debruijn == self.binder_index { if *debruijn == self.binder_index {
self.unify_free_answer_var(*bound_ct, b.into())?; self.unify_free_answer_var(*bound_ct, b.into())?;
return Ok(b); return Ok(b);
@ -299,14 +296,8 @@ impl TypeRelation<'tcx> for AnswerSubstitutor<'cx, 'tcx> {
match (a, b) { match (a, b) {
( (
ty::Const { ty::Const { val: ConstValue::Bound(a_debruijn, a_bound), .. },
val: ConstValue::Infer(InferConst::Canonical(a_debruijn, a_bound)), ty::Const { val: ConstValue::Bound(b_debruijn, b_bound), .. },
..
},
ty::Const {
val: ConstValue::Infer(InferConst::Canonical(b_debruijn, b_bound)),
..
},
) => { ) => {
assert_eq!(a_debruijn, b_debruijn); assert_eq!(a_debruijn, b_debruijn);
assert_eq!(a_bound, b_bound); assert_eq!(a_bound, b_bound);

View file

@ -1387,9 +1387,37 @@ fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) {
def.destructor(tcx); // force the destructor to be evaluated def.destructor(tcx); // force the destructor to be evaluated
check_representable(tcx, span, def_id); check_representable(tcx, span, def_id);
check_transparent(tcx, span, def_id); check_transparent(tcx, span, def_id);
check_union_fields(tcx, span, def_id);
check_packed(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` /// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
/// projections that would result in "inheriting lifetimes". /// projections that would result in "inheriting lifetimes".
fn check_opaque<'tcx>( fn check_opaque<'tcx>(

View file

@ -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##" E0733: r##"
Recursion in an `async fn` requires boxing. For example, this will not compile: Recursion in an `async fn` requires boxing. For example, this will not compile:

View file

@ -1307,7 +1307,7 @@ impl Clean<Option<Lifetime>> for ty::RegionKind {
} }
} }
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(Clone, Debug)]
pub enum WherePredicate { pub enum WherePredicate {
BoundPredicate { ty: Type, bounds: Vec<GenericBound> }, BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> }, RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
@ -1589,7 +1589,7 @@ impl Clean<GenericParamDef> for hir::GenericParam {
} }
// maybe use a Generic enum and use Vec<Generic>? // maybe use a Generic enum and use Vec<Generic>?
#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)] #[derive(Clone, Debug, Default)]
pub struct Generics { pub struct Generics {
pub params: Vec<GenericParamDef>, pub params: Vec<GenericParamDef>,
pub where_predicates: Vec<WherePredicate>, pub where_predicates: Vec<WherePredicate>,
@ -3847,7 +3847,7 @@ impl Clean<Mutability> for hir::Mutability {
} }
} }
#[derive(Clone, PartialEq, Eq, Copy, Debug, Hash)] #[derive(Clone, PartialEq, Debug)]
pub enum ImplPolarity { pub enum ImplPolarity {
Positive, Positive,
Negative, Negative,
@ -4506,7 +4506,6 @@ struct RegionDeps<'tcx> {
smaller: FxHashSet<RegionTarget<'tcx>> smaller: FxHashSet<RegionTarget<'tcx>>
} }
#[derive(Eq, PartialEq, Hash, Debug)]
enum SimpleBound { enum SimpleBound {
TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier), TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier),
Outlives(Lifetime), Outlives(Lifetime),

View file

@ -143,7 +143,7 @@ impl<T> Decodable for BTreeSet<T>
} }
impl<K, V, S> Encodable for HashMap<K, V, S> impl<K, V, S> Encodable for HashMap<K, V, S>
where K: Encodable + Hash + Eq, where K: Encodable + Eq,
V: Encodable, V: Encodable,
S: BuildHasher, S: BuildHasher,
{ {
@ -180,7 +180,7 @@ impl<K, V, S> Decodable for HashMap<K, V, S>
} }
impl<T, S> Encodable for HashSet<T, S> impl<T, S> Encodable for HashSet<T, S>
where T: Encodable + Hash + Eq, where T: Encodable + Eq,
S: BuildHasher, S: BuildHasher,
{ {
fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> { fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {

View file

@ -275,6 +275,7 @@
#![feature(link_args)] #![feature(link_args)]
#![feature(linkage)] #![feature(linkage)]
#![feature(log_syntax)] #![feature(log_syntax)]
#![feature(manually_drop_take)]
#![feature(maybe_uninit_ref)] #![feature(maybe_uninit_ref)]
#![feature(maybe_uninit_slice)] #![feature(maybe_uninit_slice)]
#![feature(needs_panic_runtime)] #![feature(needs_panic_runtime)]

View file

@ -264,7 +264,7 @@ impl RefUnwindSafe for atomic::AtomicI128 {}
#[cfg(target_has_atomic_load_store = "ptr")] #[cfg(target_has_atomic_load_store = "ptr")]
#[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
impl RefUnwindSafe for atomic::AtomicUsize {} 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")] #[unstable(feature = "integer_atomics", issue = "32976")]
impl RefUnwindSafe for atomic::AtomicU8 {} impl RefUnwindSafe for atomic::AtomicU8 {}
#[cfg(target_has_atomic_load_store = "16")] #[cfg(target_has_atomic_load_store = "16")]

View file

@ -12,8 +12,7 @@ use core::panic::{BoxMeUp, PanicInfo, Location};
use crate::any::Any; use crate::any::Any;
use crate::fmt; use crate::fmt;
use crate::intrinsics; use crate::intrinsics;
use crate::mem; use crate::mem::{self, ManuallyDrop};
use crate::ptr;
use crate::raw; use crate::raw;
use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sync::atomic::{AtomicBool, Ordering};
use crate::sys::stdio::panic_output; 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. /// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> { pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
#[allow(unions_with_drop_fields)]
union Data<F, R> { union Data<F, R> {
f: F, f: ManuallyDrop<F>,
r: R, r: ManuallyDrop<R>,
} }
// We do some sketchy operations with ownership here for the sake of // We do some sketchy operations with ownership here for the sake of
@ -261,7 +259,7 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
let mut any_data = 0; let mut any_data = 0;
let mut any_vtable = 0; let mut any_vtable = 0;
let mut data = Data { let mut data = Data {
f, f: ManuallyDrop::new(f)
}; };
let r = __rust_maybe_catch_panic(do_call::<F, R>, let r = __rust_maybe_catch_panic(do_call::<F, R>,
@ -271,7 +269,7 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
return if r == 0 { return if r == 0 {
debug_assert!(update_panic_count(0) == 0); debug_assert!(update_panic_count(0) == 0);
Ok(data.r) Ok(ManuallyDrop::into_inner(data.r))
} else { } else {
update_panic_count(-1); update_panic_count(-1);
debug_assert!(update_panic_count(0) == 0); debug_assert!(update_panic_count(0) == 0);
@ -284,8 +282,9 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
fn do_call<F: FnOnce() -> R, R>(data: *mut u8) { fn do_call<F: FnOnce() -> R, R>(data: *mut u8) {
unsafe { unsafe {
let data = data as *mut Data<F, R>; let data = data as *mut Data<F, R>;
let f = ptr::read(&mut (*data).f); let data = &mut (*data);
ptr::write(&mut (*data).r, f()); let f = ManuallyDrop::take(&mut data.f);
data.r = ManuallyDrop::new(f());
} }
} }
} }

View file

@ -1305,7 +1305,7 @@ impl MacroDef {
} }
} }
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq)] #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)]
pub enum StrStyle { pub enum StrStyle {
/// A regular string, like `"foo"`. /// A regular string, like `"foo"`.
Cooked, Cooked,
@ -1327,7 +1327,7 @@ pub struct Lit {
pub span: Span, pub span: Span,
} }
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq)] #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)]
pub enum LitIntType { pub enum LitIntType {
Signed(IntTy), Signed(IntTy),
Unsigned(UintTy), Unsigned(UintTy),
@ -1337,7 +1337,7 @@ pub enum LitIntType {
/// Literal kind. /// Literal kind.
/// ///
/// E.g., `"foo"`, `42`, `12.34`, or `bool`. /// E.g., `"foo"`, `42`, `12.34`, or `bool`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)] #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub enum LitKind { pub enum LitKind {
/// A string literal (`"foo"`). /// A string literal (`"foo"`).
Str(Symbol, StrStyle), Str(Symbol, StrStyle),

View file

@ -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 { pub enum InlineAttr {
None, None,
Hint, Hint,
@ -92,7 +92,7 @@ pub enum InlineAttr {
Never, Never,
} }
#[derive(Copy, Clone, Hash, PartialEq, RustcEncodable, RustcDecodable)] #[derive(Clone, RustcEncodable, RustcDecodable)]
pub enum OptimizeAttr { pub enum OptimizeAttr {
None, None,
Speed, Speed,
@ -624,8 +624,7 @@ pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F)
} }
} }
#[derive(RustcEncodable, RustcDecodable, Clone)]
#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
pub struct Deprecation { pub struct Deprecation {
pub since: Option<Symbol>, pub since: Option<Symbol>,
pub note: Option<Symbol>, pub note: Option<Symbol>,
@ -749,7 +748,7 @@ pub enum ReprAttr {
ReprAlign(u32), ReprAlign(u32),
} }
#[derive(Eq, Hash, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)] #[derive(Eq, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
pub enum IntType { pub enum IntType {
SignedInt(ast::IntTy), SignedInt(ast::IntTy),
UnsignedInt(ast::UintTy) UnsignedInt(ast::UintTy)

View file

@ -35,7 +35,6 @@ use rustc_serialize::{Encodable, Decodable, Encoder, Decoder};
use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
/// An owned smart pointer. /// An owned smart pointer.
#[derive(Hash, PartialEq, Eq)]
pub struct P<T: ?Sized> { pub struct P<T: ?Sized> {
ptr: Box<T> ptr: Box<T>
} }

View file

@ -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<T> { pub struct Spanned<T> {
pub node: T, pub node: T,
pub span: Span, pub span: Span,

View file

@ -73,7 +73,7 @@ impl KleeneToken {
/// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star) /// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star)
/// for token sequences. /// for token sequences.
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
enum KleeneOp { enum KleeneOp {
/// Kleene star (`*`) for zero or more repetitions /// Kleene star (`*`) for zero or more repetitions
ZeroOrMore, ZeroOrMore,

View file

@ -1311,7 +1311,7 @@ pub struct BytePos(pub u32);
/// A character offset. Because of multibyte UTF-8 characters, a byte offset /// A character offset. Because of multibyte UTF-8 characters, a byte offset
/// is not equivalent to a character offset. The `SourceMap` will convert `BytePos` /// is not equivalent to a character offset. The `SourceMap` will convert `BytePos`
/// values to `CharPos` values as necessary. /// 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); pub struct CharPos(pub usize);
// FIXME: lots of boilerplate in these impls, but so far my attempts to fix // FIXME: lots of boilerplate in these impls, but so far my attempts to fix

View file

@ -3,13 +3,13 @@
#![feature(associated_type_bounds)] #![feature(associated_type_bounds)]
#![feature(untagged_unions)] #![feature(untagged_unions)]
#![allow(unions_with_drop_fields, unused_assignments)] #![allow(unused_assignments)]
trait Tr1 { type As1; } trait Tr1: Copy { type As1: Copy; }
trait Tr2 { type As2; } trait Tr2: Copy { type As2: Copy; }
trait Tr3 { type As3; } trait Tr3: Copy { type As3: Copy; }
trait Tr4<'a> { type As4; } trait Tr4<'a>: Copy { type As4: Copy; }
trait Tr5 { type As5; } trait Tr5: Copy { type As5: Copy; }
impl Tr1 for &str { type As1 = bool; } impl Tr1 for &str { type As1 = bool; }
impl Tr2 for bool { type As2 = u8; } impl Tr2 for bool { type As2 = u8; }
@ -71,7 +71,8 @@ where
let _: &'a T = &x.f0; let _: &'a T = &x.f0;
} }
union UnSelf<T> where Self: Tr1<As1: Tr2> { #[derive(Copy, Clone)]
union UnSelf<T> where Self: Tr1<As1: Tr2>, T: Copy {
f0: T, f0: T,
f1: <Self as Tr1>::As1, f1: <Self as Tr1>::As1,
f2: <<Self as Tr1>::As1 as Tr2>::As2, f2: <<Self as Tr1>::As1 as Tr2>::As2,

View file

@ -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);
}

View file

@ -8,6 +8,7 @@
#![feature(slice_patterns)] #![feature(slice_patterns)]
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::mem::ManuallyDrop;
use std::ops::Generator; use std::ops::Generator;
use std::panic; use std::panic;
use std::pin::Pin; use std::pin::Pin;
@ -152,17 +153,16 @@ fn assignment1(a: &Allocator, c0: bool) {
_v = _w; _v = _w;
} }
#[allow(unions_with_drop_fields)]
union Boxy<T> { union Boxy<T> {
a: T, a: ManuallyDrop<T>,
b: T, b: ManuallyDrop<T>,
} }
fn union1(a: &Allocator) { fn union1(a: &Allocator) {
unsafe { unsafe {
let mut u = Boxy { a: a.alloc() }; let mut u = Boxy { a: ManuallyDrop::new(a.alloc()) };
u.b = a.alloc(); *u.b = a.alloc(); // drops first alloc
drop(u.a); drop(ManuallyDrop::into_inner(u.a));
} }
} }

View file

@ -1,7 +1,7 @@
#![feature(untagged_unions)] #![feature(untagged_unions)]
trait Tr1 { type As1; } trait Tr1 { type As1: Copy; }
trait Tr2 { type As2; } trait Tr2 { type As2: Copy; }
struct S1; struct S1;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -32,7 +32,7 @@ enum _En1<T: Tr1<As1: Tr2>> {
union _Un1<T: Tr1<As1: Tr2>> { union _Un1<T: Tr1<As1: Tr2>> {
//~^ ERROR associated type bounds are unstable //~^ ERROR associated type bounds are unstable
outest: T, outest: std::mem::ManuallyDrop<T>,
outer: T::As1, outer: T::As1,
inner: <T::As1 as Tr2>::As2, inner: <T::As1 as Tr2>::As2,
} }

View file

@ -7,11 +7,11 @@ union U2<T: Copy> { // OK
} }
union U3 { //~ ERROR unions with non-`Copy` fields are unstable 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<T> { //~ ERROR unions with non-`Copy` fields are unstable union U4<T> { //~ 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 union U5 { //~ ERROR unions with `Drop` implementations are unstable

View file

@ -31,6 +31,31 @@ LL | | }
= note: for more information, see https://github.com/rust-lang/rust/issues/32836 = note: for more information, see https://github.com/rust-lang/rust/issues/32836
= help: add `#![feature(untagged_unions)]` to the crate attributes to enable = 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,
| ^^^^^^^^^
For more information about this error, try `rustc --explain E0658`. 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
Some errors have detailed explanations: E0658, E0740.
For more information about an error, try `rustc --explain E0658`.

View file

@ -1,13 +1,12 @@
#![feature(rustc_attrs)] #![feature(rustc_attrs)]
#![feature(untagged_unions)] #![feature(untagged_unions)]
#![allow(unions_with_drop_fields)]
#[rustc_outlives] #[rustc_outlives]
union Foo<'b, U> { //~ ERROR rustc_outlives union Foo<'b, U: Copy> { //~ ERROR rustc_outlives
bar: Bar<'b, U> bar: Bar<'b, U>
} }
union Bar<'a, T> where T: 'a { union Bar<'a, T: Copy> where T: 'a {
x: &'a (), x: &'a (),
y: T, y: T,
} }

View file

@ -1,7 +1,7 @@
error: rustc_outlives 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 | | bar: Bar<'b, U>
LL | | } LL | | }
| |_^ | |_^

View file

@ -1,14 +1,13 @@
#![feature(rustc_attrs)] #![feature(rustc_attrs)]
#![feature(untagged_unions)] #![feature(untagged_unions)]
#![allow(unions_with_drop_fields)]
#[rustc_outlives] #[rustc_outlives]
union Foo<'a, T> { //~ ERROR rustc_outlives union Foo<'a, T: Copy> { //~ ERROR rustc_outlives
field1: Bar<'a, T> field1: Bar<'a, T>
} }
// Type U needs to outlive lifetime 'b // Type U needs to outlive lifetime 'b
union Bar<'b, U> { union Bar<'b, U: Copy> {
field2: &'b U field2: &'b U
} }

View file

@ -1,7 +1,7 @@
error: rustc_outlives 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 | | field1: Bar<'a, T>
LL | | } LL | | }
| |_^ | |_^

View file

@ -3,7 +3,8 @@
#![feature(untagged_unions)] #![feature(untagged_unions)]
#![allow(dead_code)] #![allow(dead_code)]
#![allow(unions_with_drop_fields)]
use std::mem::ManuallyDrop;
enum A<'a, T: 'a> enum A<'a, T: 'a>
where where
@ -24,6 +25,14 @@ where
union C<'a, T: 'a> union C<'a, T: 'a>
where where
Self: Send, T: PartialEq<Self> Self: Send, T: PartialEq<Self>
{
foo: &'a Self,
bar: ManuallyDrop<T>,
}
union D<'a, T: 'a>
where
Self: Send, T: PartialEq<Self> + Copy
{ {
foo: &'a Self, foo: &'a Self,
bar: T, bar: T,

View file

@ -46,13 +46,13 @@ error: def-path(bar::<impl foo::Foo>::baz)
LL | #[rustc_def_path] 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 --> $DIR/impl1.rs:61:13
| |
LL | #[rustc_symbol_name] 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 --> $DIR/impl1.rs:61:13
| |
LL | #[rustc_symbol_name] LL | #[rustc_symbol_name]

View file

@ -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); }
}

View file

@ -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`.

View file

@ -1,51 +1,90 @@
#![feature(untagged_unions)] #![feature(untagged_unions)]
#![allow(unused)] #![allow(unused)]
#[allow(unions_with_drop_fields)] use std::ops::{Deref, DerefMut};
#[derive(Default)]
struct MockBox<T> {
value: [T; 1],
}
impl<T> MockBox<T> {
fn new(value: T) -> Self { MockBox { value: [value] } }
}
impl<T> Deref for MockBox<T> {
type Target = T;
fn deref(&self) -> &T { &self.value[0] }
}
impl<T> DerefMut for MockBox<T> {
fn deref_mut(&mut self) -> &mut T { &mut self.value[0] }
}
#[derive(Default)]
struct MockVec<T> {
value: [T; 0],
}
impl<T> MockVec<T> {
fn new() -> Self { MockVec { value: [] } }
}
impl<T> Deref for MockVec<T> {
type Target = [T];
fn deref(&self) -> &[T] { &self.value }
}
impl<T> DerefMut for MockVec<T> {
fn deref_mut(&mut self) -> &mut [T] { &mut self.value }
}
union U { union U {
x: ((Vec<u8>, Vec<u8>), Vec<u8>), x: ((MockVec<u8>, MockVec<u8>), MockVec<u8>),
y: Box<Vec<u8>>, y: MockBox<MockVec<u8>>,
} }
fn use_borrow<T>(_: &T) {} fn use_borrow<T>(_: &T) {}
unsafe fn parent_sibling_borrow() { 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 a = &mut u.x.0;
let b = &u.y; //~ ERROR cannot borrow `u` (via `u.y`) let b = &u.y; //~ ERROR cannot borrow `u` (via `u.y`)
use_borrow(a); use_borrow(a);
} }
unsafe fn parent_sibling_move() { 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 a = u.x.0;
let b = u.y; //~ ERROR use of moved value: `u` let b = u.y; //~ ERROR use of moved value: `u`
} }
unsafe fn grandparent_sibling_borrow() { 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 a = &mut (u.x.0).0;
let b = &u.y; //~ ERROR cannot borrow `u` (via `u.y`) let b = &u.y; //~ ERROR cannot borrow `u` (via `u.y`)
use_borrow(a); use_borrow(a);
} }
unsafe fn grandparent_sibling_move() { 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 a = (u.x.0).0;
let b = u.y; //~ ERROR use of moved value: `u` let b = u.y; //~ ERROR use of moved value: `u`
} }
unsafe fn deref_sibling_borrow() { 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 a = &mut *u.y;
let b = &u.x; //~ ERROR cannot borrow `u` (via `u.x`) let b = &u.x; //~ ERROR cannot borrow `u` (via `u.x`)
use_borrow(a); use_borrow(a);
} }
unsafe fn deref_sibling_move() { unsafe fn deref_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.y; // No way to test deref-move without Box in union
let b = u.x; //~ ERROR use of moved value: `u` // let a = *u.y;
// let b = u.x; ERROR use of moved value: `u`
} }

View file

@ -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`) 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; LL | let a = &mut u.x.0;
| ---------- mutable borrow occurs here (via `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` = 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` 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 | - move occurs because `u` has type `U`, which does not implement the `Copy` trait
LL | let a = u.x.0; LL | let a = u.x.0;
| ----- value moved here | ----- value moved here
@ -21,7 +21,7 @@ LL | let b = u.y;
| ^^^ value used here after move | ^^^ 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`) 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; LL | let a = &mut (u.x.0).0;
| -------------- mutable borrow occurs here (via `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` = 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` 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 | - move occurs because `u` has type `U`, which does not implement the `Copy` trait
LL | let a = (u.x.0).0; LL | let a = (u.x.0).0;
| --------- value moved here | --------- value moved here
LL | let b = u.y; LL | let b = u.y;
| ^^^ value used here after move | ^^^ 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`) 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 --> $DIR/union-borrow-move-parent-sibling.rs:79:13
| |
LL | let a = &mut *u.y; 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; 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); LL | use_borrow(a);
| - mutable borrow later used here | - 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` error: aborting due to 5 previous errors
--> $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
Some errors have detailed explanations: E0382, E0502. Some errors have detailed explanations: E0382, E0502.
For more information about an error, try `rustc --explain E0382`. For more information about an error, try `rustc --explain E0382`.

View file

@ -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() {}

View file

@ -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`.

View file

@ -1,5 +1,7 @@
#![feature(untagged_unions)] #![feature(untagged_unions)]
use std::mem::ManuallyDrop;
#[derive(Clone)] //~ ERROR the trait bound `U1: std::marker::Copy` is not satisfied #[derive(Clone)] //~ ERROR the trait bound `U1: std::marker::Copy` is not satisfied
union U1 { union U1 {
a: u8, a: u8,
@ -18,14 +20,19 @@ union U3 {
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
union U4<T> { union U4<T: Copy> {
a: T, // OK a: T, // OK
} }
#[derive(Clone, Copy)]
union U5<T> {
a: ManuallyDrop<T>, // OK
}
#[derive(Clone)] #[derive(Clone)]
struct CloneNoCopy; struct CloneNoCopy;
fn main() { fn main() {
let u = U4 { a: CloneNoCopy }; let u = U5 { a: ManuallyDrop::new(CloneNoCopy) };
let w = u.clone(); //~ ERROR no method named `clone` found for type `U4<CloneNoCopy>` let w = u.clone(); //~ ERROR no method named `clone` found for type `U5<CloneNoCopy>`
} }

View file

@ -1,22 +1,22 @@
error[E0277]: the trait bound `U1: std::marker::Copy` is not satisfied 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)] LL | #[derive(Clone)]
| ^^^^^ the trait `std::marker::Copy` is not implemented for `U1` | ^^^^^ the trait `std::marker::Copy` is not implemented for `U1`
| |
= note: required by `std::clone::AssertParamIsCopy` = note: required by `std::clone::AssertParamIsCopy`
error[E0599]: no method named `clone` found for type `U4<CloneNoCopy>` in the current scope error[E0599]: no method named `clone` found for type `U5<CloneNoCopy>` in the current scope
--> $DIR/union-derive-clone.rs:30:15 --> $DIR/union-derive-clone.rs:37:15
| |
LL | union U4<T> { LL | union U5<T> {
| ----------- method `clone` not found for this | ----------- method `clone` not found for this
... ...
LL | let w = u.clone(); LL | let w = u.clone();
| ^^^^^ method not found in `U4<CloneNoCopy>` | ^^^^^ method not found in `U5<CloneNoCopy>`
| |
= note: the method `clone` exists but the following trait bounds were not satisfied: = note: the method `clone` exists but the following trait bounds were not satisfied:
`U4<CloneNoCopy> : std::clone::Clone` `U5<CloneNoCopy> : std::clone::Clone`
= help: items from traits can only be used if the trait is implemented and in scope = 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: = note: the following trait defines an item `clone`, perhaps you need to implement it:
candidate #1: `std::clone::Clone` candidate #1: `std::clone::Clone`

View file

@ -1,7 +1,6 @@
// run-pass // run-pass
#![allow(dead_code)] #![allow(dead_code)]
#![allow(unused_variables)] #![allow(unused_variables)]
#![allow(unions_with_drop_fields)]
// Some traits can be derived for unions. // Some traits can be derived for unions.
@ -24,11 +23,11 @@ impl PartialEq for U { fn eq(&self, rhs: &Self) -> bool { true } }
Copy, Copy,
Eq Eq
)] )]
union W<T> { union W<T: Copy> {
a: T, a: T,
} }
impl<T> PartialEq for W<T> { fn eq(&self, rhs: &Self) -> bool { true } } impl<T: Copy> PartialEq for W<T> { fn eq(&self, rhs: &Self) -> bool { true } }
fn main() { fn main() {
let u = U { b: 0 }; let u = U { b: 0 };

Some files were not shown because too many files have changed in this diff Show more