Skip to content

Commit 7ba288d

Browse files
committed
Unify the upvar variables found in closures with the actual types of the
upvars after analysis is done. Remove the `closure_upvars` helper and just consult this list of type variables directly.
1 parent a551697 commit 7ba288d

File tree

12 files changed

+215
-253
lines changed

12 files changed

+215
-253
lines changed

src/librustc/middle/free_region.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ impl FreeRegionMap {
4040
self.relate_free_regions(free_a, free_b);
4141
}
4242
Implication::RegionSubRegion(..) |
43-
Implication::RegionSubClosure(..) |
4443
Implication::RegionSubGeneric(..) |
4544
Implication::Predicate(..) => {
4645
}

src/librustc/middle/implicator.rs

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ use util::nodemap::FnvHashSet;
2828
pub enum Implication<'tcx> {
2929
RegionSubRegion(Option<Ty<'tcx>>, ty::Region, ty::Region),
3030
RegionSubGeneric(Option<Ty<'tcx>>, ty::Region, GenericKind<'tcx>),
31-
RegionSubClosure(Option<Ty<'tcx>>, ty::Region, ast::DefId, &'tcx ty::ClosureSubsts<'tcx>),
3231
Predicate(ast::DefId, ty::Predicate<'tcx>),
3332
}
3433

@@ -96,10 +95,47 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
9695
// No borrowed content reachable here.
9796
}
9897

99-
ty::TyClosure(def_id, ref substs) => {
100-
// TODO remove RegionSubClosure
101-
let &(r_a, opt_ty) = self.stack.last().unwrap();
102-
self.out.push(Implication::RegionSubClosure(opt_ty, r_a, def_id, substs));
98+
ty::TyClosure(_, ref substs) => {
99+
// FIXME(#27086). We do not accumulate from substs, since they
100+
// don't represent reachable data. This means that, in
101+
// practice, some of the lifetime parameters might not
102+
// be in scope when the body runs, so long as there is
103+
// no reachable data with that lifetime. For better or
104+
// worse, this is consistent with fn types, however,
105+
// which can also encapsulate data in this fashion
106+
// (though it's somewhat harder, and typically
107+
// requires virtual dispatch).
108+
//
109+
// Note that changing this (in a naive way, at least)
110+
// causes regressions for what appears to be perfectly
111+
// reasonable code like this:
112+
//
113+
// ```
114+
// fn foo<'a>(p: &Data<'a>) {
115+
// bar(|q: &mut Parser| q.read_addr())
116+
// }
117+
// fn bar(p: Box<FnMut(&mut Parser)+'static>) {
118+
// }
119+
// ```
120+
//
121+
// Note that `p` (and `'a`) are not used in the
122+
// closure at all, but to meet the requirement that
123+
// the closure type `C: 'static` (so it can be coerce
124+
// to the object type), we get the requirement that
125+
// `'a: 'static` since `'a` appears in the closure
126+
// type `C`.
127+
//
128+
// A smarter fix might "prune" unused `func_substs` --
129+
// this would avoid breaking simple examples like
130+
// this, but would still break others (which might
131+
// indeed be invalid, depending on your POV). Pruning
132+
// would be a subtle process, since we have to see
133+
// what func/type parameters are used and unused,
134+
// taking into consideration UFCS and so forth.
135+
136+
for &upvar_ty in &substs.upvar_tys {
137+
self.accumulate_from_ty(upvar_ty);
138+
}
103139
}
104140

105141
ty::TyTrait(ref t) => {
@@ -274,6 +310,21 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
274310
self.out.extend(obligations);
275311

276312
let variances = self.tcx().item_variances(def_id);
313+
self.accumulate_from_substs(substs, Some(&variances));
314+
}
315+
316+
fn accumulate_from_substs(&mut self,
317+
substs: &Substs<'tcx>,
318+
variances: Option<&ty::ItemVariances>)
319+
{
320+
let mut tmp_variances = None;
321+
let variances = variances.unwrap_or_else(|| {
322+
tmp_variances = Some(ty::ItemVariances {
323+
types: substs.types.map(|_| ty::Variance::Invariant),
324+
regions: substs.regions().map(|_| ty::Variance::Invariant),
325+
});
326+
tmp_variances.as_ref().unwrap()
327+
});
277328

278329
for (&region, &variance) in substs.regions().iter().zip(&variances.regions) {
279330
match variance {

src/librustc/middle/infer/mod.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,20 +1399,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
13991399
closure_ty
14001400
}
14011401
}
1402-
1403-
pub fn closure_upvars(&self,
1404-
def_id: ast::DefId,
1405-
substs: &ty::ClosureSubsts<'tcx>)
1406-
-> Option<Vec<ty::ClosureUpvar<'tcx>>>
1407-
{
1408-
let result = ty::ctxt::closure_upvars(self, def_id, substs);
1409-
1410-
if self.normalize {
1411-
normalize_associated_type(&self.tcx, &result)
1412-
} else {
1413-
result
1414-
}
1415-
}
14161402
}
14171403

14181404
impl<'tcx> TypeTrace<'tcx> {

src/librustc/middle/traits/select.rs

Lines changed: 29 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,22 +1284,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12841284
candidates.ambiguous = true;
12851285
}
12861286
_ => {
1287-
if self.constituent_types_for_ty(self_ty).is_some() {
1288-
candidates.vec.push(DefaultImplCandidate(def_id.clone()))
1289-
} else {
1290-
// We don't yet know what the constituent
1291-
// types are. So call it ambiguous for now,
1292-
// though this is a bit stronger than
1293-
// necessary: that is, we know that the
1294-
// defaulted impl applies, but we can't
1295-
// process the confirmation step without
1296-
// knowing the constituent types. (Anyway, in
1297-
// the particular case of defaulted impls, it
1298-
// doesn't really matter much either way,
1299-
// since we won't be aiding inference by
1300-
// processing the confirmation step.)
1301-
candidates.ambiguous = true;
1302-
}
1287+
candidates.vec.push(DefaultImplCandidate(def_id.clone()))
13031288
}
13041289
}
13051290
}
@@ -1729,14 +1714,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
17291714
return ok_if(Vec::new());
17301715
}
17311716

1732-
// TODO
1733-
match self.infcx.closure_upvars(def_id, substs) {
1734-
Some(upvars) => ok_if(upvars.iter().map(|c| c.ty).collect()),
1735-
None => {
1736-
debug!("assemble_builtin_bound_candidates: no upvar types available yet");
1737-
Ok(AmbiguousBuiltin)
1738-
}
1739-
}
1717+
ok_if(substs.upvar_tys.clone())
17401718
}
17411719

17421720
ty::TyStruct(def_id, substs) => {
@@ -1819,7 +1797,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
18191797
/// Bar<i32> where struct Bar<T> { x: T, y: u32 } -> [i32, u32]
18201798
/// Zed<i32> where enum Zed { A(T), B(u32) } -> [i32, u32]
18211799
/// ```
1822-
fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Option<Vec<Ty<'tcx>>> {
1800+
fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
18231801
match t.sty {
18241802
ty::TyUint(_) |
18251803
ty::TyInt(_) |
@@ -1831,7 +1809,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
18311809
ty::TyInfer(ty::IntVar(_)) |
18321810
ty::TyInfer(ty::FloatVar(_)) |
18331811
ty::TyChar => {
1834-
Some(Vec::new())
1812+
Vec::new()
18351813
}
18361814

18371815
ty::TyTrait(..) |
@@ -1848,56 +1826,56 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
18481826
}
18491827

18501828
ty::TyBox(referent_ty) => { // Box<T>
1851-
Some(vec![referent_ty])
1829+
vec![referent_ty]
18521830
}
18531831

18541832
ty::TyRawPtr(ty::TypeAndMut { ty: element_ty, ..}) |
18551833
ty::TyRef(_, ty::TypeAndMut { ty: element_ty, ..}) => {
1856-
Some(vec![element_ty])
1834+
vec![element_ty]
18571835
},
18581836

18591837
ty::TyArray(element_ty, _) | ty::TySlice(element_ty) => {
1860-
Some(vec![element_ty])
1838+
vec![element_ty]
18611839
}
18621840

18631841
ty::TyTuple(ref tys) => {
18641842
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
1865-
Some(tys.clone())
1843+
tys.clone()
18661844
}
18671845

18681846
ty::TyClosure(def_id, ref substs) => {
1847+
// FIXME(#27086). We are invariant w/r/t our
1848+
// substs.func_substs, but we don't see them as
1849+
// constituent types; this seems RIGHT but also like
1850+
// something that a normal type couldn't simulate. Is
1851+
// this just a gap with the way that PhantomData and
1852+
// OIBIT interact? That is, there is no way to say
1853+
// "make me invariant with respect to this TYPE, but
1854+
// do not act as though I can reach it"
18691855
assert_eq!(def_id.krate, ast::LOCAL_CRATE);
1870-
1871-
// TODO
1872-
match self.infcx.closure_upvars(def_id, substs) {
1873-
Some(upvars) => {
1874-
Some(upvars.iter().map(|c| c.ty).collect())
1875-
}
1876-
None => {
1877-
None
1878-
}
1879-
}
1856+
substs.upvar_tys.clone()
18801857
}
18811858

18821859
// for `PhantomData<T>`, we pass `T`
18831860
ty::TyStruct(def_id, substs)
18841861
if Some(def_id) == self.tcx().lang_items.phantom_data() =>
18851862
{
1886-
Some(substs.types.get_slice(TypeSpace).to_vec())
1863+
substs.types.get_slice(TypeSpace).to_vec()
18871864
}
18881865

18891866
ty::TyStruct(def_id, substs) => {
1890-
Some(self.tcx().struct_fields(def_id, substs).iter()
1891-
.map(|f| f.mt.ty)
1892-
.collect())
1867+
self.tcx().struct_fields(def_id, substs)
1868+
.iter()
1869+
.map(|f| f.mt.ty)
1870+
.collect()
18931871
}
18941872

18951873
ty::TyEnum(def_id, substs) => {
1896-
Some(self.tcx().substd_enum_variants(def_id, substs)
1897-
.iter()
1898-
.flat_map(|variant| &variant.args)
1899-
.map(|&ty| ty)
1900-
.collect())
1874+
self.tcx().substd_enum_variants(def_id, substs)
1875+
.iter()
1876+
.flat_map(|variant| &variant.args)
1877+
.map(|&ty| ty)
1878+
.collect()
19011879
}
19021880
}
19031881
}
@@ -2147,15 +2125,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
21472125

21482126
// binder is moved below
21492127
let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
2150-
match self.constituent_types_for_ty(self_ty) {
2151-
Some(types) => self.vtable_default_impl(obligation, trait_def_id, ty::Binder(types)),
2152-
None => {
2153-
self.tcx().sess.bug(
2154-
&format!(
2155-
"asked to confirm default implementation for ambiguous type: {:?}",
2156-
self_ty));
2157-
}
2158-
}
2128+
let types = self.constituent_types_for_ty(self_ty);
2129+
self.vtable_default_impl(obligation, trait_def_id, ty::Binder(types))
21592130
}
21602131

21612132
fn confirm_default_impl_object_candidate(&mut self,

src/librustc/middle/ty.rs

Lines changed: 2 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -4247,12 +4247,8 @@ impl<'tcx> TyS<'tcx> {
42474247
apply_lang_items(cx, did, res)
42484248
}
42494249

4250-
TyClosure(did, ref substs) => {
4251-
// TODO
4252-
let param_env = cx.empty_parameter_environment();
4253-
let infcx = infer::new_infer_ctxt(cx, &cx.tables, Some(param_env), false);
4254-
let upvars = infcx.closure_upvars(did, substs).unwrap();
4255-
TypeContents::union(&upvars, |f| tc_ty(cx, &f.ty, cache))
4250+
TyClosure(_, ref substs) => {
4251+
TypeContents::union(&substs.upvar_tys, |ty| tc_ty(cx, &ty, cache))
42564252
}
42574253

42584254
TyTuple(ref tys) => {
@@ -6007,62 +6003,6 @@ impl<'tcx> ctxt<'tcx> {
60076003
(a, b)
60086004
}
60096005

6010-
// Returns a list of `ClosureUpvar`s for each upvar.
6011-
pub fn closure_upvars<'a>(typer: &infer::InferCtxt<'a, 'tcx>,
6012-
closure_id: ast::DefId,
6013-
substs: &ClosureSubsts<'tcx>)
6014-
-> Option<Vec<ClosureUpvar<'tcx>>>
6015-
{
6016-
// Presently an unboxed closure type cannot "escape" out of a
6017-
// function, so we will only encounter ones that originated in the
6018-
// local crate or were inlined into it along with some function.
6019-
// This may change if abstract return types of some sort are
6020-
// implemented.
6021-
assert!(closure_id.krate == ast::LOCAL_CRATE);
6022-
let tcx = typer.tcx;
6023-
match tcx.freevars.borrow().get(&closure_id.node) {
6024-
None => Some(vec![]),
6025-
Some(ref freevars) => {
6026-
freevars.iter()
6027-
.map(|freevar| {
6028-
let freevar_def_id = freevar.def.def_id();
6029-
let freevar_ty = match typer.node_ty(freevar_def_id.node) {
6030-
Ok(t) => { t }
6031-
Err(()) => { return None; }
6032-
};
6033-
let freevar_ty = freevar_ty.subst(tcx, &substs.func_substs);
6034-
6035-
let upvar_id = ty::UpvarId {
6036-
var_id: freevar_def_id.node,
6037-
closure_expr_id: closure_id.node
6038-
};
6039-
6040-
typer.upvar_capture(upvar_id).map(|capture| {
6041-
let freevar_ref_ty = match capture {
6042-
UpvarCapture::ByValue => {
6043-
freevar_ty
6044-
}
6045-
UpvarCapture::ByRef(borrow) => {
6046-
tcx.mk_ref(tcx.mk_region(borrow.region),
6047-
ty::TypeAndMut {
6048-
ty: freevar_ty,
6049-
mutbl: borrow.kind.to_mutbl_lossy(),
6050-
})
6051-
}
6052-
};
6053-
6054-
ClosureUpvar {
6055-
def: freevar.def,
6056-
span: freevar.span,
6057-
ty: freevar_ref_ty,
6058-
}
6059-
})
6060-
})
6061-
.collect()
6062-
}
6063-
}
6064-
}
6065-
60666006
// Returns the repeat count for a repeating vector expression.
60676007
pub fn eval_repeat_count(&self, count_expr: &ast::Expr) -> usize {
60686008
let hint = UncheckedExprHint(self.types.usize);

src/librustc/util/ppaux.rs

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -665,22 +665,32 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
665665
TyClosure(ref did, ref substs) => ty::tls::with(|tcx| {
666666
try!(write!(f, "[closure"));
667667

668-
// TODO consider changing this to print out the upvar types instead
669-
670-
let closure_tys = &tcx.tables.borrow().closure_tys;
671-
try!(closure_tys.get(did).map(|cty| &cty.sig).and_then(|sig| {
672-
tcx.lift(&substs.func_substs).map(|substs| sig.subst(tcx, substs))
673-
}).map(|sig| {
674-
fn_sig(f, &sig.0.inputs, false, sig.0.output)
675-
}).unwrap_or_else(|| {
676-
if did.krate == ast::LOCAL_CRATE {
677-
try!(write!(f, " {:?}", tcx.map.span(did.node)));
668+
if did.krate == ast::LOCAL_CRATE {
669+
try!(write!(f, "@{:?}", tcx.map.span(did.node)));
670+
let mut sep = " ";
671+
try!(tcx.with_freevars(did.node, |freevars| {
672+
for (freevar, upvar_ty) in freevars.iter().zip(&substs.upvar_tys) {
673+
let node_id = freevar.def.local_node_id();
674+
try!(write!(f,
675+
"{}{}:{}",
676+
sep,
677+
tcx.local_var_name_str(node_id),
678+
upvar_ty));
679+
sep = ", ";
680+
}
681+
Ok(())
682+
}))
683+
} else {
684+
// cross-crate closure types should only be
685+
// visible in trans bug reports, I imagine.
686+
try!(write!(f, "@{:?}", did));
687+
let mut sep = " ";
688+
for (index, upvar_ty) in substs.upvar_tys.iter().enumerate() {
689+
try!(write!(f, "{}{}:{}", sep, index, upvar_ty));
690+
sep = ", ";
678691
}
679-
Ok(())
680-
}));
681-
if verbose() {
682-
try!(write!(f, " id={:?}", did));
683692
}
693+
684694
write!(f, "]")
685695
}),
686696
TyArray(ty, sz) => write!(f, "[{}; {}]", ty, sz),

0 commit comments

Comments
 (0)