@@ -1954,33 +1954,108 @@ impl<'tcx> TyCtxt<'tcx> {
19541954 if pred. kind ( ) != binder { self . mk_predicate ( binder) } else { pred }
19551955 }
19561956
1957- #[ inline( always) ]
1958- pub ( crate ) fn check_and_mk_args (
1957+ pub fn check_args_compatible ( self , def_id : DefId , args : & ' tcx [ ty:: GenericArg < ' tcx > ] ) -> bool {
1958+ self . check_args_compatible_inner ( def_id, args, false )
1959+ }
1960+
1961+ fn check_args_compatible_inner (
19591962 self ,
1960- _def_id : DefId ,
1961- args : impl IntoIterator < Item : Into < GenericArg < ' tcx > > > ,
1962- ) -> GenericArgsRef < ' tcx > {
1963- let args = args. into_iter ( ) . map ( Into :: into) ;
1964- #[ cfg( debug_assertions) ]
1963+ def_id : DefId ,
1964+ args : & ' tcx [ ty:: GenericArg < ' tcx > ] ,
1965+ nested : bool ,
1966+ ) -> bool {
1967+ let generics = self . generics_of ( def_id) ;
1968+
1969+ // IATs themselves have a weird arg setup (self + own args), but nested items *in* IATs
1970+ // (namely: opaques, i.e. ATPITs) do not.
1971+ let own_args = if !nested
1972+ && let DefKind :: AssocTy = self . def_kind ( def_id)
1973+ && let DefKind :: Impl { of_trait : false } = self . def_kind ( self . parent ( def_id) )
1974+ {
1975+ if generics. params . len ( ) + 1 != args. len ( ) {
1976+ return false ;
1977+ }
1978+
1979+ if !matches ! ( args[ 0 ] . unpack( ) , ty:: GenericArgKind :: Type ( _) ) {
1980+ return false ;
1981+ }
1982+
1983+ & args[ 1 ..]
1984+ } else {
1985+ if generics. count ( ) != args. len ( ) {
1986+ return false ;
1987+ }
1988+
1989+ let ( parent_args, own_args) = args. split_at ( generics. parent_count ) ;
1990+
1991+ if let Some ( parent) = generics. parent
1992+ && !self . check_args_compatible_inner ( parent, parent_args, true )
1993+ {
1994+ return false ;
1995+ }
1996+
1997+ own_args
1998+ } ;
1999+
2000+ for ( param, arg) in std:: iter:: zip ( & generics. params , own_args) {
2001+ match ( & param. kind , arg. unpack ( ) ) {
2002+ ( ty:: GenericParamDefKind :: Type { .. } , ty:: GenericArgKind :: Type ( _) )
2003+ | ( ty:: GenericParamDefKind :: Lifetime , ty:: GenericArgKind :: Lifetime ( _) )
2004+ | ( ty:: GenericParamDefKind :: Const { .. } , ty:: GenericArgKind :: Const ( _) ) => { }
2005+ _ => return false ,
2006+ }
2007+ }
2008+
2009+ true
2010+ }
2011+
2012+ /// With `cfg(debug_assertions)`, assert that args are compatible with their generics,
2013+ /// and print out the args if not.
2014+ pub fn debug_assert_args_compatible ( self , def_id : DefId , args : & ' tcx [ ty:: GenericArg < ' tcx > ] ) {
2015+ // Fast-path for non-debug, bail out early.
2016+ #[ cfg( not( debug_assertions) ) ]
19652017 {
1966- let generics = self . generics_of ( _def_id) ;
2018+ return ;
2019+ }
19672020
1968- let n = if let DefKind :: AssocTy = self . def_kind ( _def_id)
1969- && let DefKind :: Impl { of_trait : false } = self . def_kind ( self . parent ( _def_id) )
2021+ if !self . check_args_compatible ( def_id, args) {
2022+ if let DefKind :: AssocTy = self . def_kind ( def_id)
2023+ && let DefKind :: Impl { of_trait : false } = self . def_kind ( self . parent ( def_id) )
19702024 {
1971- // If this is an inherent projection.
1972- generics. params . len ( ) + 1
2025+ bug ! (
2026+ "args not compatible with generics for {}: args={:#?}, generics={:#?}" ,
2027+ self . def_path_str( def_id) ,
2028+ args,
2029+ // Make `[Self, GAT_ARGS...]` (this could be simplified)
2030+ self . mk_args_from_iter(
2031+ [ self . types. self_param. into( ) ] . into_iter( ) . chain(
2032+ self . generics_of( def_id)
2033+ . own_args( ty:: GenericArgs :: identity_for_item( self , def_id) )
2034+ . iter( )
2035+ . copied( )
2036+ )
2037+ )
2038+ ) ;
19732039 } else {
1974- generics. count ( )
1975- } ;
1976- assert_eq ! (
1977- ( n, Some ( n) ) ,
1978- args. size_hint( ) ,
1979- "wrong number of generic parameters for {_def_id:?}: {:?}" ,
1980- args. collect:: <Vec <_>>( ) ,
1981- ) ;
2040+ bug ! (
2041+ "args not compatible with generics for {}: args={:#?}, generics={:#?}" ,
2042+ self . def_path_str( def_id) ,
2043+ args,
2044+ ty:: GenericArgs :: identity_for_item( self , def_id)
2045+ ) ;
2046+ }
19822047 }
1983- self . mk_args_from_iter ( args)
2048+ }
2049+
2050+ #[ inline( always) ]
2051+ pub ( crate ) fn check_and_mk_args (
2052+ self ,
2053+ def_id : DefId ,
2054+ args : impl IntoIterator < Item : Into < GenericArg < ' tcx > > > ,
2055+ ) -> GenericArgsRef < ' tcx > {
2056+ let args = self . mk_args_from_iter ( args. into_iter ( ) . map ( Into :: into) ) ;
2057+ self . debug_assert_args_compatible ( def_id, args) ;
2058+ args
19842059 }
19852060
19862061 #[ inline]
0 commit comments