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