Skip to content

Commit bcebec5

Browse files
committed
rollup merge of rust-lang#20706: nikomatsakis/assoc-types-projections-in-structs-issue-20470
Conflicts: src/librustc_trans/trans/expr.rs
2 parents 51357e0 + cb98c3d commit bcebec5

File tree

13 files changed

+204
-79
lines changed

13 files changed

+204
-79
lines changed

src/librustc/middle/infer/freshen.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
135135
t
136136
}
137137

138-
ty::ty_open(..) => {
139-
self.tcx().sess.bug("Cannot freshen an open existential type");
140-
}
141-
138+
ty::ty_open(..) |
142139
ty::ty_bool |
143140
ty::ty_char |
144141
ty::ty_int(..) |

src/librustc/middle/traits/select.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1457,11 +1457,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
14571457
Ok(AmbiguousBuiltin)
14581458
}
14591459

1460+
ty::ty_open(ty) => {
1461+
// these only crop up in trans, and represent an
1462+
// "opened" unsized/existential type (one that has
1463+
// been dereferenced)
1464+
match bound {
1465+
ty::BoundCopy |
1466+
ty::BoundSync |
1467+
ty::BoundSend => {
1468+
Ok(If(vec!(ty)))
1469+
}
1470+
1471+
ty::BoundSized => {
1472+
Err(Unimplemented)
1473+
}
1474+
}
1475+
}
14601476
ty::ty_err => {
14611477
Ok(If(Vec::new()))
14621478
}
14631479

1464-
ty::ty_open(_) |
14651480
ty::ty_infer(ty::FreshTy(_)) |
14661481
ty::ty_infer(ty::FreshIntTy(_)) => {
14671482
self.tcx().sess.bug(

src/librustc/middle/ty.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ pub struct CrateAnalysis<'tcx> {
107107
pub glob_map: Option<GlobMap>,
108108
}
109109

110-
#[derive(Copy, PartialEq, Eq, Hash)]
110+
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
111111
pub struct field<'tcx> {
112112
pub name: ast::Name,
113113
pub mt: mt<'tcx>
@@ -7240,6 +7240,12 @@ impl<'tcx> HasProjectionTypes for FnSig<'tcx> {
72407240
}
72417241
}
72427242

7243+
impl<'tcx> HasProjectionTypes for field<'tcx> {
7244+
fn has_projection_types(&self) -> bool {
7245+
self.mt.ty.has_projection_types()
7246+
}
7247+
}
7248+
72437249
impl<'tcx> HasProjectionTypes for BareFnTy<'tcx> {
72447250
fn has_projection_types(&self) -> bool {
72457251
self.sig.has_projection_types()
@@ -7339,3 +7345,11 @@ impl<'tcx> Repr<'tcx> for UnboxedClosureUpvar<'tcx> {
73397345
self.ty.repr(tcx))
73407346
}
73417347
}
7348+
7349+
impl<'tcx> Repr<'tcx> for field<'tcx> {
7350+
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
7351+
format!("field({},{})",
7352+
self.name.repr(tcx),
7353+
self.mt.repr(tcx))
7354+
}
7355+
}

src/librustc/middle/ty_fold.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,15 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TraitRef<'tcx> {
273273
}
274274
}
275275

276+
impl<'tcx> TypeFoldable<'tcx> for ty::field<'tcx> {
277+
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::field<'tcx> {
278+
ty::field {
279+
name: self.name,
280+
mt: self.mt.fold_with(folder),
281+
}
282+
}
283+
}
284+
276285
impl<'tcx> TypeFoldable<'tcx> for ty::Region {
277286
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Region {
278287
folder.fold_region(*self)

src/librustc_trans/trans/adt.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,21 +51,21 @@ use std::rc::Rc;
5151
use llvm::{ValueRef, True, IntEQ, IntNE};
5252
use back::abi::FAT_PTR_ADDR;
5353
use middle::subst;
54-
use middle::subst::Subst;
54+
use middle::ty::{mod, Ty, UnboxedClosureTyper};
55+
use middle::ty::Disr;
56+
use syntax::ast;
57+
use syntax::attr;
58+
use syntax::attr::IntType;
5559
use trans::_match;
5660
use trans::build::*;
5761
use trans::cleanup;
5862
use trans::cleanup::CleanupMethods;
5963
use trans::common::*;
6064
use trans::datum;
6165
use trans::machine;
66+
use trans::monomorphize;
6267
use trans::type_::Type;
6368
use trans::type_of;
64-
use middle::ty::{self, Ty, UnboxedClosureTyper};
65-
use middle::ty::Disr;
66-
use syntax::ast;
67-
use syntax::attr;
68-
use syntax::attr::IntType;
6969
use util::ppaux::ty_to_string;
7070

7171
type Hint = attr::ReprAttr;
@@ -159,7 +159,8 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
159159
ty::ty_struct(def_id, substs) => {
160160
let fields = ty::lookup_struct_fields(cx.tcx(), def_id);
161161
let mut ftys = fields.iter().map(|field| {
162-
ty::lookup_field_type(cx.tcx(), def_id, field.id, substs)
162+
let fty = ty::lookup_field_type(cx.tcx(), def_id, field.id, substs);
163+
monomorphize::normalize_associated_type(cx.tcx(), &fty)
163164
}).collect::<Vec<_>>();
164165
let packed = ty::lookup_packed(cx.tcx(), def_id);
165166
let dtor = ty::ty_dtor(cx.tcx(), def_id).has_drop_flag();
@@ -432,7 +433,7 @@ fn get_cases<'tcx>(tcx: &ty::ctxt<'tcx>,
432433
-> Vec<Case<'tcx>> {
433434
ty::enum_variants(tcx, def_id).iter().map(|vi| {
434435
let arg_tys = vi.args.iter().map(|&raw_ty| {
435-
raw_ty.subst(tcx, substs)
436+
monomorphize::apply_param_substs(tcx, substs, &raw_ty)
436437
}).collect();
437438
Case { discr: vi.disr_val, tys: arg_tys }
438439
}).collect()

src/librustc_trans/trans/common.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ use std::vec::Vec;
5050
use syntax::ast::Ident;
5151
use syntax::ast;
5252
use syntax::ast_map::{PathElem, PathName};
53-
use syntax::codemap::Span;
53+
use syntax::codemap::{DUMMY_SP, Span};
5454
use syntax::parse::token::InternedString;
5555
use syntax::parse::token;
5656
use util::common::memoized;
@@ -114,8 +114,9 @@ pub fn normalize_ty<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
114114
}
115115

116116
// Is the type's representation size known at compile time?
117-
pub fn type_is_sized<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
118-
ty::type_contents(cx, ty).is_sized(cx)
117+
pub fn type_is_sized<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
118+
let param_env = ty::empty_parameter_environment(tcx);
119+
ty::type_is_sized(&param_env, DUMMY_SP, ty)
119120
}
120121

121122
pub fn lltype_is_sized<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {

src/librustc_trans/trans/expr.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ use trans::debuginfo;
5050
use trans::glue;
5151
use trans::machine;
5252
use trans::meth;
53+
use trans::monomorphize;
5354
use trans::inline;
5455
use trans::tvec;
5556
use trans::type_of;
@@ -1318,7 +1319,9 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>,
13181319
{
13191320
match ty.sty {
13201321
ty::ty_struct(did, substs) => {
1321-
op(0, &struct_fields(tcx, did, substs)[])
1322+
let fields = struct_fields(tcx, did, substs);
1323+
let fields = monomorphize::normalize_associated_type(tcx, &fields);
1324+
op(0, &fields[])
13221325
}
13231326

13241327
ty::ty_tup(ref v) => {
@@ -1340,10 +1343,9 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>,
13401343
def::DefVariant(enum_id, variant_id, _) => {
13411344
let variant_info = ty::enum_variant_with_id(
13421345
tcx, enum_id, variant_id);
1343-
op(variant_info.disr_val,
1344-
&struct_fields(tcx,
1345-
variant_id,
1346-
substs)[])
1346+
let fields = struct_fields(tcx, variant_id, substs);
1347+
let fields = monomorphize::normalize_associated_type(tcx, &fields);
1348+
op(variant_info.disr_val, &fields.index[])
13471349
}
13481350
_ => {
13491351
tcx.sess.bug("resolve didn't map this expr to a \

src/librustc_trans/trans/monomorphize.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,6 @@ pub fn apply_param_substs<'tcx,T>(tcx: &ty::ctxt<'tcx>,
300300
-> T
301301
where T : TypeFoldable<'tcx> + Repr<'tcx> + HasProjectionTypes + Clone
302302
{
303-
assert!(param_substs.regions.is_erased());
304-
305303
let substituted = value.subst(tcx, param_substs);
306304
normalize_associated_type(tcx, &substituted)
307305
}

src/librustc_typeck/astconv.rs

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ use middle::const_eval;
5252
use middle::def;
5353
use middle::resolve_lifetime as rl;
5454
use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
55-
use middle::subst::{VecPerParamSpace};
5655
use middle::traits;
5756
use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty};
5857
use rscope::{self, UnelidableRscope, RegionScope, SpecificRscope,
@@ -244,7 +243,7 @@ pub fn opt_ast_region_to_region<'tcx>(
244243

245244
/// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
246245
/// returns an appropriate set of substitutions for this particular reference to `I`.
247-
fn ast_path_substs_for_ty<'tcx>(
246+
pub fn ast_path_substs_for_ty<'tcx>(
248247
this: &AstConv<'tcx>,
249248
rscope: &RegionScope,
250249
decl_generics: &ty::Generics<'tcx>,
@@ -762,50 +761,6 @@ pub fn ast_path_to_ty<'tcx>(
762761
TypeAndSubsts { substs: substs, ty: ty }
763762
}
764763

765-
/// Returns the type that this AST path refers to. If the path has no type
766-
/// parameters and the corresponding type has type parameters, fresh type
767-
/// and/or region variables are substituted.
768-
///
769-
/// This is used when checking the constructor in struct literals.
770-
pub fn ast_path_to_ty_relaxed<'tcx>(
771-
this: &AstConv<'tcx>,
772-
rscope: &RegionScope,
773-
did: ast::DefId,
774-
path: &ast::Path)
775-
-> TypeAndSubsts<'tcx>
776-
{
777-
let tcx = this.tcx();
778-
let ty::TypeScheme {
779-
generics,
780-
ty: decl_ty
781-
} = this.get_item_type_scheme(did);
782-
783-
let wants_params =
784-
generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace);
785-
786-
let needs_defaults =
787-
wants_params &&
788-
path.segments.iter().all(|s| s.parameters.is_empty());
789-
790-
let substs = if needs_defaults {
791-
let type_params: Vec<_> = range(0, generics.types.len(TypeSpace))
792-
.map(|_| this.ty_infer(path.span)).collect();
793-
let region_params =
794-
rscope.anon_regions(path.span, generics.regions.len(TypeSpace))
795-
.unwrap();
796-
Substs::new(VecPerParamSpace::params_from_type(type_params),
797-
VecPerParamSpace::params_from_type(region_params))
798-
} else {
799-
ast_path_substs_for_ty(this, rscope, &generics, path)
800-
};
801-
802-
let ty = decl_ty.subst(tcx, &substs);
803-
TypeAndSubsts {
804-
substs: substs,
805-
ty: ty,
806-
}
807-
}
808-
809764
/// Converts the given AST type to a built-in type. A "built-in type" is, at
810765
/// present, either a core numeric type, a string, or `Box`.
811766
pub fn ast_ty_to_builtin_ty<'tcx>(

src/librustc_typeck/check/mod.rs

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ use middle::mem_categorization as mc;
9090
use middle::mem_categorization::McResult;
9191
use middle::pat_util::{self, pat_id_map};
9292
use middle::region::CodeExtent;
93-
use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace};
93+
use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
9494
use middle::traits;
9595
use middle::ty::{FnSig, VariantInfo, TypeScheme};
9696
use middle::ty::{Disr, ParamTy, ParameterEnvironment};
@@ -1947,6 +1947,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
19471947
}
19481948
}
19491949

1950+
/// Returns the type that this AST path refers to. If the path has no type
1951+
/// parameters and the corresponding type has type parameters, fresh type
1952+
/// and/or region variables are substituted.
1953+
///
1954+
/// This is used when checking the constructor in struct literals.
1955+
fn instantiate_struct_literal_ty(&self,
1956+
did: ast::DefId,
1957+
path: &ast::Path)
1958+
-> TypeAndSubsts<'tcx>
1959+
{
1960+
let tcx = self.tcx();
1961+
1962+
let ty::TypeScheme { generics, ty: decl_ty } = ty::lookup_item_type(tcx, did);
1963+
1964+
let wants_params =
1965+
generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace);
1966+
1967+
let needs_defaults =
1968+
wants_params &&
1969+
path.segments.iter().all(|s| s.parameters.is_empty());
1970+
1971+
let substs = if needs_defaults {
1972+
let tps =
1973+
self.infcx().next_ty_vars(generics.types.len(TypeSpace));
1974+
let rps =
1975+
self.infcx().region_vars_for_defs(path.span,
1976+
generics.regions.get_slice(TypeSpace));
1977+
Substs::new_type(tps, rps)
1978+
} else {
1979+
astconv::ast_path_substs_for_ty(self, self, &generics, path)
1980+
};
1981+
1982+
let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty);
1983+
1984+
TypeAndSubsts { substs: substs, ty: ty }
1985+
}
1986+
19501987
pub fn write_nil(&self, node_id: ast::NodeId) {
19511988
self.write_ty(node_id, ty::mk_nil(self.tcx()));
19521989
}
@@ -3490,17 +3527,18 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
34903527
expected_field_type =
34913528
ty::lookup_field_type(
34923529
tcx, class_id, field_id, substitutions);
3530+
expected_field_type =
3531+
fcx.normalize_associated_types_in(
3532+
field.span, &expected_field_type);
34933533
class_field_map.insert(
34943534
field.ident.node.name, (field_id, true));
34953535
fields_found += 1;
34963536
}
34973537
}
3538+
34983539
// Make sure to give a type to the field even if there's
34993540
// an error, so we can continue typechecking
3500-
check_expr_coercable_to_type(
3501-
fcx,
3502-
&*field.expr,
3503-
expected_field_type);
3541+
check_expr_coercable_to_type(fcx, &*field.expr, expected_field_type);
35043542
}
35053543

35063544
if error_happened {
@@ -4149,10 +4187,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
41494187
// parameters correctly.
41504188
let actual_structure_type = fcx.expr_ty(&*expr);
41514189
if !ty::type_is_error(actual_structure_type) {
4152-
let type_and_substs = astconv::ast_path_to_ty_relaxed(fcx,
4153-
fcx,
4154-
struct_id,
4155-
path);
4190+
let type_and_substs = fcx.instantiate_struct_literal_ty(struct_id, path);
41564191
match fcx.mk_subty(false,
41574192
infer::Misc(path.span),
41584193
actual_structure_type,

src/test/compile-fail/recursion.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
//~^^^^^^^^^^ ERROR overflow
12+
//
13+
// We also get a second error message at the top of file (dummy
14+
// span). This is not helpful, but also kind of annoying to prevent,
15+
// so for now just live with it, since we also get a second message
16+
// that is more helpful.
17+
1118
enum Nil {NilValue}
1219
struct Cons<T> {head:int, tail:T}
1320
trait Dot {fn dot(&self, other:Self) -> int;}

0 commit comments

Comments
 (0)