1+ use std:: assert_matches;
2+
13use hir:: HirId ;
24use hir:: def:: { DefKind , Res } ;
35use rustc_ast:: * ;
@@ -11,7 +13,10 @@ use rustc_span::{ErrorGuaranteed, Ident, Span, sym};
1113
1214use crate :: LoweringContext ;
1315use crate :: delegation:: resolution:: resolver:: DelegationResolver ;
14- use crate :: diagnostics:: DelegationInfersMismatch ;
16+ use crate :: diagnostics:: {
17+ DelegationInfersMismatch , DelegationToInherentImplMustContainParentGenerics ,
18+ DelegationToInherentImplParentContainsInfer ,
19+ } ;
1520
1621#[ derive( Debug , Clone , Copy , Eq , PartialEq ) ]
1722pub ( super ) enum GenericsPosition {
@@ -25,6 +30,7 @@ pub(super) enum GenericArgSlot<T> {
2530 Generate ( T , Option < usize > /* Infer arg index from AST */ ) ,
2631}
2732
33+ #[ derive( Debug ) ]
2834pub ( super ) struct DelegationGenerics < T > {
2935 data : T ,
3036 pos : GenericsPosition ,
@@ -57,11 +63,13 @@ impl<'hir> DelegationGenerics<TyGenerics<'hir>> {
5763/// meaning we did not propagate them and thus we do not need to generate generic params
5864/// (i.e., method call scenarios), in such a case this approach helps
5965/// a lot as if `into_hir_generics` will not be called then uplifting will not happen.
66+ #[ derive( Debug ) ]
6067pub ( super ) enum HirOrTyGenerics < ' hir > {
6168 Ty ( DelegationGenerics < TyGenerics < ' hir > > ) ,
6269 Hir ( DelegationGenerics < & ' hir hir:: Generics < ' hir > > ) ,
6370}
6471
72+ #[ derive( Debug ) ]
6573pub ( super ) struct GenericsGenerationResult < ' hir > {
6674 pub ( super ) generics : HirOrTyGenerics < ' hir > ,
6775 pub ( super ) args_segment_id : HirId ,
@@ -80,6 +88,7 @@ pub(super) struct GenericsGenerationResults<'hir> {
8088 pub ( super ) self_ty_propagation_kind : Option < hir:: DelegationSelfTyPropagationKind > ,
8189}
8290
91+ #[ derive( Debug ) ]
8392pub ( super ) struct DelegationGenericArgsIterator < ' hir > {
8493 index : usize = Default :: default ( ) ,
8594 params : & ' hir [ hir:: GenericParam < ' hir > ] ,
@@ -145,6 +154,7 @@ impl<'hir> DelegationGenericArgsIterator<'hir> {
145154 ctx : & mut LoweringContext < ' _ , ' hir > ,
146155 ) -> Vec < hir:: GenericArg < ' hir > > {
147156 let mut args = vec ! [ ] ;
157+
148158 while let Some ( arg) = self . next ( ctx, |ctx| ctx. next_id ( ) ) {
149159 args. push ( arg) ;
150160 }
@@ -238,6 +248,7 @@ impl<'hir> GenericsGenerationResult<'hir> {
238248 }
239249}
240250
251+ #[ derive( Debug ) ]
241252enum ParentSegmentArgs < ' a > {
242253 /// Parent segment is valid and generic args are specified:
243254 /// `reuse Trait::<'static, ()>::foo;`.
@@ -273,7 +284,7 @@ struct GenericsResolution<'a, 'tcx> {
273284 /// `reuse <_ as Trait>::foo;`.
274285 qself_is_infer : bool ,
275286 /// Whether we should generate `Self` generic param.
276- generate_self : bool ,
287+ generate_free_to_trait_self : bool ,
277288}
278289
279290impl < ' hir > DelegationResolver < ' _ , ' hir > {
@@ -288,8 +299,7 @@ impl<'hir> DelegationResolver<'_, 'hir> {
288299 let delegation_in_free_ctx =
289300 !matches ! ( delegation_parent_kind, DefKind :: Trait | DefKind :: Impl { .. } ) ;
290301
291- let sig_parent = tcx. parent ( sig_id) ;
292- let sig_in_trait = matches ! ( tcx. def_kind( sig_parent) , DefKind :: Trait ) ;
302+ let sig_in_trait = matches ! ( tcx. def_kind( tcx. parent( sig_id) ) , DefKind :: Trait ) ;
293303 let free_to_trait_delegation = delegation_in_free_ctx && sig_in_trait;
294304
295305 let mut sig_parent_params: & [ ty:: GenericParamDef ] = & [ ] ;
@@ -301,8 +311,13 @@ impl<'hir> DelegationResolver<'_, 'hir> {
301311
302312 let parent_args = if let [ .., parent_segment, _] = & delegation. path . segments [ ..] {
303313 let res = self . get_resolution_id ( parent_segment. id ) ?;
304- if matches ! ( tcx. def_kind( res) , DefKind :: Trait | DefKind :: TraitAlias ) {
305- sig_parent_params = & tcx. generics_of ( sig_parent) . own_params ;
314+ if !matches ! ( tcx. def_kind( res) , DefKind :: Mod ) {
315+ assert_matches ! (
316+ tcx. def_kind( res) ,
317+ DefKind :: Trait | DefKind :: Struct | DefKind :: Enum
318+ ) ;
319+
320+ sig_parent_params = & tcx. generics_of ( res) . own_params ;
306321 self . get_user_args ( parent_segment)
307322 . map ( |args| ParentSegmentArgs :: Specified ( args) )
308323 . unwrap_or ( ParentSegmentArgs :: NotSpecified )
@@ -319,7 +334,8 @@ impl<'hir> DelegationResolver<'_, 'hir> {
319334 qself_is_none,
320335 qself_is_infer,
321336 free_to_trait_delegation,
322- generate_self : free_to_trait_delegation && ( qself_is_none || qself_is_infer) ,
337+ generate_free_to_trait_self : free_to_trait_delegation
338+ && ( qself_is_none || qself_is_infer) ,
323339 trait_impl : matches ! ( delegation_parent_kind, DefKind :: Impl { of_trait: true } ) ,
324340 sig_child_params : & tcx. generics_of ( sig_id) . own_params ,
325341 child_args : self . get_user_args (
@@ -349,10 +365,11 @@ impl<'hir> DelegationResolver<'_, 'hir> {
349365 & self ,
350366 delegation : & Delegation ,
351367 sig_id : DefId ,
368+ span : Span ,
352369 ) -> Result < GenericsGenerationResults < ' hir > , ErrorGuaranteed > {
353370 let res @ GenericsResolution {
354371 trait_impl,
355- generate_self ,
372+ generate_free_to_trait_self ,
356373 sig_child_params,
357374 sig_parent_params,
358375 ..
@@ -376,20 +393,27 @@ impl<'hir> DelegationResolver<'_, 'hir> {
376393 return Ok ( GenericsGenerationResults { parent, child, self_ty_propagation_kind : None } ) ;
377394 }
378395
396+ self . check_delegation_to_inherent_impl ( & res. parent_args , sig_id, span) ?;
397+
379398 let tcx = self . tcx ( ) ;
399+
400+ // If parent is inherent impl then there is no `Self` param to skip, so add additional check.
401+ let skip_self =
402+ !generate_free_to_trait_self && tcx. def_kind ( tcx. parent ( sig_id) ) == DefKind :: Trait ;
403+
380404 let parent_generics = match res. parent_args {
381405 ParentSegmentArgs :: Specified ( args) => DelegationGenerics {
382406 data : Self :: create_slots_from_args (
383407 tcx,
384408 args,
385- & sig_parent_params[ usize:: from ( !generate_self ) ..] ,
386- generate_self ,
409+ & sig_parent_params[ usize:: from ( skip_self ) ..] ,
410+ generate_free_to_trait_self ,
387411 ) ,
388412 pos : GenericsPosition :: Parent ,
389413 trait_impl,
390414 } ,
391415 ParentSegmentArgs :: NotSpecified => DelegationGenerics :: generate_all (
392- & sig_parent_params[ usize:: from ( !generate_self ) ..] ,
416+ & sig_parent_params[ usize:: from ( skip_self ) ..] ,
393417 GenericsPosition :: Parent ,
394418 trait_impl,
395419 ) ,
@@ -437,6 +461,46 @@ impl<'hir> DelegationResolver<'_, 'hir> {
437461 } )
438462 }
439463
464+ fn check_delegation_to_inherent_impl (
465+ & self ,
466+ parent_args : & ParentSegmentArgs < ' _ > ,
467+ sig_id : DefId ,
468+ span : Span ,
469+ ) -> Result < ( ) , ErrorGuaranteed > {
470+ let tcx = self . tcx ( ) ;
471+
472+ if !( tcx. def_kind ( sig_id) == DefKind :: AssocFn
473+ && matches ! ( tcx. def_kind( tcx. parent( sig_id) ) , DefKind :: Impl { of_trait: false } ) )
474+ {
475+ return Ok ( ( ) ) ;
476+ }
477+
478+ let ty:: Adt ( def, _) = tcx. type_of ( tcx. parent ( sig_id) ) . skip_binder ( ) . kind ( ) else {
479+ unreachable ! ( "parent of inherent function can be only struct or enum" )
480+ } ;
481+
482+ match parent_args {
483+ ParentSegmentArgs :: Invalid => unreachable ! ( ) ,
484+ ParentSegmentArgs :: Specified ( args) => args
485+ . args
486+ . iter ( )
487+ . all ( |arg| {
488+ let AngleBracketedArg :: Arg ( arg) = arg else { return false } ;
489+ !arg. is_maybe_parenthesised_infer ( )
490+ } )
491+ . ok_or_else ( || {
492+ self . tcx ( ) . dcx ( ) . emit_err ( DelegationToInherentImplParentContainsInfer { span } )
493+ } ) ,
494+ ParentSegmentArgs :: NotSpecified => match tcx. generics_of ( def. did ( ) ) . own_params . len ( ) {
495+ 0 => Ok ( ( ) ) ,
496+ _ => Err ( self
497+ . tcx ( )
498+ . dcx ( )
499+ . emit_err ( DelegationToInherentImplMustContainParentGenerics { span } ) ) ,
500+ } ,
501+ }
502+ }
503+
440504 /// Generates generic argument slots for user-specified `args` and
441505 /// generic `params` of the signature function. This function checks whether
442506 /// there are infers (`kw::UnderscoreLifetime` or `kw::Underscore`) in
@@ -459,12 +523,7 @@ impl<'hir> DelegationResolver<'_, 'hir> {
459523 let params = & params[ usize:: from ( add_first_self) ..] ;
460524 for ( idx, ( arg, param) ) in args. args . iter ( ) . zip ( params) . enumerate ( ) {
461525 let AngleBracketedArg :: Arg ( arg) = arg else { continue } ;
462-
463- let is_infer = match arg {
464- GenericArg :: Lifetime ( lt) => lt. ident . name == kw:: UnderscoreLifetime ,
465- GenericArg :: Type ( ty) => ty. is_maybe_parenthesised_infer ( ) ,
466- GenericArg :: Const ( _) => false ,
467- } ;
526+ let is_infer = arg. is_maybe_parenthesised_infer ( ) ;
468527
469528 // If `'_` is used instead of `_` (or vice versa) we emit a meaningful
470529 // error instead of processing this infer or leaving it as is for signature
0 commit comments