Don't suppress lint type_alias_bounds for ty aliases containing inherent assoc tys
This commit is contained in:
parent
02a2f02727
commit
63a54d93be
5 changed files with 56 additions and 42 deletions
|
@ -1425,30 +1425,27 @@ impl TypeAliasBounds {
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
|
impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
|
||||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
|
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
|
||||||
let hir::ItemKind::TyAlias(hir_ty, type_alias_generics) = &item.kind else { return };
|
let hir::ItemKind::TyAlias(hir_ty, generics) = &item.kind else { return };
|
||||||
|
|
||||||
|
// There must not be a where clause.
|
||||||
|
if generics.predicates.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Bounds of lazy type aliases and TAITs are respected.
|
// Bounds of lazy type aliases and TAITs are respected.
|
||||||
if cx.tcx.type_alias_is_lazy(item.owner_id) {
|
if cx.tcx.type_alias_is_lazy(item.owner_id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ty = cx.tcx.type_of(item.owner_id).skip_binder();
|
// NOTE(inherent_associated_types): While we currently do take some bounds in type
|
||||||
if ty.has_inherent_projections() {
|
// aliases into consideration during IAT *selection*, we don't perform full use+def
|
||||||
// Bounds of type aliases that contain opaque types or inherent projections are
|
// site wfchecking for such type aliases. Therefore TAB should still trigger.
|
||||||
// respected. E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`, `type X =
|
// See also `tests/ui/associated-inherent-types/type-alias-bounds.rs`.
|
||||||
// Type::Inherent;`.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// There must not be a where clause
|
|
||||||
if type_alias_generics.predicates.is_empty() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut where_spans = Vec::new();
|
let mut where_spans = Vec::new();
|
||||||
let mut inline_spans = Vec::new();
|
let mut inline_spans = Vec::new();
|
||||||
let mut inline_sugg = Vec::new();
|
let mut inline_sugg = Vec::new();
|
||||||
for p in type_alias_generics.predicates {
|
for p in generics.predicates {
|
||||||
let span = p.span();
|
let span = p.span();
|
||||||
if p.in_where_clause() {
|
if p.in_where_clause() {
|
||||||
where_spans.push(span);
|
where_spans.push(span);
|
||||||
|
@ -1469,10 +1466,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
|
||||||
cx.emit_span_lint(
|
cx.emit_span_lint(
|
||||||
TYPE_ALIAS_BOUNDS,
|
TYPE_ALIAS_BOUNDS,
|
||||||
where_spans,
|
where_spans,
|
||||||
BuiltinTypeAliasWhereClause {
|
BuiltinTypeAliasWhereClause { suggestion: generics.where_clause_span, sub },
|
||||||
suggestion: type_alias_generics.where_clause_span,
|
|
||||||
sub,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -241,10 +241,6 @@ pub trait TypeVisitableExt<I: Interner>: TypeVisitable<I> {
|
||||||
self.has_type_flags(TypeFlags::HAS_ALIAS)
|
self.has_type_flags(TypeFlags::HAS_ALIAS)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_inherent_projections(&self) -> bool {
|
|
||||||
self.has_type_flags(TypeFlags::HAS_TY_INHERENT)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn has_opaque_types(&self) -> bool {
|
fn has_opaque_types(&self) -> bool {
|
||||||
self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
|
self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
//@ compile-flags: --crate-type=lib
|
|
||||||
//@ check-pass
|
|
||||||
|
|
||||||
#![feature(inherent_associated_types)]
|
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
// Bounds on the self type play a major role in the resolution of inherent associated types (*).
|
|
||||||
// As a result of that, if a type alias contains any then its bounds have to be respected and the
|
|
||||||
// lint `type_alias_bounds` should not fire.
|
|
||||||
|
|
||||||
#![deny(type_alias_bounds)]
|
|
||||||
|
|
||||||
pub type Alias<T: Bound> = (Source<T>::Assoc,);
|
|
||||||
|
|
||||||
pub struct Source<T>(T);
|
|
||||||
pub trait Bound {}
|
|
||||||
|
|
||||||
impl<T: Bound> Source<T> {
|
|
||||||
pub type Assoc = ();
|
|
||||||
}
|
|
29
tests/ui/associated-inherent-types/type-alias-bounds.rs
Normal file
29
tests/ui/associated-inherent-types/type-alias-bounds.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
//@ compile-flags: --crate-type=lib
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
#![feature(inherent_associated_types)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
// FIXME(inherent_associated_types):
|
||||||
|
// While we currently do take some clauses of the ParamEnv into consideration
|
||||||
|
// when performing IAT selection, we do not perform full well-formedness checking
|
||||||
|
// for (eager) type alias definition and usage sites.
|
||||||
|
//
|
||||||
|
// Therefore it's *correct* for lint `type_alias_bounds` to fire here despite the
|
||||||
|
// fact that removing `Bound` from `T` in `Alias` would lead to an error!
|
||||||
|
//
|
||||||
|
// Obviously, the present situation isn't ideal and we should fix it in one way
|
||||||
|
// or another. Either we somehow delay IAT selection until after HIR ty lowering
|
||||||
|
// to avoid the need to specify any bounds inside (eager) type aliases or we
|
||||||
|
// force the overarching type alias to be *lazy* (similar to TAITs) which would
|
||||||
|
// automatically lead to full wfchecking and lint TAB getting suppressed.
|
||||||
|
|
||||||
|
pub type Alias<T: Bound> = (Source<T>::Assoc,);
|
||||||
|
//~^ WARN bounds on generic parameters are not enforced in type aliases
|
||||||
|
|
||||||
|
pub struct Source<T>(T);
|
||||||
|
pub trait Bound {}
|
||||||
|
|
||||||
|
impl<T: Bound> Source<T> {
|
||||||
|
pub type Assoc = ();
|
||||||
|
}
|
15
tests/ui/associated-inherent-types/type-alias-bounds.stderr
Normal file
15
tests/ui/associated-inherent-types/type-alias-bounds.stderr
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
warning: bounds on generic parameters are not enforced in type aliases
|
||||||
|
--> $DIR/type-alias-bounds.rs:21:19
|
||||||
|
|
|
||||||
|
LL | pub type Alias<T: Bound> = (Source<T>::Assoc,);
|
||||||
|
| ^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(type_alias_bounds)]` on by default
|
||||||
|
help: the bound will not be checked when the type alias is used, and should be removed
|
||||||
|
|
|
||||||
|
LL - pub type Alias<T: Bound> = (Source<T>::Assoc,);
|
||||||
|
LL + pub type Alias<T> = (Source<T>::Assoc,);
|
||||||
|
|
|
||||||
|
|
||||||
|
warning: 1 warning emitted
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue