about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Wood <david@davidtw.co>2020-06-11 22:53:32 +0100
committerDavid Wood <david@davidtw.co>2020-06-19 10:10:54 +0100
commitd5b07373cef98dec5672cd94bf14609eec65aa03 (patch)
tree695583d2fb9a40679893f2b08dc83557b2a3859c
parenta39c7787ba246353178e099373b9240be0d9e603 (diff)
downloadrust-d5b07373cef98dec5672cd94bf14609eec65aa03.tar.gz
rust-d5b07373cef98dec5672cd94bf14609eec65aa03.zip
ty: projections in `transparent_newtype_field`
This commit modifies `transparent_newtype_field` so that it handles
projections with generic parameters, where `normalize_erasing_regions`
would ICE.

Signed-off-by: David Wood <david@davidtw.co>
-rw-r--r--src/librustc_middle/ty/mod.rs12
-rw-r--r--src/test/ui/lint/lint-ctypes-73249-1.rs21
-rw-r--r--src/test/ui/lint/lint-ctypes-73249.rs21
3 files changed, 50 insertions, 4 deletions
diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs
index 93ef7317199..1f94c28b357 100644
--- a/src/librustc_middle/ty/mod.rs
+++ b/src/librustc_middle/ty/mod.rs
@@ -2387,11 +2387,15 @@ impl<'tcx> AdtDef {
         assert!(self.is_struct() && self.repr.transparent());
 
         for field in &self.non_enum_variant().fields {
-            let field_ty = tcx.normalize_erasing_regions(
-                param_env,
-                field.ty(tcx, InternalSubsts::identity_for_item(tcx, self.did)),
-            );
+            let field_ty = field.ty(tcx, InternalSubsts::identity_for_item(tcx, self.did));
+
+            // `normalize_erasing_regions` will fail for projections that contain generic
+            // parameters, so check these before normalizing.
+            if field_ty.has_projections() && field_ty.needs_subst() {
+                return Some(field);
+            }
 
+            let field_ty = tcx.normalize_erasing_regions(param_env, field_ty);
             if !field_ty.is_zst(tcx, self.did) {
                 return Some(field);
             }
diff --git a/src/test/ui/lint/lint-ctypes-73249-1.rs b/src/test/ui/lint/lint-ctypes-73249-1.rs
new file mode 100644
index 00000000000..cf416c3fe8b
--- /dev/null
+++ b/src/test/ui/lint/lint-ctypes-73249-1.rs
@@ -0,0 +1,21 @@
+// check-pass
+#![deny(improper_ctypes)]
+
+pub trait Foo {
+    type Assoc: 'static;
+}
+
+impl Foo for () {
+    type Assoc = u32;
+}
+
+extern "C" {
+    pub fn lint_me(x: Bar<()>);
+}
+
+#[repr(transparent)]
+pub struct Bar<T: Foo> {
+    value: &'static <T as Foo>::Assoc,
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-ctypes-73249.rs b/src/test/ui/lint/lint-ctypes-73249.rs
new file mode 100644
index 00000000000..5b48fa9b737
--- /dev/null
+++ b/src/test/ui/lint/lint-ctypes-73249.rs
@@ -0,0 +1,21 @@
+// check-pass
+#![deny(improper_ctypes)]
+
+pub trait Foo {
+    type Assoc;
+}
+
+impl Foo for () {
+    type Assoc = u32;
+}
+
+extern "C" {
+    pub fn lint_me(x: Bar<()>);
+}
+
+#[repr(transparent)]
+pub struct Bar<T: Foo> {
+    value: <T as Foo>::Assoc,
+}
+
+fn main() {}