@@ -2821,19 +2821,27 @@ class MissingImplicitArgument(
2821
2821
val idx = paramNames.indexOf(name)
2822
2822
if (idx >= 0 ) Some (i " ${args(idx)}" ) else None
2823
2823
""" \$\{\s*([^}\s]+)\s*\}""" .r.replaceAllIn(raw, (_ : Regex .Match ) match
2824
- case Regex .Groups (v) => quoteReplacement(translate(v).getOrElse(" " )).nn
2824
+ case Regex .Groups (v) => quoteReplacement(translate(v).getOrElse(" ? " + v )).nn
2825
2825
)
2826
2826
2827
2827
/** @param rawMsg Message template with variables, e.g. "Variable A is ${A}"
2828
2828
* @param sym Symbol of the annotated type or of the method whose parameter was annotated
2829
+ * @param paramNames Names of type parameters to substitute with `args` in the message template
2830
+ * @param args Resolved type arguments to substitute for `paramNames` in the message template
2829
2831
* @param substituteType Function substituting specific types for abstract types associated with variables, e.g A -> Int
2830
2832
*/
2831
- def formatAnnotationMessage (rawMsg : String , sym : Symbol , substituteType : Type => Type )(using Context ): String =
2833
+ def formatAnnotationMessage (
2834
+ rawMsg : String ,
2835
+ sym : Symbol ,
2836
+ paramNames : List [Name ],
2837
+ args : List [Type ],
2838
+ substituteType : Type => Type ,
2839
+ )(using Context ): String =
2832
2840
val substitutableTypesSymbols = substitutableTypeSymbolsInScope(sym)
2833
2841
userDefinedErrorString(
2834
2842
rawMsg,
2835
- paramNames = substitutableTypesSymbols.map(_.name.unexpandedName.toString),
2836
- args = substitutableTypesSymbols.map(_.typeRef).map(substituteType)
2843
+ paramNames = (paramNames ::: substitutableTypesSymbols.map(_.name)).map(_ .unexpandedName.toString),
2844
+ args = args ::: substitutableTypesSymbols.map(_.typeRef).map(substituteType)
2837
2845
)
2838
2846
2839
2847
/** Extract a user defined error message from a symbol `sym`
@@ -2845,14 +2853,17 @@ class MissingImplicitArgument(
2845
2853
msg <- ann.argumentConstantString(0 )
2846
2854
yield msg
2847
2855
2848
- def userDefinedImplicitNotFoundTypeMessageFor (sym : Symbol )(using Context ): Option [String ] =
2849
- for
2850
- rawMsg <- userDefinedMsg(sym, defn.ImplicitNotFoundAnnot )
2851
- if Feature .migrateTo3 || sym != defn.Function1
2852
- // Don't inherit "No implicit view available..." message if subtypes of Function1 are not treated as implicit conversions anymore
2853
- yield
2854
- val substituteType = (_ : Type ).asSeenFrom(pt, sym)
2855
- formatAnnotationMessage(rawMsg, sym, substituteType)
2856
+ def userDefinedImplicitNotFoundTypeMessageFor (
2857
+ sym : Symbol ,
2858
+ params : List [ParamInfo ] = Nil ,
2859
+ args : List [Type ] = Nil
2860
+ )(using Context ): Option [String ] = for
2861
+ rawMsg <- userDefinedMsg(sym, defn.ImplicitNotFoundAnnot )
2862
+ if Feature .migrateTo3 || sym != defn.Function1
2863
+ // Don't inherit "No implicit view available..." message if subtypes of Function1 are not treated as implicit conversions anymore
2864
+ yield
2865
+ val paramNames = params.map(_.paramName)
2866
+ formatAnnotationMessage(rawMsg, sym, paramNames, args, _.asSeenFrom(pt, sym))
2856
2867
2857
2868
/** Extracting the message from a method parameter, e.g. in
2858
2869
*
@@ -2867,19 +2878,22 @@ class MissingImplicitArgument(
2867
2878
val targs = tpd.typeArgss(applTree).flatten
2868
2879
val methodOwner = fn.symbol.owner
2869
2880
val methodOwnerType = tpd.qualifier(fn).tpe
2870
- val methodTypeParams = fn.symbol.paramSymss.flatten.filter (_.isType)
2881
+ val methodTypeParams = fn.symbol.paramSymss.flatten.withFilter (_.isType).map(_.name )
2871
2882
val methodTypeArgs = targs.map(_.tpe)
2872
- val substituteType = (_ : Type ).asSeenFrom(methodOwnerType, methodOwner).subst(methodTypeParams, methodTypeArgs)
2873
- formatAnnotationMessage(rawMsg, sym.owner, substituteType)
2883
+ formatAnnotationMessage(rawMsg, sym.owner, methodTypeParams, methodTypeArgs, _.asSeenFrom(methodOwnerType, methodOwner))
2874
2884
2875
2885
def userDefinedImplicitNotFoundTypeMessage (using Context ): Option [String ] =
2876
- def recur (tp : Type ): Option [String ] = tp match
2886
+ def recur (tp : Type , params : List [ParamInfo ] = Nil , args : List [Type ] = Nil ): Option [String ] = tp match
2887
+ case tp : AppliedType =>
2888
+ val tycon = tp.typeConstructor
2889
+ val typeParams = if tycon.isLambdaSub then tycon.hkTypeParams else tycon.typeParams
2890
+ recur(tycon, typeParams ::: params, tp.args ::: args)
2877
2891
case tp : TypeRef =>
2878
- val sym = tp.symbol
2879
- userDefinedImplicitNotFoundTypeMessageFor(sym) .orElse(recur(tp.info))
2892
+ userDefinedImplicitNotFoundTypeMessageFor( tp.symbol, params, args)
2893
+ .orElse(recur(tp.info))
2880
2894
case tp : ClassInfo =>
2881
2895
tp.baseClasses.iterator
2882
- .map(userDefinedImplicitNotFoundTypeMessageFor)
2896
+ .map(userDefinedImplicitNotFoundTypeMessageFor(_) )
2883
2897
.find(_.isDefined).flatten
2884
2898
case tp : TypeProxy =>
2885
2899
recur(tp.superType)
0 commit comments