Skip to content

Commit

Permalink
Fix #414: Define the rest of the special Predef methods.
Browse files Browse the repository at this point in the history
  • Loading branch information
sjrd committed Dec 5, 2023
1 parent 06ffbf0 commit 6197303
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 43 deletions.
55 changes: 43 additions & 12 deletions tasty-query/shared/src/main/scala/tastyquery/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,15 @@ final class Definitions private[tastyquery] (ctx: Context, rootPackage: PackageS
owner: ClassSymbol,
name: UnsignedTermName,
tpe: TypeOrMethodic,
flags: FlagSet = EmptyFlagSet
flags: FlagSet = EmptyFlagSet,
termParamFlags: FlagSet = EmptyFlagSet
): TermSymbol =
val sym = TermSymbol
.create(name, owner)
.withFlags(Method | flags, privateWithin = None)
.withDeclaredType(tpe)
.setAnnotations(Nil)
.autoFillParamSymss()
.autoFillParamSymss(termParamFlags)
sym.paramSymss.foreach(_.merge.foreach(_.setAnnotations(Nil)))
sym.checkCompleted()
sym
Expand Down Expand Up @@ -295,20 +296,50 @@ final class Definitions private[tastyquery] (ctx: Context, rootPackage: PackageS
* cannot read other files while loading one file.
*/
private[tastyquery] def createPredefMagicMethods(cls: ClassSymbol): Unit =
val nnMethodType = PolyType(List(typeName("T")))(
_ => List(NothingAnyBounds),
pt => MethodType(List(termName("x")))(_ => List(pt.paramRefs(0)), mt => AndType(mt.paramRefs(0), pt.paramRefs(0)))
val TNameList = List(typeName("T"))
val xNameList = List(termName("x"))
val yNameList = List(termName("y"))

val NothingAnyBoundsList = List(NothingAnyBounds)

// assert
val assertMethodType1 = MethodType(List(termName("assertion")), List(BooleanType), UnitType)
val assertMethodType2 =
MethodType(List(termName("assertion"), termName("message")), List(BooleanType, ByNameType(AnyType)), UnitType)
for assertMethodType <- List(assertMethodType1, assertMethodType2) do
createSpecialMethod(
cls,
termName("assert"),
assertMethodType,
Transparent | Inline | Final,
termParamFlags = Inline
)
end for // scalafmt: don't destroy my formatting, please

// valueOf
val valueOfMethodType = PolyType(TNameList)(_ => NothingAnyBoundsList, pt => pt.paramRefs(0))
createSpecialMethod(cls, termName("valueOf"), valueOfMethodType, Inline | Final)

// summon
val summonMethodType = PolyType(TNameList)(
_ => NothingAnyBoundsList,
pt => MethodType(xNameList)(_ => pt.paramRefs, mt => mt.paramRefs(0))
)
createSpecialMethod(cls, termName("summon"), summonMethodType, Transparent | Inline | Final, termParamFlags = Given)

// nn
val nnMethodType = PolyType(TNameList)(
_ => NothingAnyBoundsList,
pt => MethodType(xNameList)(_ => List(pt.paramRefs(0)), mt => AndType(mt.paramRefs(0), pt.paramRefs(0)))
)
createSpecialMethod(cls, termName("nn"), nnMethodType, Inline | Final | Extension)

// eq and ne
val anyRefOrNull = OrType(AnyRefType, NullType)
val eqNeMethodType = MethodType(
List(termName("x")),
List(anyRefOrNull),
MethodType(List(termName("y")), List(anyRefOrNull), BooleanType)
)
createSpecialMethod(cls, termName("eq"), eqNeMethodType, Inline | Final | Extension)
createSpecialMethod(cls, termName("ne"), eqNeMethodType, Inline | Final | Extension)
val eqNeMethodType =
MethodType(xNameList, List(anyRefOrNull), MethodType(yNameList, List(anyRefOrNull), BooleanType))
createSpecialMethod(cls, termName("eq"), eqNeMethodType, Inline | Final | Extension, termParamFlags = Inline)
createSpecialMethod(cls, termName("ne"), eqNeMethodType, Inline | Final | Extension, termParamFlags = Inline)
end createPredefMagicMethods

/** Creates one of the `ContextFunctionNClass` classes.
Expand Down
66 changes: 35 additions & 31 deletions tasty-query/shared/src/main/scala/tastyquery/Symbols.scala
Original file line number Diff line number Diff line change
Expand Up @@ -477,38 +477,42 @@ object Symbols {
this

private[tastyquery] final def autoFillParamSymss(): this.type =
setParamSymss(autoComputeParamSymss(declaredType))

private def autoComputeParamSymss(tpe: TypeOrMethodic): List[ParamSymbolsClause] = tpe match
case tpe: MethodType =>
/* For term params, we do not instantiate the paramTypes.
* We only use autoFillParamSymss for Java definitions, which do not
* support term param references at all, and from Definitions, which
* does not use that capability in the term param bounds.
*/
val paramSyms = tpe.paramNames.lazyZip(tpe.paramTypes).map { (name, paramType) =>
TermSymbol
.createNotDeclaration(name, this)
.withFlags(EmptyFlagSet, privateWithin = None)
.withDeclaredType(paramType)
}
Left(paramSyms) :: autoComputeParamSymss(tpe.resultType)
setParamSymss(autoComputeParamSymss(declaredType, termParamFlags = EmptyFlagSet))

private[tastyquery] final def autoFillParamSymss(termParamFlags: FlagSet): this.type =
setParamSymss(autoComputeParamSymss(declaredType, termParamFlags))

private def autoComputeParamSymss(tpe: TypeOrMethodic, termParamFlags: FlagSet): List[ParamSymbolsClause] =
tpe match
case tpe: MethodType =>
/* For term params, we do not instantiate the paramTypes.
* We only use autoFillParamSymss for Java definitions, which do not
* support term param references at all, and from Definitions, which
* does not use that capability in the term param bounds.
*/
val paramSyms = tpe.paramNames.lazyZip(tpe.paramTypes).map { (name, paramType) =>
TermSymbol
.createNotDeclaration(name, this)
.withFlags(termParamFlags, privateWithin = None)
.withDeclaredType(paramType)
}
Left(paramSyms) :: autoComputeParamSymss(tpe.resultType, termParamFlags)

case tpe: PolyType =>
val paramSyms = tpe.paramNames.map { name =>
LocalTypeParamSymbol
.create(name, this)
.withFlags(EmptyFlagSet, privateWithin = None)
}
val paramSymRefs = paramSyms.map(_.localRef)
def subst(t: TypeOrMethodic): t.ThisTypeMappableType =
Substituters.substLocalBoundParams(t, tpe, paramSymRefs)
for (paramSym, paramTypeBounds) <- paramSyms.lazyZip(tpe.paramTypeBounds) do
paramSym.setDeclaredBounds(paramTypeBounds.mapBounds(subst(_)))
Right(paramSyms) :: autoComputeParamSymss(subst(tpe.resultType))

case tpe: Type =>
Nil
case tpe: PolyType =>
val paramSyms = tpe.paramNames.map { name =>
LocalTypeParamSymbol
.create(name, this)
.withFlags(EmptyFlagSet, privateWithin = None)
}
val paramSymRefs = paramSyms.map(_.localRef)
def subst(t: TypeOrMethodic): t.ThisTypeMappableType =
Substituters.substLocalBoundParams(t, tpe, paramSymRefs)
for (paramSym, paramTypeBounds) <- paramSyms.lazyZip(tpe.paramTypeBounds) do
paramSym.setDeclaredBounds(paramTypeBounds.mapBounds(subst(_)))
Right(paramSyms) :: autoComputeParamSymss(subst(tpe.resultType), termParamFlags)

case tpe: Type =>
Nil
end autoComputeParamSymss

def paramSymss: List[ParamSymbolsClause] =
Expand Down
15 changes: 15 additions & 0 deletions test-sources/src/main/scala/simple_trees/PredefMethods.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package simple_trees

object PredefMethods:
def test(): Unit =
val x = valueOf[5]
assert(x == 5)

val obj: List[Int] | Null = List(1, 2)
assert(obj.nn.size == 2, "with message")
assert(Predef.eq(obj)(obj))
assert(Predef.ne(obj)(List(1, 2)))

println(summon[DummyImplicit])
end test
end PredefMethods

0 comments on commit 6197303

Please sign in to comment.