From c0bd0c6bc306d7d998f9aebb6b955316c2fe3986 Mon Sep 17 00:00:00 2001 From: b-naber Date: Wed, 7 Jul 2021 11:16:03 +0200 Subject: [PATCH 1/4] reject type alias impl traits as field types --- compiler/rustc_typeck/src/check/check.rs | 119 ++++++++++++++++++++++- 1 file changed, 118 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 70d85796d002e..91ff03058e159 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -9,7 +9,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; -use rustc_hir::{def::Res, ItemKind, Node, PathSegment}; +use rustc_hir::{def::DefKind, def::Res, ItemKind, Node, PathSegment}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_middle::ty::fold::TypeFoldable; @@ -414,7 +414,12 @@ pub(super) fn check_fn<'a, 'tcx>( } fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) { + debug!("check_struct(def_id: {:?}, span: {:?})", def_id, span); + let def = tcx.adt_def(def_id); + + check_fields_for_opaque_types(tcx, def, def_id, span); + def.destructor(tcx); // force the destructor to be evaluated check_representable(tcx, span, def_id); @@ -426,8 +431,119 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) { check_packed(tcx, span, def); } +fn check_fields_for_opaque_types( + tcx: TyCtxt<'tcx>, + adt_def: &ty::AdtDef, + def_id: LocalDefId, + span: Span, +) { + fn find_span_of_field_def_and_ty_alias( + tcx: TyCtxt<'tcx>, + field_def: &ty::FieldDef, + ) -> (Option, Option) { + let field_def_def_id = field_def.did; + if let Some(field_def_local_id) = field_def_def_id.as_local() { + let field_def_hir_id = tcx.hir().local_def_id_to_hir_id(field_def_local_id); + if let hir::Node::Field(hir::FieldDef { + span: field_def_span, ty: field_def_ty, .. + }) = tcx.hir().get(field_def_hir_id) + { + if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = field_def_ty.kind { + if let Res::Def(DefKind::TyAlias, ty_alias_def_id) = path.res { + if let Some(ty_alias_local_id) = ty_alias_def_id.as_local() { + let ty_alias_hir_id = + tcx.hir().local_def_id_to_hir_id(ty_alias_local_id); + let node = tcx.hir().get(ty_alias_hir_id); + match node { + hir::Node::Item(hir::Item { + kind, span: ty_alias_span, .. + }) => match kind { + hir::ItemKind::TyAlias(_, _) => { + return (Some(*field_def_span), Some(*ty_alias_span)); + } + _ => bug!("expected an item of kind TyAlias"), + }, + _ => return (Some(*field_def_span), None), + } + } + } + } + } + } + (None, None) + } + + debug!("check_fields_of_opaque_types(adt_def: {:?}, span: {:?})", adt_def, span); + + let item_type = tcx.type_of(def_id); + let substs = match item_type.kind() { + ty::Adt(_, substs) => substs, + _ => bug!("check_fields_for_opaque_types should only be called on Adts"), + }; + adt_def.all_fields().for_each(|field_def| { + debug!("field_def: {:?}", field_def); + + let field_ty = field_def.ty(tcx, substs); + match field_ty.kind() { + ty::Opaque(..) => { + use ty::AdtKind::*; + let adt_kind = match adt_def.adt_kind() { + Struct => "struct", + Enum => "enum", + Union => "union", + }; + + let mut diag; + match find_span_of_field_def_and_ty_alias(tcx, field_def) { + (Some(field_def_span), Some(ty_alias_span)) => { + diag = tcx.sess.struct_span_err( + span, + &format!( + "type alias impl traits are not allowed as field types in {}s", + adt_kind + ), + ); + diag.span_label( + field_def_span, + "this field contains a type alias impl trait", + ); + diag.span_label(ty_alias_span, "type alias defined here"); + } + (Some(field_def_span), None) => { + diag = tcx.sess.struct_span_err( + span, + &format!( + "type alias impl traits are not allowed as field types in {}s", + adt_kind + ), + ); + + diag.span_label( + field_def_span, + "this field contains a type alias impl trait", + ); + } + _ => { + diag = tcx.sess.struct_span_err( + span, + &format!( + "type alias impl traits are not allowed as field types in {}s", + adt_kind + ), + ); + } + } + + diag.emit(); + } + _ => {} + } + }); +} + fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) { let def = tcx.adt_def(def_id); + check_fields_for_opaque_types(tcx, def, def_id, span); def.destructor(tcx); // force the destructor to be evaluated check_representable(tcx, span, def_id); check_transparent(tcx, span, def); @@ -1408,6 +1524,7 @@ fn check_enum<'tcx>( def_id: LocalDefId, ) { let def = tcx.adt_def(def_id); + check_fields_for_opaque_types(tcx, def, def_id, sp); def.destructor(tcx); // force the destructor to be evaluated if vs.is_empty() { From cba8b4c5a49bef3a869f7e6dea53093ea2bf998b Mon Sep 17 00:00:00 2001 From: b-naber Date: Wed, 7 Jul 2021 11:16:57 +0200 Subject: [PATCH 2/4] add test and update existing tests --- .../feature-gate-type_alias_impl_trait.rs | 1 + .../feature-gate-type_alias_impl_trait.stderr | 27 +++-- .../reject-opaque_types-in-fields.rs | 42 ++++++++ .../reject-opaque_types-in-fields.stderr | 102 ++++++++++++++++++ .../lint/lint-ctypes-73249-3.full_tait.stderr | 22 ++-- .../lint/lint-ctypes-73249-3.min_tait.stderr | 22 ++-- src/test/ui/lint/lint-ctypes-73249-3.rs | 3 +- .../lint/lint-ctypes-73249-5.full_tait.stderr | 22 ++-- .../lint/lint-ctypes-73249-5.min_tait.stderr | 22 ++-- src/test/ui/lint/lint-ctypes-73249-5.rs | 3 +- .../type-alias-impl-trait/cross_crate_ice.rs | 2 +- .../cross_crate_ice.stderr | 8 ++ ...pe-alias-impl-trait-tuple.full_tait.stderr | 18 +++- ...ype-alias-impl-trait-tuple.min_tait.stderr | 16 +++ .../type-alias-impl-trait-tuple.rs | 3 +- 15 files changed, 254 insertions(+), 59 deletions(-) create mode 100644 src/test/ui/impl-trait/reject-opaque_types-in-fields.rs create mode 100644 src/test/ui/impl-trait/reject-opaque_types-in-fields.stderr create mode 100644 src/test/ui/type-alias-impl-trait/cross_crate_ice.stderr create mode 100644 src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.min_tait.stderr diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs index dfd82a25f4c87..44f3c05673625 100644 --- a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs +++ b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs @@ -6,6 +6,7 @@ type Foo = impl Debug; //~^ ERROR could not find defining uses struct Bar(Foo); +//~^ ERROR type alias impl traits are not allowed as field types in structs fn define() -> Bar { Bar(42) //~ ERROR mismatched types } diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr index 43fd76ef0ed9f..4eba5a781ca35 100644 --- a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr +++ b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/feature-gate-type_alias_impl_trait.rs:10:9 + --> $DIR/feature-gate-type_alias_impl_trait.rs:11:9 | LL | type Foo = impl Debug; | ---------- the expected opaque type @@ -11,7 +11,7 @@ LL | Bar(42) found type `{integer}` error[E0658]: type alias impl trait is not permitted here - --> $DIR/feature-gate-type_alias_impl_trait.rs:16:19 + --> $DIR/feature-gate-type_alias_impl_trait.rs:17:19 | LL | let x = || -> Foo2 { 42 }; | ^^^^ @@ -20,7 +20,7 @@ LL | let x = || -> Foo2 { 42 }; = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable error[E0308]: mismatched types - --> $DIR/feature-gate-type_alias_impl_trait.rs:23:18 + --> $DIR/feature-gate-type_alias_impl_trait.rs:24:18 | LL | type Foo3 = impl Debug; | ---------- the found opaque type @@ -34,7 +34,7 @@ LL | let y: i32 = x; found opaque type `impl Debug` error[E0308]: mismatched types - --> $DIR/feature-gate-type_alias_impl_trait.rs:26:13 + --> $DIR/feature-gate-type_alias_impl_trait.rs:27:13 | LL | type Foo3 = impl Debug; | ---------- the expected opaque type @@ -46,7 +46,7 @@ LL | define3(42) found type `{integer}` error[E0658]: type alias impl trait is not permitted here - --> $DIR/feature-gate-type_alias_impl_trait.rs:33:12 + --> $DIR/feature-gate-type_alias_impl_trait.rs:34:12 | LL | let y: Foo4 = 42; | ^^^^ @@ -60,19 +60,30 @@ error: could not find defining uses LL | type Foo = impl Debug; | ^^^^^^^^^^ +error: type alias impl traits are not allowed as field types in structs + --> $DIR/feature-gate-type_alias_impl_trait.rs:8:1 + | +LL | type Foo = impl Debug; + | ---------------------- type alias defined here +... +LL | struct Bar(Foo); + | ^^^^^^^^^^^---^^ + | | + | this field contains a type alias impl trait + error: could not find defining uses - --> $DIR/feature-gate-type_alias_impl_trait.rs:19:13 + --> $DIR/feature-gate-type_alias_impl_trait.rs:20:13 | LL | type Foo3 = impl Debug; | ^^^^^^^^^^ error: could not find defining uses - --> $DIR/feature-gate-type_alias_impl_trait.rs:29:13 + --> $DIR/feature-gate-type_alias_impl_trait.rs:30:13 | LL | type Foo4 = impl Debug; | ^^^^^^^^^^ -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors Some errors have detailed explanations: E0308, E0658. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/impl-trait/reject-opaque_types-in-fields.rs b/src/test/ui/impl-trait/reject-opaque_types-in-fields.rs new file mode 100644 index 0000000000000..0fbef0490e8c6 --- /dev/null +++ b/src/test/ui/impl-trait/reject-opaque_types-in-fields.rs @@ -0,0 +1,42 @@ +#![feature(min_type_alias_impl_trait)] + +type ImplCopy = impl Copy; +//~^ ERROR could not find defining uses + +enum Wrapper { +//~^ ERROR type alias impl traits are not allowed as field types in enums + First(ImplCopy), + Second +} + +type X = impl Iterator + Unpin; +//~^ ERROR could not find defining uses + +struct Foo(X); +//~^ ERROR type alias impl traits are not allowed as field types in structs + +impl Foo { + fn new(z: Vec) -> Self { + Foo(z.into_iter()) + //~^ ERROR mismatched types + } +} + +struct Bar {a : X} +//~^ ERROR type alias impl traits are not allowed as field types in structs + +impl Bar { + fn new(z: Vec) -> Self { + Bar {a: z.into_iter() } + //~^ ERROR mismatched types + } +} + +union MyUnion { + //~^ ERROR type alias impl traits are not allowed as field types in unions + a: X, + //~^ ERROR unions may not contain fields that need dropping +} + + +fn main() {} diff --git a/src/test/ui/impl-trait/reject-opaque_types-in-fields.stderr b/src/test/ui/impl-trait/reject-opaque_types-in-fields.stderr new file mode 100644 index 0000000000000..2bfa4c5f46387 --- /dev/null +++ b/src/test/ui/impl-trait/reject-opaque_types-in-fields.stderr @@ -0,0 +1,102 @@ +error[E0308]: mismatched types + --> $DIR/reject-opaque_types-in-fields.rs:20:13 + | +LL | type X = impl Iterator + Unpin; + | --------------------------------- the expected opaque type +... +LL | Foo(z.into_iter()) + | ^^^^^^^^^^^^^ expected opaque type, found struct `std::vec::IntoIter` + | + = note: expected opaque type `impl Iterator+Unpin` + found struct `std::vec::IntoIter` + +error[E0308]: mismatched types + --> $DIR/reject-opaque_types-in-fields.rs:30:13 + | +LL | type X = impl Iterator + Unpin; + | --------------------------------- the expected opaque type +... +LL | Bar {a: z.into_iter() } + | ^^^^^^^^^^^^^ expected opaque type, found struct `std::vec::IntoIter` + | + = note: expected opaque type `impl Iterator+Unpin` + found struct `std::vec::IntoIter` + +error: could not find defining uses + --> $DIR/reject-opaque_types-in-fields.rs:3:17 + | +LL | type ImplCopy = impl Copy; + | ^^^^^^^^^ + +error: type alias impl traits are not allowed as field types in enums + --> $DIR/reject-opaque_types-in-fields.rs:6:1 + | +LL | type ImplCopy = impl Copy; + | -------------------------- type alias defined here +... +LL | / enum Wrapper { +LL | | +LL | | First(ImplCopy), + | | -------- this field contains a type alias impl trait +LL | | Second +LL | | } + | |_^ + +error: could not find defining uses + --> $DIR/reject-opaque_types-in-fields.rs:12:10 + | +LL | type X = impl Iterator + Unpin; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: type alias impl traits are not allowed as field types in structs + --> $DIR/reject-opaque_types-in-fields.rs:15:1 + | +LL | type X = impl Iterator + Unpin; + | ------------------------------------------- type alias defined here +... +LL | struct Foo(X); + | ^^^^^^^^^^^-^^ + | | + | this field contains a type alias impl trait + +error: type alias impl traits are not allowed as field types in structs + --> $DIR/reject-opaque_types-in-fields.rs:25:1 + | +LL | type X = impl Iterator + Unpin; + | ------------------------------------------- type alias defined here +... +LL | struct Bar {a : X} + | ^^^^^^^^^^^^-----^ + | | + | this field contains a type alias impl trait + +error: type alias impl traits are not allowed as field types in unions + --> $DIR/reject-opaque_types-in-fields.rs:35:1 + | +LL | type X = impl Iterator + Unpin; + | ------------------------------------------- type alias defined here +... +LL | / union MyUnion { +LL | | +LL | | a: X, + | | ---- this field contains a type alias impl trait +LL | | +LL | | } + | |_^ + +error[E0740]: unions may not contain fields that need dropping + --> $DIR/reject-opaque_types-in-fields.rs:37:3 + | +LL | a: X, + | ^^^^ + | +note: `std::mem::ManuallyDrop` can be used to wrap the type + --> $DIR/reject-opaque_types-in-fields.rs:37:3 + | +LL | a: X, + | ^^^^ + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0308, E0740. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/lint/lint-ctypes-73249-3.full_tait.stderr b/src/test/ui/lint/lint-ctypes-73249-3.full_tait.stderr index af0f26a9f43e6..ce5875aff571f 100644 --- a/src/test/ui/lint/lint-ctypes-73249-3.full_tait.stderr +++ b/src/test/ui/lint/lint-ctypes-73249-3.full_tait.stderr @@ -7,18 +7,18 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -error: `extern` block uses type `impl Baz`, which is not FFI-safe - --> $DIR/lint-ctypes-73249-3.rs:21:25 +error: type alias impl traits are not allowed as field types in structs + --> $DIR/lint-ctypes-73249-3.rs:16:1 | -LL | pub fn lint_me() -> A; - | ^ not FFI-safe - | -note: the lint level is defined here - --> $DIR/lint-ctypes-73249-3.rs:5:9 - | -LL | #![deny(improper_ctypes)] - | ^^^^^^^^^^^^^^^ - = note: opaque types have no C equivalent +LL | type Qux = impl Baz; + | -------------------- type alias defined here +... +LL | / pub struct A { +LL | | +LL | | x: Qux, + | | ------ this field contains a type alias impl trait +LL | | } + | |_^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/lint/lint-ctypes-73249-3.min_tait.stderr b/src/test/ui/lint/lint-ctypes-73249-3.min_tait.stderr index 880581ff05d22..6fd159acdd29b 100644 --- a/src/test/ui/lint/lint-ctypes-73249-3.min_tait.stderr +++ b/src/test/ui/lint/lint-ctypes-73249-3.min_tait.stderr @@ -1,15 +1,15 @@ -error: `extern` block uses type `impl Baz`, which is not FFI-safe - --> $DIR/lint-ctypes-73249-3.rs:21:25 +error: type alias impl traits are not allowed as field types in structs + --> $DIR/lint-ctypes-73249-3.rs:16:1 | -LL | pub fn lint_me() -> A; - | ^ not FFI-safe - | -note: the lint level is defined here - --> $DIR/lint-ctypes-73249-3.rs:5:9 - | -LL | #![deny(improper_ctypes)] - | ^^^^^^^^^^^^^^^ - = note: opaque types have no C equivalent +LL | type Qux = impl Baz; + | -------------------- type alias defined here +... +LL | / pub struct A { +LL | | +LL | | x: Qux, + | | ------ this field contains a type alias impl trait +LL | | } + | |_^ error: aborting due to previous error diff --git a/src/test/ui/lint/lint-ctypes-73249-3.rs b/src/test/ui/lint/lint-ctypes-73249-3.rs index 966c7d5ce3cb6..8e6723c039b09 100644 --- a/src/test/ui/lint/lint-ctypes-73249-3.rs +++ b/src/test/ui/lint/lint-ctypes-73249-3.rs @@ -14,11 +14,12 @@ fn assign() -> Qux { 3 } #[repr(C)] pub struct A { + //~^ ERROR type alias impl traits are not allowed as field types in structs x: Qux, } extern "C" { - pub fn lint_me() -> A; //~ ERROR: uses type `impl Baz` + pub fn lint_me() -> A; } fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73249-5.full_tait.stderr b/src/test/ui/lint/lint-ctypes-73249-5.full_tait.stderr index b80084fce068c..fe1ea01ecf262 100644 --- a/src/test/ui/lint/lint-ctypes-73249-5.full_tait.stderr +++ b/src/test/ui/lint/lint-ctypes-73249-5.full_tait.stderr @@ -7,18 +7,18 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -error: `extern` block uses type `impl Baz`, which is not FFI-safe - --> $DIR/lint-ctypes-73249-5.rs:21:25 +error: type alias impl traits are not allowed as field types in structs + --> $DIR/lint-ctypes-73249-5.rs:16:1 | -LL | pub fn lint_me() -> A; - | ^ not FFI-safe - | -note: the lint level is defined here - --> $DIR/lint-ctypes-73249-5.rs:5:9 - | -LL | #![deny(improper_ctypes)] - | ^^^^^^^^^^^^^^^ - = note: opaque types have no C equivalent +LL | type Qux = impl Baz; + | -------------------- type alias defined here +... +LL | / pub struct A { +LL | | +LL | | x: Qux, + | | ------ this field contains a type alias impl trait +LL | | } + | |_^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/lint/lint-ctypes-73249-5.min_tait.stderr b/src/test/ui/lint/lint-ctypes-73249-5.min_tait.stderr index f42549d909656..ce82886d54ef4 100644 --- a/src/test/ui/lint/lint-ctypes-73249-5.min_tait.stderr +++ b/src/test/ui/lint/lint-ctypes-73249-5.min_tait.stderr @@ -1,15 +1,15 @@ -error: `extern` block uses type `impl Baz`, which is not FFI-safe - --> $DIR/lint-ctypes-73249-5.rs:21:25 +error: type alias impl traits are not allowed as field types in structs + --> $DIR/lint-ctypes-73249-5.rs:16:1 | -LL | pub fn lint_me() -> A; - | ^ not FFI-safe - | -note: the lint level is defined here - --> $DIR/lint-ctypes-73249-5.rs:5:9 - | -LL | #![deny(improper_ctypes)] - | ^^^^^^^^^^^^^^^ - = note: opaque types have no C equivalent +LL | type Qux = impl Baz; + | -------------------- type alias defined here +... +LL | / pub struct A { +LL | | +LL | | x: Qux, + | | ------ this field contains a type alias impl trait +LL | | } + | |_^ error: aborting due to previous error diff --git a/src/test/ui/lint/lint-ctypes-73249-5.rs b/src/test/ui/lint/lint-ctypes-73249-5.rs index 81979a9b6e696..8b8c39bdab3af 100644 --- a/src/test/ui/lint/lint-ctypes-73249-5.rs +++ b/src/test/ui/lint/lint-ctypes-73249-5.rs @@ -14,11 +14,12 @@ fn assign() -> Qux { 3 } #[repr(transparent)] pub struct A { + //~^ ERROR type alias impl traits are not allowed as field types in structs x: Qux, } extern "C" { - pub fn lint_me() -> A; //~ ERROR: uses type `impl Baz` + pub fn lint_me() -> A; } fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/cross_crate_ice.rs b/src/test/ui/type-alias-impl-trait/cross_crate_ice.rs index c30608176aada..c8c7429b2fc05 100644 --- a/src/test/ui/type-alias-impl-trait/cross_crate_ice.rs +++ b/src/test/ui/type-alias-impl-trait/cross_crate_ice.rs @@ -1,9 +1,9 @@ // aux-build:cross_crate_ice.rs -// build-pass (FIXME(62277): could be check-pass?) extern crate cross_crate_ice; struct Bar(cross_crate_ice::Foo); +//~^ type alias impl traits are not allowed as field types in structs impl Bar { fn zero(&self) -> &cross_crate_ice::Foo { diff --git a/src/test/ui/type-alias-impl-trait/cross_crate_ice.stderr b/src/test/ui/type-alias-impl-trait/cross_crate_ice.stderr new file mode 100644 index 0000000000000..13fb6273974df --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/cross_crate_ice.stderr @@ -0,0 +1,8 @@ +error: type alias impl traits are not allowed as field types in structs + --> $DIR/cross_crate_ice.rs:5:1 + | +LL | struct Bar(cross_crate_ice::Foo); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.full_tait.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.full_tait.stderr index 1a351867bff2d..2f267367acff0 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.full_tait.stderr @@ -1,5 +1,5 @@ warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/type-alias-impl-trait-tuple.rs:5:32 + --> $DIR/type-alias-impl-trait-tuple.rs:3:32 | LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] | ^^^^^^^^^^^^^^^^^^^^^ @@ -7,5 +7,19 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -warning: 1 warning emitted +error: type alias impl traits are not allowed as field types in structs + --> $DIR/type-alias-impl-trait-tuple.rs:11:1 + | +LL | / struct Blah { +LL | | +LL | | my_foo: Foo, + | | ----------- this field contains a type alias impl trait +LL | | my_u8: u8 +LL | | } + | |_^ +... +LL | type Foo = impl MyTrait; + | ------------------------ type alias defined here + +error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.min_tait.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.min_tait.stderr new file mode 100644 index 0000000000000..23f9211ef1179 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.min_tait.stderr @@ -0,0 +1,16 @@ +error: type alias impl traits are not allowed as field types in structs + --> $DIR/type-alias-impl-trait-tuple.rs:11:1 + | +LL | / struct Blah { +LL | | +LL | | my_foo: Foo, + | | ----------- this field contains a type alias impl trait +LL | | my_u8: u8 +LL | | } + | |_^ +... +LL | type Foo = impl MyTrait; + | ------------------------ type alias defined here + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs index ad2c11d4f994e..52adcb7d2a58f 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs @@ -1,5 +1,3 @@ -// check-pass - // revisions: min_tait full_tait #![feature(min_type_alias_impl_trait)] #![cfg_attr(full_tait, feature(type_alias_impl_trait))] @@ -11,6 +9,7 @@ pub trait MyTrait {} impl MyTrait for bool {} struct Blah { + //~^ ERROR type alias impl traits are not allowed as field types in structs my_foo: Foo, my_u8: u8 } From 21548b4bfbed52b387165729841d4954bb79f902 Mon Sep 17 00:00:00 2001 From: b-naber Date: Thu, 15 Jul 2021 12:17:11 +0200 Subject: [PATCH 3/4] add typevisitor for rejecting fields with nested type alias impl types --- compiler/rustc_typeck/src/check/check.rs | 197 +++++++++++------- .../feature-gate-type_alias_impl_trait.rs | 2 +- .../feature-gate-type_alias_impl_trait.stderr | 5 +- .../reject-opaque_types-in-fields.rs | 11 +- .../reject-opaque_types-in-fields.stderr | 48 +++-- .../lint/lint-ctypes-73249-3.full_tait.stderr | 7 +- .../lint/lint-ctypes-73249-3.min_tait.stderr | 7 +- src/test/ui/lint/lint-ctypes-73249-3.rs | 2 +- .../lint/lint-ctypes-73249-5.full_tait.stderr | 7 +- .../lint/lint-ctypes-73249-5.min_tait.stderr | 7 +- src/test/ui/lint/lint-ctypes-73249-5.rs | 2 +- src/test/ui/mir/issue-75053.full_tait.stderr | 16 +- .../ui/mir/issue-75053.in_bindings.stderr | 16 +- src/test/ui/mir/issue-75053.min_tait.stderr | 16 +- src/test/ui/mir/issue-75053.rs | 1 + ...pe-alias-impl-trait-tuple.full_tait.stderr | 7 +- ...ype-alias-impl-trait-tuple.min_tait.stderr | 7 +- .../type-alias-impl-trait-tuple.rs | 2 +- 18 files changed, 245 insertions(+), 115 deletions(-) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 91ff03058e159..142f2640c0c28 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -7,7 +7,7 @@ use rustc_attr as attr; use rustc_errors::{Applicability, ErrorReported}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::Visitor; +use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::lang_items::LangItem; use rustc_hir::{def::DefKind, def::Res, ItemKind, Node, PathSegment}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -437,10 +437,66 @@ fn check_fields_for_opaque_types( def_id: LocalDefId, span: Span, ) { - fn find_span_of_field_def_and_ty_alias( + struct TyAliasFinder<'tcx> { + tcx: TyCtxt<'tcx>, + ty_alias_span: Option, + ty_alias_ident: Option, + field_ty_span: Option, + } + + impl TyAliasFinder<'_> { + fn new(tcx: TyCtxt<'tcx>) -> TyAliasFinder<'_> { + TyAliasFinder { tcx, ty_alias_span: None, ty_alias_ident: None, field_ty_span: None } + } + + fn get_collected_information(&self) -> (Option, Option, Option) { + (self.field_ty_span, self.ty_alias_ident, self.ty_alias_span) + } + } + + impl<'tcx> intravisit::Visitor<'tcx> for TyAliasFinder<'tcx> { + type Map = intravisit::ErasedMap<'tcx>; + + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { + intravisit::NestedVisitorMap::None + } + + fn visit_ty(&mut self, t: &'tcx hir::Ty<'_>) { + if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = t.kind { + if let Res::Def(DefKind::TyAlias, ty_alias_def_id) = path.res { + let span = path.span; + if let Some(ty_alias_local_id) = ty_alias_def_id.as_local() { + let ty_alias_hir_id = + self.tcx.hir().local_def_id_to_hir_id(ty_alias_local_id); + let node = self.tcx.hir().get(ty_alias_hir_id); + match node { + hir::Node::Item(hir::Item { + ident, kind, span: ty_alias_span, .. + }) => match kind { + hir::ItemKind::TyAlias(_, _) => { + self.ty_alias_span = Some(*ty_alias_span); + self.ty_alias_ident = Some(*ident); + self.field_ty_span = Some(span); + return; + } + _ => bug!("expected an item of kind TyAlias"), + }, + _ => { + self.field_ty_span = Some(span); + return; + } + } + } + } + } + intravisit::walk_ty(self, t); + } + } + + fn find_ty_alias_information( tcx: TyCtxt<'tcx>, field_def: &ty::FieldDef, - ) -> (Option, Option) { + ) -> (Option, Option, Option, Option) { let field_def_def_id = field_def.did; if let Some(field_def_local_id) = field_def_def_id.as_local() { let field_def_hir_id = tcx.hir().local_def_id_to_hir_id(field_def_local_id); @@ -448,29 +504,15 @@ fn check_fields_for_opaque_types( span: field_def_span, ty: field_def_ty, .. }) = tcx.hir().get(field_def_hir_id) { - if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = field_def_ty.kind { - if let Res::Def(DefKind::TyAlias, ty_alias_def_id) = path.res { - if let Some(ty_alias_local_id) = ty_alias_def_id.as_local() { - let ty_alias_hir_id = - tcx.hir().local_def_id_to_hir_id(ty_alias_local_id); - let node = tcx.hir().get(ty_alias_hir_id); - match node { - hir::Node::Item(hir::Item { - kind, span: ty_alias_span, .. - }) => match kind { - hir::ItemKind::TyAlias(_, _) => { - return (Some(*field_def_span), Some(*ty_alias_span)); - } - _ => bug!("expected an item of kind TyAlias"), - }, - _ => return (Some(*field_def_span), None), - } - } - } - } + let mut type_alias_finder = TyAliasFinder::new(tcx); + type_alias_finder.visit_ty(field_def_ty); + + let (field_ty_span, ty_alias_ident, ty_alias_span) = + type_alias_finder.get_collected_information(); + return (Some(*field_def_span), field_ty_span, ty_alias_ident, ty_alias_span); } } - (None, None) + (None, None, None, None) } debug!("check_fields_of_opaque_types(adt_def: {:?}, span: {:?})", adt_def, span); @@ -484,59 +526,68 @@ fn check_fields_for_opaque_types( debug!("field_def: {:?}", field_def); let field_ty = field_def.ty(tcx, substs); - match field_ty.kind() { - ty::Opaque(..) => { - use ty::AdtKind::*; - let adt_kind = match adt_def.adt_kind() { - Struct => "struct", - Enum => "enum", - Union => "union", - }; - - let mut diag; - match find_span_of_field_def_and_ty_alias(tcx, field_def) { - (Some(field_def_span), Some(ty_alias_span)) => { - diag = tcx.sess.struct_span_err( - span, - &format!( - "type alias impl traits are not allowed as field types in {}s", - adt_kind - ), - ); - diag.span_label( - field_def_span, - "this field contains a type alias impl trait", - ); - diag.span_label(ty_alias_span, "type alias defined here"); - } - (Some(field_def_span), None) => { - diag = tcx.sess.struct_span_err( - span, - &format!( - "type alias impl traits are not allowed as field types in {}s", - adt_kind - ), - ); + if field_ty.has_opaque_types() { + use ty::AdtKind::*; + let adt_kind = match adt_def.adt_kind() { + Struct => "struct", + Enum => "enum", + Union => "union", + }; - diag.span_label( - field_def_span, - "this field contains a type alias impl trait", - ); - } - _ => { - diag = tcx.sess.struct_span_err( - span, - &format!( - "type alias impl traits are not allowed as field types in {}s", - adt_kind - ), - ); - } + let mut diag; + match find_ty_alias_information(tcx, field_def) { + ( + Some(field_def_span), + Some(field_ty_span), + Some(ty_alias_ident), + Some(ty_alias_span), + ) => { + diag = tcx.sess.struct_span_err( + span, + &format!( + "type aliases of `impl Trait` are not allowed as field types in {}s", + adt_kind + ), + ); + let field_def_span_msg = format!( + "this field contains a type alias `{}` of an `impl Trait`", + ty_alias_ident + ); + + let field_ty_span_msg = + "this type is a type alias of an `impl Trait`".to_string(); + + diag.span_label(field_def_span, field_def_span_msg); + diag.span_label(field_ty_span, field_ty_span_msg); + diag.span_label(ty_alias_span, "type alias defined here"); } + (Some(field_def_span), Some(field_ty_span), None, None) => { + diag = tcx.sess.struct_span_err( + span, + &format!( + "type aliases of `impl Trait` are not allowed as field types in {}s", + adt_kind + ), + ); - diag.emit(); + diag.span_label( + field_def_span, + "this field contains a type alias of an `impl trait`", + ); + diag.span_label(field_ty_span, "this type is a type alias of an `impl trait`"); + } + _ => { + diag = tcx.sess.struct_span_err( + span, + &format!( + "type alias impl traits are not allowed as field types in {}s", + adt_kind + ), + ); + } } - _ => {} + + diag.emit(); } }); } diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs index 44f3c05673625..52a4ef14c5ce8 100644 --- a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs +++ b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs @@ -6,7 +6,7 @@ type Foo = impl Debug; //~^ ERROR could not find defining uses struct Bar(Foo); -//~^ ERROR type alias impl traits are not allowed as field types in structs +//~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs fn define() -> Bar { Bar(42) //~ ERROR mismatched types } diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr index 4eba5a781ca35..21c7447df587c 100644 --- a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr +++ b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr @@ -60,7 +60,7 @@ error: could not find defining uses LL | type Foo = impl Debug; | ^^^^^^^^^^ -error: type alias impl traits are not allowed as field types in structs +error: type aliases of `impl Trait` are not allowed as field types in structs --> $DIR/feature-gate-type_alias_impl_trait.rs:8:1 | LL | type Foo = impl Debug; @@ -69,7 +69,8 @@ LL | type Foo = impl Debug; LL | struct Bar(Foo); | ^^^^^^^^^^^---^^ | | - | this field contains a type alias impl trait + | this field contains a type alias `Foo` of an `impl Trait` + | this type is a type alias of an `impl Trait` error: could not find defining uses --> $DIR/feature-gate-type_alias_impl_trait.rs:20:13 diff --git a/src/test/ui/impl-trait/reject-opaque_types-in-fields.rs b/src/test/ui/impl-trait/reject-opaque_types-in-fields.rs index 0fbef0490e8c6..9debcc50f59a6 100644 --- a/src/test/ui/impl-trait/reject-opaque_types-in-fields.rs +++ b/src/test/ui/impl-trait/reject-opaque_types-in-fields.rs @@ -4,7 +4,7 @@ type ImplCopy = impl Copy; //~^ ERROR could not find defining uses enum Wrapper { -//~^ ERROR type alias impl traits are not allowed as field types in enums +//~^ ERROR type aliases of `impl Trait` are not allowed as field types in enums First(ImplCopy), Second } @@ -13,7 +13,7 @@ type X = impl Iterator + Unpin; //~^ ERROR could not find defining uses struct Foo(X); -//~^ ERROR type alias impl traits are not allowed as field types in structs +//~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs impl Foo { fn new(z: Vec) -> Self { @@ -22,8 +22,11 @@ impl Foo { } } +struct FooNested(Vec); +//~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs + struct Bar {a : X} -//~^ ERROR type alias impl traits are not allowed as field types in structs +//~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs impl Bar { fn new(z: Vec) -> Self { @@ -33,7 +36,7 @@ impl Bar { } union MyUnion { - //~^ ERROR type alias impl traits are not allowed as field types in unions + //~^ ERROR type aliases of `impl Trait` are not allowed as field types in unions a: X, //~^ ERROR unions may not contain fields that need dropping } diff --git a/src/test/ui/impl-trait/reject-opaque_types-in-fields.stderr b/src/test/ui/impl-trait/reject-opaque_types-in-fields.stderr index 2bfa4c5f46387..61a5b400e24c3 100644 --- a/src/test/ui/impl-trait/reject-opaque_types-in-fields.stderr +++ b/src/test/ui/impl-trait/reject-opaque_types-in-fields.stderr @@ -11,7 +11,7 @@ LL | Foo(z.into_iter()) found struct `std::vec::IntoIter` error[E0308]: mismatched types - --> $DIR/reject-opaque_types-in-fields.rs:30:13 + --> $DIR/reject-opaque_types-in-fields.rs:33:13 | LL | type X = impl Iterator + Unpin; | --------------------------------- the expected opaque type @@ -28,7 +28,7 @@ error: could not find defining uses LL | type ImplCopy = impl Copy; | ^^^^^^^^^ -error: type alias impl traits are not allowed as field types in enums +error: type aliases of `impl Trait` are not allowed as field types in enums --> $DIR/reject-opaque_types-in-fields.rs:6:1 | LL | type ImplCopy = impl Copy; @@ -37,7 +37,10 @@ LL | type ImplCopy = impl Copy; LL | / enum Wrapper { LL | | LL | | First(ImplCopy), - | | -------- this field contains a type alias impl trait + | | -------- + | | | + | | this field contains a type alias `ImplCopy` of an `impl Trait` + | | this type is a type alias of an `impl Trait` LL | | Second LL | | } | |_^ @@ -48,7 +51,7 @@ error: could not find defining uses LL | type X = impl Iterator + Unpin; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: type alias impl traits are not allowed as field types in structs +error: type aliases of `impl Trait` are not allowed as field types in structs --> $DIR/reject-opaque_types-in-fields.rs:15:1 | LL | type X = impl Iterator + Unpin; @@ -57,21 +60,35 @@ LL | type X = impl Iterator + Unpin; LL | struct Foo(X); | ^^^^^^^^^^^-^^ | | - | this field contains a type alias impl trait + | this field contains a type alias `X` of an `impl Trait` + | this type is a type alias of an `impl Trait` -error: type alias impl traits are not allowed as field types in structs +error: type aliases of `impl Trait` are not allowed as field types in structs --> $DIR/reject-opaque_types-in-fields.rs:25:1 | LL | type X = impl Iterator + Unpin; | ------------------------------------------- type alias defined here ... +LL | struct FooNested(Vec); + | ^^^^^^^^^^^^^^^^^------^^ + | | | + | | this type is a type alias of an `impl Trait` + | this field contains a type alias `X` of an `impl Trait` + +error: type aliases of `impl Trait` are not allowed as field types in structs + --> $DIR/reject-opaque_types-in-fields.rs:28:1 + | +LL | type X = impl Iterator + Unpin; + | ------------------------------------------- type alias defined here +... LL | struct Bar {a : X} | ^^^^^^^^^^^^-----^ - | | - | this field contains a type alias impl trait + | | | + | | this type is a type alias of an `impl Trait` + | this field contains a type alias `X` of an `impl Trait` -error: type alias impl traits are not allowed as field types in unions - --> $DIR/reject-opaque_types-in-fields.rs:35:1 +error: type aliases of `impl Trait` are not allowed as field types in unions + --> $DIR/reject-opaque_types-in-fields.rs:38:1 | LL | type X = impl Iterator + Unpin; | ------------------------------------------- type alias defined here @@ -79,24 +96,27 @@ LL | type X = impl Iterator + Unpin; LL | / union MyUnion { LL | | LL | | a: X, - | | ---- this field contains a type alias impl trait + | | ---- + | | | | + | | | this type is a type alias of an `impl Trait` + | | this field contains a type alias `X` of an `impl Trait` LL | | LL | | } | |_^ error[E0740]: unions may not contain fields that need dropping - --> $DIR/reject-opaque_types-in-fields.rs:37:3 + --> $DIR/reject-opaque_types-in-fields.rs:40:3 | LL | a: X, | ^^^^ | note: `std::mem::ManuallyDrop` can be used to wrap the type - --> $DIR/reject-opaque_types-in-fields.rs:37:3 + --> $DIR/reject-opaque_types-in-fields.rs:40:3 | LL | a: X, | ^^^^ -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors Some errors have detailed explanations: E0308, E0740. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/lint/lint-ctypes-73249-3.full_tait.stderr b/src/test/ui/lint/lint-ctypes-73249-3.full_tait.stderr index ce5875aff571f..5a8a54ef4563d 100644 --- a/src/test/ui/lint/lint-ctypes-73249-3.full_tait.stderr +++ b/src/test/ui/lint/lint-ctypes-73249-3.full_tait.stderr @@ -7,7 +7,7 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -error: type alias impl traits are not allowed as field types in structs +error: type aliases of `impl Trait` are not allowed as field types in structs --> $DIR/lint-ctypes-73249-3.rs:16:1 | LL | type Qux = impl Baz; @@ -16,7 +16,10 @@ LL | type Qux = impl Baz; LL | / pub struct A { LL | | LL | | x: Qux, - | | ------ this field contains a type alias impl trait + | | ------ + | | | | + | | | this type is a type alias of an `impl Trait` + | | this field contains a type alias `Qux` of an `impl Trait` LL | | } | |_^ diff --git a/src/test/ui/lint/lint-ctypes-73249-3.min_tait.stderr b/src/test/ui/lint/lint-ctypes-73249-3.min_tait.stderr index 6fd159acdd29b..7ab692384b5d9 100644 --- a/src/test/ui/lint/lint-ctypes-73249-3.min_tait.stderr +++ b/src/test/ui/lint/lint-ctypes-73249-3.min_tait.stderr @@ -1,4 +1,4 @@ -error: type alias impl traits are not allowed as field types in structs +error: type aliases of `impl Trait` are not allowed as field types in structs --> $DIR/lint-ctypes-73249-3.rs:16:1 | LL | type Qux = impl Baz; @@ -7,7 +7,10 @@ LL | type Qux = impl Baz; LL | / pub struct A { LL | | LL | | x: Qux, - | | ------ this field contains a type alias impl trait + | | ------ + | | | | + | | | this type is a type alias of an `impl Trait` + | | this field contains a type alias `Qux` of an `impl Trait` LL | | } | |_^ diff --git a/src/test/ui/lint/lint-ctypes-73249-3.rs b/src/test/ui/lint/lint-ctypes-73249-3.rs index 8e6723c039b09..eca8d0a10c7fa 100644 --- a/src/test/ui/lint/lint-ctypes-73249-3.rs +++ b/src/test/ui/lint/lint-ctypes-73249-3.rs @@ -14,7 +14,7 @@ fn assign() -> Qux { 3 } #[repr(C)] pub struct A { - //~^ ERROR type alias impl traits are not allowed as field types in structs + //~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs x: Qux, } diff --git a/src/test/ui/lint/lint-ctypes-73249-5.full_tait.stderr b/src/test/ui/lint/lint-ctypes-73249-5.full_tait.stderr index fe1ea01ecf262..08a7367c8d5bc 100644 --- a/src/test/ui/lint/lint-ctypes-73249-5.full_tait.stderr +++ b/src/test/ui/lint/lint-ctypes-73249-5.full_tait.stderr @@ -7,7 +7,7 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -error: type alias impl traits are not allowed as field types in structs +error: type aliases of `impl Trait` are not allowed as field types in structs --> $DIR/lint-ctypes-73249-5.rs:16:1 | LL | type Qux = impl Baz; @@ -16,7 +16,10 @@ LL | type Qux = impl Baz; LL | / pub struct A { LL | | LL | | x: Qux, - | | ------ this field contains a type alias impl trait + | | ------ + | | | | + | | | this type is a type alias of an `impl Trait` + | | this field contains a type alias `Qux` of an `impl Trait` LL | | } | |_^ diff --git a/src/test/ui/lint/lint-ctypes-73249-5.min_tait.stderr b/src/test/ui/lint/lint-ctypes-73249-5.min_tait.stderr index ce82886d54ef4..d60a733be126f 100644 --- a/src/test/ui/lint/lint-ctypes-73249-5.min_tait.stderr +++ b/src/test/ui/lint/lint-ctypes-73249-5.min_tait.stderr @@ -1,4 +1,4 @@ -error: type alias impl traits are not allowed as field types in structs +error: type aliases of `impl Trait` are not allowed as field types in structs --> $DIR/lint-ctypes-73249-5.rs:16:1 | LL | type Qux = impl Baz; @@ -7,7 +7,10 @@ LL | type Qux = impl Baz; LL | / pub struct A { LL | | LL | | x: Qux, - | | ------ this field contains a type alias impl trait + | | ------ + | | | | + | | | this type is a type alias of an `impl Trait` + | | this field contains a type alias `Qux` of an `impl Trait` LL | | } | |_^ diff --git a/src/test/ui/lint/lint-ctypes-73249-5.rs b/src/test/ui/lint/lint-ctypes-73249-5.rs index 8b8c39bdab3af..5a9cb47c2e61c 100644 --- a/src/test/ui/lint/lint-ctypes-73249-5.rs +++ b/src/test/ui/lint/lint-ctypes-73249-5.rs @@ -14,7 +14,7 @@ fn assign() -> Qux { 3 } #[repr(transparent)] pub struct A { - //~^ ERROR type alias impl traits are not allowed as field types in structs + //~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs x: Qux, } diff --git a/src/test/ui/mir/issue-75053.full_tait.stderr b/src/test/ui/mir/issue-75053.full_tait.stderr index aff19094b7af8..6af729e39457a 100644 --- a/src/test/ui/mir/issue-75053.full_tait.stderr +++ b/src/test/ui/mir/issue-75053.full_tait.stderr @@ -8,7 +8,7 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] = note: see issue #63063 for more information error[E0658]: type alias impl trait is not permitted here - --> $DIR/issue-75053.rs:52:15 + --> $DIR/issue-75053.rs:53:15 | LL | let _pos: Phantom1> = Scope::new().my_index(); | ^^^^^^^^^^^^^^^^^^^^ @@ -16,6 +16,18 @@ LL | let _pos: Phantom1> = Scope::new().my_index(); = note: see issue #63065 for more information = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable -error: aborting due to previous error; 1 warning emitted +error: type aliases of `impl Trait` are not allowed as field types in structs + --> $DIR/issue-75053.rs:28:1 + | +LL | type DummyT = impl F; + | ------------------------ type alias defined here +... +LL | struct Scope(Phantom2>); + | ^^^^^^^^^^^^^^^^-------------------^^ + | | | + | | this type is a type alias of an `impl Trait` + | this field contains a type alias `DummyT` of an `impl Trait` + +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/mir/issue-75053.in_bindings.stderr b/src/test/ui/mir/issue-75053.in_bindings.stderr index a43fabc8f5d91..b4984e2c953b9 100644 --- a/src/test/ui/mir/issue-75053.in_bindings.stderr +++ b/src/test/ui/mir/issue-75053.in_bindings.stderr @@ -8,7 +8,7 @@ LL | #![cfg_attr(in_bindings, feature(impl_trait_in_bindings))] = note: see issue #63065 for more information error[E0282]: type annotations needed - --> $DIR/issue-75053.rs:52:38 + --> $DIR/issue-75053.rs:53:38 | LL | type O; | ------- `>::O` defined here @@ -19,6 +19,18 @@ LL | let _pos: Phantom1> = Scope::new().my_index(); | this method call resolves to `>::O` | cannot infer type for type parameter `T` -error: aborting due to previous error; 1 warning emitted +error: type aliases of `impl Trait` are not allowed as field types in structs + --> $DIR/issue-75053.rs:28:1 + | +LL | type DummyT = impl F; + | ------------------------ type alias defined here +... +LL | struct Scope(Phantom2>); + | ^^^^^^^^^^^^^^^^-------------------^^ + | | | + | | this type is a type alias of an `impl Trait` + | this field contains a type alias `DummyT` of an `impl Trait` + +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/mir/issue-75053.min_tait.stderr b/src/test/ui/mir/issue-75053.min_tait.stderr index 7ce91e851a755..158c9f9bfa0b0 100644 --- a/src/test/ui/mir/issue-75053.min_tait.stderr +++ b/src/test/ui/mir/issue-75053.min_tait.stderr @@ -1,5 +1,5 @@ error[E0658]: type alias impl trait is not permitted here - --> $DIR/issue-75053.rs:52:15 + --> $DIR/issue-75053.rs:53:15 | LL | let _pos: Phantom1> = Scope::new().my_index(); | ^^^^^^^^^^^^^^^^^^^^ @@ -7,6 +7,18 @@ LL | let _pos: Phantom1> = Scope::new().my_index(); = note: see issue #63065 for more information = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable -error: aborting due to previous error +error: type aliases of `impl Trait` are not allowed as field types in structs + --> $DIR/issue-75053.rs:28:1 + | +LL | type DummyT = impl F; + | ------------------------ type alias defined here +... +LL | struct Scope(Phantom2>); + | ^^^^^^^^^^^^^^^^-------------------^^ + | | | + | | this type is a type alias of an `impl Trait` + | this field contains a type alias `DummyT` of an `impl Trait` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/mir/issue-75053.rs b/src/test/ui/mir/issue-75053.rs index 89ae3ca3006b9..b0a72febaf4c1 100644 --- a/src/test/ui/mir/issue-75053.rs +++ b/src/test/ui/mir/issue-75053.rs @@ -26,6 +26,7 @@ fn _dummy_t() -> DummyT {} struct Phantom1(PhantomData); struct Phantom2(PhantomData); struct Scope(Phantom2>); +//~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs impl Scope { fn new() -> Self { diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.full_tait.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.full_tait.stderr index 2f267367acff0..5d85773174a5f 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.full_tait.stderr @@ -7,13 +7,16 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -error: type alias impl traits are not allowed as field types in structs +error: type aliases of `impl Trait` are not allowed as field types in structs --> $DIR/type-alias-impl-trait-tuple.rs:11:1 | LL | / struct Blah { LL | | LL | | my_foo: Foo, - | | ----------- this field contains a type alias impl trait + | | ----------- + | | | | + | | | this type is a type alias of an `impl Trait` + | | this field contains a type alias `Foo` of an `impl Trait` LL | | my_u8: u8 LL | | } | |_^ diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.min_tait.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.min_tait.stderr index 23f9211ef1179..13919fe323c69 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.min_tait.stderr @@ -1,10 +1,13 @@ -error: type alias impl traits are not allowed as field types in structs +error: type aliases of `impl Trait` are not allowed as field types in structs --> $DIR/type-alias-impl-trait-tuple.rs:11:1 | LL | / struct Blah { LL | | LL | | my_foo: Foo, - | | ----------- this field contains a type alias impl trait + | | ----------- + | | | | + | | | this type is a type alias of an `impl Trait` + | | this field contains a type alias `Foo` of an `impl Trait` LL | | my_u8: u8 LL | | } | |_^ diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs index 52adcb7d2a58f..3d309a447b4ea 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs @@ -9,7 +9,7 @@ pub trait MyTrait {} impl MyTrait for bool {} struct Blah { - //~^ ERROR type alias impl traits are not allowed as field types in structs + //~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs my_foo: Foo, my_u8: u8 } From fb17ef1672b022913f9ef977dcf23afc628570f5 Mon Sep 17 00:00:00 2001 From: b-naber Date: Mon, 19 Jul 2021 10:56:03 +0200 Subject: [PATCH 4/4] dont check opaque type aliases in fields in type_alias_impl_trait --- compiler/rustc_typeck/src/check/check.rs | 4 +++ .../lint/lint-ctypes-73249-3.full_tait.stderr | 25 ++++++++----------- src/test/ui/lint/lint-ctypes-73249-3.rs | 3 ++- .../lint/lint-ctypes-73249-5.full_tait.stderr | 25 ++++++++----------- src/test/ui/lint/lint-ctypes-73249-5.rs | 3 ++- src/test/ui/mir/issue-75053.full_tait.stderr | 14 +---------- src/test/ui/mir/issue-75053.rs | 2 +- ...pe-alias-impl-trait-tuple.full_tait.stderr | 21 ++-------------- ...ype-alias-impl-trait-tuple.min_tait.stderr | 2 +- .../type-alias-impl-trait-tuple.rs | 3 ++- 10 files changed, 37 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 142f2640c0c28..86fdc965e0856 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -515,6 +515,10 @@ fn check_fields_for_opaque_types( (None, None, None, None) } + if tcx.features().type_alias_impl_trait { + return; + } + debug!("check_fields_of_opaque_types(adt_def: {:?}, span: {:?})", adt_def, span); let item_type = tcx.type_of(def_id); diff --git a/src/test/ui/lint/lint-ctypes-73249-3.full_tait.stderr b/src/test/ui/lint/lint-ctypes-73249-3.full_tait.stderr index 5a8a54ef4563d..0689397a56364 100644 --- a/src/test/ui/lint/lint-ctypes-73249-3.full_tait.stderr +++ b/src/test/ui/lint/lint-ctypes-73249-3.full_tait.stderr @@ -7,21 +7,18 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -error: type aliases of `impl Trait` are not allowed as field types in structs - --> $DIR/lint-ctypes-73249-3.rs:16:1 +error: `extern` block uses type `impl Baz`, which is not FFI-safe + --> $DIR/lint-ctypes-73249-3.rs:22:25 | -LL | type Qux = impl Baz; - | -------------------- type alias defined here -... -LL | / pub struct A { -LL | | -LL | | x: Qux, - | | ------ - | | | | - | | | this type is a type alias of an `impl Trait` - | | this field contains a type alias `Qux` of an `impl Trait` -LL | | } - | |_^ +LL | pub fn lint_me() -> A; + | ^ not FFI-safe + | +note: the lint level is defined here + --> $DIR/lint-ctypes-73249-3.rs:5:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + = note: opaque types have no C equivalent error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/lint/lint-ctypes-73249-3.rs b/src/test/ui/lint/lint-ctypes-73249-3.rs index eca8d0a10c7fa..1f563d2497d7e 100644 --- a/src/test/ui/lint/lint-ctypes-73249-3.rs +++ b/src/test/ui/lint/lint-ctypes-73249-3.rs @@ -14,12 +14,13 @@ fn assign() -> Qux { 3 } #[repr(C)] pub struct A { - //~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs + //[min_tait]~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs x: Qux, } extern "C" { pub fn lint_me() -> A; + //[full_tait]~^ ERROR `extern` block uses type `impl Baz`, which is not FFI-safe } fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-73249-5.full_tait.stderr b/src/test/ui/lint/lint-ctypes-73249-5.full_tait.stderr index 08a7367c8d5bc..5125a5e6caf5c 100644 --- a/src/test/ui/lint/lint-ctypes-73249-5.full_tait.stderr +++ b/src/test/ui/lint/lint-ctypes-73249-5.full_tait.stderr @@ -7,21 +7,18 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -error: type aliases of `impl Trait` are not allowed as field types in structs - --> $DIR/lint-ctypes-73249-5.rs:16:1 +error: `extern` block uses type `impl Baz`, which is not FFI-safe + --> $DIR/lint-ctypes-73249-5.rs:22:25 | -LL | type Qux = impl Baz; - | -------------------- type alias defined here -... -LL | / pub struct A { -LL | | -LL | | x: Qux, - | | ------ - | | | | - | | | this type is a type alias of an `impl Trait` - | | this field contains a type alias `Qux` of an `impl Trait` -LL | | } - | |_^ +LL | pub fn lint_me() -> A; + | ^ not FFI-safe + | +note: the lint level is defined here + --> $DIR/lint-ctypes-73249-5.rs:5:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + = note: opaque types have no C equivalent error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/lint/lint-ctypes-73249-5.rs b/src/test/ui/lint/lint-ctypes-73249-5.rs index 5a9cb47c2e61c..27bb910d10b9b 100644 --- a/src/test/ui/lint/lint-ctypes-73249-5.rs +++ b/src/test/ui/lint/lint-ctypes-73249-5.rs @@ -14,12 +14,13 @@ fn assign() -> Qux { 3 } #[repr(transparent)] pub struct A { - //~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs + //[min_tait]~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs x: Qux, } extern "C" { pub fn lint_me() -> A; + //[full_tait]~^ ERROR `extern` block uses type `impl Baz`, which is not FFI-safe } fn main() {} diff --git a/src/test/ui/mir/issue-75053.full_tait.stderr b/src/test/ui/mir/issue-75053.full_tait.stderr index 6af729e39457a..3e0217202845d 100644 --- a/src/test/ui/mir/issue-75053.full_tait.stderr +++ b/src/test/ui/mir/issue-75053.full_tait.stderr @@ -16,18 +16,6 @@ LL | let _pos: Phantom1> = Scope::new().my_index(); = note: see issue #63065 for more information = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable -error: type aliases of `impl Trait` are not allowed as field types in structs - --> $DIR/issue-75053.rs:28:1 - | -LL | type DummyT = impl F; - | ------------------------ type alias defined here -... -LL | struct Scope(Phantom2>); - | ^^^^^^^^^^^^^^^^-------------------^^ - | | | - | | this type is a type alias of an `impl Trait` - | this field contains a type alias `DummyT` of an `impl Trait` - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/mir/issue-75053.rs b/src/test/ui/mir/issue-75053.rs index b0a72febaf4c1..b45e915723f20 100644 --- a/src/test/ui/mir/issue-75053.rs +++ b/src/test/ui/mir/issue-75053.rs @@ -26,7 +26,7 @@ fn _dummy_t() -> DummyT {} struct Phantom1(PhantomData); struct Phantom2(PhantomData); struct Scope(Phantom2>); -//~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs +//[min_tait,in_bindings]~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs impl Scope { fn new() -> Self { diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.full_tait.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.full_tait.stderr index 5d85773174a5f..6d5587c29b1e5 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.full_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.full_tait.stderr @@ -1,5 +1,5 @@ warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/type-alias-impl-trait-tuple.rs:3:32 + --> $DIR/type-alias-impl-trait-tuple.rs:4:32 | LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] | ^^^^^^^^^^^^^^^^^^^^^ @@ -7,22 +7,5 @@ LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))] = note: `#[warn(incomplete_features)]` on by default = note: see issue #63063 for more information -error: type aliases of `impl Trait` are not allowed as field types in structs - --> $DIR/type-alias-impl-trait-tuple.rs:11:1 - | -LL | / struct Blah { -LL | | -LL | | my_foo: Foo, - | | ----------- - | | | | - | | | this type is a type alias of an `impl Trait` - | | this field contains a type alias `Foo` of an `impl Trait` -LL | | my_u8: u8 -LL | | } - | |_^ -... -LL | type Foo = impl MyTrait; - | ------------------------ type alias defined here - -error: aborting due to previous error; 1 warning emitted +warning: 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.min_tait.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.min_tait.stderr index 13919fe323c69..96d2783f2a1d6 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.min_tait.stderr +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.min_tait.stderr @@ -1,5 +1,5 @@ error: type aliases of `impl Trait` are not allowed as field types in structs - --> $DIR/type-alias-impl-trait-tuple.rs:11:1 + --> $DIR/type-alias-impl-trait-tuple.rs:12:1 | LL | / struct Blah { LL | | diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs index 3d309a447b4ea..09944542d5848 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs @@ -1,4 +1,5 @@ // revisions: min_tait full_tait +//[full_tait] check-pass #![feature(min_type_alias_impl_trait)] #![cfg_attr(full_tait, feature(type_alias_impl_trait))] //[full_tait]~^ WARN incomplete @@ -9,7 +10,7 @@ pub trait MyTrait {} impl MyTrait for bool {} struct Blah { - //~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs + //[min_tait]~^ ERROR type aliases of `impl Trait` are not allowed as field types in structs my_foo: Foo, my_u8: u8 }