Skip to content

Commit c005748

Browse files
committed
Ensure borrows of fn/closure params do not outlive invocations.
resolve_lifetime.rs: Switch from BlockScope to FnScope in ScopeChain construction. Lifetimes introduced by a fn signature are scoped to the call-site for that fn. (Note `add_scope_and_walk_fn` must only add FnScope for the walk of body, *not* of the fn signature.) region.rs: Introduce new CodeExtentData::CallSiteScope variant. Use CodeExtentData as the cx.parent, rather than just a NodeId. Change DestructionScopeData to CallSiteScopeData. regionck.rs: Thread call_site_scope via Rcx; constrain fn return values. (update; incorporated review feedback from niko.)
1 parent 4dbdfb4 commit c005748

File tree

16 files changed

+170
-96
lines changed

16 files changed

+170
-96
lines changed

src/librustc/middle/infer/error_reporting.rs

+3
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ impl<'tcx> ty::ctxt<'tcx> {
148148
};
149149
let scope_decorated_tag = match self.region_maps.code_extent_data(scope) {
150150
region::CodeExtentData::Misc(_) => tag,
151+
region::CodeExtentData::CallSiteScope { .. } => {
152+
"scope of call-site for function"
153+
}
151154
region::CodeExtentData::ParameterScope { .. } => {
152155
"scope of parameters for function"
153156
}

src/librustc/middle/liveness.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1466,10 +1466,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
14661466
entry_ln: LiveNode,
14671467
body: &hir::Block)
14681468
{
1469-
// within the fn body, late-bound regions are liberated:
1469+
// within the fn body, late-bound regions are liberated
1470+
// and must outlive the *call-site* of the function.
14701471
let fn_ret =
14711472
self.ir.tcx.liberate_late_bound_regions(
1472-
self.ir.tcx.region_maps.item_extent(body.id),
1473+
self.ir.tcx.region_maps.call_site_extent(id, body.id),
14731474
&self.fn_ret(id));
14741475

14751476
match fn_ret {

src/librustc/middle/region.rs

+21-8
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ pub const DUMMY_CODE_EXTENT : CodeExtent = CodeExtent(1);
125125
pub enum CodeExtentData {
126126
Misc(ast::NodeId),
127127

128+
// extent of the call-site for a function or closure (outlives
129+
// the parameters as well as the body).
130+
CallSiteScope { fn_id: ast::NodeId, body_id: ast::NodeId },
131+
128132
// extent of parameters passed to a function or closure (they
129133
// outlive its body)
130134
ParameterScope { fn_id: ast::NodeId, body_id: ast::NodeId },
@@ -136,20 +140,20 @@ pub enum CodeExtentData {
136140
Remainder(BlockRemainder)
137141
}
138142

139-
/// extent of destructors for temporaries of node-id
143+
/// extent of call-site for a function/method.
140144
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable,
141145
RustcDecodable, Debug, Copy)]
142-
pub struct DestructionScopeData {
143-
pub node_id: ast::NodeId
146+
pub struct CallSiteScopeData {
147+
pub fn_id: ast::NodeId, pub body_id: ast::NodeId,
144148
}
145149

146-
impl DestructionScopeData {
147-
pub fn new(node_id: ast::NodeId) -> DestructionScopeData {
148-
DestructionScopeData { node_id: node_id }
149-
}
150+
impl CallSiteScopeData {
150151
pub fn to_code_extent(&self, region_maps: &RegionMaps) -> CodeExtent {
151152
region_maps.lookup_code_extent(
152-
CodeExtentData::DestructionScope(self.node_id))
153+
match *self {
154+
CallSiteScopeData { fn_id, body_id } =>
155+
CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id },
156+
})
153157
}
154158
}
155159

@@ -190,6 +194,7 @@ impl CodeExtentData {
190194
// precise extent denoted by `self`.
191195
CodeExtentData::Remainder(br) => br.block,
192196
CodeExtentData::DestructionScope(node_id) => node_id,
197+
CodeExtentData::CallSiteScope { fn_id: _, body_id } |
193198
CodeExtentData::ParameterScope { fn_id: _, body_id } => body_id,
194199
}
195200
}
@@ -215,6 +220,7 @@ impl CodeExtent {
215220
match ast_map.find(self.node_id(region_maps)) {
216221
Some(ast_map::NodeBlock(ref blk)) => {
217222
match region_maps.code_extent_data(*self) {
223+
CodeExtentData::CallSiteScope { .. } |
218224
CodeExtentData::ParameterScope { .. } |
219225
CodeExtentData::Misc(_) |
220226
CodeExtentData::DestructionScope(_) => Some(blk.span),
@@ -346,6 +352,10 @@ impl RegionMaps {
346352
pub fn item_extent(&self, n: ast::NodeId) -> CodeExtent {
347353
self.lookup_code_extent(CodeExtentData::DestructionScope(n))
348354
}
355+
pub fn call_site_extent(&self, fn_id: ast::NodeId, body_id: ast::NodeId) -> CodeExtent {
356+
assert!(fn_id != body_id);
357+
self.lookup_code_extent(CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id })
358+
}
349359
pub fn opt_destruction_extent(&self, n: ast::NodeId) -> Option<CodeExtent> {
350360
self.code_extent_interner.borrow().get(&CodeExtentData::DestructionScope(n)).cloned()
351361
}
@@ -1101,6 +1111,9 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor,
11011111
body.id,
11021112
visitor.cx.parent);
11031113

1114+
visitor.cx.parent = visitor.new_code_extent(
1115+
CodeExtentData::CallSiteScope { fn_id: id, body_id: body.id });
1116+
11041117
let fn_decl_scope = visitor.new_code_extent(
11051118
CodeExtentData::ParameterScope { fn_id: id, body_id: body.id });
11061119

src/librustc/middle/resolve_lifetime.rs

+30-31
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pub enum DefRegion {
4242
/* lifetime decl */ ast::NodeId),
4343
DefLateBoundRegion(ty::DebruijnIndex,
4444
/* lifetime decl */ ast::NodeId),
45-
DefFreeRegion(/* block scope */ region::DestructionScopeData,
45+
DefFreeRegion(region::CallSiteScopeData,
4646
/* lifetime decl */ ast::NodeId),
4747
}
4848

@@ -83,9 +83,9 @@ enum ScopeChain<'a> {
8383
/// LateScope(['a, 'b, ...], s) extends s with late-bound
8484
/// lifetimes introduced by the declaration binder_id.
8585
LateScope(&'a Vec<hir::LifetimeDef>, Scope<'a>),
86-
/// lifetimes introduced by items within a code block are scoped
87-
/// to that block.
88-
BlockScope(region::DestructionScopeData, Scope<'a>),
86+
87+
/// lifetimes introduced by a fn are scoped to the call-site for that fn.
88+
FnScope { fn_id: ast::NodeId, body_id: ast::NodeId, s: Scope<'a> },
8989
RootScope
9090
}
9191

@@ -172,20 +172,20 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
172172
}
173173

174174
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
175-
b: &'v hir::Block, s: Span, _: ast::NodeId) {
175+
b: &'v hir::Block, s: Span, fn_id: ast::NodeId) {
176176
match fk {
177177
FnKind::ItemFn(_, generics, _, _, _, _) => {
178178
self.visit_early_late(subst::FnSpace, generics, |this| {
179-
this.walk_fn(fk, fd, b, s)
179+
this.add_scope_and_walk_fn(fk, fd, b, s, fn_id)
180180
})
181181
}
182182
FnKind::Method(_, sig, _) => {
183183
self.visit_early_late(subst::FnSpace, &sig.generics, |this| {
184-
this.walk_fn(fk, fd, b, s)
184+
this.add_scope_and_walk_fn(fk, fd, b, s, fn_id)
185185
})
186186
}
187187
FnKind::Closure => {
188-
self.walk_fn(fk, fd, b, s)
188+
self.add_scope_and_walk_fn(fk, fd, b, s, fn_id)
189189
}
190190
}
191191
}
@@ -236,12 +236,6 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
236236
replace(&mut self.labels_in_fn, saved);
237237
}
238238

239-
fn visit_block(&mut self, b: &hir::Block) {
240-
self.with(BlockScope(region::DestructionScopeData::new(b.id),
241-
self.scope),
242-
|_, this| intravisit::walk_block(this, b));
243-
}
244-
245239
fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) {
246240
if lifetime_ref.name == special_idents::static_lifetime.name {
247241
self.insert_lifetime(lifetime_ref, DefStaticRegion);
@@ -437,7 +431,7 @@ fn extract_labels<'v, 'a>(ctxt: &mut LifetimeContext<'a>, b: &'v hir::Block) {
437431
label_span: Span) {
438432
loop {
439433
match *scope {
440-
BlockScope(_, s) => { scope = s; }
434+
FnScope { s, .. } => { scope = s; }
441435
RootScope => { return; }
442436

443437
EarlyScope(_, lifetimes, s) |
@@ -461,14 +455,13 @@ fn extract_labels<'v, 'a>(ctxt: &mut LifetimeContext<'a>, b: &'v hir::Block) {
461455
}
462456

463457
impl<'a> LifetimeContext<'a> {
464-
// This is just like intravisit::walk_fn, except that it extracts the
465-
// labels of the function body and swaps them in before visiting
466-
// the function body itself.
467-
fn walk_fn<'b>(&mut self,
468-
fk: FnKind,
469-
fd: &hir::FnDecl,
470-
fb: &'b hir::Block,
471-
_span: Span) {
458+
fn add_scope_and_walk_fn<'b>(&mut self,
459+
fk: FnKind,
460+
fd: &hir::FnDecl,
461+
fb: &'b hir::Block,
462+
_span: Span,
463+
fn_id: ast::NodeId) {
464+
472465
match fk {
473466
FnKind::ItemFn(_, generics, _, _, _, _) => {
474467
intravisit::walk_fn_decl(self, fd);
@@ -488,7 +481,8 @@ impl<'a> LifetimeContext<'a> {
488481
// `self.labels_in_fn`.
489482
extract_labels(self, fb);
490483

491-
self.visit_block(fb);
484+
self.with(FnScope { fn_id: fn_id, body_id: fb.id, s: self.scope },
485+
|_old_scope, this| this.visit_block(fb))
492486
}
493487

494488
fn with<F>(&mut self, wrap_scope: ScopeChain, f: F) where
@@ -559,8 +553,11 @@ impl<'a> LifetimeContext<'a> {
559553
let mut scope = self.scope;
560554
loop {
561555
match *scope {
562-
BlockScope(blk_scope, s) => {
563-
return self.resolve_free_lifetime_ref(blk_scope, lifetime_ref, s);
556+
FnScope {fn_id, body_id, s } => {
557+
return self.resolve_free_lifetime_ref(
558+
region::CallSiteScopeData { fn_id: fn_id, body_id: body_id },
559+
lifetime_ref,
560+
s);
564561
}
565562

566563
RootScope => {
@@ -604,7 +601,7 @@ impl<'a> LifetimeContext<'a> {
604601
}
605602

606603
fn resolve_free_lifetime_ref(&mut self,
607-
scope_data: region::DestructionScopeData,
604+
scope_data: region::CallSiteScopeData,
608605
lifetime_ref: &hir::Lifetime,
609606
scope: Scope) {
610607
debug!("resolve_free_lifetime_ref \
@@ -622,8 +619,10 @@ impl<'a> LifetimeContext<'a> {
622619
scope_data: {:?} scope: {:?} search_result: {:?}",
623620
scope_data, scope, search_result);
624621
match *scope {
625-
BlockScope(blk_scope_data, s) => {
626-
scope_data = blk_scope_data;
622+
FnScope { fn_id, body_id, s } => {
623+
scope_data = region::CallSiteScopeData {
624+
fn_id: fn_id, body_id: body_id
625+
};
627626
scope = s;
628627
}
629628

@@ -711,7 +710,7 @@ impl<'a> LifetimeContext<'a> {
711710

712711
loop {
713712
match *old_scope {
714-
BlockScope(_, s) => {
713+
FnScope { s, .. } => {
715714
old_scope = s;
716715
}
717716

@@ -864,7 +863,7 @@ impl<'a> fmt::Debug for ScopeChain<'a> {
864863
match *self {
865864
EarlyScope(space, defs, _) => write!(fmt, "EarlyScope({:?}, {:?})", space, defs),
866865
LateScope(defs, _) => write!(fmt, "LateScope({:?})", defs),
867-
BlockScope(id, _) => write!(fmt, "BlockScope({:?})", id),
866+
FnScope { fn_id, body_id, s: _ } => write!(fmt, "FnScope({:?}, {:?})", fn_id, body_id),
868867
RootScope => write!(fmt, "RootScope"),
869868
}
870869
}

src/librustc/middle/traits/object_safety.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,8 @@ fn generics_require_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
192192
};
193193

194194
// Search for a predicate like `Self : Sized` amongst the trait bounds.
195-
let free_substs = tcx.construct_free_substs(generics, ast::DUMMY_NODE_ID);
195+
let free_substs = tcx.construct_free_substs(generics,
196+
tcx.region_maps.node_extent(ast::DUMMY_NODE_ID));
196197
let predicates = predicates.instantiate(tcx, &free_substs).predicates.into_vec();
197198
elaborate_predicates(tcx, predicates)
198199
.any(|predicate| {

0 commit comments

Comments
 (0)