diff options
| author | Manish Goregaokar <manishsmail@gmail.com> | 2020-06-20 14:44:57 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-06-20 14:44:57 -0700 |
| commit | 90030876558d9c9f8623210fd7861136d2bae4f7 (patch) | |
| tree | e03d7f670d24de6ee72b7813d08e0fa4de4c6b60 | |
| parent | 45d6aefc6047652dd32a431c1a065a692545c082 (diff) | |
| parent | 2e781ddacc126b24df93f7b547ced542262f12a2 (diff) | |
| download | rust-90030876558d9c9f8623210fd7861136d2bae4f7.tar.gz rust-90030876558d9c9f8623210fd7861136d2bae4f7.zip | |
Rollup merge of #73287 - davidtwco:issue-73251-opaque-types-in-projections, r=estebank
lint: normalize projections using opaque types Fixes #73251. This PR normalizes projections which use opaque types (opaque types are otherwise linted against, which is would have previously made the test cases added in this PR fail).
| -rw-r--r-- | src/librustc_lint/types.rs | 27 | ||||
| -rw-r--r-- | src/test/ui/lint/lint-ctypes-73251-1.rs | 24 | ||||
| -rw-r--r-- | src/test/ui/lint/lint-ctypes-73251-1.stderr | 15 | ||||
| -rw-r--r-- | src/test/ui/lint/lint-ctypes-73251-2.rs | 32 | ||||
| -rw-r--r-- | src/test/ui/lint/lint-ctypes-73251-2.stderr | 15 | ||||
| -rw-r--r-- | src/test/ui/lint/lint-ctypes-73251.rs | 22 |
6 files changed, 127 insertions, 8 deletions
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index d92c1131ff9..a19c9a35579 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -895,22 +895,33 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool { - struct ProhibitOpaqueTypes<'tcx> { + struct ProhibitOpaqueTypes<'a, 'tcx> { + cx: &'a LateContext<'a, 'tcx>, ty: Option<Ty<'tcx>>, }; - impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'tcx> { + impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { - if let ty::Opaque(..) = ty.kind { - self.ty = Some(ty); - true - } else { - ty.super_visit_with(self) + match ty.kind { + ty::Opaque(..) => { + self.ty = Some(ty); + true + } + // Consider opaque types within projections FFI-safe if they do not normalize + // to more opaque types. + ty::Projection(..) => { + let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty); + + // If `ty` is a opaque type directly then `super_visit_with` won't invoke + // this function again. + if ty.has_opaque_types() { self.visit_ty(ty) } else { false } + } + _ => ty.super_visit_with(self), } } } - let mut visitor = ProhibitOpaqueTypes { ty: None }; + let mut visitor = ProhibitOpaqueTypes { cx: self.cx, ty: None }; ty.visit_with(&mut visitor); if let Some(ty) = visitor.ty { self.emit_ffi_unsafe_type_lint(ty, sp, "opaque types have no C equivalent", None); diff --git a/src/test/ui/lint/lint-ctypes-73251-1.rs b/src/test/ui/lint/lint-ctypes-73251-1.rs new file mode 100644 index 00000000000..2ce80982f5c --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73251-1.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait Baz { } + +impl Baz for u32 { } + +type Qux = impl Baz; + +pub trait Foo { + type Assoc; +} + +impl Foo for u32 { + type Assoc = Qux; +} + +fn assign() -> Qux { 1 } + +extern "C" { + pub fn lint_me() -> <u32 as Foo>::Assoc; //~ ERROR: uses type `impl Baz` +} + +fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73251-1.stderr b/src/test/ui/lint/lint-ctypes-73251-1.stderr new file mode 100644 index 00000000000..0b4237bb96f --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73251-1.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `impl Baz`, which is not FFI-safe + --> $DIR/lint-ctypes-73251-1.rs:21:25 + | +LL | pub fn lint_me() -> <u32 as Foo>::Assoc; + | ^^^^^^^^^^^^^^^^^^^ not FFI-safe + | +note: the lint level is defined here + --> $DIR/lint-ctypes-73251-1.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + = note: opaque types have no C equivalent + +error: aborting due to previous error + diff --git a/src/test/ui/lint/lint-ctypes-73251-2.rs b/src/test/ui/lint/lint-ctypes-73251-2.rs new file mode 100644 index 00000000000..3427c657b42 --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73251-2.rs @@ -0,0 +1,32 @@ +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait TraitA { + type Assoc; +} + +impl TraitA for u32 { + type Assoc = u32; +} + +pub trait TraitB { + type Assoc; +} + +impl<T> TraitB for T where T: TraitA { + type Assoc = <T as TraitA>::Assoc; +} + +type AliasA = impl TraitA<Assoc = u32>; + +type AliasB = impl TraitB<Assoc = AliasA>; + +fn use_of_a() -> AliasA { 3 } + +fn use_of_b() -> AliasB { 3 } + +extern "C" { + pub fn lint_me() -> <AliasB as TraitB>::Assoc; //~ ERROR: uses type `impl TraitA` +} + +fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73251-2.stderr b/src/test/ui/lint/lint-ctypes-73251-2.stderr new file mode 100644 index 00000000000..43f7629b043 --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73251-2.stderr @@ -0,0 +1,15 @@ +error: `extern` block uses type `impl TraitA`, which is not FFI-safe + --> $DIR/lint-ctypes-73251-2.rs:29:25 + | +LL | pub fn lint_me() -> <AliasB as TraitB>::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | +note: the lint level is defined here + --> $DIR/lint-ctypes-73251-2.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + = note: opaque types have no C equivalent + +error: aborting due to previous error + diff --git a/src/test/ui/lint/lint-ctypes-73251.rs b/src/test/ui/lint/lint-ctypes-73251.rs new file mode 100644 index 00000000000..ebc2ca77b67 --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-73251.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(type_alias_impl_trait)] +#![deny(improper_ctypes)] + +pub trait Foo { + type Assoc; +} + +impl Foo for () { + type Assoc = u32; +} + +type Bar = impl Foo<Assoc = u32>; + +fn assign() -> Bar {} + +extern "C" { + pub fn lint_me() -> <Bar as Foo>::Assoc; +} + +fn main() {} |
