From 4925e4a49c8d57b6b9158653f66fed5a6bc9c2d7 Mon Sep 17 00:00:00 2001
From: "Felix S. Klock II" <pnkfelix@pnkfx.org>
Date: Fri, 28 Jun 2019 17:46:54 +0200
Subject: [PATCH] wfcheck: just assume needs-drop on unresolved type expression
 for last-field, rather than even a delayed ICE.

Fix #61402.
---
 src/librustc_typeck/check/wfcheck.rs          |  7 +-----
 .../packed-with-inference-vars-issue-61402.rs | 22 +++++++++++++++++++
 2 files changed, 23 insertions(+), 6 deletions(-)
 create mode 100644 src/test/run-pass/packed-with-inference-vars-issue-61402.rs

diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 83711a32e23a5..3f66d01184ab3 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -270,12 +270,7 @@ fn check_type_defn<'tcx, F>(
                     let ty = variant.fields.last().unwrap().ty;
                     fcx.tcx.erase_regions(&ty).lift_to_tcx(fcx_tcx)
                         .map(|ty| ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id)))
-                        .unwrap_or_else(|| {
-                            fcx_tcx.sess.delay_span_bug(
-                                item.span, &format!("inference variables in {:?}", ty));
-                            // Just treat unresolved type expression as if it needs drop.
-                            true
-                        })
+                        .unwrap_or(true) // #61402 treat unresolved type expression as needs-drop
                 }
             };
             let all_sized =
diff --git a/src/test/run-pass/packed-with-inference-vars-issue-61402.rs b/src/test/run-pass/packed-with-inference-vars-issue-61402.rs
new file mode 100644
index 0000000000000..60b1a31899c7e
--- /dev/null
+++ b/src/test/run-pass/packed-with-inference-vars-issue-61402.rs
@@ -0,0 +1,22 @@
+// rust-lang/rust#61402: if a struct is packed and the last
+// field of the struct needs drop glue, then the compiler's well-formedness check
+// will put a Sized bound on that last field.
+//
+// However, we do not want to ICE the compiler in our attempt to
+// avoid adding that Sized bound; it is better to just let a
+// potentially unneeded constraint through.
+
+#![allow(unused_imports, dead_code)]
+
+pub struct S;
+
+pub trait Trait<R> { type Assoc; }
+
+impl<X> Trait<X> for S { type Assoc = X; }
+
+#[repr(C, packed)]
+struct PackedAssocSized {
+    pos: Box<<S as Trait<usize>>::Assoc>,
+}
+
+fn main() { println!("Hello, world!"); }