@@ -30,12 +30,54 @@ public enum EMethodKind
3030 CTOR , INSTANCE , STATIC
3131 }
3232
33+ public class SignatureHint
34+ {
35+ public List < Type > GenericTypeArgs { get ; private set ; }
36+ public List < Type > Args { get ; private set ; }
37+ public bool IsEmpty { get ; private set ; }
38+
39+ public int ArgCount => Args ? . Count ?? 0 ;
40+
41+ public SignatureHint ( IPersistentVector tagV )
42+ {
43+ if ( tagV == null || tagV . count ( ) == 0 )
44+ {
45+ GenericTypeArgs = null ;
46+ Args = null ;
47+ IsEmpty = true ;
48+ return ;
49+ }
50+
51+ var firstItem = tagV . nth ( 0 ) ;
52+ ISeq remainingTags = null ;
53+
54+ if ( firstItem is ISeq && RT . first ( firstItem ) is Symbol symbol && symbol . Equals ( HostExpr . TypeArgsSym ) )
55+ {
56+ GenericTypeArgs = HostExpr . ParseGenericMethodTypeArgs ( RT . next ( firstItem ) ) ;
57+ remainingTags = RT . next ( tagV ) ;
58+ }
59+ else
60+ {
61+ GenericTypeArgs = null ;
62+ remainingTags = RT . seq ( tagV ) ;
63+ }
64+
65+
66+ Args = Compiler . TagsToClasses ( remainingTags ) ;
67+
68+ IsEmpty = Args is null && GenericTypeArgs is null ;
69+ }
70+
71+
72+ }
73+
74+
3375 #endregion
3476
3577 #region Data
3678
3779 public Type MethodType { get ; private set ; }
38- public List < Type > HintedSig { get ; private set ; }
80+ public SignatureHint HintedSig { get ; private set ; }
3981 readonly Symbol _methodSymbol ;
4082 public string MethodName { get ; private set ; }
4183 public EMethodKind Kind { get ; private set ; }
@@ -50,7 +92,7 @@ public QualifiedMethodExpr(Type methodType, Symbol sym)
5092 MethodType = methodType ;
5193 _methodSymbol = sym ;
5294 _tagClass = Compiler . TagOf ( sym ) != null ? HostExpr . TagToType ( Compiler . TagOf ( sym ) ) : typeof ( AFn ) ;
53- HintedSig = Compiler . TagsToClasses ( Compiler . ParamTagsOf ( sym ) ) ;
95+ HintedSig = new SignatureHint ( Compiler . ParamTagsOf ( sym ) ) ;
5496
5597 if ( sym . Name . StartsWith ( "." ) )
5698 {
@@ -116,10 +158,10 @@ private static FnExpr BuildThunk(ParserContext pcon, QualifiedMethodExpr qmexpr
116158
117159 HashSet < int > arities ;
118160
119- if ( qmexpr . HintedSig != null )
161+ if ( ! qmexpr . HintedSig . IsEmpty )
120162 {
121163 arities = new HashSet < int > ( ) ;
122- arities . Add ( qmexpr . HintedSig . Count ) ;
164+ arities . Add ( qmexpr . HintedSig . ArgCount ) ;
123165 }
124166 else
125167 arities = AritySet ( qmexpr . MethodType , qmexpr . MethodName , qmexpr . Kind ) ;
@@ -182,21 +224,36 @@ private static List<MethodBase> MethodsWithName(Type t, string methodName, EMeth
182224 return methods ;
183225 }
184226
185- internal static MethodBase ResolveHintedMethod ( Type t , string methodName , EMethodKind kind , List < Type > hintedSig )
227+ internal static MethodBase ResolveHintedMethod ( Type t , string methodName , EMethodKind kind , SignatureHint hint )
186228 {
229+ // hint is non-null and hint.IsEmpty is false;
230+ // It might have generic type args, and/or args
231+
187232 List < MethodBase > methods = MethodsWithName ( t , methodName , kind ) ;
188233
189- int arity = hintedSig . Count ;
234+ // If we have generic type args and the list is non-empty, we need to choose only methods that have the same number of generic type args, fully instantiated.
235+
236+ int gtaCount = hint . GenericTypeArgs ? . Count ?? 0 ;
237+ if ( gtaCount > 0 )
238+ {
239+ methods = methods
240+ . Where ( m => m . IsGenericMethod && m . GetGenericArguments ( ) . Length == gtaCount )
241+ . Select ( m => ( ( MethodInfo ) m ) . MakeGenericMethod ( hint . GenericTypeArgs . ToArray ( ) ) )
242+ . Cast < MethodBase > ( )
243+ . ToList ( ) ;
244+ }
245+
246+ int arity = hint . Args ? . Count ?? 0 ;
190247
191248 var filteredMethods = methods
192249 . Where ( m => m . GetParameters ( ) . Length == arity )
193- . Where ( m => Compiler . SignatureMatches ( hintedSig , m ) )
250+ . Where ( m => Compiler . SignatureMatches ( hint . Args , m ) )
194251 . ToList ( ) ;
195252
196253 if ( filteredMethods . Count == 1 )
197254 return filteredMethods [ 0 ] ;
198255 else
199- throw ParamTagsDontResolveException ( t , methodName , hintedSig ) ;
256+ throw ParamTagsDontResolveException ( t , methodName , hint ) ;
200257
201258 }
202259
@@ -206,11 +263,16 @@ private static ArgumentException NoMethodWithNameException(Type t, string method
206263 return new ArgumentException ( $ "Error - no matches found for { kindStr } { Compiler . MethodDescription ( t , methodName ) } ") ;
207264 }
208265
209- private static ArgumentException ParamTagsDontResolveException ( Type t , string methodName , List < Type > hintedSig )
266+ private static ArgumentException ParamTagsDontResolveException ( Type t , string methodName , SignatureHint hint )
210267 {
268+ List < Type > hintedSig = hint . Args ;
269+
211270 IEnumerable < Object > tagNames = hintedSig . Cast < Object > ( ) . Select ( tag => tag == null ? Compiler . ParamTagAny : tag ) ;
212271 IPersistentVector paramTags = PersistentVector . create ( tagNames ) ;
213- return new ArgumentException ( $ "Error - param-tags { paramTags } insufficient to resolve { Compiler . MethodDescription ( t , methodName ) } ") ;
272+
273+ string genericTypeArgs = hint . GenericTypeArgs == null ? "" : $ "<{ hint . GenericTypeArgs } >";
274+
275+ return new ArgumentException ( $ "Error - param-tags { genericTypeArgs } { paramTags } insufficient to resolve { Compiler . MethodDescription ( t , methodName ) } ") ;
214276 }
215277
216278
0 commit comments