Skip to content

Commit a0a352d

Browse files
eddybbrson
authored andcommitted
Propagate expected type hints through struct literals.
1 parent 46928b8 commit a0a352d

File tree

2 files changed

+41
-8
lines changed

2 files changed

+41
-8
lines changed

src/librustc_typeck/check/mod.rs

+21-8
Original file line numberDiff line numberDiff line change
@@ -3151,14 +3151,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
31513151

31523152
fn check_expr_struct_fields(&self,
31533153
adt_ty: Ty<'tcx>,
3154+
expected: Expectation<'tcx>,
31543155
expr_id: ast::NodeId,
31553156
span: Span,
31563157
variant: &'tcx ty::VariantDef,
31573158
ast_fields: &'gcx [hir::Field],
31583159
check_completeness: bool) {
31593160
let tcx = self.tcx;
3160-
let (substs, adt_kind, kind_name) = match adt_ty.sty {
3161-
ty::TyAdt(adt, substs) => (substs, adt.adt_kind(), adt.variant_descr()),
3161+
3162+
let adt_ty_hint =
3163+
self.expected_inputs_for_expected_output(span, expected, adt_ty, &[adt_ty])
3164+
.get(0).cloned().unwrap_or(adt_ty);
3165+
3166+
let (substs, hint_substs, adt_kind, kind_name) = match (&adt_ty.sty, &adt_ty_hint.sty) {
3167+
(&ty::TyAdt(adt, substs), &ty::TyAdt(_, hint_substs)) => {
3168+
(substs, hint_substs, adt.adt_kind(), adt.variant_descr())
3169+
}
31623170
_ => span_bug!(span, "non-ADT passed to check_expr_struct_fields")
31633171
};
31643172

@@ -3173,10 +3181,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
31733181

31743182
// Typecheck each field.
31753183
for field in ast_fields {
3176-
let expected_field_type;
3184+
let final_field_type;
3185+
let field_type_hint;
31773186

31783187
if let Some(v_field) = remaining_fields.remove(&field.name.node) {
3179-
expected_field_type = self.field_ty(field.span, v_field, substs);
3188+
final_field_type = self.field_ty(field.span, v_field, substs);
3189+
field_type_hint = self.field_ty(field.span, v_field, hint_substs);
31803190

31813191
seen_fields.insert(field.name.node, field.span);
31823192

@@ -3188,7 +3198,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
31883198
}
31893199
} else {
31903200
error_happened = true;
3191-
expected_field_type = tcx.types.err;
3201+
final_field_type = tcx.types.err;
3202+
field_type_hint = tcx.types.err;
31923203
if let Some(_) = variant.find_field_named(field.name.node) {
31933204
let mut err = struct_span_err!(self.tcx.sess,
31943205
field.name.span,
@@ -3210,7 +3221,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
32103221

32113222
// Make sure to give a type to the field even if there's
32123223
// an error, so we can continue typechecking
3213-
self.check_expr_coercable_to_type(&field.expr, expected_field_type);
3224+
let ty = self.check_expr_with_hint(&field.expr, field_type_hint);
3225+
self.demand_coerce(&field.expr, ty, final_field_type);
32143226
}
32153227

32163228
// Make sure the programmer specified correct number of fields.
@@ -3320,6 +3332,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
33203332

33213333
fn check_expr_struct(&self,
33223334
expr: &hir::Expr,
3335+
expected: Expectation<'tcx>,
33233336
qpath: &hir::QPath,
33243337
fields: &'gcx [hir::Field],
33253338
base_expr: &'gcx Option<P<hir::Expr>>) -> Ty<'tcx>
@@ -3338,7 +3351,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
33383351
hir::QPath::TypeRelative(ref qself, _) => qself.span
33393352
};
33403353

3341-
self.check_expr_struct_fields(struct_ty, expr.id, path_span, variant, fields,
3354+
self.check_expr_struct_fields(struct_ty, expected, expr.id, path_span, variant, fields,
33423355
base_expr.is_none());
33433356
if let &Some(ref base_expr) = base_expr {
33443357
self.check_expr_has_type(base_expr, struct_ty);
@@ -3883,7 +3896,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
38833896
}
38843897
}
38853898
hir::ExprStruct(ref qpath, ref fields, ref base_expr) => {
3886-
self.check_expr_struct(expr, qpath, fields, base_expr)
3899+
self.check_expr_struct(expr, expected, qpath, fields, base_expr)
38873900
}
38883901
hir::ExprField(ref base, ref field) => {
38893902
self.check_field(expr, lvalue_pref, &base, field)

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

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2017 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+
pub struct Struct<K: 'static> {
12+
pub field: K,
13+
}
14+
15+
// Partial fix for #31260, doesn't work without {...}.
16+
static STRUCT: Struct<&'static [u8]> = Struct {
17+
field: {&[1]}
18+
};
19+
20+
fn main() {}

0 commit comments

Comments
 (0)