diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs index cc36ea7f713..30067d7e163 100644 --- a/src/libcore/nonzero.rs +++ b/src/libcore/nonzero.rs @@ -14,7 +14,8 @@ use ops::CoerceUnsized; /// A wrapper type for raw pointers and integers that will never be /// NULL or 0 that might allow certain optimizations. -#[lang = "non_zero"] +#[cfg_attr(stage0, lang = "non_zero")] +#[cfg_attr(not(stage0), rustc_layout_scalar_valid_range_start(1))] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(transparent)] pub(crate) struct NonZero(pub(crate) T); diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index 420ffbcfee6..cd91b85689b 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -16,25 +16,53 @@ use std::fmt; use std::u32; newtype_index! { - pub struct CrateNum { + pub struct CrateId { ENCODABLE = custom - DEBUG_FORMAT = "crate{}", + } +} - /// Item definitions in the currently-compiled crate would have the CrateNum - /// LOCAL_CRATE in their DefId. - const LOCAL_CRATE = 0, +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum CrateNum { + /// Virtual crate for builtin macros + // FIXME(jseyfried): this is also used for custom derives until proc-macro crates get + // `CrateNum`s. + BuiltinMacros, + /// A CrateNum value that indicates that something is wrong. + Invalid, + /// A special CrateNum that we use for the tcx.rcache when decoding from + /// the incr. comp. cache. + ReservedForIncrCompCache, + Index(CrateId), +} - /// Virtual crate for builtin macros - // FIXME(jseyfried): this is also used for custom derives until proc-macro crates get - // `CrateNum`s. - const BUILTIN_MACROS_CRATE = CrateNum::MAX_AS_U32, +impl ::std::fmt::Debug for CrateNum { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + CrateNum::Index(id) => write!(fmt, "crate{}", id.private), + CrateNum::Invalid => write!(fmt, "invalid crate"), + CrateNum::BuiltinMacros => write!(fmt, "bultin macros crate"), + CrateNum::ReservedForIncrCompCache => write!(fmt, "crate for decoding incr comp cache"), + } + } +} - /// A CrateNum value that indicates that something is wrong. - const INVALID_CRATE = CrateNum::MAX_AS_U32 - 1, +/// Item definitions in the currently-compiled crate would have the CrateNum +/// LOCAL_CRATE in their DefId. +pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32_const(0)); - /// A special CrateNum that we use for the tcx.rcache when decoding from - /// the incr. comp. cache. - const RESERVED_FOR_INCR_COMP_CACHE = CrateNum::MAX_AS_U32 - 2, + +impl Idx for CrateNum { + #[inline] + fn new(value: usize) -> Self { + CrateNum::Index(Idx::new(value)) + } + + #[inline] + fn index(self) -> usize { + match self { + CrateNum::Index(idx) => Idx::index(idx), + _ => bug!("Tried to get crate index of {:?}", self), + } } } @@ -43,12 +71,39 @@ impl CrateNum { CrateNum::from_usize(x) } + pub fn from_usize(x: usize) -> CrateNum { + CrateNum::Index(CrateId::from_usize(x)) + } + + pub fn from_u32(x: u32) -> CrateNum { + CrateNum::Index(CrateId::from_u32(x)) + } + + pub fn as_usize(self) -> usize { + match self { + CrateNum::Index(id) => id.as_usize(), + _ => bug!("tried to get index of nonstandard crate {:?}", self), + } + } + + pub fn as_u32(self) -> u32 { + match self { + CrateNum::Index(id) => id.as_u32(), + _ => bug!("tried to get index of nonstandard crate {:?}", self), + } + } + pub fn as_def_id(&self) -> DefId { DefId { krate: *self, index: CRATE_DEF_INDEX } } } impl fmt::Display for CrateNum { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&self.as_u32(), f) + match self { + CrateNum::Index(id) => fmt::Display::fmt(&id.private, f), + CrateNum::Invalid => write!(f, "invalid crate"), + CrateNum::BuiltinMacros => write!(f, "bultin macros crate"), + CrateNum::ReservedForIncrCompCache => write!(f, "crate for decoding incr comp cache"), + } } } diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 16175e159dd..2bf1c79c8a4 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -772,7 +772,15 @@ impl_stable_hash_for!(enum ty::cast::CastKind { FnPtrAddrCast }); -impl_stable_hash_for!(struct ::middle::region::Scope { id, code }); +impl_stable_hash_for!(struct ::middle::region::Scope { id, data }); + +impl_stable_hash_for!(enum ::middle::region::ScopeData { + Node, + CallSite, + Arguments, + Destruction, + Remainder(first_statement_index) +}); impl<'a> ToStableHashKey> for region::Scope { type KeyType = region::Scope; @@ -783,11 +791,6 @@ impl<'a> ToStableHashKey> for region::Scope { } } -impl_stable_hash_for!(struct ::middle::region::BlockRemainder { - block, - first_statement_index -}); - impl_stable_hash_for!(struct ty::adjustment::CoerceUnsizedInfo { custom_kind }); diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index eabcf1ce413..a0c96554c91 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -119,17 +119,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } }; let scope_decorated_tag = match scope.data() { - region::ScopeData::Node(_) => tag, - region::ScopeData::CallSite(_) => "scope of call-site for function", - region::ScopeData::Arguments(_) => "scope of function body", - region::ScopeData::Destruction(_) => { + region::ScopeData::Node => tag, + region::ScopeData::CallSite => "scope of call-site for function", + region::ScopeData::Arguments => "scope of function body", + region::ScopeData::Destruction => { new_string = format!("destruction scope surrounding {}", tag); &new_string[..] } - region::ScopeData::Remainder(r) => { + region::ScopeData::Remainder(first_statement_index) => { new_string = format!( "block suffix following statement {}", - r.first_statement_index.index() + first_statement_index.index() ); &new_string[..] } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 56096a5d423..c017c90b895 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -58,6 +58,8 @@ #![feature(optin_builtin_traits)] #![feature(refcell_replace_swap)] #![feature(rustc_diagnostic_macros)] +#![feature(rustc_attrs)] +#![cfg_attr(stage0, feature(attr_literals))] #![feature(slice_patterns)] #![feature(slice_sort_by_cached_key)] #![feature(specialization)] diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index d92f856fa4d..bfde4e4a3ae 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -326,8 +326,6 @@ language_item_table! { PhantomDataItem, "phantom_data", phantom_data; - NonZeroItem, "non_zero", non_zero; - ManuallyDropItem, "manually_drop", manually_drop; DebugTraitLangItem, "debug_trait", debug_trait; diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index f6a8f8dc172..2f99743cfbd 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -20,8 +20,8 @@ use ich::{StableHashingContext, NodeIdHashingMode}; use util::nodemap::{FxHashMap, FxHashSet}; use ty; -use std::fmt; use std::mem; +use std::fmt; use rustc_data_structures::sync::Lrc; use syntax::source_map; use syntax::ast; @@ -51,7 +51,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, /// `DestructionScope`, but those that are `terminating_scopes` do; /// see discussion with `ScopeTree`. /// -/// `Remainder(BlockRemainder { block, statement_index })` represents +/// `Remainder { block, statement_index }` represents /// the scope of user code running immediately after the initializer /// expression for the indexed statement, until the end of the block. /// @@ -100,39 +100,46 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, /// placate the same deriving in `ty::FreeRegion`, but we may want to /// actually attach a more meaningful ordering to scopes than the one /// generated via deriving here. -/// -/// Scope is a bit-packed to save space - if `code` is SCOPE_DATA_REMAINDER_MAX -/// or less, it is a `ScopeData::Remainder`, otherwise it is a type specified -/// by the bitpacking. #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy, RustcEncodable, RustcDecodable)] pub struct Scope { pub(crate) id: hir::ItemLocalId, - pub(crate) code: u32 + pub(crate) data: ScopeData, } -const SCOPE_DATA_NODE: u32 = !0; -const SCOPE_DATA_CALLSITE: u32 = !1; -const SCOPE_DATA_ARGUMENTS: u32 = !2; -const SCOPE_DATA_DESTRUCTION: u32 = !3; -const SCOPE_DATA_REMAINDER_MAX: u32 = !4; +impl fmt::Debug for Scope { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match self.data { + ScopeData::Node => write!(fmt, "Node({:?})", self.id), + ScopeData::CallSite => write!(fmt, "CallSite({:?})", self.id), + ScopeData::Arguments => write!(fmt, "Arguments({:?})", self.id), + ScopeData::Destruction => write!(fmt, "Destruction({:?})", self.id), + ScopeData::Remainder(fsi) => write!( + fmt, + "Remainder {{ block: {:?}, first_statement_index: {}}}", + self.id, + fsi.as_u32(), + ), + } + } +} #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)] pub enum ScopeData { - Node(hir::ItemLocalId), + Node, // Scope of the call-site for a function or closure // (outlives the arguments as well as the body). - CallSite(hir::ItemLocalId), + CallSite, // Scope of arguments passed to a function or closure // (they outlive its body). - Arguments(hir::ItemLocalId), + Arguments, // Scope of destructors for temporaries of node-id. - Destruction(hir::ItemLocalId), + Destruction, // Scope following a `let id = expr;` binding in a block. - Remainder(BlockRemainder) + Remainder(FirstStatementIndex) } /// Represents a subscope of `block` for a binding that is introduced @@ -152,83 +159,61 @@ pub enum ScopeData { /// /// * the subscope with `first_statement_index == 1` is scope of `c`, /// and thus does not include EXPR_2, but covers the `...`. -#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, - RustcDecodable, Debug, Copy)] -pub struct BlockRemainder { - pub block: hir::ItemLocalId, - pub first_statement_index: FirstStatementIndex, -} newtype_index! { - pub struct FirstStatementIndex { - MAX = SCOPE_DATA_REMAINDER_MAX - } + pub struct FirstStatementIndex { .. } } impl_stable_hash_for!(struct ::middle::region::FirstStatementIndex { private }); -impl From for Scope { - #[inline] - fn from(scope_data: ScopeData) -> Self { - let (id, code) = match scope_data { - ScopeData::Node(id) => (id, SCOPE_DATA_NODE), - ScopeData::CallSite(id) => (id, SCOPE_DATA_CALLSITE), - ScopeData::Arguments(id) => (id, SCOPE_DATA_ARGUMENTS), - ScopeData::Destruction(id) => (id, SCOPE_DATA_DESTRUCTION), - ScopeData::Remainder(r) => (r.block, r.first_statement_index.index() as u32) - }; - Self { id, code } - } -} - -impl fmt::Debug for Scope { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&self.data(), formatter) - } -} +// compilation error if size of `ScopeData` is not the same as a `u32` +#[allow(dead_code)] +// only works on stage 1 when the rustc_layout_scalar_valid_range attribute actually exists +#[cfg(not(stage0))] +static ASSERT: () = [()][!(mem::size_of::() == 4) as usize]; #[allow(non_snake_case)] impl Scope { #[inline] pub fn data(self) -> ScopeData { - match self.code { - SCOPE_DATA_NODE => ScopeData::Node(self.id), - SCOPE_DATA_CALLSITE => ScopeData::CallSite(self.id), - SCOPE_DATA_ARGUMENTS => ScopeData::Arguments(self.id), - SCOPE_DATA_DESTRUCTION => ScopeData::Destruction(self.id), - idx => ScopeData::Remainder(BlockRemainder { - block: self.id, - first_statement_index: FirstStatementIndex::new(idx as usize) - }) - } + self.data + } + + #[inline] + pub fn new(id: hir::ItemLocalId, data: ScopeData) -> Self { + Scope { id, data } } #[inline] pub fn Node(id: hir::ItemLocalId) -> Self { - Self::from(ScopeData::Node(id)) + Self::new(id, ScopeData::Node) } #[inline] pub fn CallSite(id: hir::ItemLocalId) -> Self { - Self::from(ScopeData::CallSite(id)) + Self::new(id, ScopeData::CallSite) } #[inline] pub fn Arguments(id: hir::ItemLocalId) -> Self { - Self::from(ScopeData::Arguments(id)) + Self::new(id, ScopeData::Arguments) } #[inline] pub fn Destruction(id: hir::ItemLocalId) -> Self { - Self::from(ScopeData::Destruction(id)) + Self::new(id, ScopeData::Destruction) } #[inline] - pub fn Remainder(r: BlockRemainder) -> Self { - Self::from(ScopeData::Remainder(r)) + pub fn Remainder( + id: hir::ItemLocalId, + first: FirstStatementIndex, + ) -> Self { + Self::new(id, ScopeData::Remainder(first)) } } + impl Scope { /// Returns a item-local id associated with this scope. /// @@ -259,7 +244,7 @@ impl Scope { return DUMMY_SP; } let span = tcx.hir.span(node_id); - if let ScopeData::Remainder(r) = self.data() { + if let ScopeData::Remainder(first_statement_index) = self.data() { if let Node::Block(ref blk) = tcx.hir.get(node_id) { // Want span for scope starting after the // indexed statement and ending at end of @@ -269,7 +254,7 @@ impl Scope { // (This is the special case aluded to in the // doc-comment for this method) - let stmt_span = blk.stmts[r.first_statement_index.index()].span; + let stmt_span = blk.stmts[first_statement_index.index()].span; // To avoid issues with macro-generated spans, the span // of the statement must be nested in that of the block. @@ -513,8 +498,8 @@ impl<'tcx> ScopeTree { } // record the destruction scopes for later so we can query them - if let ScopeData::Destruction(n) = child.data() { - self.destruction_scopes.insert(n, child); + if let ScopeData::Destruction = child.data() { + self.destruction_scopes.insert(child.item_local_id(), child); } } @@ -597,7 +582,7 @@ impl<'tcx> ScopeTree { while let Some(&(p, _)) = self.parent_map.get(&id) { match p.data() { - ScopeData::Destruction(..) => { + ScopeData::Destruction => { debug!("temporary_scope({:?}) = {:?} [enclosing]", expr_id, id); return Some(id); @@ -652,8 +637,8 @@ impl<'tcx> ScopeTree { /// Returns the id of the innermost containing body pub fn containing_body(&self, mut scope: Scope)-> Option { loop { - if let ScopeData::CallSite(id) = scope.data() { - return Some(id); + if let ScopeData::CallSite = scope.data() { + return Some(scope.item_local_id()); } match self.opt_encl_scope(scope) { @@ -869,10 +854,7 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk: // except for the first such subscope, which has the // block itself as a parent. visitor.enter_scope( - Scope::Remainder(BlockRemainder { - block: blk.hir_id.local_id, - first_statement_index: FirstStatementIndex::new(i) - }) + Scope::Remainder(blk.hir_id.local_id, FirstStatementIndex::new(i)) ); visitor.cx.var_parent = visitor.cx.parent; } @@ -1035,7 +1017,7 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: match visitor.scope_tree.parent_map.get(&scope) { // Don't cross from closure bodies to their parent. Some(&(superscope, _)) => match superscope.data() { - ScopeData::CallSite(_) => break, + ScopeData::CallSite => break, _ => scope = superscope }, None => break diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 6cc648b572c..d1f37250379 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -66,7 +66,7 @@ use std::collections::hash_map::{self, Entry}; use std::hash::{Hash, Hasher}; use std::fmt; use std::mem; -use std::ops::Deref; +use std::ops::{Deref, Bound}; use std::iter; use std::sync::mpsc; use std::sync::Arc; @@ -829,10 +829,12 @@ impl<'a, 'gcx> HashStable> for TypeckTables<'gcx> { impl<'tcx> CommonTypes<'tcx> { fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> { // Ensure our type representation does not grow - #[cfg(target_pointer_width = "64")] - assert!(mem::size_of::() <= 24); - #[cfg(target_pointer_width = "64")] - assert!(mem::size_of::() <= 32); + #[cfg(all(not(stage0), target_pointer_width = "64"))] + #[allow(dead_code)] + static ASSERT_TY_KIND: () = [()][!(::std::mem::size_of::() <= 24) as usize]; + #[cfg(all(not(stage0), target_pointer_width = "64"))] + #[allow(dead_code)] + static ASSERT_TYS: () = [()][!(::std::mem::size_of::() <= 32) as usize]; let mk = |sty| CtxtInterners::intern_ty(interners, interners, sty); let mk_region = |r| { @@ -1083,6 +1085,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { interned } + /// Returns a range of the start/end indices specified with the + /// `rustc_layout_scalar_valid_range` attribute. + pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound, Bound) { + let attrs = self.get_attrs(def_id); + let get = |name| { + let attr = match attrs.iter().find(|a| a.check_name(name)) { + Some(attr) => attr, + None => return Bound::Unbounded, + }; + for meta in attr.meta_item_list().expect("rustc_layout_scalar_valid_range takes args") { + match meta.literal().expect("attribute takes lit").node { + ast::LitKind::Int(a, _) => return Bound::Included(a), + _ => span_bug!(attr.span, "rustc_layout_scalar_valid_range expects int arg"), + } + } + span_bug!(attr.span, "no arguments to `rustc_layout_scalar_valid_range` attribute"); + }; + (get("rustc_layout_scalar_valid_range_start"), get("rustc_layout_scalar_valid_range_end")) + } + pub fn lift>(self, value: &T) -> Option { value.lift_to_tcx(self) } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index a3316c2b8e2..4e37a34a0c8 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -20,6 +20,7 @@ use std::fmt; use std::i128; use std::iter; use std::mem; +use std::ops::Bound; use ich::StableHashingContext; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, @@ -761,17 +762,29 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let mut st = univariant_uninterned(&variants[v], &def.repr, kind)?; st.variants = Variants::Single { index: v }; - // Exclude 0 from the range of a newtype ABI NonZero. - if Some(def.did) == self.tcx.lang_items().non_zero() { - match st.abi { - Abi::Scalar(ref mut scalar) | - Abi::ScalarPair(ref mut scalar, _) => { - if *scalar.valid_range.start() == 0 { - scalar.valid_range = 1..=*scalar.valid_range.end(); - } + let (start, end) = self.tcx.layout_scalar_valid_range(def.did); + match st.abi { + Abi::Scalar(ref mut scalar) | + Abi::ScalarPair(ref mut scalar, _) => { + // the asserts ensure that we are not using the + // `#[rustc_layout_scalar_valid_range(n)]` + // attribute to widen the range of anything as that would probably + // result in UB somewhere + if let Bound::Included(start) = start { + assert!(*scalar.valid_range.start() <= start); + scalar.valid_range = start..=*scalar.valid_range.end(); + } + if let Bound::Included(end) = end { + assert!(*scalar.valid_range.end() >= end); + scalar.valid_range = *scalar.valid_range.start()..=end; } - _ => {} } + _ => assert!( + start == Bound::Unbounded && end == Bound::Unbounded, + "nonscalar layout for layout_scalar_valid_range type {:?}: {:#?}", + def, + st, + ), } return Ok(tcx.intern_layout(st)); } @@ -1350,8 +1363,12 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> { if def.variants.len() == 1 { if let Some(SizeSkeleton::Pointer { non_zero, tail }) = v0 { return Ok(SizeSkeleton::Pointer { - non_zero: non_zero || - Some(def.did) == tcx.lang_items().non_zero(), + non_zero: non_zero || match tcx.layout_scalar_valid_range(def.did) { + (Bound::Included(start), Bound::Unbounded) => start > 0, + (Bound::Included(start), Bound::Included(end)) => + 0 < start && start < end, + _ => false, + }, tail, }); } else { diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 19e235154cb..0e4d2f1f647 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -11,8 +11,7 @@ use dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; use errors::Diagnostic; use hir; -use hir::def_id::{CrateNum, DefIndex, DefId, LocalDefId, - RESERVED_FOR_INCR_COMP_CACHE, LOCAL_CRATE}; +use hir::def_id::{CrateNum, DefIndex, DefId, LocalDefId, LOCAL_CRATE}; use hir::map::definitions::DefPathHash; use ich::{CachingSourceMapView, Fingerprint}; use mir::{self, interpret}; @@ -566,7 +565,7 @@ impl<'a, 'tcx: 'a, 'x> ty_codec::TyDecoder<'a, 'tcx> for CacheDecoder<'a, 'tcx, let tcx = self.tcx(); let cache_key = ty::CReaderCacheKey { - cnum: RESERVED_FOR_INCR_COMP_CACHE, + cnum: CrateNum::ReservedForIncrCompCache, pos: shorthand, }; diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 3d7117dd46a..5ffb77dda68 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -11,7 +11,7 @@ use hir::def_id::DefId; use hir::map::definitions::DefPathData; use mir::interpret::ConstValue; -use middle::region::{self, BlockRemainder}; +use middle::region; use ty::subst::{self, Subst}; use ty::{BrAnon, BrEnv, BrFresh, BrNamed}; use ty::{Bool, Char, Adt}; @@ -770,17 +770,20 @@ define_print! { } ty::ReScope(scope) if cx.identify_regions => { match scope.data() { - region::ScopeData::Node(id) => - write!(f, "'{}s", id.as_usize()), - region::ScopeData::CallSite(id) => - write!(f, "'{}cs", id.as_usize()), - region::ScopeData::Arguments(id) => - write!(f, "'{}as", id.as_usize()), - region::ScopeData::Destruction(id) => - write!(f, "'{}ds", id.as_usize()), - region::ScopeData::Remainder(BlockRemainder - { block, first_statement_index }) => - write!(f, "'{}_{}rs", block.as_usize(), first_statement_index.index()), + region::ScopeData::Node => + write!(f, "'{}s", scope.item_local_id().as_usize()), + region::ScopeData::CallSite => + write!(f, "'{}cs", scope.item_local_id().as_usize()), + region::ScopeData::Arguments => + write!(f, "'{}as", scope.item_local_id().as_usize()), + region::ScopeData::Destruction => + write!(f, "'{}ds", scope.item_local_id().as_usize()), + region::ScopeData::Remainder(first_statement_index) => write!( + f, + "'{}_{}rs", + scope.item_local_id().as_usize(), + first_statement_index.index() + ), } } ty::ReVar(region_vid) if cx.identify_regions => { diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 186bc6d43cc..2f11fea46d6 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -72,7 +72,8 @@ macro_rules! newtype_index { newtype_index!( // Leave out derives marker so we can use its absence to ensure it comes first @type [$name] - @max [::std::u32::MAX - 1] + // shave off 256 indices at the end to allow space for packing these indices into enums + @max [0xFFFF_FF00] @vis [$v] @debug_format ["{}"]); ); @@ -82,7 +83,8 @@ macro_rules! newtype_index { newtype_index!( // Leave out derives marker so we can use its absence to ensure it comes first @type [$name] - @max [::std::u32::MAX - 1] + // shave off 256 indices at the end to allow space for packing these indices into enums + @max [0xFFFF_FF00] @vis [$v] @debug_format ["{}"] $($tokens)+); @@ -97,6 +99,7 @@ macro_rules! newtype_index { @vis [$v:vis] @debug_format [$debug_format:tt]) => ( #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, $($derives),*)] + #[rustc_layout_scalar_valid_range_end($max)] $v struct $type { private: u32 } diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs index 1ed8289d441..d46b0813ca7 100644 --- a/src/librustc_mir/build/cfg.rs +++ b/src/librustc_mir/build/cfg.rs @@ -51,7 +51,7 @@ impl<'tcx> CFG<'tcx> { source_info: SourceInfo, region_scope: region::Scope) { if tcx.emit_end_regions() { - if let region::ScopeData::CallSite(_) = region_scope.data() { + if let region::ScopeData::CallSite = region_scope.data() { // The CallSite scope (aka the root scope) is sort of weird, in that it is // supposed to "separate" the "interior" and "exterior" of a closure. Being // that, it is not really a part of the region hierarchy, but for some diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 38e0854bcd6..1406183955b 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -566,7 +566,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // We want `scopes[1]`, which is the `ParameterScope`. assert!(self.scopes.len() >= 2); assert!(match self.scopes[1].region_scope.data() { - region::ScopeData::Arguments(_) => true, + region::ScopeData::Arguments => true, _ => false, }); self.scopes[1].region_scope diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index 85a9734a601..b0a60fedfbb 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -11,7 +11,7 @@ use hair::*; use hair::cx::Cx; use hair::cx::to_ref::ToRef; -use rustc::middle::region::{self, BlockRemainder}; +use rustc::middle::region; use rustc::hir; use rustc_data_structures::indexed_vec::Idx; @@ -71,10 +71,10 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // ignore for purposes of the MIR } hir::DeclKind::Local(ref local) => { - let remainder_scope = region::Scope::Remainder(BlockRemainder { - block: block_id, - first_statement_index: region::FirstStatementIndex::new(index), - }); + let remainder_scope = region::Scope::Remainder( + block_id, + region::FirstStatementIndex::new(index), + ); let mut pattern = cx.pattern_from_hir(&local.pat); diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 461285ff9bc..8bb93d09a2a 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -340,7 +340,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { let field = field.try_into().unwrap(); let field_layout = op.layout.field(self, field)?; - if field_layout.size.bytes() == 0 { + if field_layout.is_zst() { let val = Value::Scalar(Scalar::zst().into()); return Ok(OpTy { op: Operand::Immediate(val), layout: field_layout }); } @@ -397,9 +397,15 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { Field(field, _) => self.operand_field(base, field.index() as u64)?, Downcast(_, variant) => self.operand_downcast(base, variant)?, Deref => self.deref_operand(base)?.into(), - // The rest should only occur as mplace, we do not use Immediates for types - // allowing such operations. This matches place_projection forcing an allocation. - Subslice { .. } | ConstantIndex { .. } | Index(_) => { + Subslice { .. } | ConstantIndex { .. } | Index(_) => if base.layout.is_zst() { + OpTy { + op: Operand::Immediate(Value::Scalar(Scalar::zst().into())), + // the actual index doesn't matter, so we just pick a convenient one like 0 + layout: base.layout.field(self, 0)?, + } + } else { + // The rest should only occur as mplace, we do not use Immediates for types + // allowing such operations. This matches place_projection forcing an allocation. let mplace = base.to_mem_place(); self.mplace_projection(mplace, proj_elem)?.into() } diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index e71de0001fb..1594755b4ab 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -29,6 +29,8 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(exhaustive_patterns)] #![feature(range_contains)] #![feature(rustc_diagnostic_macros)] +#![feature(rustc_attrs)] +#![cfg_attr(stage0, feature(attr_literals))] #![feature(never_type)] #![feature(specialization)] #![feature(try_trait)] diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 7d9139df415..25a7ff9cd3f 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -22,7 +22,7 @@ use Namespace::{self, TypeNS, ValueNS, MacroNS}; use {resolve_error, resolve_struct_error, ResolutionError}; use rustc::hir::def::*; -use rustc::hir::def_id::{BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; +use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; use rustc::ty; use rustc::middle::cstore::CrateStore; use rustc_metadata::cstore::LoadedMacro; @@ -769,7 +769,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let def_id = self.macro_defs[&expansion]; if let Some(id) = self.definitions.as_local_node_id(def_id) { self.local_macro_def_scopes[&id] - } else if def_id.krate == BUILTIN_MACROS_CRATE { + } else if def_id.krate == CrateNum::BuiltinMacros { self.injected_crate.unwrap_or(self.graph_root) } else { let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap(); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index f687e022a41..f8b5f891579 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -14,8 +14,8 @@ use ModuleOrUniformRoot; use Namespace::{self, TypeNS, MacroNS}; use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport}; use resolve_imports::ImportResolver; -use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex, - DefIndexAddressSpace}; +use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex, + CrateNum, DefIndexAddressSpace}; use rustc::hir::def::{Def, NonMacroAttrKind}; use rustc::hir::map::{self, DefCollector}; use rustc::{ty, lint}; @@ -218,7 +218,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc) { let def_id = DefId { - krate: BUILTIN_MACROS_CRATE, + krate: CrateNum::BuiltinMacros, index: DefIndex::from_array_index(self.macro_map.len(), DefIndexAddressSpace::Low), }; @@ -352,7 +352,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.mark, normal_module_def_id); invoc.expansion_data.mark.set_default_transparency(ext.default_transparency()); - invoc.expansion_data.mark.set_is_builtin(def_id.krate == BUILTIN_MACROS_CRATE); + invoc.expansion_data.mark.set_is_builtin(def_id.krate == CrateNum::BuiltinMacros); } Ok(Some(ext)) @@ -1135,7 +1135,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { }; // Plugin-based syntax extensions are exempt from this check - if krate == BUILTIN_MACROS_CRATE { return; } + if krate == CrateNum::BuiltinMacros { return; } let ext = binding.get_macro(self); diff --git a/src/test/mir-opt/validate_1.rs b/src/test/mir-opt/validate_1.rs index 2d5c98ff0ed..882579c5710 100644 --- a/src/test/mir-opt/validate_1.rs +++ b/src/test/mir-opt/validate_1.rs @@ -64,11 +64,11 @@ fn main() { // bb0: { // Validate(Acquire, [_1: &ReFree(DefId(0/1:11 ~ validate_1[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(50)], _2: &ReFree(DefId(0/1:11 ~ validate_1[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]); // StorageLive(_3); -// Validate(Suspend(ReScope(Remainder(BlockRemainder { block: ItemLocalId(25), first_statement_index: 0 }))), [(*_2): i32]); +// Validate(Suspend(ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 })), [(*_2): i32]); // _3 = &ReErased (*_2); -// Validate(Acquire, [(*_3): i32/ReScope(Remainder(BlockRemainder { block: ItemLocalId(25), first_statement_index: 0 })) (imm)]); +// Validate(Acquire, [(*_3): i32/ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 }) (imm)]); // _0 = (*_3); -// EndRegion(ReScope(Remainder(BlockRemainder { block: ItemLocalId(25), first_statement_index: 0 }))); +// EndRegion(ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 })); // StorageDead(_3); // return; // } diff --git a/src/test/mir-opt/validate_3.rs b/src/test/mir-opt/validate_3.rs index 72ec9ce400f..07f5b2aa84b 100644 --- a/src/test/mir-opt/validate_3.rs +++ b/src/test/mir-opt/validate_3.rs @@ -48,12 +48,12 @@ fn main() { // StorageLive(_1); // _1 = Test { x: const 0i32 }; // StorageLive(_2); -// Validate(Suspend(ReScope(Remainder(BlockRemainder { block: ItemLocalId(20), first_statement_index: 3 }))), [_1: Test]); +// Validate(Suspend(ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 })), [_1: Test]); // _2 = &ReErased _1; -// Validate(Acquire, [(*_2): Test/ReScope(Remainder(BlockRemainder { block: ItemLocalId(20), first_statement_index: 3 })) (imm)]); +// Validate(Acquire, [(*_2): Test/ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 }) (imm)]); // StorageLive(_4); // StorageLive(_5); -// Validate(Suspend(ReScope(Node(ItemLocalId(18)))), [((*_2).0: i32): i32/ReScope(Remainder(BlockRemainder { block: ItemLocalId(20), first_statement_index: 3 })) (imm)]); +// Validate(Suspend(ReScope(Node(ItemLocalId(18)))), [((*_2).0: i32): i32/ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 }) (imm)]); // _5 = &ReErased ((*_2).0: i32); // Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(18))) (imm)]); // Validate(Suspend(ReScope(Node(ItemLocalId(18)))), [(*_5): i32/ReScope(Node(ItemLocalId(18))) (imm)]); @@ -68,7 +68,7 @@ fn main() { // StorageDead(_4); // StorageDead(_5); // _0 = (); -// EndRegion(ReScope(Remainder(BlockRemainder { block: ItemLocalId(20), first_statement_index: 3 }))); +// EndRegion(ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 })); // StorageDead(_2); // StorageDead(_1); // return; diff --git a/src/test/run-pass-fulldeps/newtype_index.rs b/src/test/run-pass-fulldeps/newtype_index.rs new file mode 100644 index 00000000000..08e2c35e072 --- /dev/null +++ b/src/test/run-pass-fulldeps/newtype_index.rs @@ -0,0 +1,20 @@ +#![feature(min_const_fn, rustc_attrs, rustc_private, step_trait)] + +#[macro_use] extern crate rustc_data_structures; +extern crate rustc_serialize; + +use rustc_data_structures::indexed_vec::Idx; + +newtype_index!(struct MyIdx { MAX = 0xFFFF_FFFA }); + +use std::mem::size_of; + +fn main() { + assert_eq!(size_of::(), 4); + assert_eq!(size_of::>(), 4); + assert_eq!(size_of::>>(), 4); + assert_eq!(size_of::>>>(), 4); + assert_eq!(size_of::>>>>(), 4); + assert_eq!(size_of::>>>>>(), 4); + assert_eq!(size_of::>>>>>>(), 8); +} diff --git a/src/test/ui/consts/const-eval/zst_operand_eval.rs b/src/test/ui/consts/const-eval/zst_operand_eval.rs new file mode 100644 index 00000000000..d837da1066d --- /dev/null +++ b/src/test/ui/consts/const-eval/zst_operand_eval.rs @@ -0,0 +1,5 @@ +// compile-pass + +static ASSERT: () = [()][!(std::mem::size_of::() == 4) as usize]; + +fn main() {}