From d272e2f6e2e40dadcc68a0f4be5a4145e3d6a006 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 7 Sep 2018 13:41:59 +0200 Subject: [PATCH 01/15] Get rid of the `non_zero` lang item in favour of arbitrary range specifications --- src/libcore/nonzero.rs | 3 ++- src/librustc/middle/lang_items.rs | 2 -- src/librustc/ty/context.rs | 23 +++++++++++++++++++++++ src/librustc/ty/layout.rs | 22 +++++++++++++++------- 4 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs index cc36ea7f713..6f27d3207bb 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_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/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/ty/context.rs b/src/librustc/ty/context.rs index eb6f7140a7d..922308d51fb 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1083,6 +1083,29 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { interned } + /// Returns a range of the start/end indices specified with the `rustc_layout_scalar_range` + /// attribute. Missing range ends may be denoted by `None` and will just use the max/min of + /// the type. + pub fn layout_scalar_range(self, def_id: DefId) -> Option<(Option, Option)> { + let attrs = self.get_attrs(def_id); + let get = |name| -> Option { + let attr = attrs.iter().find(|a| a.check_name(name))?; + for meta in attr.meta_item_list().expect("rustc_layout_scalar_range takes args") { + match meta.literal().expect("rustc_layout_scalar_range attribute takes lit").node { + ast::LitKind::Int(a, _) => return Some(a), + _ => span_bug!(attr.span, "rustc_layout_scalar_range expects integer arg"), + } + } + bug!("no arguments to `rustc_layout_scalar_range` attribute"); + }; + let start = get("rustc_layout_scalar_range_start"); + let end = get("rustc_layout_scalar_range_end"); + if start.is_none() && end.is_none() { + return None; + } + Some((start, 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 17d613a2b18..be9357dd4a7 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -761,16 +761,19 @@ 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() { + if let Some((start, end)) = self.tcx.layout_scalar_range(def.did) { 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 = start.unwrap_or(*scalar.valid_range.start()); + let end = end.unwrap_or(*scalar.valid_range.end()); + scalar.valid_range = start..=end; } - _ => {} + _ => bug!( + "nonscalar layout for rustc_layout_scalar_range type {:?}: {:#?}", + def, + st, + ), } } return Ok(tcx.intern_layout(st)); @@ -1351,7 +1354,12 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> { 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(), + tcx.layout_scalar_range(def.did).map_or(false, |(start, end)| { + // `n..` for `n > 0` or `n..m` for `n > 0 && m > n` + start.map_or(true, |start| start > 0 && end.map_or(true, |end| { + end > start + })) + }), tail, }); } else { From 06a041cbd399dc641cadef2bc22c6e519b01856e Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 7 Sep 2018 15:28:23 +0200 Subject: [PATCH 02/15] Forbid the upper indices of `IndexVec` indices to allow for niche optimizations --- src/librustc/lib.rs | 2 ++ src/librustc/middle/region.rs | 6 ++---- src/librustc_data_structures/indexed_vec.rs | 5 +++-- src/librustc_mir/lib.rs | 2 ++ src/test/run-pass-fulldeps/newtype_index.rs | 20 ++++++++++++++++++++ 5 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 src/test/run-pass-fulldeps/newtype_index.rs diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index d79281666d6..301fc76f932 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -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)] diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index f6a8f8dc172..a2a056a3590 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -114,7 +114,7 @@ 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; +// be sure to add the MAX of FirstStatementIndex if you add more constants here #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)] pub enum ScopeData { @@ -160,9 +160,7 @@ pub struct BlockRemainder { } newtype_index! { - pub struct FirstStatementIndex { - MAX = SCOPE_DATA_REMAINDER_MAX - } + pub struct FirstStatementIndex; } impl_stable_hash_for!(struct ::middle::region::FirstStatementIndex { private }); diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 186bc6d43cc..2d1709f2374 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -72,7 +72,7 @@ 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] + @max [0xFFFF_FFFE] @vis [$v] @debug_format ["{}"]); ); @@ -82,7 +82,7 @@ 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] + @max [0xFFFF_FFFE] @vis [$v] @debug_format ["{}"] $($tokens)+); @@ -97,6 +97,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_range_end($max)] $v struct $type { private: u32 } diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index d4024981c37..08ee40dbcf4 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -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)] 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..d10c51bbe47 --- /dev/null +++ b/src/test/run-pass-fulldeps/newtype_index.rs @@ -0,0 +1,20 @@ +#![feature(rustc_attrs, step_trait, rustc_private)] + +#[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); +} \ No newline at end of file From 3828e9e16f4eb3d7b19f777b9490b9ce468fe7bf Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 7 Sep 2018 17:07:42 +0200 Subject: [PATCH 03/15] Use the same way to specifiy the `SCOPE_DATA_*` constants as used for the MAX --- src/librustc/middle/region.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index a2a056a3590..0fbd74e250e 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -110,10 +110,10 @@ pub struct Scope { pub(crate) code: u32 } -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_NODE: u32 = 0xFFFF_FFFF; +const SCOPE_DATA_CALLSITE: u32 = 0xFFFF_FFFE; +const SCOPE_DATA_ARGUMENTS: u32 = 0xFFFF_FFFD; +const SCOPE_DATA_DESTRUCTION: u32 = 0xFFFF_FFFC; // be sure to add the MAX of FirstStatementIndex if you add more constants here #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)] From a2c924b5ae21b67be77aa7e944ae9d9f883a0bde Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 7 Sep 2018 17:32:07 +0200 Subject: [PATCH 04/15] Satisfy tidy --- src/test/run-pass-fulldeps/newtype_index.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-pass-fulldeps/newtype_index.rs b/src/test/run-pass-fulldeps/newtype_index.rs index d10c51bbe47..e1eeb3f3aa1 100644 --- a/src/test/run-pass-fulldeps/newtype_index.rs +++ b/src/test/run-pass-fulldeps/newtype_index.rs @@ -17,4 +17,4 @@ fn main() { assert_eq!(size_of::>>>>(), 4); assert_eq!(size_of::>>>>>(), 4); assert_eq!(size_of::>>>>>>(), 8); -} \ No newline at end of file +} From 833dc7e6826483b19c819fc19727efe4e8ddbf12 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 10 Sep 2018 13:40:34 +0200 Subject: [PATCH 05/15] Address attribute naming and use `Bound` enum --- src/libcore/nonzero.rs | 2 +- src/librustc/ty/context.rs | 33 +++++++-------- src/librustc/ty/layout.rs | 46 ++++++++++++--------- src/librustc_data_structures/indexed_vec.rs | 2 +- 4 files changed, 44 insertions(+), 39 deletions(-) diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs index 6f27d3207bb..30067d7e163 100644 --- a/src/libcore/nonzero.rs +++ b/src/libcore/nonzero.rs @@ -15,7 +15,7 @@ use ops::CoerceUnsized; /// A wrapper type for raw pointers and integers that will never be /// NULL or 0 that might allow certain optimizations. #[cfg_attr(stage0, lang = "non_zero")] -#[cfg_attr(not(stage0), rustc_layout_scalar_range_start(1))] +#[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/ty/context.rs b/src/librustc/ty/context.rs index 922308d51fb..9c759b38d38 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; @@ -1083,27 +1083,24 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { interned } - /// Returns a range of the start/end indices specified with the `rustc_layout_scalar_range` - /// attribute. Missing range ends may be denoted by `None` and will just use the max/min of - /// the type. - pub fn layout_scalar_range(self, def_id: DefId) -> Option<(Option, Option)> { + /// 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| -> Option { - let attr = attrs.iter().find(|a| a.check_name(name))?; - for meta in attr.meta_item_list().expect("rustc_layout_scalar_range takes args") { - match meta.literal().expect("rustc_layout_scalar_range attribute takes lit").node { - ast::LitKind::Int(a, _) => return Some(a), - _ => span_bug!(attr.span, "rustc_layout_scalar_range expects integer arg"), + 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"), } } - bug!("no arguments to `rustc_layout_scalar_range` attribute"); + span_bug!(attr.span, "no arguments to `rustc_layout_scalar_valid_range` attribute"); }; - let start = get("rustc_layout_scalar_range_start"); - let end = get("rustc_layout_scalar_range_end"); - if start.is_none() && end.is_none() { - return None; - } - Some((start, end)) + (get("rustc_layout_scalar_valid_range_start"), get("rustc_layout_scalar_valid_range_end")) } pub fn lift>(self, value: &T) -> Option { diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index be9357dd4a7..71cdec0f83e 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,20 +762,28 @@ 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 }; - if let Some((start, end)) = self.tcx.layout_scalar_range(def.did) { - match st.abi { - Abi::Scalar(ref mut scalar) | - Abi::ScalarPair(ref mut scalar, _) => { - let start = start.unwrap_or(*scalar.valid_range.start()); - let end = end.unwrap_or(*scalar.valid_range.end()); - scalar.valid_range = start..=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; } - _ => bug!( - "nonscalar layout for rustc_layout_scalar_range type {:?}: {:#?}", - def, - st, - ), } + _ => bug!( + "nonscalar layout for layout_scalar_valid_range type {:?}: {:#?}", + def, + st, + ), } return Ok(tcx.intern_layout(st)); } @@ -1353,13 +1362,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 || - tcx.layout_scalar_range(def.did).map_or(false, |(start, end)| { - // `n..` for `n > 0` or `n..m` for `n > 0 && m > n` - start.map_or(true, |start| start > 0 && end.map_or(true, |end| { - end > start - })) - }), + 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_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 2d1709f2374..0b5fb97f0e1 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -97,7 +97,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_range_end($max)] + #[rustc_layout_scalar_valid_range_end($max)] $v struct $type { private: u32 } From 88ebb95f46c077baf165c9d2b174f90e5d369854 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 10 Sep 2018 14:39:22 +0200 Subject: [PATCH 06/15] only allow restricting scalar layouts --- src/librustc/ty/layout.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 71cdec0f83e..d03b038d6ed 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -779,7 +779,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { scalar.valid_range = *scalar.valid_range.start()..=end; } } - _ => bug!( + _ => assert!( + start == Bound::Unbounded && end == Bound::Unbounded, "nonscalar layout for layout_scalar_valid_range type {:?}: {:#?}", def, st, From 24dca6aecaded209d47aba6e60e0b87eae2d49d6 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 10 Sep 2018 14:40:12 +0200 Subject: [PATCH 07/15] Simplify Scope/ScopeData to have less chance of introducing UB or size increases --- src/librustc/ich/impls_ty.rs | 15 +-- src/librustc/infer/error_reporting/mod.rs | 12 +-- src/librustc/middle/region.rs | 106 +++++++------------- src/librustc/util/ppaux.rs | 27 ++--- src/librustc_data_structures/indexed_vec.rs | 6 +- src/librustc_mir/build/cfg.rs | 2 +- src/librustc_mir/build/scope.rs | 2 +- src/librustc_mir/hair/cx/block.rs | 10 +- 8 files changed, 77 insertions(+), 103 deletions(-) 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/middle/region.rs b/src/librustc/middle/region.rs index 0fbd74e250e..6fa5d363ffa 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -20,7 +20,6 @@ use ich::{StableHashingContext, NodeIdHashingMode}; use util::nodemap::{FxHashMap, FxHashSet}; use ty; -use std::fmt; use std::mem; use rustc_data_structures::sync::Lrc; use syntax::source_map; @@ -100,39 +99,29 @@ 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)] +#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)] pub struct Scope { pub(crate) id: hir::ItemLocalId, - pub(crate) code: u32 + pub(crate) data: ScopeData, } -const SCOPE_DATA_NODE: u32 = 0xFFFF_FFFF; -const SCOPE_DATA_CALLSITE: u32 = 0xFFFF_FFFE; -const SCOPE_DATA_ARGUMENTS: u32 = 0xFFFF_FFFD; -const SCOPE_DATA_DESTRUCTION: u32 = 0xFFFF_FFFC; -// be sure to add the MAX of FirstStatementIndex if you add more constants here - #[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,12 +141,6 @@ 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; @@ -165,68 +148,54 @@ newtype_index! { 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. /// @@ -257,7 +226,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 @@ -267,7 +236,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. @@ -511,8 +480,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); } } @@ -595,7 +564,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); @@ -650,8 +619,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) { @@ -867,10 +836,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; } @@ -1033,7 +999,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/util/ppaux.rs b/src/librustc/util/ppaux.rs index ddcc0fa9c92..1206690c86e 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 0b5fb97f0e1..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 [0xFFFF_FFFE] + // 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 [0xFFFF_FFFE] + // shave off 256 indices at the end to allow space for packing these indices into enums + @max [0xFFFF_FF00] @vis [$v] @debug_format ["{}"] $($tokens)+); 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 6c8b5d97b6f..730603dff56 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 ty = local.ty.clone().map(|ty| ty.hir_id); let pattern = cx.pattern_from_hir(&local.pat); From d1b5231aa75d6c25efc839454331d3c9fb09ffb3 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 10 Sep 2018 17:46:30 +0200 Subject: [PATCH 08/15] Fix const eval of ZST index operations to make the static assertion work --- src/librustc_mir/interpret/operand.rs | 14 ++++++++++---- src/test/ui/consts/const-eval/zst_operand_eval.rs | 5 +++++ 2 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/consts/const-eval/zst_operand_eval.rs 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/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..c6deb88d4f1 --- /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() {} From 1ec86708caa23dda718f58a52d9159bc40201b7a Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 11 Sep 2018 11:18:58 +0200 Subject: [PATCH 09/15] Split `CrateNum` into an enum instead of having magic constants --- src/librustc/hir/def_id.rs | 61 ++++++++++++++++----- src/librustc/ty/context.rs | 4 +- src/librustc/ty/query/on_disk_cache.rs | 5 +- src/librustc_resolve/build_reduced_graph.rs | 4 +- src/librustc_resolve/macros.rs | 10 ++-- 5 files changed, 58 insertions(+), 26 deletions(-) diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index 420ffbcfee6..1dc668066d8 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -18,23 +18,51 @@ use std::u32; newtype_index! { pub struct CrateNum { 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.0), + 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(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), + } } } @@ -48,7 +76,12 @@ impl CrateNum { 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.0, 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/ty/context.rs b/src/librustc/ty/context.rs index 9c759b38d38..cfc5cd60b17 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -829,9 +829,9 @@ 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")] + #[cfg(all(not(stage0), target_pointer_width = "64"))] assert!(mem::size_of::() <= 24); - #[cfg(target_pointer_width = "64")] + #[cfg(all(not(stage0), target_pointer_width = "64"))] assert!(mem::size_of::() <= 32); let mk = |sty| CtxtInterners::intern_ty(interners, interners, sty); diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 6e16d92ba0c..cb82e28f1d1 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_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 1fa9979edb8..0c9d563f47f 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; @@ -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(); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index fe0cb523a15..d40edef6862 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}; @@ -202,7 +202,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), }; @@ -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); From 8053f6319a6c18a23a406e12dede7ff158d3d561 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 11 Sep 2018 12:06:37 +0200 Subject: [PATCH 10/15] Rebase fallout --- src/librustc/hir/def_id.rs | 30 ++++++++++++++++++++++++++---- src/librustc/middle/region.rs | 2 +- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index 1dc668066d8..cd91b85689b 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -16,7 +16,7 @@ use std::fmt; use std::u32; newtype_index! { - pub struct CrateNum { + pub struct CrateId { ENCODABLE = custom } } @@ -38,7 +38,7 @@ pub enum CrateNum { 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.0), + 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"), @@ -48,7 +48,7 @@ impl ::std::fmt::Debug for CrateNum { /// Item definitions in the currently-compiled crate would have the CrateNum /// LOCAL_CRATE in their DefId. -pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId(0)); +pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32_const(0)); impl Idx for CrateNum { @@ -71,13 +71,35 @@ 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 { match self { - CrateNum::Index(id) => fmt::Display::fmt(&id.0, f), + 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/middle/region.rs b/src/librustc/middle/region.rs index 6fa5d363ffa..56960675b74 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -143,7 +143,7 @@ pub enum ScopeData { /// and thus does not include EXPR_2, but covers the `...`. newtype_index! { - pub struct FirstStatementIndex; + pub struct FirstStatementIndex { .. } } impl_stable_hash_for!(struct ::middle::region::FirstStatementIndex { private }); From 68298a5087307792aec3141db4be8fc9f68b682a Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 11 Sep 2018 13:30:26 +0200 Subject: [PATCH 11/15] Use assertion-like static assertions --- src/librustc/middle/region.rs | 2 +- src/librustc/ty/context.rs | 4 ++-- src/test/ui/consts/const-eval/zst_operand_eval.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 56960675b74..b1d6cce11f4 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -152,7 +152,7 @@ impl_stable_hash_for!(struct ::middle::region::FirstStatementIndex { private }); #[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]; +static ASSERT: () = [()][!(mem::size_of::() == 4) as usize]; #[allow(non_snake_case)] impl Scope { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index cfc5cd60b17..2aaccb59900 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -830,9 +830,9 @@ impl<'tcx> CommonTypes<'tcx> { fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> { // Ensure our type representation does not grow #[cfg(all(not(stage0), target_pointer_width = "64"))] - assert!(mem::size_of::() <= 24); + static ASSERT_TY_KIND: () = [()][!(std::mem::size_of::() <= 24) as usize]; #[cfg(all(not(stage0), target_pointer_width = "64"))] - assert!(mem::size_of::() <= 32); + static ASSERT_TYS: () = [()][!(std::mem::size_of::() <= 32) as usize]; let mk = |sty| CtxtInterners::intern_ty(interners, interners, sty); let mk_region = |r| { diff --git a/src/test/ui/consts/const-eval/zst_operand_eval.rs b/src/test/ui/consts/const-eval/zst_operand_eval.rs index c6deb88d4f1..d837da1066d 100644 --- a/src/test/ui/consts/const-eval/zst_operand_eval.rs +++ b/src/test/ui/consts/const-eval/zst_operand_eval.rs @@ -1,5 +1,5 @@ // compile-pass -static ASSERT: () = [()][(std::mem::size_of::() != 4) as usize]; +static ASSERT: () = [()][!(std::mem::size_of::() == 4) as usize]; fn main() {} From 5f42a0f005ea0d4c34ab2a29d1c4a8a4bd615467 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 11 Sep 2018 13:49:10 +0200 Subject: [PATCH 12/15] Change debug printing to print in the old concise style --- src/librustc/middle/region.rs | 24 +++++++++++++++++++++--- src/test/mir-opt/validate_1.rs | 6 +++--- src/test/mir-opt/validate_3.rs | 8 ++++---- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index b1d6cce11f4..2f99743cfbd 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -21,6 +21,7 @@ use util::nodemap::{FxHashMap, FxHashSet}; use ty; use std::mem; +use std::fmt; use rustc_data_structures::sync::Lrc; use syntax::source_map; use syntax::ast; @@ -50,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. /// @@ -99,12 +100,29 @@ 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. -#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)] +#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy, RustcEncodable, RustcDecodable)] pub struct Scope { pub(crate) id: hir::ItemLocalId, pub(crate) data: ScopeData, } +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, @@ -159,7 +177,7 @@ impl Scope { #[inline] pub fn data(self) -> ScopeData { self.data - } + } #[inline] pub fn new(id: hir::ItemLocalId, data: ScopeData) -> 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; From f3417c524c384f9435f3a45c4b1deb43c2319968 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 11 Sep 2018 14:14:52 +0200 Subject: [PATCH 13/15] Properly access `std::mem::size_of` --- src/librustc/ty/context.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 2aaccb59900..eaa1c5d0189 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -830,9 +830,9 @@ impl<'tcx> CommonTypes<'tcx> { fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> { // Ensure our type representation does not grow #[cfg(all(not(stage0), target_pointer_width = "64"))] - static ASSERT_TY_KIND: () = [()][!(std::mem::size_of::() <= 24) as usize]; + static ASSERT_TY_KIND: () = [()][!(::std::mem::size_of::() <= 24) as usize]; #[cfg(all(not(stage0), target_pointer_width = "64"))] - static ASSERT_TYS: () = [()][!(std::mem::size_of::() <= 32) as usize]; + static ASSERT_TYS: () = [()][!(::std::mem::size_of::() <= 32) as usize]; let mk = |sty| CtxtInterners::intern_ty(interners, interners, sty); let mk_region = |r| { From 79f2cc08e61b25a71a7528f7436a7e011017c56b Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 11 Sep 2018 14:24:19 +0200 Subject: [PATCH 14/15] Silence dead code warning for the assertion statics --- src/librustc/ty/context.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index eaa1c5d0189..1a7c1b3eef8 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -830,8 +830,10 @@ impl<'tcx> CommonTypes<'tcx> { fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> { // Ensure our type representation does not grow #[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); From a94c16614c3a43d609a437afa92ef5ae7d3965ea Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 11 Sep 2018 22:52:00 +0300 Subject: [PATCH 15/15] Add missing #![feature(min_const_fn)] to the newtype_index test. --- src/test/run-pass-fulldeps/newtype_index.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/run-pass-fulldeps/newtype_index.rs b/src/test/run-pass-fulldeps/newtype_index.rs index e1eeb3f3aa1..08e2c35e072 100644 --- a/src/test/run-pass-fulldeps/newtype_index.rs +++ b/src/test/run-pass-fulldeps/newtype_index.rs @@ -1,4 +1,4 @@ -#![feature(rustc_attrs, step_trait, rustc_private)] +#![feature(min_const_fn, rustc_attrs, rustc_private, step_trait)] #[macro_use] extern crate rustc_data_structures; extern crate rustc_serialize;