Skip to content

Commit 24dca6a

Browse files
committed
Simplify Scope/ScopeData to have less chance of introducing UB or size increases
1 parent 88ebb95 commit 24dca6a

File tree

8 files changed

+77
-103
lines changed

8 files changed

+77
-103
lines changed

src/librustc/ich/impls_ty.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,15 @@ impl_stable_hash_for!(enum ty::cast::CastKind {
772772
FnPtrAddrCast
773773
});
774774

775-
impl_stable_hash_for!(struct ::middle::region::Scope { id, code });
775+
impl_stable_hash_for!(struct ::middle::region::Scope { id, data });
776+
777+
impl_stable_hash_for!(enum ::middle::region::ScopeData {
778+
Node,
779+
CallSite,
780+
Arguments,
781+
Destruction,
782+
Remainder(first_statement_index)
783+
});
776784

777785
impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope {
778786
type KeyType = region::Scope;
@@ -783,11 +791,6 @@ impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope {
783791
}
784792
}
785793

786-
impl_stable_hash_for!(struct ::middle::region::BlockRemainder {
787-
block,
788-
first_statement_index
789-
});
790-
791794
impl_stable_hash_for!(struct ty::adjustment::CoerceUnsizedInfo {
792795
custom_kind
793796
});

src/librustc/infer/error_reporting/mod.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,17 +119,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
119119
}
120120
};
121121
let scope_decorated_tag = match scope.data() {
122-
region::ScopeData::Node(_) => tag,
123-
region::ScopeData::CallSite(_) => "scope of call-site for function",
124-
region::ScopeData::Arguments(_) => "scope of function body",
125-
region::ScopeData::Destruction(_) => {
122+
region::ScopeData::Node => tag,
123+
region::ScopeData::CallSite => "scope of call-site for function",
124+
region::ScopeData::Arguments => "scope of function body",
125+
region::ScopeData::Destruction => {
126126
new_string = format!("destruction scope surrounding {}", tag);
127127
&new_string[..]
128128
}
129-
region::ScopeData::Remainder(r) => {
129+
region::ScopeData::Remainder(first_statement_index) => {
130130
new_string = format!(
131131
"block suffix following statement {}",
132-
r.first_statement_index.index()
132+
first_statement_index.index()
133133
);
134134
&new_string[..]
135135
}

src/librustc/middle/region.rs

Lines changed: 36 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ use ich::{StableHashingContext, NodeIdHashingMode};
2020
use util::nodemap::{FxHashMap, FxHashSet};
2121
use ty;
2222

23-
use std::fmt;
2423
use std::mem;
2524
use rustc_data_structures::sync::Lrc;
2625
use syntax::source_map;
@@ -100,39 +99,29 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
10099
/// placate the same deriving in `ty::FreeRegion`, but we may want to
101100
/// actually attach a more meaningful ordering to scopes than the one
102101
/// generated via deriving here.
103-
///
104-
/// Scope is a bit-packed to save space - if `code` is SCOPE_DATA_REMAINDER_MAX
105-
/// or less, it is a `ScopeData::Remainder`, otherwise it is a type specified
106-
/// by the bitpacking.
107-
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy, RustcEncodable, RustcDecodable)]
102+
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)]
108103
pub struct Scope {
109104
pub(crate) id: hir::ItemLocalId,
110-
pub(crate) code: u32
105+
pub(crate) data: ScopeData,
111106
}
112107

113-
const SCOPE_DATA_NODE: u32 = 0xFFFF_FFFF;
114-
const SCOPE_DATA_CALLSITE: u32 = 0xFFFF_FFFE;
115-
const SCOPE_DATA_ARGUMENTS: u32 = 0xFFFF_FFFD;
116-
const SCOPE_DATA_DESTRUCTION: u32 = 0xFFFF_FFFC;
117-
// be sure to add the MAX of FirstStatementIndex if you add more constants here
118-
119108
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)]
120109
pub enum ScopeData {
121-
Node(hir::ItemLocalId),
110+
Node,
122111

123112
// Scope of the call-site for a function or closure
124113
// (outlives the arguments as well as the body).
125-
CallSite(hir::ItemLocalId),
114+
CallSite,
126115

127116
// Scope of arguments passed to a function or closure
128117
// (they outlive its body).
129-
Arguments(hir::ItemLocalId),
118+
Arguments,
130119

131120
// Scope of destructors for temporaries of node-id.
132-
Destruction(hir::ItemLocalId),
121+
Destruction,
133122

134123
// Scope following a `let id = expr;` binding in a block.
135-
Remainder(BlockRemainder)
124+
Remainder(FirstStatementIndex)
136125
}
137126

138127
/// Represents a subscope of `block` for a binding that is introduced
@@ -152,81 +141,61 @@ pub enum ScopeData {
152141
///
153142
/// * the subscope with `first_statement_index == 1` is scope of `c`,
154143
/// and thus does not include EXPR_2, but covers the `...`.
155-
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable,
156-
RustcDecodable, Debug, Copy)]
157-
pub struct BlockRemainder {
158-
pub block: hir::ItemLocalId,
159-
pub first_statement_index: FirstStatementIndex,
160-
}
161144
162145
newtype_index! {
163146
pub struct FirstStatementIndex;
164147
}
165148

166149
impl_stable_hash_for!(struct ::middle::region::FirstStatementIndex { private });
167150

168-
impl From<ScopeData> for Scope {
169-
#[inline]
170-
fn from(scope_data: ScopeData) -> Self {
171-
let (id, code) = match scope_data {
172-
ScopeData::Node(id) => (id, SCOPE_DATA_NODE),
173-
ScopeData::CallSite(id) => (id, SCOPE_DATA_CALLSITE),
174-
ScopeData::Arguments(id) => (id, SCOPE_DATA_ARGUMENTS),
175-
ScopeData::Destruction(id) => (id, SCOPE_DATA_DESTRUCTION),
176-
ScopeData::Remainder(r) => (r.block, r.first_statement_index.index() as u32)
177-
};
178-
Self { id, code }
179-
}
180-
}
181-
182-
impl fmt::Debug for Scope {
183-
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
184-
fmt::Debug::fmt(&self.data(), formatter)
185-
}
186-
}
151+
// compilation error if size of `ScopeData` is not the same as a `u32`
152+
#[allow(dead_code)]
153+
// only works on stage 1 when the rustc_layout_scalar_valid_range attribute actually exists
154+
#[cfg(not(stage0))]
155+
static ASSERT: () = [()][(mem::size_of::<ScopeData>() != 4) as usize];
187156

188157
#[allow(non_snake_case)]
189158
impl Scope {
190159
#[inline]
191160
pub fn data(self) -> ScopeData {
192-
match self.code {
193-
SCOPE_DATA_NODE => ScopeData::Node(self.id),
194-
SCOPE_DATA_CALLSITE => ScopeData::CallSite(self.id),
195-
SCOPE_DATA_ARGUMENTS => ScopeData::Arguments(self.id),
196-
SCOPE_DATA_DESTRUCTION => ScopeData::Destruction(self.id),
197-
idx => ScopeData::Remainder(BlockRemainder {
198-
block: self.id,
199-
first_statement_index: FirstStatementIndex::new(idx as usize)
200-
})
161+
self.data
201162
}
163+
164+
#[inline]
165+
pub fn new(id: hir::ItemLocalId, data: ScopeData) -> Self {
166+
Scope { id, data }
202167
}
203168

204169
#[inline]
205170
pub fn Node(id: hir::ItemLocalId) -> Self {
206-
Self::from(ScopeData::Node(id))
171+
Self::new(id, ScopeData::Node)
207172
}
208173

209174
#[inline]
210175
pub fn CallSite(id: hir::ItemLocalId) -> Self {
211-
Self::from(ScopeData::CallSite(id))
176+
Self::new(id, ScopeData::CallSite)
212177
}
213178

214179
#[inline]
215180
pub fn Arguments(id: hir::ItemLocalId) -> Self {
216-
Self::from(ScopeData::Arguments(id))
181+
Self::new(id, ScopeData::Arguments)
217182
}
218183

219184
#[inline]
220185
pub fn Destruction(id: hir::ItemLocalId) -> Self {
221-
Self::from(ScopeData::Destruction(id))
186+
Self::new(id, ScopeData::Destruction)
222187
}
223188

224189
#[inline]
225-
pub fn Remainder(r: BlockRemainder) -> Self {
226-
Self::from(ScopeData::Remainder(r))
190+
pub fn Remainder(
191+
id: hir::ItemLocalId,
192+
first: FirstStatementIndex,
193+
) -> Self {
194+
Self::new(id, ScopeData::Remainder(first))
227195
}
228196
}
229197

198+
230199
impl Scope {
231200
/// Returns a item-local id associated with this scope.
232201
///
@@ -257,7 +226,7 @@ impl Scope {
257226
return DUMMY_SP;
258227
}
259228
let span = tcx.hir.span(node_id);
260-
if let ScopeData::Remainder(r) = self.data() {
229+
if let ScopeData::Remainder(first_statement_index) = self.data() {
261230
if let Node::Block(ref blk) = tcx.hir.get(node_id) {
262231
// Want span for scope starting after the
263232
// indexed statement and ending at end of
@@ -267,7 +236,7 @@ impl Scope {
267236
// (This is the special case aluded to in the
268237
// doc-comment for this method)
269238

270-
let stmt_span = blk.stmts[r.first_statement_index.index()].span;
239+
let stmt_span = blk.stmts[first_statement_index.index()].span;
271240

272241
// To avoid issues with macro-generated spans, the span
273242
// of the statement must be nested in that of the block.
@@ -511,8 +480,8 @@ impl<'tcx> ScopeTree {
511480
}
512481

513482
// record the destruction scopes for later so we can query them
514-
if let ScopeData::Destruction(n) = child.data() {
515-
self.destruction_scopes.insert(n, child);
483+
if let ScopeData::Destruction = child.data() {
484+
self.destruction_scopes.insert(child.item_local_id(), child);
516485
}
517486
}
518487

@@ -595,7 +564,7 @@ impl<'tcx> ScopeTree {
595564

596565
while let Some(&(p, _)) = self.parent_map.get(&id) {
597566
match p.data() {
598-
ScopeData::Destruction(..) => {
567+
ScopeData::Destruction => {
599568
debug!("temporary_scope({:?}) = {:?} [enclosing]",
600569
expr_id, id);
601570
return Some(id);
@@ -650,8 +619,8 @@ impl<'tcx> ScopeTree {
650619
/// Returns the id of the innermost containing body
651620
pub fn containing_body(&self, mut scope: Scope)-> Option<hir::ItemLocalId> {
652621
loop {
653-
if let ScopeData::CallSite(id) = scope.data() {
654-
return Some(id);
622+
if let ScopeData::CallSite = scope.data() {
623+
return Some(scope.item_local_id());
655624
}
656625

657626
match self.opt_encl_scope(scope) {
@@ -867,10 +836,7 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk:
867836
// except for the first such subscope, which has the
868837
// block itself as a parent.
869838
visitor.enter_scope(
870-
Scope::Remainder(BlockRemainder {
871-
block: blk.hir_id.local_id,
872-
first_statement_index: FirstStatementIndex::new(i)
873-
})
839+
Scope::Remainder(blk.hir_id.local_id, FirstStatementIndex::new(i))
874840
);
875841
visitor.cx.var_parent = visitor.cx.parent;
876842
}
@@ -1033,7 +999,7 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr:
1033999
match visitor.scope_tree.parent_map.get(&scope) {
10341000
// Don't cross from closure bodies to their parent.
10351001
Some(&(superscope, _)) => match superscope.data() {
1036-
ScopeData::CallSite(_) => break,
1002+
ScopeData::CallSite => break,
10371003
_ => scope = superscope
10381004
},
10391005
None => break

src/librustc/util/ppaux.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use hir::def_id::DefId;
1212
use hir::map::definitions::DefPathData;
1313
use mir::interpret::ConstValue;
14-
use middle::region::{self, BlockRemainder};
14+
use middle::region;
1515
use ty::subst::{self, Subst};
1616
use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
1717
use ty::{Bool, Char, Adt};
@@ -770,17 +770,20 @@ define_print! {
770770
}
771771
ty::ReScope(scope) if cx.identify_regions => {
772772
match scope.data() {
773-
region::ScopeData::Node(id) =>
774-
write!(f, "'{}s", id.as_usize()),
775-
region::ScopeData::CallSite(id) =>
776-
write!(f, "'{}cs", id.as_usize()),
777-
region::ScopeData::Arguments(id) =>
778-
write!(f, "'{}as", id.as_usize()),
779-
region::ScopeData::Destruction(id) =>
780-
write!(f, "'{}ds", id.as_usize()),
781-
region::ScopeData::Remainder(BlockRemainder
782-
{ block, first_statement_index }) =>
783-
write!(f, "'{}_{}rs", block.as_usize(), first_statement_index.index()),
773+
region::ScopeData::Node =>
774+
write!(f, "'{}s", scope.item_local_id().as_usize()),
775+
region::ScopeData::CallSite =>
776+
write!(f, "'{}cs", scope.item_local_id().as_usize()),
777+
region::ScopeData::Arguments =>
778+
write!(f, "'{}as", scope.item_local_id().as_usize()),
779+
region::ScopeData::Destruction =>
780+
write!(f, "'{}ds", scope.item_local_id().as_usize()),
781+
region::ScopeData::Remainder(first_statement_index) => write!(
782+
f,
783+
"'{}_{}rs",
784+
scope.item_local_id().as_usize(),
785+
first_statement_index.index()
786+
),
784787
}
785788
}
786789
ty::ReVar(region_vid) if cx.identify_regions => {

src/librustc_data_structures/indexed_vec.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ macro_rules! newtype_index {
7272
newtype_index!(
7373
// Leave out derives marker so we can use its absence to ensure it comes first
7474
@type [$name]
75-
@max [0xFFFF_FFFE]
75+
// shave off 256 indices at the end to allow space for packing these indices into enums
76+
@max [0xFFFF_FF00]
7677
@vis [$v]
7778
@debug_format ["{}"]);
7879
);
@@ -82,7 +83,8 @@ macro_rules! newtype_index {
8283
newtype_index!(
8384
// Leave out derives marker so we can use its absence to ensure it comes first
8485
@type [$name]
85-
@max [0xFFFF_FFFE]
86+
// shave off 256 indices at the end to allow space for packing these indices into enums
87+
@max [0xFFFF_FF00]
8688
@vis [$v]
8789
@debug_format ["{}"]
8890
$($tokens)+);

src/librustc_mir/build/cfg.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl<'tcx> CFG<'tcx> {
5151
source_info: SourceInfo,
5252
region_scope: region::Scope) {
5353
if tcx.emit_end_regions() {
54-
if let region::ScopeData::CallSite(_) = region_scope.data() {
54+
if let region::ScopeData::CallSite = region_scope.data() {
5555
// The CallSite scope (aka the root scope) is sort of weird, in that it is
5656
// supposed to "separate" the "interior" and "exterior" of a closure. Being
5757
// that, it is not really a part of the region hierarchy, but for some

src/librustc_mir/build/scope.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
566566
// We want `scopes[1]`, which is the `ParameterScope`.
567567
assert!(self.scopes.len() >= 2);
568568
assert!(match self.scopes[1].region_scope.data() {
569-
region::ScopeData::Arguments(_) => true,
569+
region::ScopeData::Arguments => true,
570570
_ => false,
571571
});
572572
self.scopes[1].region_scope

src/librustc_mir/hair/cx/block.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use hair::*;
1212
use hair::cx::Cx;
1313
use hair::cx::to_ref::ToRef;
14-
use rustc::middle::region::{self, BlockRemainder};
14+
use rustc::middle::region;
1515
use rustc::hir;
1616

1717
use rustc_data_structures::indexed_vec::Idx;
@@ -71,10 +71,10 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
7171
// ignore for purposes of the MIR
7272
}
7373
hir::DeclKind::Local(ref local) => {
74-
let remainder_scope = region::Scope::Remainder(BlockRemainder {
75-
block: block_id,
76-
first_statement_index: region::FirstStatementIndex::new(index),
77-
});
74+
let remainder_scope = region::Scope::Remainder(
75+
block_id,
76+
region::FirstStatementIndex::new(index),
77+
);
7878

7979
let ty = local.ty.clone().map(|ty| ty.hir_id);
8080
let pattern = cx.pattern_from_hir(&local.pat);

0 commit comments

Comments
 (0)