Skip to content

Commit 2d8bd9b

Browse files
committed
Auto merge of #73257 - davidtwco:issue-73249-improper-ctypes-projection, 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.
2 parents 72417d8 + a730d88 commit 2d8bd9b

11 files changed

+299
-159
lines changed

src/librustc_lint/types.rs

+104-136
Large diffs are not rendered by default.

src/librustc_middle/ty/mod.rs

+13-23
Original file line numberDiff line numberDiff line change
@@ -1807,6 +1807,19 @@ impl<'tcx> VariantDef {
18071807
pub fn is_field_list_non_exhaustive(&self) -> bool {
18081808
self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE)
18091809
}
1810+
1811+
/// `repr(transparent)` structs can have a single non-ZST field, this function returns that
1812+
/// field.
1813+
pub fn transparent_newtype_field(&self, tcx: TyCtxt<'tcx>) -> Option<&FieldDef> {
1814+
for field in &self.fields {
1815+
let field_ty = field.ty(tcx, InternalSubsts::identity_for_item(tcx, self.def_id));
1816+
if !field_ty.is_zst(tcx, self.def_id) {
1817+
return Some(field);
1818+
}
1819+
}
1820+
1821+
None
1822+
}
18101823
}
18111824

18121825
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
@@ -2376,29 +2389,6 @@ impl<'tcx> AdtDef {
23762389
pub fn sized_constraint(&self, tcx: TyCtxt<'tcx>) -> &'tcx [Ty<'tcx>] {
23772390
tcx.adt_sized_constraint(self.did).0
23782391
}
2379-
2380-
/// `repr(transparent)` structs can have a single non-ZST field, this function returns that
2381-
/// field.
2382-
pub fn transparent_newtype_field(
2383-
&self,
2384-
tcx: TyCtxt<'tcx>,
2385-
param_env: ParamEnv<'tcx>,
2386-
) -> Option<&FieldDef> {
2387-
assert!(self.is_struct() && self.repr.transparent());
2388-
2389-
for field in &self.non_enum_variant().fields {
2390-
let field_ty = tcx.normalize_erasing_regions(
2391-
param_env,
2392-
field.ty(tcx, InternalSubsts::identity_for_item(tcx, self.did)),
2393-
);
2394-
2395-
if !field_ty.is_zst(tcx, self.did) {
2396-
return Some(field);
2397-
}
2398-
}
2399-
2400-
None
2401-
}
24022392
}
24032393

24042394
impl<'tcx> FieldDef {
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// check-pass
2+
#![deny(improper_ctypes)]
3+
4+
pub trait Foo {
5+
type Assoc: 'static;
6+
}
7+
8+
impl Foo for () {
9+
type Assoc = u32;
10+
}
11+
12+
extern "C" {
13+
pub fn lint_me(x: Bar<()>);
14+
}
15+
16+
#[repr(transparent)]
17+
pub struct Bar<T: Foo> {
18+
value: &'static <T as Foo>::Assoc,
19+
}
20+
21+
fn main() {}
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#![feature(type_alias_impl_trait)]
2+
#![deny(improper_ctypes)]
3+
4+
pub trait Baz { }
5+
6+
impl Baz for () { }
7+
8+
type Qux = impl Baz;
9+
10+
fn assign() -> Qux {}
11+
12+
pub trait Foo {
13+
type Assoc: 'static;
14+
}
15+
16+
impl Foo for () {
17+
type Assoc = Qux;
18+
}
19+
20+
#[repr(transparent)]
21+
pub struct A<T: Foo> {
22+
x: &'static <T as Foo>::Assoc,
23+
}
24+
25+
extern "C" {
26+
pub fn lint_me() -> A<()>; //~ ERROR: uses type `impl Baz`
27+
}
28+
29+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: `extern` block uses type `impl Baz`, which is not FFI-safe
2+
--> $DIR/lint-ctypes-73249-2.rs:26:25
3+
|
4+
LL | pub fn lint_me() -> A<()>;
5+
| ^^^^^ not FFI-safe
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/lint-ctypes-73249-2.rs:2:9
9+
|
10+
LL | #![deny(improper_ctypes)]
11+
| ^^^^^^^^^^^^^^^
12+
= note: opaque types have no C equivalent
13+
14+
error: aborting due to previous error
15+
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#![feature(type_alias_impl_trait)]
2+
#![deny(improper_ctypes)]
3+
4+
pub trait Baz { }
5+
6+
impl Baz for u32 { }
7+
8+
type Qux = impl Baz;
9+
10+
fn assign() -> Qux { 3 }
11+
12+
#[repr(C)]
13+
pub struct A {
14+
x: Qux,
15+
}
16+
17+
extern "C" {
18+
pub fn lint_me() -> A; //~ ERROR: uses type `impl Baz`
19+
}
20+
21+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: `extern` block uses type `impl Baz`, which is not FFI-safe
2+
--> $DIR/lint-ctypes-73249-3.rs:18:25
3+
|
4+
LL | pub fn lint_me() -> A;
5+
| ^ not FFI-safe
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/lint-ctypes-73249-3.rs:2:9
9+
|
10+
LL | #![deny(improper_ctypes)]
11+
| ^^^^^^^^^^^^^^^
12+
= note: opaque types have no C equivalent
13+
14+
error: aborting due to previous error
15+
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// check-pass
2+
#![deny(improper_ctypes)]
3+
4+
use std::marker::PhantomData;
5+
6+
trait Foo {
7+
type Assoc;
8+
}
9+
10+
impl Foo for () {
11+
type Assoc = PhantomData<()>;
12+
}
13+
14+
#[repr(transparent)]
15+
struct Wow<T> where T: Foo<Assoc = PhantomData<T>> {
16+
x: <T as Foo>::Assoc,
17+
v: u32,
18+
}
19+
20+
extern "C" {
21+
fn test(v: Wow<()>);
22+
}
23+
24+
fn main() {}
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#![feature(type_alias_impl_trait)]
2+
#![deny(improper_ctypes)]
3+
4+
pub trait Baz { }
5+
6+
impl Baz for u32 { }
7+
8+
type Qux = impl Baz;
9+
10+
fn assign() -> Qux { 3 }
11+
12+
#[repr(transparent)]
13+
pub struct A {
14+
x: Qux,
15+
}
16+
17+
extern "C" {
18+
pub fn lint_me() -> A; //~ ERROR: uses type `impl Baz`
19+
}
20+
21+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: `extern` block uses type `impl Baz`, which is not FFI-safe
2+
--> $DIR/lint-ctypes-73249-5.rs:18:25
3+
|
4+
LL | pub fn lint_me() -> A;
5+
| ^ not FFI-safe
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/lint-ctypes-73249-5.rs:2:9
9+
|
10+
LL | #![deny(improper_ctypes)]
11+
| ^^^^^^^^^^^^^^^
12+
= note: opaque types have no C equivalent
13+
14+
error: aborting due to previous error
15+

src/test/ui/lint/lint-ctypes-73249.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// check-pass
2+
#![deny(improper_ctypes)]
3+
4+
pub trait Foo {
5+
type Assoc;
6+
}
7+
8+
impl Foo for () {
9+
type Assoc = u32;
10+
}
11+
12+
extern "C" {
13+
pub fn lint_me(x: Bar<()>);
14+
}
15+
16+
#[repr(transparent)]
17+
pub struct Bar<T: Foo> {
18+
value: <T as Foo>::Assoc,
19+
}
20+
21+
fn main() {}

0 commit comments

Comments
 (0)