@@ -1164,10 +1164,7 @@ fn build_constructor_template_subs(
11641164 } ;
11651165
11661166 // Get the corresponding argument text.
1167- let arg_text = match arg_texts. get ( param_idx) {
1168- Some ( text) => text. trim ( ) ,
1169- None => continue ,
1170- } ;
1167+ let provided_arg = arg_texts. get ( param_idx) . map ( |t| t. trim ( ) ) ;
11711168
11721169 // Determine the binding mode by inspecting the parameter's
11731170 // docblock type hint. The type hint tells us how the template
@@ -1178,6 +1175,27 @@ fn build_constructor_template_subs(
11781175 . and_then ( |p| p. type_hint . as_ref ( ) ) ;
11791176 let binding_mode = classify_template_binding ( tpl_name, param_hint) ;
11801177
1178+ // Fall back to the parameter's default value only for binding
1179+ // modes where the default is meaningful.
1180+ let default_value = ctor
1181+ . parameters
1182+ . get ( param_idx)
1183+ . and_then ( |p| p. default_value . as_deref ( ) ) ;
1184+ let arg_text: & str = match provided_arg {
1185+ Some ( text) => text,
1186+ None => match & binding_mode {
1187+ TemplateBindingMode :: ClassStringInner => match default_value {
1188+ Some ( d) => d,
1189+ None => continue ,
1190+ } ,
1191+ TemplateBindingMode :: Direct => match default_value {
1192+ Some ( d) if d. ends_with ( "::class" ) => d,
1193+ _ => continue ,
1194+ } ,
1195+ _ => continue ,
1196+ } ,
1197+ } ;
1198+
11811199 match binding_mode {
11821200 TemplateBindingMode :: Direct => {
11831201 // `@param T $bar` — the argument resolves directly to T.
@@ -1856,10 +1874,7 @@ pub(crate) fn build_function_template_subs(
18561874 None => continue ,
18571875 } ;
18581876
1859- let arg_text = match arg_texts. get ( param_idx) {
1860- Some ( text) => text. trim ( ) ,
1861- None => continue ,
1862- } ;
1877+ let provided_arg = arg_texts. get ( param_idx) . map ( |t| t. trim ( ) ) ;
18631878
18641879 // Determine the binding mode by inspecting the parameter's
18651880 // docblock type hint. The type hint tells us how the template
@@ -1870,6 +1885,28 @@ pub(crate) fn build_function_template_subs(
18701885 . and_then ( |p| p. type_hint . as_ref ( ) ) ;
18711886 let binding_mode = classify_template_binding ( tpl_name, param_hint) ;
18721887
1888+ // Fall back to the parameter's default value only for binding
1889+ // modes where the default is meaningful (class-string<T> with
1890+ // a `Foo::class` default, or direct bindings with `::class`).
1891+ let default_value = func_info
1892+ . parameters
1893+ . get ( param_idx)
1894+ . and_then ( |p| p. default_value . as_deref ( ) ) ;
1895+ let arg_text: & str = match provided_arg {
1896+ Some ( text) => text,
1897+ None => match & binding_mode {
1898+ TemplateBindingMode :: ClassStringInner => match default_value {
1899+ Some ( d) => d,
1900+ None => continue ,
1901+ } ,
1902+ TemplateBindingMode :: Direct => match default_value {
1903+ Some ( d) if d. ends_with ( "::class" ) => d,
1904+ _ => continue ,
1905+ } ,
1906+ _ => continue ,
1907+ } ,
1908+ } ;
1909+
18731910 match binding_mode {
18741911 TemplateBindingMode :: Direct => {
18751912 if let Some ( resolved_type) = Backend :: resolve_arg_text_to_type ( arg_text, rctx) {
0 commit comments