Skip to content

Commit 4bcabbd

Browse files
committed
add comments and tests
1 parent 73f39a0 commit 4bcabbd

File tree

6 files changed

+73
-13
lines changed

6 files changed

+73
-13
lines changed

src/librustc/ty/mod.rs

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1721,6 +1721,17 @@ impl<'tcx, 'container> AdtDefData<'tcx, 'container> {
17211721

17221722
/// Returns a simpler type such that `Self: Sized` if and only
17231723
/// if that type is Sized, or `TyErr` if this type is recursive.
1724+
///
1725+
/// This is generally the `struct_tail` if this is a struct, or a
1726+
/// tuple of them if this is an enum.
1727+
///
1728+
/// Oddly enough, checking that the sized-constraint is Sized is
1729+
/// actually more expressive than checking all members:
1730+
/// the Sized trait is inductive, so an associated type that references
1731+
/// Self would prevent its containing ADT from being Sized.
1732+
///
1733+
/// Due to normalization being eager, this applies even if
1734+
/// the associated type is behind a pointer, e.g. issue #31299.
17241735
pub fn sized_constraint(&self, tcx: &ty::TyCtxt<'tcx>) -> Ty<'tcx> {
17251736
let dep_node = DepNode::SizedConstraint(self.did);
17261737
match self.sized_constraint.get(dep_node) {
@@ -1749,6 +1760,7 @@ impl<'tcx> AdtDefData<'tcx, 'tcx> {
17491760
.collect();
17501761

17511762
match tys.len() {
1763+
_ if tys.references_error() => tcx.types.err,
17521764
0 => tcx.types.bool,
17531765
1 => tys[0],
17541766
_ => tcx.mk_tup(tys)
@@ -1768,7 +1780,7 @@ impl<'tcx> AdtDefData<'tcx, 'tcx> {
17681780
tcx.types.bool
17691781
}
17701782

1771-
TyStr | TyTrait(..) | TySlice(_) => {
1783+
TyStr | TyTrait(..) | TySlice(_) | TyError => {
17721784
// these are never sized - return the target type
17731785
ty
17741786
}
@@ -1797,6 +1809,10 @@ impl<'tcx> AdtDefData<'tcx, 'tcx> {
17971809
}
17981810

17991811
TyParam(..) => {
1812+
// perf hack: if there is a `T: Sized` bound, then
1813+
// we know that `T` is Sized and do not need to check
1814+
// it on the impl.
1815+
18001816
let sized_trait = match tcx.lang_items.sized_trait() {
18011817
Some(x) => x,
18021818
_ => return ty
@@ -1815,7 +1831,7 @@ impl<'tcx> AdtDefData<'tcx, 'tcx> {
18151831
}
18161832
}
18171833

1818-
TyInfer(..) | TyError => {
1834+
TyInfer(..) => {
18191835
bug!("unexpected type `{:?}` in sized_constraint_for_ty",
18201836
ty)
18211837
}
@@ -1824,9 +1840,21 @@ impl<'tcx> AdtDefData<'tcx, 'tcx> {
18241840
result
18251841
}
18261842

1827-
/// Calculates the Sized-constraint. This replaces all always-Sized
1828-
/// types with bool. I could have made the TyIVar an Option, but that
1829-
/// would have been so much code.
1843+
/// Calculates the Sized-constraint.
1844+
///
1845+
/// As the Sized-constraint of enums can be a *set* of types,
1846+
/// the Sized-constraint may need to be a set also. Because introducing
1847+
/// a new type of IVar is currently a complex affair, the Sized-constraint
1848+
/// may be a tuple.
1849+
///
1850+
/// In fact, there are only a few options for the constraint:
1851+
/// - `bool`, if the type is always Sized
1852+
/// - an obviously-unsized type
1853+
/// - a type parameter or projection whose Sizedness can't be known
1854+
/// - a tuple of type parameters or projections, if there are multiple
1855+
/// such.
1856+
/// - a TyError, if a type contained itself. The representability
1857+
/// check should catch this case.
18301858
fn calculate_sized_constraint_inner(&'tcx self, tcx: &ty::TyCtxt<'tcx>,
18311859
stack: &mut Vec<AdtDefMaster<'tcx>>)
18321860
{

src/test/compile-fail/issue-17431-2.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
struct Baz { q: Option<Foo> }
12+
//~^ ERROR recursive type `Baz` has infinite size
1213

1314
struct Foo { q: Option<Baz> }
1415
//~^ ERROR recursive type `Foo` has infinite size

src/test/compile-fail/issue-26548.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// error-pattern: overflow representing the type `S`
12+
1113
trait Mirror { type It: ?Sized; }
1214
impl<T: ?Sized> Mirror for T { type It = Self; }
1315
struct S(Option<<S as Mirror>::It>);
14-
//~^ ERROR recursive type `S` has infinite size
1516

1617
fn main() {
1718
let _s = S(None);

src/test/compile-fail/range-1.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,4 @@ pub fn main() {
2323
let arr: &[_] = &[1, 2, 3];
2424
let range = *arr..;
2525
//~^ ERROR `[_]: std::marker::Sized` is not satisfied
26-
//~| ERROR `[_]: std::marker::Sized` is not satisfied
2726
}

src/test/compile-fail/sized-cycle-note.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,9 @@
1717
// 2. it should elaborate the steps that led to the cycle.
1818

1919
struct Baz { q: Option<Foo> }
20-
20+
//~^ ERROR recursive type `Baz` has infinite size
2121
struct Foo { q: Option<Baz> }
2222
//~^ ERROR recursive type `Foo` has infinite size
23-
//~| NOTE type `Foo` is embedded within `std::option::Option<Foo>`...
24-
//~| NOTE ...which in turn is embedded within `std::option::Option<Foo>`...
25-
//~| NOTE ...which in turn is embedded within `Baz`...
26-
//~| NOTE ...which in turn is embedded within `std::option::Option<Baz>`...
27-
//~| NOTE ...which in turn is embedded within `Foo`, completing the cycle.
2823

2924
impl Foo { fn bar(&self) {} }
3025

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2012 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+
// Regression test for #31299. This was generating an overflow error
12+
// because of eager normalization:
13+
//
14+
// proving `M: Sized` requires
15+
// - proving `PtrBack<Vec<M>>: Sized` requis
16+
// - normalizing `Vec<<Vec<M> as Front>::Back>>: Sized` requires
17+
// - proving `Vec<M>: Front` requires
18+
// - `M: Sized` <-- cycle!
19+
//
20+
// If we skip the normalization step, though, everything goes fine.
21+
22+
trait Front {
23+
type Back;
24+
}
25+
26+
impl<T> Front for Vec<T> {
27+
type Back = Vec<T>;
28+
}
29+
30+
struct PtrBack<T: Front>(Vec<T::Back>);
31+
32+
struct M(PtrBack<Vec<M>>);
33+
34+
fn main() {
35+
std::mem::size_of::<M>();
36+
}

0 commit comments

Comments
 (0)