about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <ariel.byd@gmail.com>2017-06-21 20:28:09 +0300
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2017-06-21 20:28:09 +0300
commit7769c9a7ec8aec50260956a6383c38f4e8dbdf35 (patch)
tree7c8bb5ccdf4dce57b7b33475cc4f9fec525a6bf3
parent03198da2add75a0bcec792ffd84fcc8d94e8637e (diff)
downloadrust-7769c9a7ec8aec50260956a6383c38f4e8dbdf35.tar.gz
rust-7769c9a7ec8aec50260956a6383c38f4e8dbdf35.zip
coerce fields to the expected field type
Fully fixes #31260.

This needs a crater run.
-rw-r--r--src/librustc_typeck/check/mod.rs29
-rw-r--r--src/test/run-pass/issue-31260.rs5
-rw-r--r--src/test/ui/mismatched_types/abridged.rs10
-rw-r--r--src/test/ui/mismatched_types/abridged.stderr24
4 files changed, 29 insertions, 39 deletions
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index f7e23d28987..9d93388edc7 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -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")
         };
@@ -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
@@ -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,
@@ -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.
diff --git a/src/test/run-pass/issue-31260.rs b/src/test/run-pass/issue-31260.rs
index e771fc7464d..d21ffb96bef 100644
--- a/src/test/run-pass/issue-31260.rs
+++ b/src/test/run-pass/issue-31260.rs
@@ -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() {}
diff --git a/src/test/ui/mismatched_types/abridged.rs b/src/test/ui/mismatched_types/abridged.rs
index c448ad955fa..03f889224be 100644
--- a/src/test/ui/mismatched_types/abridged.rs
+++ b/src/test/ui/mismatched_types/abridged.rs
@@ -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() {}
diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr
index 78b5dcda1d9..8513da1e1d2 100644
--- a/src/test/ui/mismatched_types/abridged.stderr
+++ b/src/test/ui/mismatched_types/abridged.stderr
@@ -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}>, _>`