From 0ca432844c89668e1ae123d66b7033a5b39b3b39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sun, 30 Jul 2023 01:46:20 +0200 Subject: [PATCH] Check lazy type aliases for well-formedness --- .../rustc_hir_analysis/src/check/wfcheck.rs | 7 +++++-- compiler/rustc_lint/src/builtin.rs | 19 ++++++++++++------- src/tools/tidy/src/ui_tests.rs | 2 +- .../enum-variant.rs} | 0 .../enum-variant.stderr} | 2 +- .../type-alias-bounds-are-enforced.rs | 14 ++++++++++++++ .../unsatisfied-bounds-type-alias-body.rs | 8 ++++++++ .../unsatisfied-bounds-type-alias-body.stderr | 14 ++++++++++++++ 8 files changed, 55 insertions(+), 11 deletions(-) rename tests/ui/{type-alias/lazy-type-alias-enum-variant.rs => lazy-type-alias/enum-variant.rs} (100%) rename tests/ui/{type-alias/lazy-type-alias-enum-variant.stderr => lazy-type-alias/enum-variant.stderr} (88%) 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 diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 4df572f61998c..ad886ce82b142 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 ba05622bf3718..e6917f4b2d3b7 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 6cc7fbcacaf96..1a46747ba5311 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/type-alias/lazy-type-alias-enum-variant.rs b/tests/ui/lazy-type-alias/enum-variant.rs similarity index 100% rename from tests/ui/type-alias/lazy-type-alias-enum-variant.rs rename to tests/ui/lazy-type-alias/enum-variant.rs diff --git a/tests/ui/type-alias/lazy-type-alias-enum-variant.stderr b/tests/ui/lazy-type-alias/enum-variant.stderr similarity index 88% rename from tests/ui/type-alias/lazy-type-alias-enum-variant.stderr rename to tests/ui/lazy-type-alias/enum-variant.stderr index 381261b95c736..4360db917783f 100644 --- a/tests/ui/type-alias/lazy-type-alias-enum-variant.stderr +++ b/tests/ui/lazy-type-alias/enum-variant.stderr @@ -1,5 +1,5 @@ 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 + --> $DIR/enum-variant.rs:4:12 | LL | #![feature(lazy_type_alias)] | ^^^^^^^^^^^^^^^ 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 0000000000000..d0abd3ebf24b8 --- /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 0000000000000..c798e4e436824 --- /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 0000000000000..d022f82514075 --- /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`.