mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-25 05:14:27 +00:00
Auto merge of #87648 - JulianKnodt:const_eq_constrain, r=oli-obk
allow eq constraints on associated constants Updates #70256 (cc `@varkor,` `@Centril)`
This commit is contained in:
commit
5a25c0e6e9
@ -6,7 +6,7 @@ use if_chain::if_chain;
|
|||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::intravisit::FnKind;
|
use rustc_hir::intravisit::FnKind;
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
AsyncGeneratorKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound, HirId,
|
Term, AsyncGeneratorKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound, HirId,
|
||||||
IsAsync, ItemKind, LifetimeName, TraitRef, Ty, TyKind, TypeBindingKind,
|
IsAsync, ItemKind, LifetimeName, TraitRef, Ty, TyKind, TypeBindingKind,
|
||||||
};
|
};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
@ -140,7 +140,7 @@ fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'t
|
|||||||
if args.bindings.len() == 1;
|
if args.bindings.len() == 1;
|
||||||
let binding = &args.bindings[0];
|
let binding = &args.bindings[0];
|
||||||
if binding.ident.name == sym::Output;
|
if binding.ident.name == sym::Output;
|
||||||
if let TypeBindingKind::Equality{ty: output} = binding.kind;
|
if let TypeBindingKind::Equality{term: Term::Ty(output)} = binding.kind;
|
||||||
then {
|
then {
|
||||||
return Some(output)
|
return Some(output)
|
||||||
}
|
}
|
||||||
|
@ -2178,12 +2178,16 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
|
|||||||
// one of the associated types must be Self
|
// one of the associated types must be Self
|
||||||
for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
|
for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
|
||||||
if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() {
|
if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() {
|
||||||
|
let assoc_ty = match projection_predicate.term {
|
||||||
|
ty::Term::Ty(ty) => ty,
|
||||||
|
ty::Term::Const(_c) => continue,
|
||||||
|
};
|
||||||
// walk the associated type and check for Self
|
// walk the associated type and check for Self
|
||||||
if let Some(self_adt) = self_ty.ty_adt_def() {
|
if let Some(self_adt) = self_ty.ty_adt_def() {
|
||||||
if contains_adt_constructor(projection_predicate.ty, self_adt) {
|
if contains_adt_constructor(assoc_ty, self_adt) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if contains_ty(projection_predicate.ty, self_ty) {
|
} else if contains_ty(assoc_ty, self_ty) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -243,9 +243,10 @@ fn check_other_call_arg<'tcx>(
|
|||||||
if if trait_predicate.def_id() == deref_trait_id {
|
if if trait_predicate.def_id() == deref_trait_id {
|
||||||
if let [projection_predicate] = projection_predicates[..] {
|
if let [projection_predicate] = projection_predicates[..] {
|
||||||
let normalized_ty =
|
let normalized_ty =
|
||||||
cx.tcx.subst_and_normalize_erasing_regions(call_substs, cx.param_env, projection_predicate.ty);
|
cx.tcx.subst_and_normalize_erasing_regions(call_substs, cx.param_env, projection_predicate.term);
|
||||||
implements_trait(cx, receiver_ty, deref_trait_id, &[])
|
implements_trait(cx, receiver_ty, deref_trait_id, &[])
|
||||||
&& get_associated_type(cx, receiver_ty, deref_trait_id, "Target") == Some(normalized_ty)
|
&& get_associated_type(cx, receiver_ty, deref_trait_id,
|
||||||
|
"Target").map_or(false, |ty| ty::Term::Ty(ty) == normalized_ty)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -98,9 +98,10 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve
|
|||||||
if trait_pred.self_ty() == inp;
|
if trait_pred.self_ty() == inp;
|
||||||
if let Some(return_ty_pred) = get_projection_pred(cx, generics, *trait_pred);
|
if let Some(return_ty_pred) = get_projection_pred(cx, generics, *trait_pred);
|
||||||
then {
|
then {
|
||||||
if ord_preds.iter().any(|ord| ord.self_ty() == return_ty_pred.ty) {
|
if ord_preds.iter().any(|ord| Some(ord.self_ty()) ==
|
||||||
|
return_ty_pred.term.ty()) {
|
||||||
args_to_check.push((i, "Ord".to_string()));
|
args_to_check.push((i, "Ord".to_string()));
|
||||||
} else if partial_ord_preds.iter().any(|pord| pord.self_ty() == return_ty_pred.ty) {
|
} else if partial_ord_preds.iter().any(|pord| pord.self_ty() == return_ty_pred.term.ty().unwrap()) {
|
||||||
args_to_check.push((i, "PartialOrd".to_string()));
|
args_to_check.push((i, "PartialOrd".to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -645,11 +645,19 @@ pub fn eq_generic_bound(l: &GenericBound, r: &GenericBound) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eq_assoc_constraint(l: &AssocTyConstraint, r: &AssocTyConstraint) -> bool {
|
fn eq_term(l: &Term, r: &Term) -> bool {
|
||||||
use AssocTyConstraintKind::*;
|
match (l, r) {
|
||||||
|
(Term::Ty(l), Term::Ty(r)) => eq_ty(l,r),
|
||||||
|
(Term::Const(l), Term::Const(r)) => eq_anon_const(l,r),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn eq_assoc_constraint(l: &AssocConstraint, r: &AssocConstraint) -> bool {
|
||||||
|
use AssocConstraintKind::*;
|
||||||
eq_id(l.ident, r.ident)
|
eq_id(l.ident, r.ident)
|
||||||
&& match (&l.kind, &r.kind) {
|
&& match (&l.kind, &r.kind) {
|
||||||
(Equality { ty: l }, Equality { ty: r }) => eq_ty(l, r),
|
(Equality { term: l }, Equality { term: r }) => eq_term(l, r),
|
||||||
(Bound { bounds: l }, Bound { bounds: r }) => over(l, r, eq_generic_bound),
|
(Bound { bounds: l }, Bound { bounds: r }) => over(l, r, eq_generic_bound),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user