diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 8471b06b7e97..ab77350be26c 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -1987,10 +1987,12 @@ object desugar { .collect: case vd: ValDef => vd - def makeContextualFunction(formals: List[Tree], paramNamesOrNil: List[TermName], body: Tree, erasedParams: List[Boolean])(using Context): Function = + def makeContextualFunction(formals: List[Tree], paramNamesOrNil: List[TermName], body: Tree, erasedParams: List[Boolean], augmenting: Boolean = false)(using Context): Function = val paramNames = - if paramNamesOrNil.nonEmpty then paramNamesOrNil - else formals.map(_ => ContextFunctionParamName.fresh()) + if paramNamesOrNil.nonEmpty then + if augmenting then paramNamesOrNil.map(ContextFunctionParamName.fresh(_)) + else paramNamesOrNil + else List.fill(formals.length)(ContextFunctionParamName.fresh()) val params = for (tpt, pname) <- formals.zip(paramNames) yield ValDef(pname, tpt, EmptyTree).withFlags(Given | Param) FunctionWithMods(params, body, Modifiers(Given), erasedParams) diff --git a/compiler/src/dotty/tools/dotc/core/NameKinds.scala b/compiler/src/dotty/tools/dotc/core/NameKinds.scala index 6738c73113f9..d16bb3802b0c 100644 --- a/compiler/src/dotty/tools/dotc/core/NameKinds.scala +++ b/compiler/src/dotty/tools/dotc/core/NameKinds.scala @@ -303,10 +303,12 @@ object NameKinds { /** The name of an inferred contextual function parameter: * * val x: A ?=> B = b + * val f: (x: A) ?=> B = b * * becomes: * * val x: A ?=> B = (contextual$1: A) ?=> b + * val f: (x: A) ?=> B = (xcontextual$1: A) ?=> b */ val ContextFunctionParamName: UniqueNameKind = new UniqueNameKind("contextual$") diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 90dfb72ef010..962133fbacc6 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -4,6 +4,7 @@ package printing import core.* import Texts.*, Types.*, Flags.*, Names.*, Symbols.*, NameOps.*, Constants.*, Denotations.* import StdNames.* +import NameKinds.ContextFunctionParamName import Contexts.* import Scopes.Scope, Denotations.Denotation, Annotations.Annotation import StdNames.nme @@ -361,9 +362,7 @@ class PlainPrinter(_ctx: Context) extends Printer { case tp: LazyRef => def refTxt = try toTextGlobal(tp.ref) - catch { - case ex: Throwable => Str("...") - } + catch case _: Throwable => Str("...") // reconsider catching errors "LazyRef(" ~ refTxt ~ ")" case Range(lo, hi) => toText(lo) ~ ".." ~ toText(hi) @@ -395,10 +394,17 @@ class PlainPrinter(_ctx: Context) extends Printer { Text(lam.paramRefs.map(paramText), ", ") } - protected def ParamRefNameString(name: Name): String = nameString(name) + protected def ParamRefNameString(name: Name): String = + nameString(name) protected def ParamRefNameString(param: ParamRef): String = - ParamRefNameString(param.binder.paramNames(param.paramNum)) + val name = param.binder.paramNames(param.paramNum) + ParamRefNameString: + if name.is(ContextFunctionParamName) then + name match + case ContextFunctionParamName(name, _) if !name.isEmpty => name + case name => name + else name /** The name of the symbol without a unique id. */ protected def simpleNameString(sym: Symbol): String = nameString(sym.name) diff --git a/compiler/src/dotty/tools/dotc/reporting/Message.scala b/compiler/src/dotty/tools/dotc/reporting/Message.scala index f0bb57652fd9..e025594cad50 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Message.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Message.scala @@ -132,9 +132,9 @@ object Message: def sameSuperscript(cur: Recorded, existing: Recorded) = (cur eq existing) || (cur, existing).match - case (cur: ParamRef, existing: ParamRef) => - (cur.paramName eq existing.paramName) - && cur.binder.paramNames == existing.binder.paramNames + case (cur: ParamRef, existing: ParamRef) => true + //(cur.paramName eq existing.paramName) + //&& cur.binder.paramNames == existing.binder.paramNames case _ => false diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 164ff411e73b..42e192a09207 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -3912,7 +3912,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer case _ => paramTypes.map(_ => false) } - val ifun = desugar.makeContextualFunction(paramTypes, paramNamesOrNil, tree, erasedParams) + val ifun = desugar.makeContextualFunction(paramTypes, paramNamesOrNil, tree, erasedParams, augmenting = true) typr.println(i"make contextual function $tree / $pt ---> $ifun") typedFunctionValue(ifun, pt) .tap: diff --git a/tests/neg/i24375.scala b/tests/neg/i24375.scala new file mode 100644 index 000000000000..d6c3bf83cfbd --- /dev/null +++ b/tests/neg/i24375.scala @@ -0,0 +1,12 @@ +trait Ord[X]: + def compare(x: X, y: X): Int + type T + +trait Show[X]: + def show(x: X): String + +val f0: Show[String] ?=> String = summon[Show[String]].show("hello, world") * 2 + +val f1: (x: Show[String]) ?=> String = x.show("hello, world") * 2 // error + +val f2 = (x: Show[String]) ?=> x.show("hello, world") * 2