Skip to content

Commit

Permalink
Rollup merge of #114228 - fmease:wf-lazy-ty-aliases, r=oli-obk
Browse files Browse the repository at this point in the history
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`
  • Loading branch information
matthiaskrgr committed Jul 31, 2023
2 parents b8f78fb + 0ca4328 commit 95b7116
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 11 deletions.
7 changes: 5 additions & 2 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
19 changes: 12 additions & 7 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/tools/tidy/src/ui_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -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)]
| ^^^^^^^^^^^^^^^
Expand Down
14 changes: 14 additions & 0 deletions tests/ui/lazy-type-alias/type-alias-bounds-are-enforced.rs
Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -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() {}
14 changes: 14 additions & 0 deletions tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 95b7116

Please sign in to comment.