Skip to content

Commit

Permalink
Auto merge of #73257 - davidtwco:issue-73249-improper-ctypes-projecti…
Browse files Browse the repository at this point in the history
…on, r=lcnr,varkor

ty: projections in `transparent_newtype_field`

Fixes #73249.

This PR modifies `transparent_newtype_field` so that it handles
projections with generic parameters, where `normalize_erasing_regions`
would ICE.
  • Loading branch information
bors committed Jun 19, 2020
2 parents 72417d8 + a730d88 commit 2d8bd9b
Show file tree
Hide file tree
Showing 11 changed files with 299 additions and 159 deletions.
240 changes: 104 additions & 136 deletions src/librustc_lint/types.rs

Large diffs are not rendered by default.

36 changes: 13 additions & 23 deletions src/librustc_middle/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1807,6 +1807,19 @@ impl<'tcx> VariantDef {
pub fn is_field_list_non_exhaustive(&self) -> bool {
self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE)
}

/// `repr(transparent)` structs can have a single non-ZST field, this function returns that
/// field.
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));
if !field_ty.is_zst(tcx, self.def_id) {
return Some(field);
}
}

None
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
Expand Down Expand Up @@ -2376,29 +2389,6 @@ impl<'tcx> AdtDef {
pub fn sized_constraint(&self, tcx: TyCtxt<'tcx>) -> &'tcx [Ty<'tcx>] {
tcx.adt_sized_constraint(self.did).0
}

/// `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> {
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)),
);

if !field_ty.is_zst(tcx, self.did) {
return Some(field);
}
}

None
}
}

impl<'tcx> FieldDef {
Expand Down
21 changes: 21 additions & 0 deletions src/test/ui/lint/lint-ctypes-73249-1.rs
Original file line number Diff line number Diff line change
@@ -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() {}
29 changes: 29 additions & 0 deletions src/test/ui/lint/lint-ctypes-73249-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#![feature(type_alias_impl_trait)]
#![deny(improper_ctypes)]

pub trait Baz { }

impl Baz for () { }

type Qux = impl Baz;

fn assign() -> Qux {}

pub trait Foo {
type Assoc: 'static;
}

impl Foo for () {
type Assoc = Qux;
}

#[repr(transparent)]
pub struct A<T: Foo> {
x: &'static <T as Foo>::Assoc,
}

extern "C" {
pub fn lint_me() -> A<()>; //~ ERROR: uses type `impl Baz`
}

fn main() {}
15 changes: 15 additions & 0 deletions src/test/ui/lint/lint-ctypes-73249-2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error: `extern` block uses type `impl Baz`, which is not FFI-safe
--> $DIR/lint-ctypes-73249-2.rs:26:25
|
LL | pub fn lint_me() -> A<()>;
| ^^^^^ not FFI-safe
|
note: the lint level is defined here
--> $DIR/lint-ctypes-73249-2.rs:2:9
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
= note: opaque types have no C equivalent

error: aborting due to previous error

21 changes: 21 additions & 0 deletions src/test/ui/lint/lint-ctypes-73249-3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#![feature(type_alias_impl_trait)]
#![deny(improper_ctypes)]

pub trait Baz { }

impl Baz for u32 { }

type Qux = impl Baz;

fn assign() -> Qux { 3 }

#[repr(C)]
pub struct A {
x: Qux,
}

extern "C" {
pub fn lint_me() -> A; //~ ERROR: uses type `impl Baz`
}

fn main() {}
15 changes: 15 additions & 0 deletions src/test/ui/lint/lint-ctypes-73249-3.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error: `extern` block uses type `impl Baz`, which is not FFI-safe
--> $DIR/lint-ctypes-73249-3.rs:18:25
|
LL | pub fn lint_me() -> A;
| ^ not FFI-safe
|
note: the lint level is defined here
--> $DIR/lint-ctypes-73249-3.rs:2:9
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
= note: opaque types have no C equivalent

error: aborting due to previous error

24 changes: 24 additions & 0 deletions src/test/ui/lint/lint-ctypes-73249-4.rs
Original file line number Diff line number Diff line change
@@ -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() {}
21 changes: 21 additions & 0 deletions src/test/ui/lint/lint-ctypes-73249-5.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#![feature(type_alias_impl_trait)]
#![deny(improper_ctypes)]

pub trait Baz { }

impl Baz for u32 { }

type Qux = impl Baz;

fn assign() -> Qux { 3 }

#[repr(transparent)]
pub struct A {
x: Qux,
}

extern "C" {
pub fn lint_me() -> A; //~ ERROR: uses type `impl Baz`
}

fn main() {}
15 changes: 15 additions & 0 deletions src/test/ui/lint/lint-ctypes-73249-5.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error: `extern` block uses type `impl Baz`, which is not FFI-safe
--> $DIR/lint-ctypes-73249-5.rs:18:25
|
LL | pub fn lint_me() -> A;
| ^ not FFI-safe
|
note: the lint level is defined here
--> $DIR/lint-ctypes-73249-5.rs:2:9
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
= note: opaque types have no C equivalent

error: aborting due to previous error

21 changes: 21 additions & 0 deletions src/test/ui/lint/lint-ctypes-73249.rs
Original file line number Diff line number Diff line change
@@ -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() {}

0 comments on commit 2d8bd9b

Please sign in to comment.