Skip to content

Commit fad5b8d

Browse files
authored
Merge pull request #10940 from dotty-staging/fix-#9530
Allow leading context parameters in extension methods
2 parents c9bf740 + c4b210e commit fad5b8d

File tree

108 files changed

+1204
-855
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+1204
-855
lines changed

compiler/src-bootstrapped/scala/quoted/runtime/impl/QuotesImpl.scala

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,14 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
5555

5656
end extension
5757

58-
extension [X](self: scala.quoted.Expr[Any])
58+
extension (self: scala.quoted.Expr[Any])
5959
/** Checks is the `quoted.Expr[?]` is valid expression of type `X` */
60-
def isExprOf(using scala.quoted.Type[X]): Boolean =
60+
def isExprOf[X](using scala.quoted.Type[X]): Boolean =
6161
reflect.TypeReprMethods.<:<(reflect.asTerm(self).tpe)(reflect.TypeRepr.of[X])
6262

6363
/** Convert this to an `quoted.Expr[X]` if this expression is a valid expression of type `X` or throws */
64-
def asExprOf(using scala.quoted.Type[X]): scala.quoted.Expr[X] = {
65-
if isExprOf[X] then
64+
def asExprOf[X](using scala.quoted.Type[X]): scala.quoted.Expr[X] = {
65+
if self.isExprOf[X] then
6666
self.asInstanceOf[scala.quoted.Expr[X]]
6767
else
6868
throw Exception(
@@ -107,9 +107,9 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
107107
case _ => throw new Exception("Expected a Term but was: " + self)
108108
end extension
109109

110-
extension [T](self: Tree)
111-
def asExprOf(using tp: scala.quoted.Type[T]): scala.quoted.Expr[T] =
112-
QuotesImpl.this.asExprOf[T](self.asExpr)(using tp)
110+
extension (self: Tree)
111+
def asExprOf[T](using tp: scala.quoted.Type[T]): scala.quoted.Expr[T] =
112+
QuotesImpl.this.asExprOf(self.asExpr)[T](using tp)
113113
end extension
114114

115115
extension [ThisTree <: Tree](self: ThisTree)
@@ -257,17 +257,20 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
257257

258258
object DefDef extends DefDefModule:
259259
def apply(symbol: Symbol, rhsFn: List[TypeRepr] => List[List[Term]] => Option[Term]): DefDef =
260-
withDefaultPos(tpd.polyDefDef(symbol.asTerm, tparams => vparamss => yCheckedOwners(rhsFn(tparams)(vparamss), symbol).getOrElse(tpd.EmptyTree)))
260+
withDefaultPos(tpd.DefDef(symbol.asTerm, prefss => {
261+
val (tparams, vparamss) = tpd.splitArgs(prefss)
262+
yCheckedOwners(rhsFn(tparams.map(_.tpe))(vparamss), symbol).getOrElse(tpd.EmptyTree)
263+
}))
261264
def copy(original: Tree)(name: String, typeParams: List[TypeDef], paramss: List[List[ValDef]], tpt: TypeTree, rhs: Option[Term]): DefDef =
262-
tpd.cpy.DefDef(original)(name.toTermName, typeParams, paramss, tpt, yCheckedOwners(rhs, original.symbol).getOrElse(tpd.EmptyTree))
265+
tpd.cpy.DefDef(original)(name.toTermName, tpd.joinParams(typeParams, paramss), tpt, yCheckedOwners(rhs, original.symbol).getOrElse(tpd.EmptyTree))
263266
def unapply(ddef: DefDef): (String, List[TypeDef], List[List[ValDef]], TypeTree, Option[Term]) =
264-
(ddef.name.toString, ddef.typeParams, ddef.paramss, ddef.tpt, optional(ddef.rhs))
267+
(ddef.name.toString, ddef.typeParams, ddef.termParamss, ddef.tpt, optional(ddef.rhs))
265268
end DefDef
266269

267270
given DefDefMethods: DefDefMethods with
268271
extension (self: DefDef)
269-
def typeParams: List[TypeDef] = self.tparams
270-
def paramss: List[List[ValDef]] = self.vparamss
272+
def typeParams: List[TypeDef] = self.leadingTypeParams // TODO: adapt to multiple type parameter clauses
273+
def paramss: List[List[ValDef]] = self.termParamss
271274
def returnTpt: TypeTree = self.tpt
272275
def rhs: Option[Term] = optional(self.rhs)
273276
end extension
@@ -380,7 +383,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
380383
}
381384
val closureTpe = Types.MethodType(mtpe.paramNames, mtpe.paramInfos, closureResType)
382385
val closureMethod = dotc.core.Symbols.newSymbol(owner, nme.ANON_FUN, Synthetic | Method, closureTpe)
383-
tpd.Closure(closureMethod, tss => new tpd.TreeOps(self).appliedToArgs(tss.head).etaExpand(closureMethod))
386+
tpd.Closure(closureMethod, tss => new tpd.TreeOps(self).appliedToTermArgs(tss.head).etaExpand(closureMethod))
384387
case _ => self
385388
}
386389

compiler/src-non-bootstrapped/scala/quoted/runtime/impl/QuotesImpl.scala

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
6060

6161
/** Convert this to an `quoted.Expr[X]` if this expression is a valid expression of type `X` or throws */
6262
def asExprOf(using scala.quoted.Type[X]): scala.quoted.Expr[X] = {
63-
if isExprOf[X] then
63+
if self.isExprOf[X] then
6464
self.asInstanceOf[scala.quoted.Expr[X]]
6565
else
6666
throw Exception(
@@ -255,17 +255,20 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
255255

256256
object DefDef extends DefDefModule:
257257
def apply(symbol: Symbol, rhsFn: List[TypeRepr] => List[List[Term]] => Option[Term]): DefDef =
258-
withDefaultPos(tpd.polyDefDef(symbol.asTerm, tparams => vparamss => yCheckedOwners(rhsFn(tparams)(vparamss), symbol).getOrElse(tpd.EmptyTree)))
258+
withDefaultPos(tpd.DefDef(symbol.asTerm, prefss => {
259+
val (tparams, vparamss) = tpd.splitArgs(prefss)
260+
yCheckedOwners(rhsFn(tparams.map(_.tpe))(vparamss), symbol).getOrElse(tpd.EmptyTree)
261+
}))
259262
def copy(original: Tree)(name: String, typeParams: List[TypeDef], paramss: List[List[ValDef]], tpt: TypeTree, rhs: Option[Term]): DefDef =
260-
tpd.cpy.DefDef(original)(name.toTermName, typeParams, paramss, tpt, yCheckedOwners(rhs, original.symbol).getOrElse(tpd.EmptyTree))
263+
tpd.cpy.DefDef(original)(name.toTermName, tpd.joinParams(typeParams, paramss), tpt, yCheckedOwners(rhs, original.symbol).getOrElse(tpd.EmptyTree))
261264
def unapply(ddef: DefDef): (String, List[TypeDef], List[List[ValDef]], TypeTree, Option[Term]) =
262-
(ddef.name.toString, ddef.typeParams, ddef.paramss, ddef.tpt, optional(ddef.rhs))
265+
(ddef.name.toString, ddef.typeParams, ddef.termParamss, ddef.tpt, optional(ddef.rhs))
263266
end DefDef
264267

265268
given DefDefMethods: DefDefMethods with
266269
extension (self: DefDef)
267-
def typeParams: List[TypeDef] = self.tparams
268-
def paramss: List[List[ValDef]] = self.vparamss
270+
def typeParams: List[TypeDef] = self.leadingTypeParams // TODO: adapt to multiple type parameter clauses
271+
def paramss: List[List[ValDef]] = self.termParamss
269272
def returnTpt: TypeTree = self.tpt
270273
def rhs: Option[Term] = optional(self.rhs)
271274
end extension
@@ -378,7 +381,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
378381
}
379382
val closureTpe = Types.MethodType(mtpe.paramNames, mtpe.paramInfos, closureResType)
380383
val closureMethod = dotc.core.Symbols.newSymbol(owner, nme.ANON_FUN, Synthetic | Method, closureTpe)
381-
tpd.Closure(closureMethod, tss => new tpd.TreeOps(self).appliedToArgs(tss.head).etaExpand(closureMethod))
384+
tpd.Closure(closureMethod, tss => new tpd.TreeOps(self).appliedToTermArgs(tss.head).etaExpand(closureMethod))
382385
case _ => self
383386
}
384387

@@ -2653,6 +2656,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
26532656
def startColumn: Int = self.startColumn
26542657
def endColumn: Int = self.endColumn
26552658
def sourceCode: Option[String] =
2659+
// TODO detect when we do not have a source and return None
26562660
Some(new String(self.source.content(), self.start, self.end - self.start))
26572661
end extension
26582662
end PositionMethods
@@ -2667,6 +2671,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
26672671
extension (self: SourceFile)
26682672
def jpath: java.nio.file.Path = self.file.jpath
26692673
def content: Option[String] =
2674+
// TODO detect when we do not have a source and return None
26702675
Some(new String(self.content()))
26712676
end extension
26722677
end SourceFileMethods
@@ -2863,8 +2868,11 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
28632868
if pat1.isType then matcher.termMatch(scrutinee.asInstanceOf[matcher.qctx.reflect.Term], pat1.asInstanceOf[matcher.qctx.reflect.Term])
28642869
else matcher.termMatch(scrutinee.asInstanceOf[matcher.qctx.reflect.Term], pat1.asInstanceOf[matcher.qctx.reflect.Term])
28652870

2871+
// val matchings = matcher.termMatch(scrutinee, pattern)
28662872
if typeHoles.isEmpty then matchings
28672873
else {
2874+
// After matching and doing all subtype checks, we have to approximate all the type bindings
2875+
// that we have found, seal them in a quoted.Type and add them to the result
28682876
def typeHoleApproximation(sym: Symbol) =
28692877
ctx1.gadt.approximation(sym, !sym.hasAnnotation(dotc.core.Symbols.defn.QuotedRuntimePatterns_fromAboveAnnot)).asInstanceOf[qctx1.reflect.TypeRepr].asType
28702878
matchings.map { tup =>

compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
181181

182182
def rewire(stat: Tree) = thisMap.transform(stat).changeOwner(claszSymbol.primaryConstructor, clInitSymbol)
183183

184-
val callConstructor = New(claszSymbol.typeRef).select(claszSymbol.primaryConstructor).appliedToArgs(Nil)
184+
val callConstructor = New(claszSymbol.typeRef).select(claszSymbol.primaryConstructor).appliedToTermArgs(Nil)
185185
val assignModuleField = Assign(ref(moduleField), callConstructor)
186186
val remainingConstrStatsSubst = remainingConstrStats.map(rewire)
187187
val clinit = clinits match {
@@ -667,7 +667,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
667667
val enclosingClass = origSym.owner.asClass
668668
new TreeTypeMap(
669669
typeMap = _.substThis(enclosingClass, selfParamRef.symbol.termRef)
670-
.subst(dd.vparamss.head.map(_.symbol), regularParamRefs.map(_.symbol.termRef)),
670+
.subst(dd.termParamss.head.map(_.symbol), regularParamRefs.map(_.symbol.termRef)),
671671
treeMap = {
672672
case tree: This if tree.symbol == enclosingClass => selfParamRef
673673
case tree => tree
@@ -714,7 +714,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
714714

715715
def genDefDef(dd: DefDef): Unit = {
716716
val rhs = dd.rhs
717-
val vparamss = dd.vparamss
717+
val vparamss = dd.termParamss
718718
// the only method whose implementation is not emitted: getClass()
719719
if (dd.symbol eq defn.Any_getClass) { return }
720720
assert(mnode == null, "GenBCode detected nested method.")

compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1035,7 +1035,7 @@ class JSCodeGen()(using genCtx: Context) {
10351035
private def genMethodWithCurrentLocalNameScope(dd: DefDef): Option[js.MethodDef] = {
10361036
implicit val pos = dd.span
10371037
val sym = dd.symbol
1038-
val vparamss = dd.vparamss
1038+
val vparamss = dd.termParamss
10391039
val rhs = dd.rhs
10401040

10411041
withScopedVars(

0 commit comments

Comments
 (0)