From d5b07373cef98dec5672cd94bf14609eec65aa03 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 11 Jun 2020 22:53:32 +0100 Subject: [PATCH] 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 --- src/librustc_middle/ty/mod.rs | 12 ++++++++---- src/test/ui/lint/lint-ctypes-73249-1.rs | 21 +++++++++++++++++++++ src/test/ui/lint/lint-ctypes-73249.rs | 21 +++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/lint/lint-ctypes-73249-1.rs create mode 100644 src/test/ui/lint/lint-ctypes-73249.rs diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 93ef73171993..1f94c28b3572 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 000000000000..cf416c3fe8b1 --- /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 { + value: &'static ::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 000000000000..5b48fa9b7376 --- /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 { + value: ::Assoc, +} + +fn main() {}