From 0ca432844c89668e1ae123d66b7033a5b39b3b39 Mon Sep 17 00:00:00 2001 From: León Orell Valerian Liehr Date: Sun, 30 Jul 2023 01:46:20 +0200 Subject: Check lazy type aliases for well-formedness --- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 7 +++++-- compiler/rustc_lint/src/builtin.rs | 19 ++++++++++++------- src/tools/tidy/src/ui_tests.rs | 2 +- tests/ui/lazy-type-alias/enum-variant.rs | 18 ++++++++++++++++++ tests/ui/lazy-type-alias/enum-variant.stderr | 11 +++++++++++ .../lazy-type-alias/type-alias-bounds-are-enforced.rs | 14 ++++++++++++++ .../unsatisfied-bounds-type-alias-body.rs | 8 ++++++++ .../unsatisfied-bounds-type-alias-body.stderr | 14 ++++++++++++++ tests/ui/type-alias/lazy-type-alias-enum-variant.rs | 18 ------------------ .../ui/type-alias/lazy-type-alias-enum-variant.stderr | 11 ----------- 10 files changed, 83 insertions(+), 39 deletions(-) create mode 100644 tests/ui/lazy-type-alias/enum-variant.rs create mode 100644 tests/ui/lazy-type-alias/enum-variant.stderr create mode 100644 tests/ui/lazy-type-alias/type-alias-bounds-are-enforced.rs create mode 100644 tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.rs create mode 100644 tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr delete mode 100644 tests/ui/type-alias/lazy-type-alias-enum-variant.rs delete mode 100644 tests/ui/type-alias/lazy-type-alias-enum-variant.stderr diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 4df572f6199..ad886ce82b1 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -246,8 +246,11 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { // `ForeignItem`s are handled separately. hir::ItemKind::ForeignMod { .. } => {} hir::ItemKind::TyAlias(hir_ty, ..) => { - if tcx.type_of(item.owner_id.def_id).skip_binder().has_opaque_types() { - // Bounds are respected for `type X = impl Trait` and `type X = (impl Trait, Y);` + if tcx.features().lazy_type_alias + || tcx.type_of(item.owner_id).skip_binder().has_opaque_types() + { + // Bounds of lazy type aliases and of eager ones that contain opaque types are respected. + // E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`. check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow); } } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index ba05622bf37..e6917f4b2d3 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1458,15 +1458,20 @@ impl TypeAliasBounds { impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - let hir::ItemKind::TyAlias(ty, type_alias_generics) = &item.kind else { return }; - if cx.tcx.type_of(item.owner_id.def_id).skip_binder().has_opaque_types() { - // Bounds are respected for `type X = impl Trait` and `type X = (impl Trait, Y);` + let hir::ItemKind::TyAlias(hir_ty, type_alias_generics) = &item.kind else { return }; + + if cx.tcx.features().lazy_type_alias { + // Bounds of lazy type aliases are respected. return; } - if cx.tcx.type_of(item.owner_id).skip_binder().has_inherent_projections() { - // Bounds are respected for `type X = … Type::Inherent …` + + let ty = cx.tcx.type_of(item.owner_id).skip_binder(); + if ty.has_opaque_types() || ty.has_inherent_projections() { + // Bounds of type aliases that contain opaque types or inherent projections are respected. + // E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`, `type X = Type::Inherent;`. return; } + // There must not be a where clause if type_alias_generics.predicates.is_empty() { return; @@ -1491,7 +1496,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { if !where_spans.is_empty() { let sub = (!suggested_changing_assoc_types).then(|| { suggested_changing_assoc_types = true; - SuggestChangingAssocTypes { ty } + SuggestChangingAssocTypes { ty: hir_ty } }); cx.emit_spanned_lint( TYPE_ALIAS_BOUNDS, @@ -1507,7 +1512,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { let suggestion = BuiltinTypeAliasGenericBoundsSuggestion { suggestions: inline_sugg }; let sub = (!suggested_changing_assoc_types).then(|| { suggested_changing_assoc_types = true; - SuggestChangingAssocTypes { ty } + SuggestChangingAssocTypes { ty: hir_ty } }); cx.emit_spanned_lint( TYPE_ALIAS_BOUNDS, diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 6cc7fbcacaf..1a46747ba53 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -11,7 +11,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: usize = 900; // FIXME: The following limits should be reduced eventually. const ISSUES_ENTRY_LIMIT: usize = 1893; -const ROOT_ENTRY_LIMIT: usize = 872; +const ROOT_ENTRY_LIMIT: usize = 873; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/ui/lazy-type-alias/enum-variant.rs b/tests/ui/lazy-type-alias/enum-variant.rs new file mode 100644 index 00000000000..6d18e9eca62 --- /dev/null +++ b/tests/ui/lazy-type-alias/enum-variant.rs @@ -0,0 +1,18 @@ +// Regression test for issue #113736. +// check-pass + +#![feature(lazy_type_alias)] +//~^ WARN the feature `lazy_type_alias` is incomplete and may not be safe to use + +enum Enum { + Unit, + Tuple(), + Struct {}, +} + +fn main() { + type Alias = Enum; + let _ = Alias::Unit; + let _ = Alias::Tuple(); + let _ = Alias::Struct {}; +} diff --git a/tests/ui/lazy-type-alias/enum-variant.stderr b/tests/ui/lazy-type-alias/enum-variant.stderr new file mode 100644 index 00000000000..4360db91778 --- /dev/null +++ b/tests/ui/lazy-type-alias/enum-variant.stderr @@ -0,0 +1,11 @@ +warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/enum-variant.rs:4:12 + | +LL | #![feature(lazy_type_alias)] + | ^^^^^^^^^^^^^^^ + | + = note: see issue #112792 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lazy-type-alias/type-alias-bounds-are-enforced.rs b/tests/ui/lazy-type-alias/type-alias-bounds-are-enforced.rs new file mode 100644 index 00000000000..d0abd3ebf24 --- /dev/null +++ b/tests/ui/lazy-type-alias/type-alias-bounds-are-enforced.rs @@ -0,0 +1,14 @@ +// Check that we don't issue the lint `type_alias_bounds` for +// lazy type aliases since the bounds are indeed enforced. + +// check-pass + +#![feature(lazy_type_alias)] +#![allow(incomplete_features)] +#![deny(type_alias_bounds)] + +use std::ops::Mul; + +type Alias = ::Output; + +fn main() {} diff --git a/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.rs b/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.rs new file mode 100644 index 00000000000..c798e4e4368 --- /dev/null +++ b/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.rs @@ -0,0 +1,8 @@ +// Test that we check lazy type aliases for well-formedness. + +#![feature(lazy_type_alias)] +#![allow(incomplete_features)] + +type Alias = ::Output; //~ ERROR cannot multiply `T` by `T` + +fn main() {} diff --git a/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr b/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr new file mode 100644 index 00000000000..d022f825140 --- /dev/null +++ b/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr @@ -0,0 +1,14 @@ +error[E0277]: cannot multiply `T` by `T` + --> $DIR/unsatisfied-bounds-type-alias-body.rs:6:17 + | +LL | type Alias = ::Output; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T * T` + | +help: consider restricting type parameter `T` + | +LL | type Alias = ::Output; + | +++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias/lazy-type-alias-enum-variant.rs b/tests/ui/type-alias/lazy-type-alias-enum-variant.rs deleted file mode 100644 index 6d18e9eca62..00000000000 --- a/tests/ui/type-alias/lazy-type-alias-enum-variant.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Regression test for issue #113736. -// check-pass - -#![feature(lazy_type_alias)] -//~^ WARN the feature `lazy_type_alias` is incomplete and may not be safe to use - -enum Enum { - Unit, - Tuple(), - Struct {}, -} - -fn main() { - type Alias = Enum; - let _ = Alias::Unit; - let _ = Alias::Tuple(); - let _ = Alias::Struct {}; -} diff --git a/tests/ui/type-alias/lazy-type-alias-enum-variant.stderr b/tests/ui/type-alias/lazy-type-alias-enum-variant.stderr deleted file mode 100644 index 381261b95c7..00000000000 --- a/tests/ui/type-alias/lazy-type-alias-enum-variant.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/lazy-type-alias-enum-variant.rs:4:12 - | -LL | #![feature(lazy_type_alias)] - | ^^^^^^^^^^^^^^^ - | - = note: see issue #112792 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - -- cgit 1.4.1-3-g733a5