diff --git a/pod/perldiag.pod b/pod/perldiag.pod index 0ab63025a162..cdb7b1eb0882 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -4163,9 +4163,12 @@ which is forbidden. See L and L. =item Missing required named parameter '%s' to subroutine '%s' -(F) A subroutine was invoked that uses a signature that declares a -non-optional named parameter, but the caller did not provide a value associated -with that name. The caller of the subroutine is presumably at fault. +=item Missing required named parameters '%s' to subroutine '%s' + +(F) A subroutine was invoked that uses a signature that declares at least +one non-optional named parameter, but the caller did not provide a value +associated with that name. The caller of the subroutine is presumably at +fault. The message attempts to include the name of the called subroutine. If the subroutine has been aliased, the subroutine's original name will be @@ -7530,10 +7533,12 @@ perl does not recognise the name of the requested attribute. =item Unrecognized named parameter '%s' to subroutine '%s' -(F) A subroutine was invoked that uses a signature that declares named parameters but has no -slurpy parameter, and the caller provided a name that did not -match any declared named parameter. The caller of the subroutine is -presumably at fault. +=item Unrecognized named parameters '%s' to subroutine '%s' + +(F) A subroutine was invoked that uses a signature that declares named +parameters but has no slurpy parameter, and the caller provided at least one +name that did not match any declared named parameter. The caller of the +subroutine is presumably at fault. The message attempts to include the name of the called subroutine. If the subroutine has been aliased, the subroutine's original name will be diff --git a/pp.c b/pp.c index 1651de4c3b0c..a15bdd32c842 100644 --- a/pp.c +++ b/pp.c @@ -7983,6 +7983,9 @@ PP(pp_multiparam) SvPADSTALE_on(PAD_SVl(named->padix)); } + size_t n_errors = 0; + SV *error_names = NULL; + while(argc) { SV **svp; @@ -8060,22 +8063,48 @@ PP(pp_multiparam) hv_store_ent(hv, name, newSVsv(val), 0); } else { - // TODO: Consider collecting up all the names of unrecognised - // in one string - croak_caller("Unrecognized named parameter '%" UTF8f "' to subroutine '%" SVf "'", - UTF8fARG(true, namelen, namepv), S_find_runcv_name()); + n_errors++; + if(!error_names) + error_names = sv_2mortal(newSVpvs("")); + if(n_errors <= 5) { + /* Only bother collecting up the first 5 */ + if(n_errors > 1) + sv_catpvs(error_names, ", "); + sv_catpvf(error_names, "'%" UTF8f "'", UTF8fARG(true, namelen, namepv)); + } } } + if(n_errors) { + if(n_errors > 5) + sv_catpvs(error_names, ", ..."); + /* diag_listed_as: Unrecognized named parameter '%s' to subroutine '%s' */ + croak_caller("Unrecognized named parameter%s %" SVf " to subroutine '%" SVf "'", + n_errors > 1 ? "s" : "", SVfARG(error_names), SVfARG(S_find_runcv_name())); + } + for(size_t namedix = 0; namedix < n_named; namedix++) { struct op_multiparam_named_aux *named = aux->named + namedix; if(!named->is_required || !SvPADSTALE(PAD_SVl(named->padix))) continue; - // TODO: Consider collecting up all the names of missing - // parameters in one string - croak_caller("Missing required named parameter '%" UTF8f "' to subroutine '%" SVf "'", - UTF8fARG(true, named->namelen, named->namepv), S_find_runcv_name()); + n_errors++; + if(!error_names) + error_names = sv_2mortal(newSVpvs("")); + if(n_errors <= 5) { + /* Only bother collecting up the first 5 */ + if(n_errors > 1) + sv_catpvs(error_names, ", "); + sv_catpvf(error_names, "'%" UTF8f "'", UTF8fARG(true, named->namelen, named->namepv)); + } + } + + if(n_errors) { + if(n_errors > 5) + sv_catpvs(error_names, ", ..."); + /* diag_listed_as: Missing required named parameter '%s' to subroutine '%s' */ + croak_caller("Missing required named parameter%s %" SVf " to subroutine '%" SVf "'", + n_errors > 1 ? "s" : "", SVfARG(error_names), SVfARG(S_find_runcv_name())); } } diff --git a/t/lib/croak/signatures b/t/lib/croak/signatures index 49fb4e855917..ae77e8604074 100644 --- a/t/lib/croak/signatures +++ b/t/lib/croak/signatures @@ -285,9 +285,30 @@ f(alpha => 123); ## line 4 EXPECT Missing required named parameter 'beta' to subroutine 'main::f' at - line 4. ######## +# NAME multiple missing required named +no warnings 'experimental::signature_named_parameters'; +sub f (:$alpha, :$beta) { } ## line 3 +f(); ## line 4 +EXPECT +Missing required named parameters 'alpha', 'beta' to subroutine 'main::f' at - line 4. +######## # NAME unrecognised named no warnings 'experimental::signature_named_parameters'; sub f (:$alpha) { } ## line 3 f(alpha => 123, gamma => 456); ## line 4 EXPECT Unrecognized named parameter 'gamma' to subroutine 'main::f' at - line 4. +######## +# NAME multiple unrecognised named +no warnings 'experimental::signature_named_parameters'; +sub f (:$alpha) { } ## line 3 +f(alpha => 123, gamma => 456, delta => 789); ## line 4 +EXPECT +Unrecognized named parameters 'gamma', 'delta' to subroutine 'main::f' at - line 4. +######## +# NAME multiple unrecognised named limiting +no warnings 'experimental::signature_named_parameters'; +sub f (:$alpha) { } ## line 3 +f(alpha => 123, 'a' .. 'z'); ## line 4 +EXPECT +Unrecognized named parameters 'a', 'c', 'e', 'g', 'i', ... to subroutine 'main::f' at - line 4.