Skip to content

Commit d8bd153

Browse files
Normalize types before looking for opaques
1 parent 742d3f0 commit d8bd153

File tree

3 files changed

+73
-22
lines changed

3 files changed

+73
-22
lines changed

compiler/rustc_lint/src/types.rs

+17-22
Original file line numberDiff line numberDiff line change
@@ -1195,35 +1195,30 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
11951195
}
11961196

11971197
fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
1198-
struct ProhibitOpaqueTypes<'a, 'tcx> {
1199-
cx: &'a LateContext<'tcx>,
1200-
}
1201-
1202-
impl<'a, 'tcx> ty::visit::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> {
1198+
struct ProhibitOpaqueTypes;
1199+
impl<'tcx> ty::visit::TypeVisitor<'tcx> for ProhibitOpaqueTypes {
12031200
type BreakTy = Ty<'tcx>;
12041201

12051202
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
1206-
match ty.kind() {
1207-
ty::Opaque(..) => ControlFlow::Break(ty),
1208-
// Consider opaque types within projections FFI-safe if they do not normalize
1209-
// to more opaque types.
1210-
ty::Projection(..) => {
1211-
let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty);
1212-
1213-
// If `ty` is an opaque type directly then `super_visit_with` won't invoke
1214-
// this function again.
1215-
if ty.has_opaque_types() {
1216-
self.visit_ty(ty)
1217-
} else {
1218-
ControlFlow::CONTINUE
1219-
}
1220-
}
1221-
_ => ty.super_visit_with(self),
1203+
if !ty.has_opaque_types() {
1204+
return ControlFlow::CONTINUE;
1205+
}
1206+
1207+
if let ty::Opaque(..) = ty.kind() {
1208+
ControlFlow::Break(ty)
1209+
} else {
1210+
ty.super_visit_with(self)
12221211
}
12231212
}
12241213
}
12251214

1226-
if let Some(ty) = ty.visit_with(&mut ProhibitOpaqueTypes { cx: self.cx }).break_value() {
1215+
if let Some(ty) = self
1216+
.cx
1217+
.tcx
1218+
.normalize_erasing_regions(self.cx.param_env, ty)
1219+
.visit_with(&mut ProhibitOpaqueTypes)
1220+
.break_value()
1221+
{
12271222
self.emit_ffi_unsafe_type_lint(ty, sp, fluent::lint_improper_ctypes_opaque, None);
12281223
true
12291224
} else {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#![feature(type_alias_impl_trait)]
2+
#![allow(unused)]
3+
#![deny(improper_ctypes)]
4+
5+
pub trait TraitA {
6+
type Assoc;
7+
}
8+
9+
impl TraitA for u32 {
10+
type Assoc = u32;
11+
}
12+
13+
pub trait TraitB {
14+
type Assoc;
15+
}
16+
17+
impl<T> TraitB for T
18+
where
19+
T: TraitA,
20+
{
21+
type Assoc = <T as TraitA>::Assoc;
22+
}
23+
24+
type AliasA = impl TraitA<Assoc = u32>;
25+
26+
type AliasB = impl TraitB;
27+
28+
fn use_of_a() -> AliasA {
29+
3
30+
}
31+
32+
fn use_of_b() -> AliasB {
33+
3
34+
}
35+
36+
extern "C" {
37+
fn lint_me() -> <AliasB as TraitB>::Assoc;
38+
//~^ ERROR `extern` block uses type `AliasB`, which is not FFI-safe
39+
}
40+
41+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: `extern` block uses type `AliasB`, which is not FFI-safe
2+
--> $DIR/opaque-ty-ffi-normalization-cycle.rs:37:21
3+
|
4+
LL | fn lint_me() -> <AliasB as TraitB>::Assoc;
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
6+
|
7+
= note: opaque types have no C equivalent
8+
note: the lint level is defined here
9+
--> $DIR/opaque-ty-ffi-normalization-cycle.rs:3:9
10+
|
11+
LL | #![deny(improper_ctypes)]
12+
| ^^^^^^^^^^^^^^^
13+
14+
error: aborting due to previous error
15+

0 commit comments

Comments
 (0)