Skip to content

Commit

Permalink
coerce fields to the expected field type
Browse files Browse the repository at this point in the history
Fully fixes rust-lang#31260.

This needs a crater run.
  • Loading branch information
arielb1 committed Jun 21, 2017
1 parent 03198da commit 7769c9a
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 39 deletions.
29 changes: 13 additions & 16 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3159,11 +3159,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {

let adt_ty_hint =
self.expected_inputs_for_expected_output(span, expected, adt_ty, &[adt_ty])
.get(0).cloned().unwrap_or(adt_ty);
.get(0).cloned().unwrap_or(adt_ty);
// re-link the regions that EIfEO can erase.
self.demand_eqtype(span, adt_ty_hint, adt_ty);

let (substs, hint_substs, adt_kind, kind_name) = match (&adt_ty.sty, &adt_ty_hint.sty) {
(&ty::TyAdt(adt, substs), &ty::TyAdt(_, hint_substs)) => {
(substs, hint_substs, adt.adt_kind(), adt.variant_descr())
let (substs, adt_kind, kind_name) = match &adt_ty.sty{
&ty::TyAdt(adt, substs) => {
(substs, adt.adt_kind(), adt.variant_descr())
}
_ => span_bug!(span, "non-ADT passed to check_expr_struct_fields")
};
Expand All @@ -3179,14 +3181,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {

// Typecheck each field.
for field in ast_fields {
let final_field_type;
let field_type_hint;

let ident = tcx.adjust(field.name.node, variant.did, self.body_id).0;
if let Some(v_field) = remaining_fields.remove(&ident) {
final_field_type = self.field_ty(field.span, v_field, substs);
field_type_hint = self.field_ty(field.span, v_field, hint_substs);

let field_type = if let Some(v_field) = remaining_fields.remove(&ident) {
seen_fields.insert(field.name.node, field.span);

// we don't look at stability attributes on
Expand All @@ -3195,10 +3191,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
if adt_kind != ty::AdtKind::Enum {
tcx.check_stability(v_field.did, expr_id, field.span);
}

self.field_ty(field.span, v_field, substs)
} else {
error_happened = true;
final_field_type = tcx.types.err;
field_type_hint = tcx.types.err;
if let Some(_) = variant.find_field_named(field.name.node) {
let mut err = struct_span_err!(self.tcx.sess,
field.name.span,
Expand All @@ -3216,12 +3212,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} else {
self.report_unknown_field(adt_ty, variant, field, ast_fields, kind_name);
}
}

tcx.types.err
};

// Make sure to give a type to the field even if there's
// an error, so we can continue typechecking
let ty = self.check_expr_with_hint(&field.expr, field_type_hint);
self.demand_coerce(&field.expr, ty, final_field_type);
self.check_expr_coercable_to_type(&field.expr, field_type);
}

// Make sure the programmer specified correct number of fields.
Expand Down
5 changes: 4 additions & 1 deletion src/test/run-pass/issue-31260.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ pub struct Struct<K: 'static> {
pub field: K,
}

// Partial fix for #31260, doesn't work without {...}.
static STRUCT: Struct<&'static [u8]> = Struct {
field: {&[1]}
};

static STRUCT2: Struct<&'static [u8]> = Struct {
field: &[1]
};

fn main() {}
10 changes: 6 additions & 4 deletions src/test/ui/mismatched_types/abridged.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,25 @@ fn c() -> Result<Foo, Bar> {
}

fn d() -> X<X<String, String>, String> {
X {
let x = X {
x: X {
x: "".to_string(),
y: 2,
},
y: 3,
}
};
x
}

fn e() -> X<X<String, String>, String> {
X {
let x = X {
x: X {
x: "".to_string(),
y: 2,
},
y: "".to_string(),
}
};
x
}

fn main() {}
24 changes: 6 additions & 18 deletions src/test/ui/mismatched_types/abridged.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -35,31 +35,19 @@ error[E0308]: mismatched types
found type `Foo`

error[E0308]: mismatched types
--> $DIR/abridged.rs:42:5
--> $DIR/abridged.rs:49:5
|
42 | / X {
43 | | x: X {
44 | | x: "".to_string(),
45 | | y: 2,
46 | | },
47 | | y: 3,
48 | | }
| |_____^ expected struct `std::string::String`, found integral variable
49 | x
| ^ expected struct `std::string::String`, found integral variable
|
= note: expected type `X<X<_, std::string::String>, std::string::String>`
found type `X<X<_, {integer}>, {integer}>`

error[E0308]: mismatched types
--> $DIR/abridged.rs:52:5
--> $DIR/abridged.rs:60:5
|
52 | / X {
53 | | x: X {
54 | | x: "".to_string(),
55 | | y: 2,
56 | | },
57 | | y: "".to_string(),
58 | | }
| |_____^ expected struct `std::string::String`, found integral variable
60 | x
| ^ expected struct `std::string::String`, found integral variable
|
= note: expected type `X<X<_, std::string::String>, _>`
found type `X<X<_, {integer}>, _>`
Expand Down

0 comments on commit 7769c9a

Please sign in to comment.