Skip to content

Commit 05f1a05

Browse files
committed
address review comments
1 parent 6fc19ad commit 05f1a05

File tree

2 files changed

+83
-82
lines changed

2 files changed

+83
-82
lines changed

src/librustc/ty/mod.rs

Lines changed: 75 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,28 +1750,69 @@ impl<'tcx, 'container> AdtDefData<'tcx, 'container> {
17501750
}
17511751

17521752
impl<'tcx> AdtDefData<'tcx, 'tcx> {
1753-
fn sized_constraint_for_tys<TYS>(
1754-
&'tcx self,
1755-
tcx: &ty::TyCtxt<'tcx>,
1756-
stack: &mut Vec<AdtDefMaster<'tcx>>,
1757-
tys: TYS
1758-
) -> Ty<'tcx>
1759-
where TYS: IntoIterator<Item=Ty<'tcx>>
1753+
/// Calculates the Sized-constraint.
1754+
///
1755+
/// As the Sized-constraint of enums can be a *set* of types,
1756+
/// the Sized-constraint may need to be a set also. Because introducing
1757+
/// a new type of IVar is currently a complex affair, the Sized-constraint
1758+
/// may be a tuple.
1759+
///
1760+
/// In fact, there are only a few options for the constraint:
1761+
/// - `bool`, if the type is always Sized
1762+
/// - an obviously-unsized type
1763+
/// - a type parameter or projection whose Sizedness can't be known
1764+
/// - a tuple of type parameters or projections, if there are multiple
1765+
/// such.
1766+
/// - a TyError, if a type contained itself. The representability
1767+
/// check should catch this case.
1768+
fn calculate_sized_constraint_inner(&'tcx self, tcx: &ty::TyCtxt<'tcx>,
1769+
stack: &mut Vec<AdtDefMaster<'tcx>>)
17601770
{
1761-
let tys : Vec<_> = tys.into_iter()
1762-
.map(|ty| self.sized_constraint_for_ty(tcx, stack, ty))
1763-
.flat_map(|ty| match ty.sty {
1764-
ty::TyTuple(ref tys) => tys.last().cloned(),
1765-
_ => Some(ty)
1766-
})
1767-
.filter(|ty| *ty != tcx.types.bool)
1768-
.collect();
1769-
1770-
match tys.len() {
1771+
1772+
let dep_node = DepNode::SizedConstraint(self.did);
1773+
1774+
if self.sized_constraint.get(dep_node).is_some() {
1775+
return;
1776+
}
1777+
1778+
if stack.contains(&self) {
1779+
debug!("calculate_sized_constraint: {:?} is recursive", self);
1780+
// This should be reported as an error by `check_representable`.
1781+
//
1782+
// Consider the type as Sized in the meanwhile to avoid
1783+
// further errors.
1784+
self.sized_constraint.fulfill(dep_node, tcx.types.err);
1785+
return;
1786+
}
1787+
1788+
stack.push(self);
1789+
1790+
let tys : Vec<_> =
1791+
self.variants.iter().flat_map(|v| {
1792+
v.fields.last()
1793+
}).flat_map(|f| {
1794+
self.sized_constraint_for_ty(tcx, stack, f.unsubst_ty())
1795+
}).collect();
1796+
1797+
let self_ = stack.pop().unwrap();
1798+
assert_eq!(self_, self);
1799+
1800+
let ty = match tys.len() {
17711801
_ if tys.references_error() => tcx.types.err,
17721802
0 => tcx.types.bool,
17731803
1 => tys[0],
17741804
_ => tcx.mk_tup(tys)
1805+
};
1806+
1807+
match self.sized_constraint.get(dep_node) {
1808+
Some(old_ty) => {
1809+
debug!("calculate_sized_constraint: {:?} recurred", self);
1810+
assert_eq!(old_ty, tcx.types.err)
1811+
}
1812+
None => {
1813+
debug!("calculate_sized_constraint: {:?} => {:?}", self, ty);
1814+
self.sized_constraint.fulfill(dep_node, ty)
1815+
}
17751816
}
17761817
}
17771818

@@ -1780,22 +1821,23 @@ impl<'tcx> AdtDefData<'tcx, 'tcx> {
17801821
tcx: &ty::TyCtxt<'tcx>,
17811822
stack: &mut Vec<AdtDefMaster<'tcx>>,
17821823
ty: Ty<'tcx>
1783-
) -> Ty<'tcx> {
1824+
) -> Vec<Ty<'tcx>> {
17841825
let result = match ty.sty {
17851826
TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
17861827
TyBox(..) | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
17871828
TyArray(..) | TyClosure(..) => {
1788-
// these are always sized - return a primitive
1789-
tcx.types.bool
1829+
vec![]
17901830
}
17911831

17921832
TyStr | TyTrait(..) | TySlice(_) | TyError => {
17931833
// these are never sized - return the target type
1794-
ty
1834+
vec![ty]
17951835
}
17961836

17971837
TyTuple(ref tys) => {
1798-
self.sized_constraint_for_tys(tcx, stack, tys.iter().cloned())
1838+
tys.last().into_iter().flat_map(|ty| {
1839+
self.sized_constraint_for_ty(tcx, stack, ty)
1840+
}).collect()
17991841
}
18001842

18011843
TyEnum(adt, substs) | TyStruct(adt, substs) => {
@@ -1808,13 +1850,19 @@ impl<'tcx> AdtDefData<'tcx, 'tcx> {
18081850
.subst(tcx, substs);
18091851
debug!("sized_constraint_for_ty({:?}) intermediate = {:?}",
18101852
ty, adt_ty);
1811-
self.sized_constraint_for_ty(tcx, stack, adt_ty)
1853+
if let ty::TyTuple(ref tys) = adt_ty.sty {
1854+
tys.iter().flat_map(|ty| {
1855+
self.sized_constraint_for_ty(tcx, stack, ty)
1856+
}).collect()
1857+
} else {
1858+
self.sized_constraint_for_ty(tcx, stack, adt_ty)
1859+
}
18121860
}
18131861

18141862
TyProjection(..) => {
18151863
// must calculate explicitly.
18161864
// FIXME: consider special-casing always-Sized projections
1817-
ty
1865+
vec![ty]
18181866
}
18191867

18201868
TyParam(..) => {
@@ -1824,7 +1872,7 @@ impl<'tcx> AdtDefData<'tcx, 'tcx> {
18241872

18251873
let sized_trait = match tcx.lang_items.sized_trait() {
18261874
Some(x) => x,
1827-
_ => return ty
1875+
_ => return vec![ty]
18281876
};
18291877
let sized_predicate = Binder(TraitRef {
18301878
def_id: sized_trait,
@@ -1834,9 +1882,9 @@ impl<'tcx> AdtDefData<'tcx, 'tcx> {
18341882
}).to_predicate();
18351883
let predicates = tcx.lookup_predicates(self.did).predicates;
18361884
if predicates.into_iter().any(|p| p == sized_predicate) {
1837-
tcx.types.bool
1885+
vec![]
18381886
} else {
1839-
ty
1887+
vec![ty]
18401888
}
18411889
}
18421890

@@ -1848,60 +1896,6 @@ impl<'tcx> AdtDefData<'tcx, 'tcx> {
18481896
debug!("sized_constraint_for_ty({:?}) = {:?}", ty, result);
18491897
result
18501898
}
1851-
1852-
/// Calculates the Sized-constraint.
1853-
///
1854-
/// As the Sized-constraint of enums can be a *set* of types,
1855-
/// the Sized-constraint may need to be a set also. Because introducing
1856-
/// a new type of IVar is currently a complex affair, the Sized-constraint
1857-
/// may be a tuple.
1858-
///
1859-
/// In fact, there are only a few options for the constraint:
1860-
/// - `bool`, if the type is always Sized
1861-
/// - an obviously-unsized type
1862-
/// - a type parameter or projection whose Sizedness can't be known
1863-
/// - a tuple of type parameters or projections, if there are multiple
1864-
/// such.
1865-
/// - a TyError, if a type contained itself. The representability
1866-
/// check should catch this case.
1867-
fn calculate_sized_constraint_inner(&'tcx self, tcx: &ty::TyCtxt<'tcx>,
1868-
stack: &mut Vec<AdtDefMaster<'tcx>>)
1869-
{
1870-
1871-
let dep_node = DepNode::SizedConstraint(self.did);
1872-
1873-
if self.sized_constraint.get(dep_node).is_some() {
1874-
return;
1875-
}
1876-
1877-
if stack.contains(&self) {
1878-
debug!("calculate_sized_constraint: {:?} is recursive", self);
1879-
self.sized_constraint.fulfill(dep_node, tcx.types.err);
1880-
return;
1881-
}
1882-
1883-
stack.push(self);
1884-
let ty = self.sized_constraint_for_tys(
1885-
tcx, stack,
1886-
self.variants.iter().flat_map(|v| {
1887-
v.fields.last()
1888-
}).map(|f| f.unsubst_ty())
1889-
);
1890-
1891-
let self_ = stack.pop().unwrap();
1892-
assert_eq!(self_, self);
1893-
1894-
match self.sized_constraint.get(dep_node) {
1895-
Some(old_ty) => {
1896-
debug!("calculate_sized_constraint: {:?} recurred", self);
1897-
assert_eq!(old_ty, tcx.types.err)
1898-
}
1899-
None => {
1900-
debug!("calculate_sized_constraint: {:?} => {:?}", self, ty);
1901-
self.sized_constraint.fulfill(dep_node, ty)
1902-
}
1903-
}
1904-
}
19051899
}
19061900

19071901
impl<'tcx, 'container> VariantDefData<'tcx, 'container> {

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,19 @@
1212
// because of eager normalization:
1313
//
1414
// proving `M: Sized` requires
15-
// - proving `PtrBack<Vec<M>>: Sized` requis
15+
// - proving `PtrBack<Vec<M>>: Sized` requires
1616
// - normalizing `Vec<<Vec<M> as Front>::Back>>: Sized` requires
1717
// - proving `Vec<M>: Front` requires
1818
// - `M: Sized` <-- cycle!
1919
//
2020
// If we skip the normalization step, though, everything goes fine.
21+
//
22+
// This could be fixed by implementing lazy normalization everywhere.
23+
//
24+
// However, we want this to work before then. For that, when checking
25+
// whether a type is Sized we only check that the tails are Sized. As
26+
// PtrBack does not have a tail, we don't need to normalize anything
27+
// and this compiles
2128

2229
trait Front {
2330
type Back;

0 commit comments

Comments
 (0)