Skip to content

Commit 2fe870a

Browse files
committed
Auto merge of #26831 - arielb1:lifetime-fixes, r=nikomatsakis
r? @nikomatsakis
2 parents 47265bb + 28ce509 commit 2fe870a

File tree

7 files changed

+118
-30
lines changed

7 files changed

+118
-30
lines changed

src/librustc/middle/free_region.rs

+23-7
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,21 @@
1313
use middle::implicator::Implication;
1414
use middle::ty::{self, FreeRegion};
1515
use util::common::can_reach;
16-
use util::nodemap::FnvHashMap;
16+
use util::nodemap::{FnvHashMap, FnvHashSet};
1717

1818
#[derive(Clone)]
1919
pub struct FreeRegionMap {
20-
/// `free_region_map` maps from a free region `a` to a list of
20+
/// `map` maps from a free region `a` to a list of
2121
/// free regions `bs` such that `a <= b for all b in bs`
2222
map: FnvHashMap<FreeRegion, Vec<FreeRegion>>,
23+
/// regions that are required to outlive (and therefore be
24+
/// equal to) 'static.
25+
statics: FnvHashSet<FreeRegion>
2326
}
2427

2528
impl FreeRegionMap {
2629
pub fn new() -> FreeRegionMap {
27-
FreeRegionMap { map: FnvHashMap() }
30+
FreeRegionMap { map: FnvHashMap(), statics: FnvHashSet() }
2831
}
2932

3033
pub fn relate_free_regions_from_implications<'tcx>(&mut self,
@@ -59,6 +62,8 @@ impl FreeRegionMap {
5962
}
6063
ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r_a, r_b))) => {
6164
match (r_a, r_b) {
65+
(ty::ReStatic, ty::ReFree(_)) => {},
66+
(ty::ReFree(fr_a), ty::ReStatic) => self.relate_to_static(fr_a),
6267
(ty::ReFree(fr_a), ty::ReFree(fr_b)) => {
6368
// Record that `'a:'b`. Or, put another way, `'b <= 'a`.
6469
self.relate_free_regions(fr_b, fr_a);
@@ -76,8 +81,12 @@ impl FreeRegionMap {
7681
}
7782
}
7883

79-
pub fn relate_free_regions(&mut self, sub: FreeRegion, sup: FreeRegion) {
80-
let mut sups = self.map.entry(sub).or_insert(Vec::new());
84+
fn relate_to_static(&mut self, sup: FreeRegion) {
85+
self.statics.insert(sup);
86+
}
87+
88+
fn relate_free_regions(&mut self, sub: FreeRegion, sup: FreeRegion) {
89+
let mut sups = self.map.entry(sub).or_insert(Vec::new());
8190
if !sups.contains(&sup) {
8291
sups.push(sup);
8392
}
@@ -88,7 +97,7 @@ impl FreeRegionMap {
8897
/// it is possible that `sub != sup` and `sub <= sup` and `sup <= sub`
8998
/// (that is, the user can give two different names to the same lifetime).
9099
pub fn sub_free_region(&self, sub: FreeRegion, sup: FreeRegion) -> bool {
91-
can_reach(&self.map, sub, sup)
100+
can_reach(&self.map, sub, sup) || self.is_static(&sup)
92101
}
93102

94103
/// Determines whether one region is a subregion of another. This is intended to run *after
@@ -116,10 +125,17 @@ impl FreeRegionMap {
116125
(ty::ReFree(sub_fr), ty::ReFree(super_fr)) =>
117126
self.sub_free_region(sub_fr, super_fr),
118127

128+
(ty::ReStatic, ty::ReFree(ref sup_fr)) => self.is_static(sup_fr),
129+
119130
_ =>
120131
false,
121132
}
122133
}
123134
}
124-
}
125135

136+
/// Determines whether this free-region is required to be 'static
137+
pub fn is_static(&self, super_region: &ty::FreeRegion) -> bool {
138+
debug!("is_static(super_region={:?})", super_region);
139+
self.statics.iter().any(|s| can_reach(&self.map, *s, *super_region))
140+
}
141+
}

src/librustc/middle/infer/region_inference/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
869869
// is the scope `s_id`. Otherwise, as we do not know
870870
// big the free region is precisely, the GLB is undefined.
871871
let fr_scope = fr.scope.to_code_extent();
872-
if self.tcx.region_maps.nearest_common_ancestor(fr_scope, s_id) == fr_scope {
872+
if self.tcx.region_maps.nearest_common_ancestor(fr_scope, s_id) == fr_scope ||
873+
free_regions.is_static(fr) {
873874
Ok(s)
874875
} else {
875876
Err(TypeError::RegionsNoOverlap(b, a))

src/librustc_trans/trans/common.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -905,11 +905,13 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
905905
let vtable = selection.map(|predicate| {
906906
fulfill_cx.register_predicate_obligation(&infcx, predicate);
907907
});
908-
let vtable = drain_fulfillment_cx_or_panic(span, &infcx, &mut fulfill_cx, &vtable);
908+
let vtable = erase_regions(tcx,
909+
&drain_fulfillment_cx_or_panic(span, &infcx, &mut fulfill_cx, &vtable)
910+
);
909911

910-
info!("Cache miss: {:?}", trait_ref);
911-
ccx.trait_cache().borrow_mut().insert(trait_ref,
912-
vtable.clone());
912+
info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
913+
914+
ccx.trait_cache().borrow_mut().insert(trait_ref, vtable.clone());
913915

914916
vtable
915917
}

src/librustc_typeck/astconv.rs

+12-18
Original file line numberDiff line numberDiff line change
@@ -1112,7 +1112,7 @@ fn report_ambiguous_associated_type(tcx: &ty::ctxt,
11121112
// any ambiguity.
11131113
fn find_bound_for_assoc_item<'tcx>(this: &AstConv<'tcx>,
11141114
ty_param_node_id: ast::NodeId,
1115-
ty_param_name: Option<ast::Name>,
1115+
ty_param_name: ast::Name,
11161116
assoc_name: ast::Name,
11171117
span: Span)
11181118
-> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
@@ -1138,21 +1138,11 @@ fn find_bound_for_assoc_item<'tcx>(this: &AstConv<'tcx>,
11381138
.filter(|b| this.trait_defines_associated_type_named(b.def_id(), assoc_name))
11391139
.collect();
11401140

1141-
if let Some(s) = ty_param_name {
1142-
// borrowck doesn't like this any other way
1143-
one_bound_for_assoc_type(tcx,
1144-
suitable_bounds,
1145-
&token::get_name(s),
1146-
&token::get_name(assoc_name),
1147-
span)
1148-
} else {
1149-
one_bound_for_assoc_type(tcx,
1150-
suitable_bounds,
1151-
"Self",
1152-
&token::get_name(assoc_name),
1153-
span)
1154-
1155-
}
1141+
one_bound_for_assoc_type(tcx,
1142+
suitable_bounds,
1143+
&token::get_name(ty_param_name),
1144+
&token::get_name(assoc_name),
1145+
span)
11561146
}
11571147

11581148

@@ -1251,7 +1241,11 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
12511241
}
12521242
(&ty::TyParam(_), def::DefSelfTy(Some(trait_did), None)) => {
12531243
assert_eq!(trait_did.krate, ast::LOCAL_CRATE);
1254-
match find_bound_for_assoc_item(this, trait_did.node, None, assoc_name, span) {
1244+
match find_bound_for_assoc_item(this,
1245+
trait_did.node,
1246+
token::special_idents::type_self.name,
1247+
assoc_name,
1248+
span) {
12551249
Ok(bound) => bound,
12561250
Err(ErrorReported) => return (tcx.types.err, ty_path_def),
12571251
}
@@ -1260,7 +1254,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
12601254
assert_eq!(param_did.krate, ast::LOCAL_CRATE);
12611255
match find_bound_for_assoc_item(this,
12621256
param_did.node,
1263-
Some(param_name),
1257+
param_name,
12641258
assoc_name,
12651259
span) {
12661260
Ok(bound) => bound,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn static_id<'a,'b>(t: &'a ()) -> &'static ()
12+
where 'a: 'static { t }
13+
fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
14+
where 'a: 'b, 'b: 'static { t }
15+
fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
16+
t //~ ERROR cannot infer an appropriate lifetime
17+
}
18+
19+
fn error(u: &(), v: &()) {
20+
static_id(&u); //~ ERROR cannot infer an appropriate lifetime
21+
static_id_indirect(&v); //~ ERROR cannot infer an appropriate lifetime
22+
}
23+
24+
fn main() {}

src/test/run-pass/issue-26802.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
trait Foo<'a> {
12+
fn bar<'b>(&self, x: &'b u8) -> u8 where 'a: 'b { *x+7 }
13+
}
14+
15+
pub struct FooBar;
16+
impl Foo<'static> for FooBar {}
17+
fn test(foobar: FooBar) -> Box<Foo<'static>> {
18+
Box::new(foobar)
19+
}
20+
21+
fn main() {
22+
assert_eq!(test(FooBar).bar(&4), 11);
23+
}
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn invariant_id<'a,'b>(t: &'b mut &'static ()) -> &'b mut &'a ()
12+
where 'a: 'static { t }
13+
fn static_id<'a>(t: &'a ()) -> &'static ()
14+
where 'a: 'static { t }
15+
fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
16+
where 'a: 'b, 'b: 'static { t }
17+
fn ref_id<'a>(t: &'a ()) -> &'a () where 'static: 'a { t }
18+
19+
static UNIT: () = ();
20+
21+
fn main()
22+
{
23+
let mut val : &'static () = &UNIT;
24+
invariant_id(&mut val);
25+
static_id(val);
26+
static_id_indirect(val);
27+
ref_id(val);
28+
}

0 commit comments

Comments
 (0)