Skip to content

Add forever unstable attribute to allow specifying arbitrary scalar ranges #54032

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Sep 14, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/libcore/nonzero.rs
Original file line number Diff line number Diff line change
@@ -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<T>(pub(crate) T);
85 changes: 70 additions & 15 deletions src/librustc/hir/def_id.rs
Original file line number Diff line number Diff line change
@@ -16,25 +16,53 @@ use std::fmt;
use std::u32;

newtype_index! {
pub struct CrateNum {
pub struct CrateId {
ENCODABLE = custom
DEBUG_FORMAT = "crate{}",
}
}

#[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),
}

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"),
}
}
}

/// Item definitions in the currently-compiled crate would have the CrateNum
/// LOCAL_CRATE in their DefId.
const LOCAL_CRATE = 0,
/// 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));

/// 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,

/// A CrateNum value that indicates that something is wrong.
const INVALID_CRATE = CrateNum::MAX_AS_U32 - 1,
impl Idx for CrateNum {
#[inline]
fn new(value: usize) -> Self {
CrateNum::Index(Idx::new(value))
}

/// 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,
#[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"),
}
}
}

15 changes: 9 additions & 6 deletions src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
@@ -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<StableHashingContext<'a>> for region::Scope {
type KeyType = region::Scope;
@@ -783,11 +791,6 @@ impl<'a> ToStableHashKey<StableHashingContext<'a>> 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
});
12 changes: 6 additions & 6 deletions src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
@@ -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[..]
}
2 changes: 2 additions & 0 deletions src/librustc/lib.rs
Original file line number Diff line number Diff line change
@@ -59,6 +59,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)]
2 changes: 0 additions & 2 deletions src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
@@ -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;
128 changes: 55 additions & 73 deletions src/librustc/middle/region.rs
Original file line number Diff line number Diff line change
@@ -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: {}}}",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably want to use the fmt.debug_struct wrapper, to automate this.

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<ScopeData> 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::<ScopeData>() == 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<hir::ItemLocalId> {
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
32 changes: 27 additions & 5 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
@@ -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<StableHashingContext<'a>> 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::<ty::TyKind>() <= 24);
#[cfg(target_pointer_width = "64")]
assert!(mem::size_of::<ty::TyS>() <= 32);
#[cfg(all(not(stage0), target_pointer_width = "64"))]
#[allow(dead_code)]
static ASSERT_TY_KIND: () = [()][!(::std::mem::size_of::<ty::TyKind>() <= 24) as usize];
#[cfg(all(not(stage0), target_pointer_width = "64"))]
#[allow(dead_code)]
static ASSERT_TYS: () = [()][!(::std::mem::size_of::<ty::TyS>() <= 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<u128>, Bound<u128>) {
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<T: ?Sized + Lift<'tcx>>(self, value: &T) -> Option<T::Lifted> {
value.lift_to_tcx(self)
}
39 changes: 28 additions & 11 deletions src/librustc/ty/layout.rs
Original file line number Diff line number Diff line change
@@ -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<T>.
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 {
5 changes: 2 additions & 3 deletions src/librustc/ty/query/on_disk_cache.rs
Original file line number Diff line number Diff line change
@@ -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,
};

27 changes: 15 additions & 12 deletions src/librustc/util/ppaux.rs
Original file line number Diff line number Diff line change
@@ -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 => {
7 changes: 5 additions & 2 deletions src/librustc_data_structures/indexed_vec.rs
Original file line number Diff line number Diff line change
@@ -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]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohhhh, this is clever!

@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
}
2 changes: 1 addition & 1 deletion src/librustc_mir/build/cfg.rs
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion src/librustc_mir/build/scope.rs
Original file line number Diff line number Diff line change
@@ -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
10 changes: 5 additions & 5 deletions src/librustc_mir/hair/cx/block.rs
Original file line number Diff line number Diff line change
@@ -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 ty = local.ty.clone().map(|ty| ty.hir_id);
let pattern = cx.pattern_from_hir(&local.pat);
14 changes: 10 additions & 4 deletions src/librustc_mir/interpret/operand.rs
Original file line number Diff line number Diff line change
@@ -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()
}
2 changes: 2 additions & 0 deletions src/librustc_mir/lib.rs
Original file line number Diff line number Diff line change
@@ -30,6 +30,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)]
4 changes: 2 additions & 2 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
@@ -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;
@@ -768,7 +768,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();
10 changes: 5 additions & 5 deletions src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
@@ -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};
@@ -202,7 +202,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {

fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>) {
let def_id = DefId {
krate: BUILTIN_MACROS_CRATE,
krate: CrateNum::BuiltinMacros,
index: DefIndex::from_array_index(self.macro_map.len(),
DefIndexAddressSpace::Low),
};
@@ -335,7 +335,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))
@@ -1087,7 +1087,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);

6 changes: 3 additions & 3 deletions src/test/mir-opt/validate_1.rs
Original file line number Diff line number Diff line change
@@ -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;
// }
8 changes: 4 additions & 4 deletions src/test/mir-opt/validate_3.rs
Original file line number Diff line number Diff line change
@@ -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;
20 changes: 20 additions & 0 deletions src/test/run-pass-fulldeps/newtype_index.rs
Original file line number Diff line number Diff line change
@@ -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::<MyIdx>(), 4);
assert_eq!(size_of::<Option<MyIdx>>(), 4);
assert_eq!(size_of::<Option<Option<MyIdx>>>(), 4);
assert_eq!(size_of::<Option<Option<Option<MyIdx>>>>(), 4);
assert_eq!(size_of::<Option<Option<Option<Option<MyIdx>>>>>(), 4);
assert_eq!(size_of::<Option<Option<Option<Option<Option<MyIdx>>>>>>(), 4);
assert_eq!(size_of::<Option<Option<Option<Option<Option<Option<MyIdx>>>>>>>(), 8);
}
5 changes: 5 additions & 0 deletions src/test/ui/consts/const-eval/zst_operand_eval.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// compile-pass

static ASSERT: () = [()][!(std::mem::size_of::<u32>() == 4) as usize];

fn main() {}