@@ -2737,19 +2737,27 @@ class MissingImplicitArgument(
2737
2737
val idx = paramNames.indexOf(name)
2738
2738
if (idx >= 0 ) Some (i " ${args(idx)}" ) else None
2739
2739
""" \$\{\s*([^}\s]+)\s*\}""" .r.replaceAllIn(raw, (_ : Regex .Match ) match
2740
- case Regex .Groups (v) => quoteReplacement(translate(v).getOrElse(" " )).nn
2740
+ case Regex .Groups (v) => quoteReplacement(translate(v).getOrElse(" ? " + v )).nn
2741
2741
)
2742
2742
2743
2743
/** @param rawMsg Message template with variables, e.g. "Variable A is ${A}"
2744
2744
* @param sym Symbol of the annotated type or of the method whose parameter was annotated
2745
+ * @param paramNames Names of type parameters to substitute with `args` in the message template
2746
+ * @param args Resolved type arguments to substitute for `paramNames` in the message template
2745
2747
* @param substituteType Function substituting specific types for abstract types associated with variables, e.g A -> Int
2746
2748
*/
2747
- def formatAnnotationMessage (rawMsg : String , sym : Symbol , substituteType : Type => Type )(using Context ): String =
2749
+ def formatAnnotationMessage (
2750
+ rawMsg : String ,
2751
+ sym : Symbol ,
2752
+ paramNames : List [Name ],
2753
+ args : List [Type ],
2754
+ substituteType : Type => Type ,
2755
+ )(using Context ): String =
2748
2756
val substitutableTypesSymbols = substitutableTypeSymbolsInScope(sym)
2749
2757
userDefinedErrorString(
2750
2758
rawMsg,
2751
- paramNames = substitutableTypesSymbols.map(_.name.unexpandedName.toString),
2752
- args = substitutableTypesSymbols.map(_.typeRef).map(substituteType)
2759
+ paramNames = (paramNames ::: substitutableTypesSymbols.map(_.name)).map(_ .unexpandedName.toString),
2760
+ args = args ::: substitutableTypesSymbols.map(_.typeRef).map(substituteType)
2753
2761
)
2754
2762
2755
2763
/** Extract a user defined error message from a symbol `sym`
@@ -2761,14 +2769,17 @@ class MissingImplicitArgument(
2761
2769
msg <- ann.argumentConstantString(0 )
2762
2770
yield msg
2763
2771
2764
- def userDefinedImplicitNotFoundTypeMessageFor (sym : Symbol )(using Context ): Option [String ] =
2765
- for
2766
- rawMsg <- userDefinedMsg(sym, defn.ImplicitNotFoundAnnot )
2767
- if Feature .migrateTo3 || sym != defn.Function1
2768
- // Don't inherit "No implicit view available..." message if subtypes of Function1 are not treated as implicit conversions anymore
2769
- yield
2770
- val substituteType = (_ : Type ).asSeenFrom(pt, sym)
2771
- formatAnnotationMessage(rawMsg, sym, substituteType)
2772
+ def userDefinedImplicitNotFoundTypeMessageFor (
2773
+ sym : Symbol ,
2774
+ params : List [ParamInfo ] = Nil ,
2775
+ args : List [Type ] = Nil
2776
+ )(using Context ): Option [String ] = for
2777
+ rawMsg <- userDefinedMsg(sym, defn.ImplicitNotFoundAnnot )
2778
+ if Feature .migrateTo3 || sym != defn.Function1
2779
+ // Don't inherit "No implicit view available..." message if subtypes of Function1 are not treated as implicit conversions anymore
2780
+ yield
2781
+ val paramNames = params.map(_.paramName)
2782
+ formatAnnotationMessage(rawMsg, sym, paramNames, args, _.asSeenFrom(pt, sym))
2772
2783
2773
2784
/** Extracting the message from a method parameter, e.g. in
2774
2785
*
@@ -2783,19 +2794,22 @@ class MissingImplicitArgument(
2783
2794
val targs = tpd.typeArgss(applTree).flatten
2784
2795
val methodOwner = fn.symbol.owner
2785
2796
val methodOwnerType = tpd.qualifier(fn).tpe
2786
- val methodTypeParams = fn.symbol.paramSymss.flatten.filter (_.isType)
2797
+ val methodTypeParams = fn.symbol.paramSymss.flatten.withFilter (_.isType).map(_.name )
2787
2798
val methodTypeArgs = targs.map(_.tpe)
2788
- val substituteType = (_ : Type ).asSeenFrom(methodOwnerType, methodOwner).subst(methodTypeParams, methodTypeArgs)
2789
- formatAnnotationMessage(rawMsg, sym.owner, substituteType)
2799
+ formatAnnotationMessage(rawMsg, sym.owner, methodTypeParams, methodTypeArgs, _.asSeenFrom(methodOwnerType, methodOwner))
2790
2800
2791
2801
def userDefinedImplicitNotFoundTypeMessage (using Context ): Option [String ] =
2792
- def recur (tp : Type ): Option [String ] = tp match
2802
+ def recur (tp : Type , params : List [ParamInfo ] = Nil , args : List [Type ] = Nil ): Option [String ] = tp match
2803
+ case tp : AppliedType =>
2804
+ val tycon = tp.typeConstructor
2805
+ val typeParams = if tycon.isLambdaSub then tycon.hkTypeParams else tycon.typeParams
2806
+ recur(tycon, typeParams ::: params, tp.args ::: args)
2793
2807
case tp : TypeRef =>
2794
- val sym = tp.symbol
2795
- userDefinedImplicitNotFoundTypeMessageFor(sym) .orElse(recur(tp.info))
2808
+ userDefinedImplicitNotFoundTypeMessageFor( tp.symbol, params, args)
2809
+ .orElse(recur(tp.info))
2796
2810
case tp : ClassInfo =>
2797
2811
tp.baseClasses.iterator
2798
- .map(userDefinedImplicitNotFoundTypeMessageFor)
2812
+ .map(userDefinedImplicitNotFoundTypeMessageFor(_) )
2799
2813
.find(_.isDefined).flatten
2800
2814
case tp : TypeProxy =>
2801
2815
recur(tp.superType)
0 commit comments