From 619730366ef9463e9f950658b3b55b934c9c8e06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Tue, 5 Dec 2023 10:04:29 +0100 Subject: [PATCH] Fix #414: Define the rest of the special Predef methods. --- .../main/scala/tastyquery/Definitions.scala | 55 ++++++++++++---- .../src/main/scala/tastyquery/Symbols.scala | 66 ++++++++++--------- .../scala/simple_trees/PredefMethods.scala | 15 +++++ 3 files changed, 93 insertions(+), 43 deletions(-) create mode 100644 test-sources/src/main/scala/simple_trees/PredefMethods.scala diff --git a/tasty-query/shared/src/main/scala/tastyquery/Definitions.scala b/tasty-query/shared/src/main/scala/tastyquery/Definitions.scala index 69917e5d..d26493ff 100644 --- a/tasty-query/shared/src/main/scala/tastyquery/Definitions.scala +++ b/tasty-query/shared/src/main/scala/tastyquery/Definitions.scala @@ -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 @@ -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. diff --git a/tasty-query/shared/src/main/scala/tastyquery/Symbols.scala b/tasty-query/shared/src/main/scala/tastyquery/Symbols.scala index e82b5f03..152672a3 100644 --- a/tasty-query/shared/src/main/scala/tastyquery/Symbols.scala +++ b/tasty-query/shared/src/main/scala/tastyquery/Symbols.scala @@ -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] = diff --git a/test-sources/src/main/scala/simple_trees/PredefMethods.scala b/test-sources/src/main/scala/simple_trees/PredefMethods.scala new file mode 100644 index 00000000..3c701f77 --- /dev/null +++ b/test-sources/src/main/scala/simple_trees/PredefMethods.scala @@ -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