Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/core/NameKinds.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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$")

Expand Down
16 changes: 11 additions & 5 deletions compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Answering @Sporarum's comment on the issue :
#24375 (comment)

Maybe we should work on the toString function for ContectFunctionParamNames instead of intervening here.

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)
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/reporting/Message.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
12 changes: 12 additions & 0 deletions tests/neg/i24375.scala
Original file line number Diff line number Diff line change
@@ -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
Loading