ty: simplify transparent_newtype_field

This commit removes the normalization from `transparent_newtype_field` -
turns out it wasn't necessary and that makes it a bunch simpler -
particularly when handling projections.

Signed-off-by: David Wood <david@davidtw.co>
This commit is contained in:
David Wood 2020-06-12 16:14:05 +01:00
parent 0cccaa0a27
commit a730d888ae
No known key found for this signature in database
GPG Key ID: 2592E76C87381FD9
3 changed files with 26 additions and 14 deletions

View File

@ -627,7 +627,7 @@ fn check_variant_for_ffi(
if def.repr.transparent() { if def.repr.transparent() {
// Can assume that only one field is not a ZST, so only check // Can assume that only one field is not a ZST, so only check
// that field's type for FFI-safety. // that field's type for FFI-safety.
if let Some(field) = variant.transparent_newtype_field(self.cx.tcx, self.cx.param_env) { if let Some(field) = variant.transparent_newtype_field(self.cx.tcx) {
self.check_field_type_for_ffi(cache, field, substs) self.check_field_type_for_ffi(cache, field, substs)
} else { } else {
bug!("malformed transparent type"); bug!("malformed transparent type");

View File

@ -1810,21 +1810,9 @@ pub fn is_field_list_non_exhaustive(&self) -> bool {
/// `repr(transparent)` structs can have a single non-ZST field, this function returns that /// `repr(transparent)` structs can have a single non-ZST field, this function returns that
/// field. /// field.
pub fn transparent_newtype_field( pub fn transparent_newtype_field(&self, tcx: TyCtxt<'tcx>) -> Option<&FieldDef> {
&self,
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
) -> Option<&FieldDef> {
for field in &self.fields { for field in &self.fields {
let field_ty = field.ty(tcx, InternalSubsts::identity_for_item(tcx, self.def_id)); let field_ty = field.ty(tcx, InternalSubsts::identity_for_item(tcx, self.def_id));
// `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.def_id) { if !field_ty.is_zst(tcx, self.def_id) {
return Some(field); return Some(field);
} }

View File

@ -0,0 +1,24 @@
// check-pass
#![deny(improper_ctypes)]
use std::marker::PhantomData;
trait Foo {
type Assoc;
}
impl Foo for () {
type Assoc = PhantomData<()>;
}
#[repr(transparent)]
struct Wow<T> where T: Foo<Assoc = PhantomData<T>> {
x: <T as Foo>::Assoc,
v: u32,
}
extern "C" {
fn test(v: Wow<()>);
}
fn main() {}