Uplift and start using check_args_compatible more liberally
This commit is contained in:
parent
e3025d6a55
commit
c9f8529793
@ -1961,33 +1961,90 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
if pred.kind() != binder { self.mk_predicate(binder) } else { pred }
|
if pred.kind() != binder { self.mk_predicate(binder) } else { pred }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn check_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) -> bool {
|
||||||
|
self.check_args_compatible_inner(def_id, args, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_args_compatible_inner(
|
||||||
|
self,
|
||||||
|
def_id: DefId,
|
||||||
|
args: &'tcx [ty::GenericArg<'tcx>],
|
||||||
|
nested: bool,
|
||||||
|
) -> bool {
|
||||||
|
let generics = self.generics_of(def_id);
|
||||||
|
|
||||||
|
// IATs themselves have a weird arg setup (self + own args), but nested items *in* IATs
|
||||||
|
// (namely: opaques, i.e. ATPITs) do not.
|
||||||
|
let own_args = if !nested
|
||||||
|
&& let DefKind::AssocTy = self.def_kind(def_id)
|
||||||
|
&& let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id))
|
||||||
|
{
|
||||||
|
if generics.params.len() + 1 != args.len() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !matches!(args[0].unpack(), ty::GenericArgKind::Type(_)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
&args[1..]
|
||||||
|
} else {
|
||||||
|
if generics.count() != args.len() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (parent_args, own_args) = args.split_at(generics.parent_count);
|
||||||
|
|
||||||
|
if let Some(parent) = generics.parent
|
||||||
|
&& !self.check_args_compatible_inner(parent, parent_args, true)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
own_args
|
||||||
|
};
|
||||||
|
|
||||||
|
for (param, arg) in std::iter::zip(&generics.params, own_args) {
|
||||||
|
match (¶m.kind, arg.unpack()) {
|
||||||
|
(ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_))
|
||||||
|
| (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_))
|
||||||
|
| (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {}
|
||||||
|
_ => return false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn assert_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) {
|
||||||
|
if !self.check_args_compatible(def_id, args) {
|
||||||
|
if let DefKind::AssocTy = self.def_kind(def_id)
|
||||||
|
&& let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id))
|
||||||
|
{
|
||||||
|
bug!()
|
||||||
|
} else {
|
||||||
|
bug!(
|
||||||
|
"args not compatible with generics for {}: args={:#?}, generics={:#?}",
|
||||||
|
self.def_path_str(def_id),
|
||||||
|
args,
|
||||||
|
ty::GenericArgs::identity_for_item(self, def_id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn check_and_mk_args(
|
pub(crate) fn check_and_mk_args(
|
||||||
self,
|
self,
|
||||||
_def_id: DefId,
|
_def_id: DefId,
|
||||||
args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
|
args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
|
||||||
) -> GenericArgsRef<'tcx> {
|
) -> GenericArgsRef<'tcx> {
|
||||||
let args = args.into_iter().map(Into::into);
|
let args = self.mk_args_from_iter(args.into_iter().map(Into::into));
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
{
|
{
|
||||||
let generics = self.generics_of(_def_id);
|
self.assert_args_compatible(_def_id, args);
|
||||||
|
|
||||||
let n = if let DefKind::AssocTy = self.def_kind(_def_id)
|
|
||||||
&& let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(_def_id))
|
|
||||||
{
|
|
||||||
// If this is an inherent projection.
|
|
||||||
generics.params.len() + 1
|
|
||||||
} else {
|
|
||||||
generics.count()
|
|
||||||
};
|
|
||||||
assert_eq!(
|
|
||||||
(n, Some(n)),
|
|
||||||
args.size_hint(),
|
|
||||||
"wrong number of generic parameters for {_def_id:?}: {:?}",
|
|
||||||
args.collect::<Vec<_>>(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
self.mk_args_from_iter(args)
|
args
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1624,13 +1624,9 @@ impl<'tcx> Ty<'tcx> {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_adt(tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
|
pub fn new_adt(tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
|
||||||
debug_assert_eq!(
|
if cfg!(debug_assertions) {
|
||||||
tcx.generics_of(def.did()).count(),
|
tcx.assert_args_compatible(def.did(), args);
|
||||||
args.len(),
|
}
|
||||||
"wrong number of args for ADT: {:#?} vs {:#?}",
|
|
||||||
tcx.generics_of(def.did()).params,
|
|
||||||
args
|
|
||||||
);
|
|
||||||
Ty::new(tcx, Adt(def, args))
|
Ty::new(tcx, Adt(def, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1711,11 +1707,9 @@ impl<'tcx> Ty<'tcx> {
|
|||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
closure_args: GenericArgsRef<'tcx>,
|
closure_args: GenericArgsRef<'tcx>,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
debug_assert_eq!(
|
if cfg!(debug_assertions) {
|
||||||
closure_args.len(),
|
tcx.assert_args_compatible(def_id, closure_args);
|
||||||
tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 3,
|
}
|
||||||
"closure constructed with incorrect generic parameters"
|
|
||||||
);
|
|
||||||
Ty::new(tcx, Closure(def_id, closure_args))
|
Ty::new(tcx, Closure(def_id, closure_args))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1725,11 +1719,9 @@ impl<'tcx> Ty<'tcx> {
|
|||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
closure_args: GenericArgsRef<'tcx>,
|
closure_args: GenericArgsRef<'tcx>,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
debug_assert_eq!(
|
if cfg!(debug_assertions) {
|
||||||
closure_args.len(),
|
tcx.assert_args_compatible(def_id, closure_args);
|
||||||
tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 5,
|
}
|
||||||
"closure constructed with incorrect generic parameters"
|
|
||||||
);
|
|
||||||
Ty::new(tcx, CoroutineClosure(def_id, closure_args))
|
Ty::new(tcx, CoroutineClosure(def_id, closure_args))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1739,11 +1731,9 @@ impl<'tcx> Ty<'tcx> {
|
|||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
coroutine_args: GenericArgsRef<'tcx>,
|
coroutine_args: GenericArgsRef<'tcx>,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
debug_assert_eq!(
|
if cfg!(debug_assertions) {
|
||||||
coroutine_args.len(),
|
tcx.assert_args_compatible(def_id, coroutine_args);
|
||||||
tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 6,
|
}
|
||||||
"coroutine constructed with incorrect number of generic parameters"
|
|
||||||
);
|
|
||||||
Ty::new(tcx, Coroutine(def_id, coroutine_args))
|
Ty::new(tcx, Coroutine(def_id, coroutine_args))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::traits::{check_args_compatible, specialization_graph};
|
use crate::traits::specialization_graph;
|
||||||
|
|
||||||
use super::assembly::structural_traits::AsyncCallableRelevantTypes;
|
use super::assembly::structural_traits::AsyncCallableRelevantTypes;
|
||||||
use super::assembly::{self, structural_traits, Candidate};
|
use super::assembly::{self, structural_traits, Candidate};
|
||||||
@ -247,7 +247,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
|||||||
assoc_def.defining_node,
|
assoc_def.defining_node,
|
||||||
);
|
);
|
||||||
|
|
||||||
if !check_args_compatible(tcx, assoc_def.item, args) {
|
if !tcx.check_args_compatible(assoc_def.item.def_id, args) {
|
||||||
return error_response(
|
return error_response(
|
||||||
ecx,
|
ecx,
|
||||||
"associated item has mismatched generic item arguments",
|
"associated item has mismatched generic item arguments",
|
||||||
|
@ -61,12 +61,12 @@ pub use self::specialize::{
|
|||||||
pub use self::structural_match::search_for_structural_match_violation;
|
pub use self::structural_match::search_for_structural_match_violation;
|
||||||
pub use self::structural_normalize::StructurallyNormalizeExt;
|
pub use self::structural_normalize::StructurallyNormalizeExt;
|
||||||
pub use self::util::elaborate;
|
pub use self::util::elaborate;
|
||||||
pub use self::util::{
|
|
||||||
check_args_compatible, supertrait_def_ids, supertraits, transitive_bounds,
|
|
||||||
transitive_bounds_that_define_assoc_item, SupertraitDefIds,
|
|
||||||
};
|
|
||||||
pub use self::util::{expand_trait_aliases, TraitAliasExpander, TraitAliasExpansionInfo};
|
pub use self::util::{expand_trait_aliases, TraitAliasExpander, TraitAliasExpansionInfo};
|
||||||
pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
|
pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
|
||||||
|
pub use self::util::{
|
||||||
|
supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_item,
|
||||||
|
SupertraitDefIds,
|
||||||
|
};
|
||||||
pub use self::util::{with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer};
|
pub use self::util::{with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer};
|
||||||
|
|
||||||
pub use rustc_infer::traits::*;
|
pub use rustc_infer::traits::*;
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use super::check_args_compatible;
|
|
||||||
use super::specialization_graph;
|
use super::specialization_graph;
|
||||||
use super::translate_args;
|
use super::translate_args;
|
||||||
use super::util;
|
use super::util;
|
||||||
@ -2030,7 +2029,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
|
|||||||
} else {
|
} else {
|
||||||
ty.map_bound(|ty| ty.into())
|
ty.map_bound(|ty| ty.into())
|
||||||
};
|
};
|
||||||
if !check_args_compatible(tcx, assoc_ty.item, args) {
|
if !tcx.check_args_compatible(assoc_ty.item.def_id, args) {
|
||||||
let err = Ty::new_error_with_message(
|
let err = Ty::new_error_with_message(
|
||||||
tcx,
|
tcx,
|
||||||
obligation.cause.span,
|
obligation.cause.span,
|
||||||
|
@ -344,46 +344,6 @@ pub enum TupleArgumentsFlag {
|
|||||||
No,
|
No,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the trait item and its implementation have compatible args lists
|
|
||||||
pub fn check_args_compatible<'tcx>(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
assoc_item: ty::AssocItem,
|
|
||||||
args: ty::GenericArgsRef<'tcx>,
|
|
||||||
) -> bool {
|
|
||||||
fn check_args_compatible_inner<'tcx>(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
generics: &'tcx ty::Generics,
|
|
||||||
args: &'tcx [ty::GenericArg<'tcx>],
|
|
||||||
) -> bool {
|
|
||||||
if generics.count() != args.len() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let (parent_args, own_args) = args.split_at(generics.parent_count);
|
|
||||||
|
|
||||||
if let Some(parent) = generics.parent
|
|
||||||
&& let parent_generics = tcx.generics_of(parent)
|
|
||||||
&& !check_args_compatible_inner(tcx, parent_generics, parent_args)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (param, arg) in std::iter::zip(&generics.params, own_args) {
|
|
||||||
match (¶m.kind, arg.unpack()) {
|
|
||||||
(ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_))
|
|
||||||
| (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_))
|
|
||||||
| (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {}
|
|
||||||
_ => return false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
let generics = tcx.generics_of(assoc_item.def_id);
|
|
||||||
check_args_compatible_inner(tcx, generics, args)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Executes `f` on `value` after replacing all escaping bound variables with placeholders
|
/// Executes `f` on `value` after replacing all escaping bound variables with placeholders
|
||||||
/// and then replaces these placeholders with the original bound variables in the result.
|
/// and then replaces these placeholders with the original bound variables in the result.
|
||||||
///
|
///
|
||||||
|
@ -7,7 +7,6 @@ use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
|
|||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
|
use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_trait_selection::traits::check_args_compatible;
|
|
||||||
|
|
||||||
use crate::errors::{DuplicateArg, NotParam};
|
use crate::errors::{DuplicateArg, NotParam};
|
||||||
|
|
||||||
@ -250,7 +249,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
|
|||||||
ty::GenericArgs::identity_for_item(self.tcx, parent),
|
ty::GenericArgs::identity_for_item(self.tcx, parent),
|
||||||
);
|
);
|
||||||
|
|
||||||
if check_args_compatible(self.tcx, assoc, impl_args) {
|
if self.tcx.check_args_compatible(assoc.def_id, impl_args) {
|
||||||
self.tcx
|
self.tcx
|
||||||
.type_of(assoc.def_id)
|
.type_of(assoc.def_id)
|
||||||
.instantiate(self.tcx, impl_args)
|
.instantiate(self.tcx, impl_args)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user