about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-07-31 16:57:54 +0200
committerGitHub <noreply@github.com>2023-07-31 16:57:54 +0200
commit95b7116d70ac2cd4c9418ebdca16fc82b52ca890 (patch)
tree94e8b8fd623aaf9fef47397ac2971a1f93c40dc3
parentb8f78fb47cac063a3f6d8a8f8b3e8abc75bd7c29 (diff)
parent0ca432844c89668e1ae123d66b7033a5b39b3b39 (diff)
downloadrust-95b7116d70ac2cd4c9418ebdca16fc82b52ca890.tar.gz
rust-95b7116d70ac2cd4c9418ebdca16fc82b52ca890.zip
Rollup merge of #114228 - fmease:wf-lazy-ty-aliases, r=oli-obk
Check lazy type aliases for well-formedness

Previously we didn't check if `T: Mul` holds given lazy `type Alias<T> = <T as Mul>::Output;`.
Now we do. It only makes sense.

`@rustbot` label F-lazy_type_alias

r? `@oli-obk`
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs7
-rw-r--r--compiler/rustc_lint/src/builtin.rs19
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
-rw-r--r--tests/ui/lazy-type-alias/enum-variant.rs (renamed from tests/ui/type-alias/lazy-type-alias-enum-variant.rs)0
-rw-r--r--tests/ui/lazy-type-alias/enum-variant.stderr (renamed from tests/ui/type-alias/lazy-type-alias-enum-variant.stderr)2
-rw-r--r--tests/ui/lazy-type-alias/type-alias-bounds-are-enforced.rs14
-rw-r--r--tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.rs8
-rw-r--r--tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr14
8 files changed, 55 insertions, 11 deletions
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 a1822c83986..44c7c07d3a0 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
index 6d18e9eca62..6d18e9eca62 100644
--- a/tests/ui/type-alias/lazy-type-alias-enum-variant.rs
+++ b/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
index 381261b95c7..4360db91778 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 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<T: Mul> = <T as Mul>::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<T> = <T as std::ops::Mul>::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<T> = <T as std::ops::Mul>::Output;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T * T`
+   |
+help: consider restricting type parameter `T`
+   |
+LL | type Alias<T: std::ops::Mul> = <T as std::ops::Mul>::Output;
+   |             +++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.