未验证 提交 95b7116d 编写于 作者: M Matthias Krüger 提交者: GitHub

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`
......@@ -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);
}
}
......
......@@ -1458,15 +1458,20 @@ pub(crate) fn is_type_variable_assoc(qpath: &hir::QPath<'_>) -> bool {
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 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
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 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
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,
......
......@@ -11,7 +11,7 @@
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
......
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)]
| ^^^^^^^^^^^^^^^
......
// 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() {}
// 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() {}
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`.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册