Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #414: Define the rest of the special Predef methods. #418

Merged
merged 2 commits into from
Dec 6, 2023
Merged
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
54 changes: 42 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,49 @@ 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
)

// 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
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ object Traversers:
traverse(expr)
case Inlined(expr, caller, bindings) =>
traverse(expr)
traverse(caller)
traverse(bindings)
case _: ImportIdent | _: Ident | _: This | _: Literal =>
()
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