Skip to content

Commit 2a17b84

Browse files
committed
rustc: provide adt_sized_constraint as an on-demand query.
1 parent 5f13a3b commit 2a17b84

File tree

2 files changed

+61
-77
lines changed

2 files changed

+61
-77
lines changed

src/librustc/ty/mod.rs

+60-77
Original file line numberDiff line numberDiff line change
@@ -1695,85 +1695,21 @@ impl<'a, 'gcx, 'tcx> AdtDef {
16951695
/// Due to normalization being eager, this applies even if
16961696
/// the associated type is behind a pointer, e.g. issue #31299.
16971697
pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
1698-
self.calculate_sized_constraint_inner(tcx.global_tcx(), &mut Vec::new())
1699-
}
1700-
1701-
/// Calculates the Sized-constraint.
1702-
///
1703-
/// As the Sized-constraint of enums can be a *set* of types,
1704-
/// the Sized-constraint may need to be a set also. Because introducing
1705-
/// a new type of IVar is currently a complex affair, the Sized-constraint
1706-
/// may be a tuple.
1707-
///
1708-
/// In fact, there are only a few options for the constraint:
1709-
/// - `bool`, if the type is always Sized
1710-
/// - an obviously-unsized type
1711-
/// - a type parameter or projection whose Sizedness can't be known
1712-
/// - a tuple of type parameters or projections, if there are multiple
1713-
/// such.
1714-
/// - a TyError, if a type contained itself. The representability
1715-
/// check should catch this case.
1716-
fn calculate_sized_constraint_inner(&self,
1717-
tcx: TyCtxt<'a, 'tcx, 'tcx>,
1718-
stack: &mut Vec<DefId>)
1719-
-> Ty<'tcx>
1720-
{
1721-
if let Some(ty) = tcx.maps.adt_sized_constraint.borrow().get(&self.did) {
1722-
return ty;
1723-
}
1724-
1725-
// Follow the memoization pattern: push the computation of
1726-
// DepNode::SizedConstraint as our current task.
1727-
let _task = tcx.dep_graph.in_task(DepNode::SizedConstraint(self.did));
1728-
1729-
if stack.contains(&self.did) {
1730-
debug!("calculate_sized_constraint: {:?} is recursive", self);
1731-
// This should be reported as an error by `check_representable`.
1732-
//
1733-
// Consider the type as Sized in the meanwhile to avoid
1734-
// further errors.
1735-
tcx.maps.adt_sized_constraint.borrow_mut().insert(self.did, tcx.types.err);
1736-
return tcx.types.err;
1737-
}
1738-
1739-
stack.push(self.did);
1740-
1741-
let tys : Vec<_> =
1742-
self.variants.iter().flat_map(|v| {
1743-
v.fields.last()
1744-
}).flat_map(|f| {
1745-
let ty = tcx.item_type(f.did);
1746-
self.sized_constraint_for_ty(tcx, stack, ty)
1747-
}).collect();
1748-
1749-
let self_ = stack.pop().unwrap();
1750-
assert_eq!(self_, self.did);
1751-
1752-
let ty = match tys.len() {
1753-
_ if tys.references_error() => tcx.types.err,
1754-
0 => tcx.types.bool,
1755-
1 => tys[0],
1756-
_ => tcx.intern_tup(&tys[..], false)
1757-
};
1758-
1759-
let old = tcx.maps.adt_sized_constraint.borrow().get(&self.did).cloned();
1760-
match old {
1761-
Some(old_ty) => {
1762-
debug!("calculate_sized_constraint: {:?} recurred", self);
1763-
assert_eq!(old_ty, tcx.types.err);
1764-
old_ty
1765-
}
1766-
None => {
1767-
debug!("calculate_sized_constraint: {:?} => {:?}", self, ty);
1768-
tcx.maps.adt_sized_constraint.borrow_mut().insert(self.did, ty);
1769-
ty
1698+
match queries::adt_sized_constraint::try_get(tcx, DUMMY_SP, self.did) {
1699+
Ok(ty) => ty,
1700+
Err(_) => {
1701+
debug!("adt_sized_constraint: {:?} is recursive", self);
1702+
// This should be reported as an error by `check_representable`.
1703+
//
1704+
// Consider the type as Sized in the meanwhile to avoid
1705+
// further errors.
1706+
tcx.types.err
17701707
}
17711708
}
17721709
}
17731710

17741711
fn sized_constraint_for_ty(&self,
17751712
tcx: TyCtxt<'a, 'tcx, 'tcx>,
1776-
stack: &mut Vec<DefId>,
17771713
ty: Ty<'tcx>)
17781714
-> Vec<Ty<'tcx>> {
17791715
let result = match ty.sty {
@@ -1791,23 +1727,23 @@ impl<'a, 'gcx, 'tcx> AdtDef {
17911727
TyTuple(ref tys, _) => {
17921728
match tys.last() {
17931729
None => vec![],
1794-
Some(ty) => self.sized_constraint_for_ty(tcx, stack, ty)
1730+
Some(ty) => self.sized_constraint_for_ty(tcx, ty)
17951731
}
17961732
}
17971733

17981734
TyAdt(adt, substs) => {
17991735
// recursive case
18001736
let adt_ty =
1801-
adt.calculate_sized_constraint_inner(tcx, stack)
1737+
adt.sized_constraint(tcx)
18021738
.subst(tcx, substs);
18031739
debug!("sized_constraint_for_ty({:?}) intermediate = {:?}",
18041740
ty, adt_ty);
18051741
if let ty::TyTuple(ref tys, _) = adt_ty.sty {
18061742
tys.iter().flat_map(|ty| {
1807-
self.sized_constraint_for_ty(tcx, stack, ty)
1743+
self.sized_constraint_for_ty(tcx, ty)
18081744
}).collect()
18091745
} else {
1810-
self.sized_constraint_for_ty(tcx, stack, adt_ty)
1746+
self.sized_constraint_for_ty(tcx, adt_ty)
18111747
}
18121748
}
18131749

@@ -2703,9 +2639,56 @@ fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
27032639
panic!("associated item not found for def_id: {:?}", def_id);
27042640
}
27052641

2642+
/// Calculates the Sized-constraint.
2643+
///
2644+
/// As the Sized-constraint of enums can be a *set* of types,
2645+
/// the Sized-constraint may need to be a set also. Because introducing
2646+
/// a new type of IVar is currently a complex affair, the Sized-constraint
2647+
/// may be a tuple.
2648+
///
2649+
/// In fact, there are only a few options for the constraint:
2650+
/// - `bool`, if the type is always Sized
2651+
/// - an obviously-unsized type
2652+
/// - a type parameter or projection whose Sizedness can't be known
2653+
/// - a tuple of type parameters or projections, if there are multiple
2654+
/// such.
2655+
/// - a TyError, if a type contained itself. The representability
2656+
/// check should catch this case.
2657+
fn adt_sized_constraint<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
2658+
def_id: DefId)
2659+
-> Ty<'tcx> {
2660+
let def = tcx.lookup_adt_def(def_id);
2661+
2662+
let tys: Vec<_> = def.variants.iter().flat_map(|v| {
2663+
v.fields.last()
2664+
}).flat_map(|f| {
2665+
let ty = tcx.item_type(f.did);
2666+
def.sized_constraint_for_ty(tcx, ty)
2667+
}).collect();
2668+
2669+
let ty = match tys.len() {
2670+
_ if tys.references_error() => tcx.types.err,
2671+
0 => tcx.types.bool,
2672+
1 => tys[0],
2673+
_ => tcx.intern_tup(&tys[..], false)
2674+
};
2675+
2676+
debug!("adt_sized_constraint: {:?} => {:?}", def, ty);
2677+
2678+
ty
2679+
}
2680+
27062681
pub fn provide(providers: &mut ty::maps::Providers) {
27072682
*providers = ty::maps::Providers {
27082683
associated_item,
2684+
adt_sized_constraint,
2685+
..*providers
2686+
};
2687+
}
2688+
2689+
pub fn provide_extern(providers: &mut ty::maps::Providers) {
2690+
*providers = ty::maps::Providers {
2691+
adt_sized_constraint,
27092692
..*providers
27102693
};
27112694
}

src/librustc_driver/driver.rs

+1
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
898898

899899
let mut extern_providers = ty::maps::Providers::default();
900900
cstore::provide(&mut extern_providers);
901+
ty::provide_extern(&mut extern_providers);
901902

902903
TyCtxt::create_and_enter(sess,
903904
local_providers,

0 commit comments

Comments
 (0)