diff --git a/compiler/rustc_ast_lowering/src/delegation/generics.rs b/compiler/rustc_ast_lowering/src/delegation/generics.rs index 4e960e3b9290..fa51772b4002 100644 --- a/compiler/rustc_ast_lowering/src/delegation/generics.rs +++ b/compiler/rustc_ast_lowering/src/delegation/generics.rs @@ -10,18 +10,38 @@ use crate::{LoweringContext, ResolverAstLoweringExt}; -pub(super) enum DelegationGenerics { +#[derive(Clone, Copy)] +pub(super) enum DelegationGenericsKind { /// User-specified args are present: `reuse foo::;`. UserSpecified, /// The default case when no user-specified args are present: `reuse Trait::foo;`. - Default(T), + Default, /// In free-to-trait reuse, when user specified args for trait `reuse Trait::::foo;` /// in this case we need to both generate `Self` and process user args. - SelfAndUserSpecified(T), + SelfAndUserSpecified, /// In delegations from trait impl to other entities like free functions or trait functions, /// we want to generate a function whose generics matches generics of signature function /// in trait. - TraitImpl(T, bool /* Has user-specified args */), + TraitImpl(bool /* Has user-specified args */), +} + +pub(super) struct DelegationGenerics { + generics: T, + kind: DelegationGenericsKind, +} + +impl<'hir> DelegationGenerics<&'hir [ty::GenericParamDef]> { + fn default(generics: &'hir [ty::GenericParamDef]) -> Self { + DelegationGenerics { generics, kind: DelegationGenericsKind::Default } + } + + fn user_specified(generics: &'hir [ty::GenericParamDef]) -> Self { + DelegationGenerics { generics, kind: DelegationGenericsKind::UserSpecified } + } + + fn trait_impl(generics: &'hir [ty::GenericParamDef], user_specified: bool) -> Self { + DelegationGenerics { generics, kind: DelegationGenericsKind::TraitImpl(user_specified) } + } } /// Used for storing either ty generics or their uplifted HIR version. First we obtain @@ -54,20 +74,19 @@ pub(super) struct GenericArgsPropagationDetails { pub(super) use_args_in_sig_inheritance: bool, } -impl DelegationGenerics { - fn args_propagation_details(&self) -> GenericArgsPropagationDetails { +impl DelegationGenericsKind { + fn args_propagation_details(self) -> GenericArgsPropagationDetails { match self { - DelegationGenerics::UserSpecified | DelegationGenerics::SelfAndUserSpecified { .. } => { - GenericArgsPropagationDetails { - should_propagate: false, - use_args_in_sig_inheritance: true, - } - } - DelegationGenerics::TraitImpl(_, user_specified) => GenericArgsPropagationDetails { - should_propagate: !*user_specified, + DelegationGenericsKind::UserSpecified + | DelegationGenericsKind::SelfAndUserSpecified => GenericArgsPropagationDetails { + should_propagate: false, + use_args_in_sig_inheritance: true, + }, + DelegationGenericsKind::TraitImpl(user_specified) => GenericArgsPropagationDetails { + should_propagate: !user_specified, use_args_in_sig_inheritance: false, }, - DelegationGenerics::Default(_) => GenericArgsPropagationDetails { + DelegationGenericsKind::Default => GenericArgsPropagationDetails { should_propagate: true, use_args_in_sig_inheritance: false, }, @@ -81,25 +100,9 @@ pub(super) fn into_hir_generics( ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>, span: Span, ) -> &mut HirOrTyGenerics<'hir> { - if let HirOrTyGenerics::Ty(params) = self { - let mut uplift_params = |generics: &'hir [ty::GenericParamDef]| { - ctx.uplift_delegation_generic_params(span, generics) - }; - - let hir_generics = match params { - DelegationGenerics::UserSpecified => DelegationGenerics::UserSpecified, - DelegationGenerics::Default(params) => { - DelegationGenerics::Default(uplift_params(params)) - } - DelegationGenerics::SelfAndUserSpecified(params) => { - DelegationGenerics::SelfAndUserSpecified(uplift_params(params)) - } - DelegationGenerics::TraitImpl(params, user_specified) => { - DelegationGenerics::TraitImpl(uplift_params(params), *user_specified) - } - }; - - *self = HirOrTyGenerics::Hir(hir_generics); + if let HirOrTyGenerics::Ty(ty) = self { + let params = ctx.uplift_delegation_generic_params(span, ty.generics); + *self = HirOrTyGenerics::Hir(DelegationGenerics { generics: params, kind: ty.kind }); } self @@ -108,12 +111,7 @@ pub(super) fn into_hir_generics( fn hir_generics_or_empty(&self) -> &'hir hir::Generics<'hir> { match self { HirOrTyGenerics::Ty(_) => hir::Generics::empty(), - HirOrTyGenerics::Hir(hir_generics) => match hir_generics { - DelegationGenerics::UserSpecified => hir::Generics::empty(), - DelegationGenerics::Default(generics) - | DelegationGenerics::SelfAndUserSpecified(generics) - | DelegationGenerics::TraitImpl(generics, _) => generics, - }, + HirOrTyGenerics::Hir(hir) => hir.generics, } } @@ -127,21 +125,16 @@ pub(super) fn into_generic_args( HirOrTyGenerics::Ty(_) => { bug!("Attempting to get generic args before uplifting to HIR") } - HirOrTyGenerics::Hir(hir_generics) => match hir_generics { - DelegationGenerics::UserSpecified => hir::GenericArgs::NONE, - DelegationGenerics::Default(generics) - | DelegationGenerics::SelfAndUserSpecified(generics) - | DelegationGenerics::TraitImpl(generics, _) => { - ctx.create_generics_args_from_params(generics.params, add_lifetimes, span) - } - }, + HirOrTyGenerics::Hir(hir) => { + ctx.create_generics_args_from_params(hir.generics.params, add_lifetimes, span) + } } } pub(super) fn args_propagation_details(&self) -> GenericArgsPropagationDetails { match self { - HirOrTyGenerics::Ty(ty_generics) => ty_generics.args_propagation_details(), - HirOrTyGenerics::Hir(hir_generics) => hir_generics.args_propagation_details(), + HirOrTyGenerics::Ty(ty) => ty.kind.args_propagation_details(), + HirOrTyGenerics::Hir(hir) => hir.kind.args_propagation_details(), } } } @@ -231,9 +224,10 @@ pub(super) fn uplift_delegation_generics( if matches!(delegation_parent_kind, DefKind::Impl { of_trait: true }) { // Considering parent generics, during signature inheritance // we will take those args that are in trait impl header trait ref. - let parent = GenericsGenerationResult::new(DelegationGenerics::TraitImpl(&[], true)); + let parent = DelegationGenerics::trait_impl(&[], true); + let parent = GenericsGenerationResult::new(parent); - let child = DelegationGenerics::TraitImpl(sig_params, child_user_specified); + let child = DelegationGenerics::trait_impl(sig_params, child_user_specified); let child = GenericsGenerationResult::new(child); return GenericsGenerationResults { parent, child }; @@ -257,22 +251,28 @@ pub(super) fn uplift_delegation_generics( if segments[len - 2].args.is_some() { if generate_self { // Take only first Self parameter, it is trait so Self must be present. - DelegationGenerics::SelfAndUserSpecified(&sig_parent_params[..1]) + DelegationGenerics { + kind: DelegationGenericsKind::SelfAndUserSpecified, + generics: &sig_parent_params[..1], + } } else { - DelegationGenerics::UserSpecified + DelegationGenerics::user_specified(&[]) } } else { let skip_self = usize::from(!generate_self); - DelegationGenerics::Default(&sig_parent_params[skip_self..]) + DelegationGenerics::default(&sig_parent_params[skip_self..]) } } else { - DelegationGenerics::<&'hir [ty::GenericParamDef]>::Default(&[]) + DelegationGenerics::default(&[]) }; let child_generics = if child_user_specified { - DelegationGenerics::UserSpecified + let synth_params_index = + sig_params.iter().position(|p| p.kind.is_synthetic()).unwrap_or(sig_params.len()); + + DelegationGenerics::user_specified(&sig_params[synth_params_index..]) } else { - DelegationGenerics::Default(sig_params) + DelegationGenerics::default(sig_params) }; GenericsGenerationResults { diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index 593284df38a3..e97830ccd23f 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -318,11 +318,15 @@ fn create_generic_args<'tcx>( let (caller_kind, callee_kind) = (fn_kind(tcx, delegation_id), fn_kind(tcx, sig_id)); let delegation_args = ty::GenericArgs::identity_for_item(tcx, delegation_id); - let delegation_parent_args_count = tcx.generics_of(delegation_id).parent_count; let deleg_parent_args_without_self_count = get_delegation_parent_args_count_without_self(tcx, delegation_id, sig_id); + let delegation_generics = tcx.generics_of(delegation_id); + let real_args_count = delegation_args.len() - delegation_generics.own_synthetic_params_count(); + let synth_args = &delegation_args[real_args_count..]; + let delegation_args = &delegation_args[..real_args_count]; + let args = match (caller_kind, callee_kind) { (FnKind::Free, FnKind::Free) | (FnKind::Free, FnKind::AssocTrait) @@ -339,14 +343,15 @@ fn create_generic_args<'tcx>( assert!(child_args.is_empty(), "Child args can not be used in trait impl case"); - tcx.mk_args(&delegation_args[delegation_parent_args_count..]) + tcx.mk_args(&delegation_args[delegation_generics.parent_count..]) } (FnKind::AssocInherentImpl, FnKind::AssocTrait) => { let self_ty = tcx.type_of(tcx.local_parent(delegation_id)).instantiate_identity(); tcx.mk_args_from_iter( - std::iter::once(ty::GenericArg::from(self_ty)).chain(delegation_args.iter()), + std::iter::once(ty::GenericArg::from(self_ty)) + .chain(delegation_args.iter().copied()), ) } @@ -411,7 +416,7 @@ fn create_generic_args<'tcx>( new_args.extend_from_slice(&child_args[child_lifetimes_count..]); } else if !parent_args.is_empty() { - let child_args = &delegation_args[delegation_parent_args_count..]; + let child_args = &delegation_args[delegation_generics.parent_count..]; let child_lifetimes_count = child_args.iter().take_while(|a| a.as_region().is_some()).count(); @@ -424,6 +429,8 @@ fn create_generic_args<'tcx>( new_args.extend(&child_args[child_lifetimes_count + skip_self as usize..]); } + new_args.extend(synth_args); + new_args } @@ -606,7 +613,8 @@ fn get_delegation_user_specified_args<'tcx>( .lower_generic_args_of_path(segment.ident.span, def_id, parent_args, segment, None) .0; - &args[parent_args.len()..] + let synth_params_count = tcx.generics_of(def_id).own_synthetic_params_count(); + &args[parent_args.len()..args.len() - synth_params_count] }); (parent_args.unwrap_or_default(), child_args.unwrap_or_default()) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index ede9de6adc2d..c47bd227e3d9 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -747,7 +747,7 @@ fn inferred_kind( GenericParamDefKind::Lifetime => { self.lowerer.re_infer(self.span, RegionInferReason::Param(param)).into() } - GenericParamDefKind::Type { has_default, .. } => { + GenericParamDefKind::Type { has_default, synthetic } => { if !infer_args && has_default { // No type parameter provided, but a default exists. if let Some(prev) = @@ -763,6 +763,8 @@ fn inferred_kind( .type_of(param.def_id) .instantiate(tcx, preceding_args) .into() + } else if synthetic { + Ty::new_param(tcx, param.index, param.name).into() } else if infer_args { self.lowerer.ty_infer(Some(param), self.span).into() } else { diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index ed587cbc3c28..11a236f314c2 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -274,6 +274,10 @@ pub fn has_impl_trait(&'tcx self) -> bool { }) } + pub fn own_synthetic_params_count(&'tcx self) -> usize { + self.own_params.iter().filter(|p| p.kind.is_synthetic()).count() + } + /// Returns the args corresponding to the generic parameters /// of this item, excluding `Self`. /// diff --git a/tests/ui/delegation/generics/mapping/free-to-free-pass.rs b/tests/ui/delegation/generics/mapping/free-to-free-pass.rs index 2b877cc668ff..bfdcb416d644 100644 --- a/tests/ui/delegation/generics/mapping/free-to-free-pass.rs +++ b/tests/ui/delegation/generics/mapping/free-to-free-pass.rs @@ -9,14 +9,32 @@ //! delegation parent if applicable. At some tests predicates are //! added. At some tests user-specified args are specified in reuse statement. -// Testing lifetimes + types + consts, reusing without -// user args, checking predicates inheritance +// Testing lifetimes + types + consts, reusing with(out) +// user args, checking predicates inheritance, testing with impl Traits mod test_1 { - fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} + trait Bound1 {} + trait Bound2 {} + trait Bound3 {} + + struct X {} + + impl Bound1 for X {} + impl Bound2 for X {} + impl Bound3 for X {} + + fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>( + _x: impl Bound1 + Bound2 + Bound3, + _f: impl FnOnce(T) -> U, + ) { + } pub fn check() { reuse foo as bar; - bar::(); + bar::(X {}, |x| x); + + reuse foo::<'static, 'static, usize, String, 132> as bar1; + + bar1(X {}, |x| x.to_string()); } } diff --git a/tests/ui/delegation/generics/mapping/free-to-trait-pass.rs b/tests/ui/delegation/generics/mapping/free-to-trait-pass.rs index 0aa3798cdbef..cd779a9887a2 100644 --- a/tests/ui/delegation/generics/mapping/free-to-trait-pass.rs +++ b/tests/ui/delegation/generics/mapping/free-to-trait-pass.rs @@ -10,10 +10,10 @@ //! added. At some tests user-specified args are specified in reuse statement. // Testing lifetimes + types + consts in both parent and child, reusing in -// a function without generic params +// a function without generic params, with impl traits mod test_1 { trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { - fn foo<'d: 'd, U, const M: bool>(self) {} + fn foo<'d: 'd, U, const M: bool>(self, _f: impl FnOnce() -> ()) {} } impl Trait<'static, 'static, 'static, i32, 1> for u8 {} @@ -21,12 +21,12 @@ impl Trait<'static, 'static, 'static, i32, 1> for u8 {} pub fn check() { fn no_ctx() { reuse Trait::foo as bar; - bar::<'static, 'static, 'static, 'static, u8, i32, 1, String, true>(123); + bar::<'static, 'static, 'static, 'static, u8, i32, 1, String, true>(123, || ()); } fn with_ctx<'a, 'b, 'c, A, B, C, const N: usize, const M: bool>() { reuse Trait::foo as bar; - bar::<'static, 'static, 'static, 'a, u8, i32, 1, A, M>(123); + bar::<'static, 'static, 'static, 'a, u8, i32, 1, A, M>(123, || ()); } no_ctx(); diff --git a/tests/ui/delegation/generics/mapping/impl-trait-to-free-pass.rs b/tests/ui/delegation/generics/mapping/impl-trait-to-free-pass.rs index 53947c41cf57..7abd9e19dde6 100644 --- a/tests/ui/delegation/generics/mapping/impl-trait-to-free-pass.rs +++ b/tests/ui/delegation/generics/mapping/impl-trait-to-free-pass.rs @@ -10,19 +10,19 @@ //! delegation parent if applicable. At some tests predicates are //! added. At some tests user-specified args are specified in reuse statement. -// Testing lifetimes + types/consts in child reuses, +// Testing lifetimes + types/consts in child reuses, with impl traits, // with (un)specified user args with additional generic params in delegation parent mod test_1 { mod to_reuse { pub fn foo<'a: 'a, 'b: 'b, A, B, const N: usize>() {} - pub fn bar<'a: 'a, 'b: 'b, A, B, const N: usize>(_x: &super::XX) {} + pub fn bar<'a: 'a, 'b: 'b, A, B, const N: usize>(_x: &super::XX, _f: impl FnOnce(A) -> B) {} } trait Trait<'a, 'b, 'c, A, B, const N: usize>: Sized { fn foo<'x: 'x, 'y: 'y, AA, BB, const NN: usize>() {} - fn bar<'x: 'x, 'y: 'y, AA, BB, const NN: usize>(&self) {} + fn bar<'x: 'x, 'y: 'y, AA, BB, const NN: usize>(&self, _f: impl FnOnce(AA) -> BB) {} fn oof() {} - fn rab(&self) {} + fn rab(&self, _f: impl FnOnce(A) -> B) {} } #[allow(dead_code)] // Fields are used instead of phantom data for generics use @@ -44,9 +44,9 @@ pub fn check() { > ::foo::<'static, 'static, i8, i16, 123>(); > - ::bar::<'static, 'static, String, i16, 123>(&x); + ::bar::<'static, 'static, String, i16, 123>(&x, |_| 123); >::oof(); - >::rab(&x); + >::rab(&x, |_| 123.to_string()); } } diff --git a/tests/ui/delegation/generics/mapping/impl-trait-to-trait-pass.rs b/tests/ui/delegation/generics/mapping/impl-trait-to-trait-pass.rs index 2f556f81c1ef..3dcb359ab2e5 100644 --- a/tests/ui/delegation/generics/mapping/impl-trait-to-trait-pass.rs +++ b/tests/ui/delegation/generics/mapping/impl-trait-to-trait-pass.rs @@ -12,12 +12,12 @@ // Testing types in parent, types in child reuse, // testing predicates inheritance, -// with additional generic params in delegation parent +// with additional generic params in delegation parent, with impl traits mod test_1 { trait Trait0 {} trait Trait1 { - fn foo(&self) + fn foo(&self, _f: impl FnOnce(T, U) -> (U, T)) where T: Trait0, U: Trait0, @@ -39,7 +39,7 @@ impl Trait0 for u16 {} pub fn check() { let s = S(F, &123, &123, &123); - as Trait1>::foo::(&s); + as Trait1>::foo::(&s, |x, y| (y, x)); } } diff --git a/tests/ui/delegation/generics/mapping/inherent-impl-to-free-pass.rs b/tests/ui/delegation/generics/mapping/inherent-impl-to-free-pass.rs index 7d99bc753cc2..1e08e155c5de 100644 --- a/tests/ui/delegation/generics/mapping/inherent-impl-to-free-pass.rs +++ b/tests/ui/delegation/generics/mapping/inherent-impl-to-free-pass.rs @@ -11,10 +11,10 @@ // Testing lifetimes + types/consts OR types/consts OR none in delegation parent, // lifetimes + types/consts in child reuse, -// with(out) user-specified args +// with(out) user-specified args, with impl traits mod test_1 { mod to_reuse { - pub fn foo<'a: 'a, 'b: 'b, A, B, const N: usize>() {} + pub fn foo<'a: 'a, 'b: 'b, A, B, const N: usize>(_f: impl FnOnce(A, B) -> B) {} } #[allow(dead_code)] // Fields are used instead of phantom data for generics use @@ -39,14 +39,14 @@ impl X3 { pub fn check() { X1::<'static, 'static, i32, i32, 1> - ::foo::<'static, 'static, String, String, 123>(); - X1::<'static, 'static, i32, i32, 1>::bar(); + ::foo::<'static, 'static, String, String, 123>(|_, y| y); + X1::<'static, 'static, i32, i32, 1>::bar(|_, y| y); - X2::::foo::<'static, 'static, String, String, 123>(); - X2::::bar(); + X2::::foo::<'static, 'static, String, String, 123>(|_, y| y); + X2::::bar(|_, y| y); - X3::foo::<'static, 'static, String, String, 123>(); - X3::bar(); + X3::foo::<'static, 'static, String, String, 123>(|_, y| y); + X3::bar(|_, y| y); } } diff --git a/tests/ui/delegation/generics/mapping/inherent-impl-to-trait-pass.rs b/tests/ui/delegation/generics/mapping/inherent-impl-to-trait-pass.rs index 9e85a7c07c3a..bf4d1a7ca2cb 100644 --- a/tests/ui/delegation/generics/mapping/inherent-impl-to-trait-pass.rs +++ b/tests/ui/delegation/generics/mapping/inherent-impl-to-trait-pass.rs @@ -12,10 +12,10 @@ // Testing types in parent, none in child, // user-specified args in parent, checking predicates inheritance, -// with additional generic params in delegation parent +// with additional generic params in delegation parent, with impl traits mod test_1 { trait Trait { - fn foo(&self) {} + fn foo(&self, _f: impl FnOnce(T) -> String) {} } struct F; @@ -29,8 +29,8 @@ impl<'a, 'b, 'c, A, B> S<'a, 'b, 'c, A, B> { pub fn check() { let s = S(F, &123, &123, &123); - S::<'static, 'static, 'static, i32, i32>::foo(&s); - s.foo(); + S::<'static, 'static, 'static, i32, i32>::foo(&s, |t| t.to_string()); + s.foo(|t| t.to_string()); } } diff --git a/tests/ui/delegation/generics/mapping/trait-to-free-pass.rs b/tests/ui/delegation/generics/mapping/trait-to-free-pass.rs index c43dc41931e9..12edc3b72fac 100644 --- a/tests/ui/delegation/generics/mapping/trait-to-free-pass.rs +++ b/tests/ui/delegation/generics/mapping/trait-to-free-pass.rs @@ -10,9 +10,10 @@ //! added. At some tests user-specified args are specified in reuse statement. // Testing lifetimes + types/consts in child, lifetimes + types/consts in delegation parent, -// with(out) user-specified args +// with(out) user-specified args, with impl traits mod test_1 { - fn foo<'a: 'a, 'b: 'b, T: Clone + ToString, U: Clone, const N: usize>() {} + fn foo<'a: 'a, 'b: 'b, T: Clone + ToString, U: Clone, const N: usize>( + _f: impl FnOnce(T) -> (T, U)) {} trait Trait<'a, A, B, C, const N: usize> { reuse foo; @@ -21,8 +22,10 @@ trait Trait<'a, A, B, C, const N: usize> { impl Trait<'static, i32, i32, i32, 1> for u32 {} pub fn check() { - >::foo::<'static, 'static, i32, String, 1>(); - >::bar(); + > + ::foo::<'static, 'static, i32, String, 1>(|t| (t, "".to_string())); + >::bar(|t| (t, t.to_string())); + u32::bar(|t| (t, t.to_string())); } } diff --git a/tests/ui/delegation/generics/mapping/trait-to-trait-pass.rs b/tests/ui/delegation/generics/mapping/trait-to-trait-pass.rs index 0e96f045065a..bcc1369aa440 100644 --- a/tests/ui/delegation/generics/mapping/trait-to-trait-pass.rs +++ b/tests/ui/delegation/generics/mapping/trait-to-trait-pass.rs @@ -14,10 +14,10 @@ // lifetimes + types/consts in child, // in delegation parent with: // lifetimes + types OR none OR lifetimes OR types, -// with(out) user-specified args, with different target expr +// with(out) user-specified args, with different target expr, with impl traits mod test_1 { trait Trait<'b, 'c, 'a, T>: Sized { - fn foo<'d: 'd, U, const M: bool>(&self) {} + fn foo<'d: 'd, U, const M: bool>(&self, _f: impl FnOnce(T) -> U) {} } impl<'b, 'c, 'a, T> Trait<'b, 'c, 'a, T> for u8 {} @@ -83,26 +83,26 @@ impl Trait5 for u32 {} pub fn check<'a: 'a>() { > - ::bar1::<'static, String, true>(&123); - ::bar1::<'static, String, true>(&123); - >::bar1::<'static, String, true>(&123); - >::bar1::<'static, String, true>(&123); + ::bar1::<'static, String, true>(&123, |x| x.to_string()); + ::bar1::<'static, String, true>(&123, |x| x.to_string()); + >::bar1::<'static, String, true>(&123, |x| x.to_string()); + >::bar1::<'static, String, true>(&123, |x| x.to_string()); - >::bar2(&123); - ::bar2(&123); - >::bar2(&123); - >::bar2(&123); + >::bar2(&123, |x| x.to_string()); + ::bar2(&123, |x| x.to_string()); + >::bar2(&123, |x| x.to_string()); + >::bar2(&123, |x| x.to_string()); > - ::bar3::<'static, String, true>(&123); - ::bar3::<'static, String, true>(&123); - >::bar3::<'static, String, true>(&123); - >::bar3::<'static, String, true>(&123); + ::bar3::<'static, String, true>(&123, |x| x.to_string()); + ::bar3::<'static, String, true>(&123, |x| x.to_string()); + >::bar3::<'static, String, true>(&123, |x| x.to_string()); + >::bar3::<'static, String, true>(&123, |x| x.to_string()); - >::bar4(&123); - ::bar4(&123); - >::bar4(&123); - >::bar4(&123); + >::bar4(&123, |x| x.to_string()); + ::bar4(&123, |x| x.to_string()); + >::bar4(&123, |x| x.to_string()); + >::bar4(&123, |x| x.to_string()); } } diff --git a/tests/ui/delegation/generics/synth-params-ice-154780.rs b/tests/ui/delegation/generics/synth-params-ice-154780.rs new file mode 100644 index 000000000000..96af4ed86b4c --- /dev/null +++ b/tests/ui/delegation/generics/synth-params-ice-154780.rs @@ -0,0 +1,101 @@ +//@ run-pass + +#![feature(fn_delegation)] + +// Almost original ICE with recursive delegation. +mod test_1 { + pub fn check() { + fn foo(f: impl FnOnce() -> usize) -> usize { + f() + } + + reuse foo::<1, String, String> as bar; + + reuse bar as bar2; + + assert_eq!(bar(|| 123), 123); + assert_eq!(bar2(|| 123), 123); + } +} + +// Test recursive delegations through trait. +mod test_2 { + fn foo<'a, const B: bool, T, U>(_x: impl Trait<'a, T, B>, f: impl FnOnce() -> usize) -> usize { + f() + } + + trait Trait<'a, A, const B: bool> { + reuse foo; + reuse foo::<'a, false, (), ()> as bar; + } + + struct X; + impl<'a, A, const B: bool> Trait<'a, A, B> for X {} + + reuse ::foo as foo2; + reuse ::bar as bar2; + + pub fn check() { + assert_eq!(foo2::<'static, 'static, X, (), true, false, (), ()>(X, || 123), 123); + assert_eq!(bar2::<'static, X, (), true>(X, || 123), 123); + } +} + +// Testing impl Traits with SelfAndUserSpecified case. +mod test_3 { + trait Trait<'a, A, const B: bool> { + fn foo<'b, const B2: bool, T, U>(&self, f: impl FnOnce() -> usize) -> usize { + f() + } + } + + struct X; + impl<'a, A, const B: bool> Trait<'a, A, B> for X {} + + reuse Trait::foo; + reuse Trait::<'static, (), true>::foo:: as bar; + + pub fn check() { + assert_eq!(foo::<'static, X, (), true, false, (), ()>(&X, || 123), 123); + assert_eq!(bar::(&X, || 123), 123); + assert_eq!(bar(&X, || 123), 123); + } +} + +// FIXME(fn_delegation): rename Self generic param in recursive delegations +// mod test_4 { +// trait Trait<'a, A, const B: bool> { +// fn foo<'b, const B2: bool, T, U>(&self, f: impl FnOnce() -> usize) -> usize { +// f() +// } +// } + +// struct X; +// impl<'a, A, const B: bool> Trait<'a, A, B> for X {} + +// reuse Trait::foo; +// reuse Trait::<'static, (), true>::foo:: as bar; + +// trait Trait2 { +// reuse foo; +// reuse bar; +// } + +// reuse Trait2::foo as foo2; +// reuse Trait2::foo::<'static, X, (), true, false, (), ()> as foo3; +// reuse Trait2::bar as bar2; +// reuse Trait2::bar:: as bar3; + +// pub fn check() { +// assert_eq!(foo::<'static, X, (), true, false, (), ()>(&X, || 123), 123); +// assert_eq!(bar::(&X, || 123), 123); +// assert_eq!(bar(&X, || 123), 123); +// } +// } + +fn main() { + test_1::check(); + test_2::check(); + test_3::check(); + // test_4::check(); +}