Skip to content

Commit

Permalink
ty: simplify transparent_newtype_field
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
davidtwco committed Jun 19, 2020
1 parent 0cccaa0 commit a730d88
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/librustc_lint/types.rs
Expand Up @@ -627,7 +627,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
if def.repr.transparent() {
// Can assume that only one field is not a ZST, so only check
// 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)
} else {
bug!("malformed transparent type");
Expand Down
14 changes: 1 addition & 13 deletions src/librustc_middle/ty/mod.rs
Expand Up @@ -1810,21 +1810,9 @@ impl<'tcx> VariantDef {

/// `repr(transparent)` structs can have a single non-ZST field, this function returns that
/// field.
pub fn transparent_newtype_field(
&self,
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
) -> Option<&FieldDef> {
pub fn transparent_newtype_field(&self, tcx: TyCtxt<'tcx>) -> Option<&FieldDef> {
for field in &self.fields {
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) {
return Some(field);
}
Expand Down
24 changes: 24 additions & 0 deletions src/test/ui/lint/lint-ctypes-73249-4.rs
@@ -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() {}

0 comments on commit a730d88

Please sign in to comment.