Skip to content

Commit 56506cf

Browse files
committed
support user-given types in adts
1 parent 2d1d3fe commit 56506cf

27 files changed

+686
-40
lines changed

src/librustc/ich/impls_mir.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,10 +479,11 @@ for mir::AggregateKind<'gcx> {
479479
mir::AggregateKind::Array(t) => {
480480
t.hash_stable(hcx, hasher);
481481
}
482-
mir::AggregateKind::Adt(adt_def, idx, substs, active_field) => {
482+
mir::AggregateKind::Adt(adt_def, idx, substs, user_substs, active_field) => {
483483
adt_def.hash_stable(hcx, hasher);
484484
idx.hash_stable(hcx, hasher);
485485
substs.hash_stable(hcx, hasher);
486+
user_substs.hash_stable(hcx, hasher);
486487
active_field.hash_stable(hcx, hasher);
487488
}
488489
mir::AggregateKind::Closure(def_id, ref substs) => {

src/librustc/mir/mod.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2009,7 +2009,7 @@ pub enum AggregateKind<'tcx> {
20092009
/// active field number and is present only for union expressions
20102010
/// -- e.g. for a union expression `SomeUnion { c: .. }`, the
20112011
/// active field index would identity the field `c`
2012-
Adt(&'tcx AdtDef, usize, &'tcx Substs<'tcx>, Option<usize>),
2012+
Adt(&'tcx AdtDef, usize, &'tcx Substs<'tcx>, Option<CanonicalTy<'tcx>>, Option<usize>),
20132013

20142014
Closure(DefId, ClosureSubsts<'tcx>),
20152015
Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability),
@@ -2135,7 +2135,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
21352135
_ => fmt_tuple(fmt, places),
21362136
},
21372137

2138-
AggregateKind::Adt(adt_def, variant, substs, _) => {
2138+
AggregateKind::Adt(adt_def, variant, substs, _user_ty, _) => {
21392139
let variant_def = &adt_def.variants[variant];
21402140

21412141
ppaux::parameterized(fmt, substs, variant_def.did, &[])?;
@@ -2813,8 +2813,14 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
28132813
let kind = box match **kind {
28142814
AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
28152815
AggregateKind::Tuple => AggregateKind::Tuple,
2816-
AggregateKind::Adt(def, v, substs, n) => {
2817-
AggregateKind::Adt(def, v, substs.fold_with(folder), n)
2816+
AggregateKind::Adt(def, v, substs, user_ty, n) => {
2817+
AggregateKind::Adt(
2818+
def,
2819+
v,
2820+
substs.fold_with(folder),
2821+
user_ty.fold_with(folder),
2822+
n,
2823+
)
28182824
}
28192825
AggregateKind::Closure(id, substs) => {
28202826
AggregateKind::Closure(id, substs.fold_with(folder))
@@ -2846,7 +2852,8 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
28462852
(match **kind {
28472853
AggregateKind::Array(ty) => ty.visit_with(visitor),
28482854
AggregateKind::Tuple => false,
2849-
AggregateKind::Adt(_, _, substs, _) => substs.visit_with(visitor),
2855+
AggregateKind::Adt(_, _, substs, user_ty, _) =>
2856+
substs.visit_with(visitor) || user_ty.visit_with(visitor),
28502857
AggregateKind::Closure(_, substs) => substs.visit_with(visitor),
28512858
AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor),
28522859
}) || fields.visit_with(visitor)

src/librustc/mir/tcx.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ impl<'tcx> Rvalue<'tcx> {
216216
AggregateKind::Tuple => {
217217
tcx.mk_tup(ops.iter().map(|op| op.ty(local_decls, tcx)))
218218
}
219-
AggregateKind::Adt(def, _, substs, _) => {
219+
AggregateKind::Adt(def, _, substs, _, _) => {
220220
tcx.type_of(def.did).subst(tcx, substs)
221221
}
222222
AggregateKind::Closure(did, substs) => {

src/librustc/mir/visit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,7 @@ macro_rules! make_mir_visitor {
589589
AggregateKind::Adt(_adt_def,
590590
_variant_index,
591591
ref $($mutability)* substs,
592+
_user_substs,
592593
_active_field_index) => {
593594
self.visit_substs(substs, location);
594595
}

src/librustc_codegen_llvm/mir/rvalue.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
148148

149149
mir::Rvalue::Aggregate(ref kind, ref operands) => {
150150
let (dest, active_field_index) = match **kind {
151-
mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => {
151+
mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => {
152152
dest.codegen_set_discr(&bx, variant_index);
153153
if adt_def.is_enum() {
154154
(dest.project_downcast(&bx, variant_index), active_field_index)

src/librustc_mir/borrow_check/nll/type_check/mod.rs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,20 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
917917
terr
918918
);
919919
}
920+
921+
if let Some(user_ty) = self.rvalue_user_ty(rv) {
922+
if let Err(terr) = self.eq_canonical_type_and_type(user_ty, rv_ty, location.boring()) {
923+
span_mirbug!(
924+
self,
925+
stmt,
926+
"bad user type on rvalue ({:?} = {:?}): {:?}",
927+
user_ty,
928+
rv_ty,
929+
terr
930+
);
931+
}
932+
}
933+
920934
self.check_rvalue(mir, rv, location);
921935
if !self.tcx().features().unsized_locals {
922936
let trait_ref = ty::TraitRef {
@@ -1391,7 +1405,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
13911405
let tcx = self.tcx();
13921406

13931407
match *ak {
1394-
AggregateKind::Adt(def, variant_index, substs, active_field_index) => {
1408+
AggregateKind::Adt(def, variant_index, substs, _, active_field_index) => {
13951409
let variant = &def.variants[variant_index];
13961410
let adj_field_index = active_field_index.unwrap_or(field_index);
13971411
if let Some(field) = variant.fields.get(adj_field_index) {
@@ -1557,6 +1571,36 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
15571571
}
15581572
}
15591573

1574+
/// If this rvalue supports a user-given type annotation, then
1575+
/// extract and return it. This represents the final type of the
1576+
/// rvalue and will be unified with the inferred type.
1577+
fn rvalue_user_ty(
1578+
&self,
1579+
rvalue: &Rvalue<'tcx>,
1580+
) -> Option<CanonicalTy<'tcx>> {
1581+
match rvalue {
1582+
Rvalue::Use(_) |
1583+
Rvalue::Repeat(..) |
1584+
Rvalue::Ref(..) |
1585+
Rvalue::Len(..) |
1586+
Rvalue::Cast(..) |
1587+
Rvalue::BinaryOp(..) |
1588+
Rvalue::CheckedBinaryOp(..) |
1589+
Rvalue::NullaryOp(..) |
1590+
Rvalue::UnaryOp(..) |
1591+
Rvalue::Discriminant(..) =>
1592+
None,
1593+
1594+
Rvalue::Aggregate(aggregate, _) => match **aggregate {
1595+
AggregateKind::Adt(_, _, _, user_ty, _) => user_ty,
1596+
AggregateKind::Array(_) => None,
1597+
AggregateKind::Tuple => None,
1598+
AggregateKind::Closure(_, _) => None,
1599+
AggregateKind::Generator(_, _, _) => None,
1600+
}
1601+
}
1602+
}
1603+
15601604
fn check_aggregate_rvalue(
15611605
&mut self,
15621606
mir: &Mir<'tcx>,
@@ -1750,7 +1794,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
17501794
);
17511795

17521796
let instantiated_predicates = match aggregate_kind {
1753-
AggregateKind::Adt(def, _, substs, _) => {
1797+
AggregateKind::Adt(def, _, substs, _, _) => {
17541798
tcx.predicates_of(def.did).instantiate(tcx, substs)
17551799
}
17561800

src/librustc_mir/build/expr/as_rvalue.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
255255
block.and(Rvalue::Aggregate(result, operands))
256256
}
257257
ExprKind::Adt {
258-
adt_def, variant_index, substs, fields, base
258+
adt_def, variant_index, substs, user_ty, fields, base
259259
} => { // see (*) above
260260
let is_union = adt_def.is_union();
261261
let active_field_index = if is_union { Some(fields[0].name.index()) } else { None };
@@ -286,7 +286,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
286286
};
287287

288288
let adt =
289-
box AggregateKind::Adt(adt_def, variant_index, substs, active_field_index);
289+
box AggregateKind::Adt(adt_def, variant_index, substs, user_ty, active_field_index);
290290
block.and(Rvalue::Aggregate(adt, fields))
291291
}
292292
ExprKind::Assign { .. } |

src/librustc_mir/hair/cx/expr.rs

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,16 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
256256
};
257257
if let Some((adt_def, index)) = adt_data {
258258
let substs = cx.tables().node_substs(fun.hir_id);
259+
260+
let user_ty = cx.tables().user_substs(fun.hir_id)
261+
.map(|user_substs| {
262+
user_substs.unchecked_map(|user_substs| {
263+
// Here, we just pair an `AdtDef` with the
264+
// `user_substs`, so no new types etc are introduced.
265+
cx.tcx().mk_adt(adt_def, user_substs)
266+
})
267+
});
268+
259269
let field_refs = args.iter()
260270
.enumerate()
261271
.map(|(idx, e)| {
@@ -265,12 +275,12 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
265275
}
266276
})
267277
.collect();
268-
// FIXME(#47184) -- user given type annot on ADTs
269278
ExprKind::Adt {
270279
adt_def,
271280
substs,
272281
variant_index: index,
273282
fields: field_refs,
283+
user_ty,
274284
base: None,
275285
}
276286
} else {
@@ -424,11 +434,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
424434
ty::Adt(adt, substs) => {
425435
match adt.adt_kind() {
426436
AdtKind::Struct | AdtKind::Union => {
427-
// FIXME(#47184) -- user given type annot on ADTs
428437
ExprKind::Adt {
429438
adt_def: adt,
430439
variant_index: 0,
431440
substs,
441+
user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt),
432442
fields: field_refs(cx, fields),
433443
base: base.as_ref().map(|base| {
434444
FruInfo {
@@ -450,11 +460,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
450460
assert!(base.is_none());
451461

452462
let index = adt.variant_index_with_id(variant_id);
453-
// FIXME(#47184) -- user given type annot on ADTs
454463
ExprKind::Adt {
455464
adt_def: adt,
456465
variant_index: index,
457466
substs,
467+
user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt),
458468
fields: field_refs(cx, fields),
459469
base: None,
460470
}
@@ -694,20 +704,19 @@ fn user_annotated_ty_for_def(
694704
hir_id: hir::HirId,
695705
def: &Def,
696706
) -> Option<CanonicalTy<'tcx>> {
697-
let user_substs = cx.tables().user_substs(hir_id)?;
698-
Some(match def {
707+
match def {
699708
// A reference to something callable -- e.g., a fn, method, or
700709
// a tuple-struct or tuple-variant. This has the type of a
701710
// `Fn` but with the user-given substitutions.
702711
Def::Fn(_) |
703712
Def::Method(_) |
704713
Def::StructCtor(_, CtorKind::Fn) |
705714
Def::VariantCtor(_, CtorKind::Fn) =>
706-
user_substs.unchecked_map(|user_substs| {
715+
Some(cx.tables().user_substs(hir_id)?.unchecked_map(|user_substs| {
707716
// Here, we just pair a `DefId` with the
708717
// `user_substs`, so no new types etc are introduced.
709718
cx.tcx().mk_fn_def(def.def_id(), user_substs)
710-
}),
719+
})),
711720

712721
Def::Const(_def_id) |
713722
Def::AssociatedConst(_def_id) =>
@@ -720,18 +729,26 @@ fn user_annotated_ty_for_def(
720729
Def::StructCtor(_def_id, CtorKind::Const) |
721730
Def::VariantCtor(_def_id, CtorKind::Const) =>
722731
match &cx.tables().node_id_to_type(hir_id).sty {
723-
ty::TyAdt(adt_def, _) =>
724-
user_substs.unchecked_map(|user_substs| {
725-
// Here, we just pair an `AdtDef` with the
726-
// `user_substs`, so no new types etc are introduced.
727-
cx.tcx().mk_adt(adt_def, user_substs)
728-
}),
732+
ty::Adt(adt_def, _) => user_annotated_ty_for_adt(cx, hir_id, adt_def),
729733
sty => bug!("unexpected sty: {:?}", sty),
730734
},
731735

732736
_ =>
733737
bug!("user_annotated_ty_for_def: unexpected def {:?} at {:?}", def, hir_id)
734-
})
738+
}
739+
}
740+
741+
fn user_annotated_ty_for_adt(
742+
cx: &mut Cx<'a, 'gcx, 'tcx>,
743+
hir_id: hir::HirId,
744+
adt_def: &'tcx AdtDef,
745+
) -> Option<CanonicalTy<'tcx>> {
746+
let user_substs = cx.tables().user_substs(hir_id)?;
747+
Some(user_substs.unchecked_map(|user_substs| {
748+
// Here, we just pair an `AdtDef` with the
749+
// `user_substs`, so no new types etc are introduced.
750+
cx.tcx().mk_adt(adt_def, user_substs)
751+
}))
735752
}
736753

737754
fn method_callee<'a, 'gcx, 'tcx>(
@@ -835,7 +852,6 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
835852

836853
Def::StructCtor(def_id, CtorKind::Const) |
837854
Def::VariantCtor(def_id, CtorKind::Const) => {
838-
// FIXME(#47184) -- user given type annot on ADTs
839855
match cx.tables().node_id_to_type(expr.hir_id).sty {
840856
// A unit struct/variant which is used as a value.
841857
// We return a completely different ExprKind here to account for this special case.
@@ -844,6 +860,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
844860
adt_def,
845861
variant_index: adt_def.variant_index_with_id(def_id),
846862
substs,
863+
user_ty: user_annotated_ty_for_adt(cx, expr.hir_id, adt_def),
847864
fields: vec![],
848865
base: None,
849866
}

src/librustc_mir/hair/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,11 @@ pub enum ExprKind<'tcx> {
261261
adt_def: &'tcx AdtDef,
262262
variant_index: usize,
263263
substs: &'tcx Substs<'tcx>,
264+
265+
/// Optional user-given substs: for something like `let x =
266+
/// Bar::<T> { ... }`.
267+
user_ty: Option<CanonicalTy<'tcx>>,
268+
264269
fields: Vec<FieldExprRef<'tcx>>,
265270
base: Option<FruInfo<'tcx>>
266271
},

src/librustc_mir/interpret/step.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
208208

209209
Aggregate(ref kind, ref operands) => {
210210
let (dest, active_field_index) = match **kind {
211-
mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => {
211+
mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => {
212212
self.write_discriminant_value(variant_index, dest)?;
213213
if adt_def.is_enum() {
214214
(self.place_downcast(dest, variant_index)?, active_field_index)

0 commit comments

Comments
 (0)