Skip to content

Commit 0ca4328

Browse files
committed
Check lazy type aliases for well-formedness
1 parent 2e0136a commit 0ca4328

File tree

8 files changed

+55
-11
lines changed

8 files changed

+55
-11
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,11 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
246246
// `ForeignItem`s are handled separately.
247247
hir::ItemKind::ForeignMod { .. } => {}
248248
hir::ItemKind::TyAlias(hir_ty, ..) => {
249-
if tcx.type_of(item.owner_id.def_id).skip_binder().has_opaque_types() {
250-
// Bounds are respected for `type X = impl Trait` and `type X = (impl Trait, Y);`
249+
if tcx.features().lazy_type_alias
250+
|| tcx.type_of(item.owner_id).skip_binder().has_opaque_types()
251+
{
252+
// Bounds of lazy type aliases and of eager ones that contain opaque types are respected.
253+
// E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`.
251254
check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow);
252255
}
253256
}

compiler/rustc_lint/src/builtin.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -1458,15 +1458,20 @@ impl TypeAliasBounds {
14581458

14591459
impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
14601460
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
1461-
let hir::ItemKind::TyAlias(ty, type_alias_generics) = &item.kind else { return };
1462-
if cx.tcx.type_of(item.owner_id.def_id).skip_binder().has_opaque_types() {
1463-
// Bounds are respected for `type X = impl Trait` and `type X = (impl Trait, Y);`
1461+
let hir::ItemKind::TyAlias(hir_ty, type_alias_generics) = &item.kind else { return };
1462+
1463+
if cx.tcx.features().lazy_type_alias {
1464+
// Bounds of lazy type aliases are respected.
14641465
return;
14651466
}
1466-
if cx.tcx.type_of(item.owner_id).skip_binder().has_inherent_projections() {
1467-
// Bounds are respected for `type X = … Type::Inherent …`
1467+
1468+
let ty = cx.tcx.type_of(item.owner_id).skip_binder();
1469+
if ty.has_opaque_types() || ty.has_inherent_projections() {
1470+
// Bounds of type aliases that contain opaque types or inherent projections are respected.
1471+
// E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`, `type X = Type::Inherent;`.
14681472
return;
14691473
}
1474+
14701475
// There must not be a where clause
14711476
if type_alias_generics.predicates.is_empty() {
14721477
return;
@@ -1491,7 +1496,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
14911496
if !where_spans.is_empty() {
14921497
let sub = (!suggested_changing_assoc_types).then(|| {
14931498
suggested_changing_assoc_types = true;
1494-
SuggestChangingAssocTypes { ty }
1499+
SuggestChangingAssocTypes { ty: hir_ty }
14951500
});
14961501
cx.emit_spanned_lint(
14971502
TYPE_ALIAS_BOUNDS,
@@ -1507,7 +1512,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
15071512
let suggestion = BuiltinTypeAliasGenericBoundsSuggestion { suggestions: inline_sugg };
15081513
let sub = (!suggested_changing_assoc_types).then(|| {
15091514
suggested_changing_assoc_types = true;
1510-
SuggestChangingAssocTypes { ty }
1515+
SuggestChangingAssocTypes { ty: hir_ty }
15111516
});
15121517
cx.emit_spanned_lint(
15131518
TYPE_ALIAS_BOUNDS,

src/tools/tidy/src/ui_tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::path::{Path, PathBuf};
1111
const ENTRY_LIMIT: usize = 900;
1212
// FIXME: The following limits should be reduced eventually.
1313
const ISSUES_ENTRY_LIMIT: usize = 1893;
14-
const ROOT_ENTRY_LIMIT: usize = 872;
14+
const ROOT_ENTRY_LIMIT: usize = 873;
1515

1616
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
1717
"rs", // test source files

tests/ui/type-alias/lazy-type-alias-enum-variant.stderr tests/ui/lazy-type-alias/enum-variant.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
2-
--> $DIR/lazy-type-alias-enum-variant.rs:4:12
2+
--> $DIR/enum-variant.rs:4:12
33
|
44
LL | #![feature(lazy_type_alias)]
55
| ^^^^^^^^^^^^^^^
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Check that we don't issue the lint `type_alias_bounds` for
2+
// lazy type aliases since the bounds are indeed enforced.
3+
4+
// check-pass
5+
6+
#![feature(lazy_type_alias)]
7+
#![allow(incomplete_features)]
8+
#![deny(type_alias_bounds)]
9+
10+
use std::ops::Mul;
11+
12+
type Alias<T: Mul> = <T as Mul>::Output;
13+
14+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Test that we check lazy type aliases for well-formedness.
2+
3+
#![feature(lazy_type_alias)]
4+
#![allow(incomplete_features)]
5+
6+
type Alias<T> = <T as std::ops::Mul>::Output; //~ ERROR cannot multiply `T` by `T`
7+
8+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0277]: cannot multiply `T` by `T`
2+
--> $DIR/unsatisfied-bounds-type-alias-body.rs:6:17
3+
|
4+
LL | type Alias<T> = <T as std::ops::Mul>::Output;
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T * T`
6+
|
7+
help: consider restricting type parameter `T`
8+
|
9+
LL | type Alias<T: std::ops::Mul> = <T as std::ops::Mul>::Output;
10+
| +++++++++++++++
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)