Skip to content

Commit c9f8529

Browse files
Uplift and start using check_args_compatible more liberally
1 parent e3025d6 commit c9f8529

File tree

7 files changed

+95
-90
lines changed

7 files changed

+95
-90
lines changed

compiler/rustc_middle/src/ty/context.rs

+75-18
Original file line numberDiff line numberDiff line change
@@ -1961,33 +1961,90 @@ impl<'tcx> TyCtxt<'tcx> {
19611961
if pred.kind() != binder { self.mk_predicate(binder) } else { pred }
19621962
}
19631963

1964+
pub fn check_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) -> bool {
1965+
self.check_args_compatible_inner(def_id, args, false)
1966+
}
1967+
1968+
fn check_args_compatible_inner(
1969+
self,
1970+
def_id: DefId,
1971+
args: &'tcx [ty::GenericArg<'tcx>],
1972+
nested: bool,
1973+
) -> bool {
1974+
let generics = self.generics_of(def_id);
1975+
1976+
// IATs themselves have a weird arg setup (self + own args), but nested items *in* IATs
1977+
// (namely: opaques, i.e. ATPITs) do not.
1978+
let own_args = if !nested
1979+
&& let DefKind::AssocTy = self.def_kind(def_id)
1980+
&& let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id))
1981+
{
1982+
if generics.params.len() + 1 != args.len() {
1983+
return false;
1984+
}
1985+
1986+
if !matches!(args[0].unpack(), ty::GenericArgKind::Type(_)) {
1987+
return false;
1988+
}
1989+
1990+
&args[1..]
1991+
} else {
1992+
if generics.count() != args.len() {
1993+
return false;
1994+
}
1995+
1996+
let (parent_args, own_args) = args.split_at(generics.parent_count);
1997+
1998+
if let Some(parent) = generics.parent
1999+
&& !self.check_args_compatible_inner(parent, parent_args, true)
2000+
{
2001+
return false;
2002+
}
2003+
2004+
own_args
2005+
};
2006+
2007+
for (param, arg) in std::iter::zip(&generics.params, own_args) {
2008+
match (&param.kind, arg.unpack()) {
2009+
(ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_))
2010+
| (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_))
2011+
| (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {}
2012+
_ => return false,
2013+
}
2014+
}
2015+
2016+
true
2017+
}
2018+
2019+
pub fn assert_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) {
2020+
if !self.check_args_compatible(def_id, args) {
2021+
if let DefKind::AssocTy = self.def_kind(def_id)
2022+
&& let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id))
2023+
{
2024+
bug!()
2025+
} else {
2026+
bug!(
2027+
"args not compatible with generics for {}: args={:#?}, generics={:#?}",
2028+
self.def_path_str(def_id),
2029+
args,
2030+
ty::GenericArgs::identity_for_item(self, def_id)
2031+
);
2032+
}
2033+
}
2034+
}
2035+
19642036
#[inline(always)]
19652037
pub(crate) fn check_and_mk_args(
19662038
self,
19672039
_def_id: DefId,
19682040
args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
19692041
) -> GenericArgsRef<'tcx> {
1970-
let args = args.into_iter().map(Into::into);
2042+
let args = self.mk_args_from_iter(args.into_iter().map(Into::into));
19712043
#[cfg(debug_assertions)]
19722044
{
1973-
let generics = self.generics_of(_def_id);
1974-
1975-
let n = if let DefKind::AssocTy = self.def_kind(_def_id)
1976-
&& let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(_def_id))
1977-
{
1978-
// If this is an inherent projection.
1979-
generics.params.len() + 1
1980-
} else {
1981-
generics.count()
1982-
};
1983-
assert_eq!(
1984-
(n, Some(n)),
1985-
args.size_hint(),
1986-
"wrong number of generic parameters for {_def_id:?}: {:?}",
1987-
args.collect::<Vec<_>>(),
1988-
);
2045+
self.assert_args_compatible(_def_id, args);
19892046
}
1990-
self.mk_args_from_iter(args)
2047+
args
19912048
}
19922049

19932050
#[inline]

compiler/rustc_middle/src/ty/sty.rs

+12-22
Original file line numberDiff line numberDiff line change
@@ -1624,13 +1624,9 @@ impl<'tcx> Ty<'tcx> {
16241624

16251625
#[inline]
16261626
pub fn new_adt(tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
1627-
debug_assert_eq!(
1628-
tcx.generics_of(def.did()).count(),
1629-
args.len(),
1630-
"wrong number of args for ADT: {:#?} vs {:#?}",
1631-
tcx.generics_of(def.did()).params,
1632-
args
1633-
);
1627+
if cfg!(debug_assertions) {
1628+
tcx.assert_args_compatible(def.did(), args);
1629+
}
16341630
Ty::new(tcx, Adt(def, args))
16351631
}
16361632

@@ -1711,11 +1707,9 @@ impl<'tcx> Ty<'tcx> {
17111707
def_id: DefId,
17121708
closure_args: GenericArgsRef<'tcx>,
17131709
) -> Ty<'tcx> {
1714-
debug_assert_eq!(
1715-
closure_args.len(),
1716-
tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 3,
1717-
"closure constructed with incorrect generic parameters"
1718-
);
1710+
if cfg!(debug_assertions) {
1711+
tcx.assert_args_compatible(def_id, closure_args);
1712+
}
17191713
Ty::new(tcx, Closure(def_id, closure_args))
17201714
}
17211715

@@ -1725,11 +1719,9 @@ impl<'tcx> Ty<'tcx> {
17251719
def_id: DefId,
17261720
closure_args: GenericArgsRef<'tcx>,
17271721
) -> Ty<'tcx> {
1728-
debug_assert_eq!(
1729-
closure_args.len(),
1730-
tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 5,
1731-
"closure constructed with incorrect generic parameters"
1732-
);
1722+
if cfg!(debug_assertions) {
1723+
tcx.assert_args_compatible(def_id, closure_args);
1724+
}
17331725
Ty::new(tcx, CoroutineClosure(def_id, closure_args))
17341726
}
17351727

@@ -1739,11 +1731,9 @@ impl<'tcx> Ty<'tcx> {
17391731
def_id: DefId,
17401732
coroutine_args: GenericArgsRef<'tcx>,
17411733
) -> Ty<'tcx> {
1742-
debug_assert_eq!(
1743-
coroutine_args.len(),
1744-
tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 6,
1745-
"coroutine constructed with incorrect number of generic parameters"
1746-
);
1734+
if cfg!(debug_assertions) {
1735+
tcx.assert_args_compatible(def_id, coroutine_args);
1736+
}
17471737
Ty::new(tcx, Coroutine(def_id, coroutine_args))
17481738
}
17491739

compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::traits::{check_args_compatible, specialization_graph};
1+
use crate::traits::specialization_graph;
22

33
use super::assembly::structural_traits::AsyncCallableRelevantTypes;
44
use super::assembly::{self, structural_traits, Candidate};
@@ -247,7 +247,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
247247
assoc_def.defining_node,
248248
);
249249

250-
if !check_args_compatible(tcx, assoc_def.item, args) {
250+
if !tcx.check_args_compatible(assoc_def.item.def_id, args) {
251251
return error_response(
252252
ecx,
253253
"associated item has mismatched generic item arguments",

compiler/rustc_trait_selection/src/traits/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,12 @@ pub use self::specialize::{
6161
pub use self::structural_match::search_for_structural_match_violation;
6262
pub use self::structural_normalize::StructurallyNormalizeExt;
6363
pub use self::util::elaborate;
64-
pub use self::util::{
65-
check_args_compatible, supertrait_def_ids, supertraits, transitive_bounds,
66-
transitive_bounds_that_define_assoc_item, SupertraitDefIds,
67-
};
6864
pub use self::util::{expand_trait_aliases, TraitAliasExpander, TraitAliasExpansionInfo};
6965
pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
66+
pub use self::util::{
67+
supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_item,
68+
SupertraitDefIds,
69+
};
7070
pub use self::util::{with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer};
7171

7272
pub use rustc_infer::traits::*;

compiler/rustc_trait_selection/src/traits/project.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
use std::ops::ControlFlow;
44

5-
use super::check_args_compatible;
65
use super::specialization_graph;
76
use super::translate_args;
87
use super::util;
@@ -2030,7 +2029,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
20302029
} else {
20312030
ty.map_bound(|ty| ty.into())
20322031
};
2033-
if !check_args_compatible(tcx, assoc_ty.item, args) {
2032+
if !tcx.check_args_compatible(assoc_ty.item.def_id, args) {
20342033
let err = Ty::new_error_with_message(
20352034
tcx,
20362035
obligation.cause.span,

compiler/rustc_trait_selection/src/traits/util.rs

-40
Original file line numberDiff line numberDiff line change
@@ -344,46 +344,6 @@ pub enum TupleArgumentsFlag {
344344
No,
345345
}
346346

347-
// Verify that the trait item and its implementation have compatible args lists
348-
pub fn check_args_compatible<'tcx>(
349-
tcx: TyCtxt<'tcx>,
350-
assoc_item: ty::AssocItem,
351-
args: ty::GenericArgsRef<'tcx>,
352-
) -> bool {
353-
fn check_args_compatible_inner<'tcx>(
354-
tcx: TyCtxt<'tcx>,
355-
generics: &'tcx ty::Generics,
356-
args: &'tcx [ty::GenericArg<'tcx>],
357-
) -> bool {
358-
if generics.count() != args.len() {
359-
return false;
360-
}
361-
362-
let (parent_args, own_args) = args.split_at(generics.parent_count);
363-
364-
if let Some(parent) = generics.parent
365-
&& let parent_generics = tcx.generics_of(parent)
366-
&& !check_args_compatible_inner(tcx, parent_generics, parent_args)
367-
{
368-
return false;
369-
}
370-
371-
for (param, arg) in std::iter::zip(&generics.params, own_args) {
372-
match (&param.kind, arg.unpack()) {
373-
(ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_))
374-
| (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_))
375-
| (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {}
376-
_ => return false,
377-
}
378-
}
379-
380-
true
381-
}
382-
383-
let generics = tcx.generics_of(assoc_item.def_id);
384-
check_args_compatible_inner(tcx, generics, args)
385-
}
386-
387347
/// Executes `f` on `value` after replacing all escaping bound variables with placeholders
388348
/// and then replaces these placeholders with the original bound variables in the result.
389349
///

compiler/rustc_ty_utils/src/opaque_types.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
77
use rustc_middle::ty::{self, Ty, TyCtxt};
88
use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
99
use rustc_span::Span;
10-
use rustc_trait_selection::traits::check_args_compatible;
1110

1211
use crate::errors::{DuplicateArg, NotParam};
1312

@@ -250,7 +249,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
250249
ty::GenericArgs::identity_for_item(self.tcx, parent),
251250
);
252251

253-
if check_args_compatible(self.tcx, assoc, impl_args) {
252+
if self.tcx.check_args_compatible(assoc.def_id, impl_args) {
254253
self.tcx
255254
.type_of(assoc.def_id)
256255
.instantiate(self.tcx, impl_args)

0 commit comments

Comments
 (0)