|
| 1 | +import scala.quoted.* |
| 2 | +import scala.tasty.inspector.* |
| 3 | + |
| 4 | +val experimentalDefinitionInLibrary = Set( |
| 5 | + |
| 6 | + // README |
| 7 | + // - Definitions should be grouped under a language feature or API |
| 8 | + // - API definitions that must be stabilized at the same time should be added in the same line |
| 9 | + // - Language definitions are assumed to be stabilized all at once unless stated otherwise |
| 10 | + |
| 11 | + |
| 12 | + //// New feature: Safe Exceptions |
| 13 | + // Can be stabilized when safe exeptions language feature is stabilized. |
| 14 | + "scala.CanThrow", |
| 15 | + "scala.unsafeExceptions", "scala.unsafeExceptions$", |
| 16 | + "scala.runtime.$throws$package$.$throws", |
| 17 | + |
| 18 | + //// New feature: Tupled Functions |
| 19 | + // Can be stabilized when language feature is stabilized. |
| 20 | + // Needs user feedback. |
| 21 | + // Needs generalization to polymorphic types (at least proof of concept that shows that that design is compatible). |
| 22 | + "scala.runtime.TupledFunctions", |
| 23 | + "scala.runtime.TupledFunctions$", |
| 24 | + "scala.util.TupledFunction", |
| 25 | + "scala.util.TupledFunction$", |
| 26 | + |
| 27 | + //// New feature: main annotation generalization |
| 28 | + // Can be stabilized when language feature is stabilized. |
| 29 | + // Needs user feedback. |
| 30 | + // Should argGetter/varargGetter be simplified? |
| 31 | + // Should we have better support for main annotation macros? |
| 32 | + "scala.annotation.MainAnnotation", |
| 33 | + "scala.annotation.MainAnnotation$", |
| 34 | + |
| 35 | + //// New APIs: compiletime.ops |
| 36 | + // Can be stabilized in 3.3.0 or later. |
| 37 | + // Needs user feedback |
| 38 | + "scala.compiletime.ops.any$.IsConst", |
| 39 | + "scala.compiletime.ops.any$.ToString", |
| 40 | + "scala.compiletime.ops.double", "scala.compiletime.ops.double$", |
| 41 | + "scala.compiletime.ops.float", |
| 42 | + "scala.compiletime.ops.float$", |
| 43 | + "scala.compiletime.ops.int$.NumberOfLeadingZeros", |
| 44 | + "scala.compiletime.ops.int$.ToDouble", |
| 45 | + "scala.compiletime.ops.int$.ToFloat", |
| 46 | + "scala.compiletime.ops.int$.ToLong", |
| 47 | + "scala.compiletime.ops.long", "scala.compiletime.ops.long$", |
| 48 | + "scala.compiletime.ops.string$.Length", |
| 49 | + "scala.compiletime.ops.string$.Matches", |
| 50 | + "scala.compiletime.ops.string$.Substring", |
| 51 | + |
| 52 | + //// New APIs: Mirror |
| 53 | + // Can be stabilized in 3.2.0 or later. |
| 54 | + "scala.deriving.Mirror$.fromTuple", // Probably for 3.2.0 |
| 55 | + "scala.deriving.Mirror$.fromProductTyped", // This API is a bit convoluted. We may need some more feedback before we can stabilize it. |
| 56 | + |
| 57 | + //// New APIs: Tuples |
| 58 | + // Should be stabilized in 3.2.0. |
| 59 | + "scala.Tuple.:*", "scala.Tuple$.Append", "scala.runtime.Tuples$.append", |
| 60 | + "scala.NonEmptyTuple.init", "scala.Tuple$.Init", "scala.runtime.Tuples$.init", |
| 61 | + "scala.Tuple$.Last", "scala.NonEmptyTuple.last", "scala.runtime.Tuples$.last", |
| 62 | + |
| 63 | + //// New APIs: Quotes |
| 64 | + // Should be stabilized in 3.2.0. |
| 65 | + "scala.quoted.Quotes.reflectModule.AppliedTypeModule.apply", |
| 66 | + "scala.quoted.Quotes.reflectModule.SymbolMethods.asQuotes", |
| 67 | + "scala.quoted.Quotes.reflectModule.SymbolMethods.termRef", |
| 68 | + "scala.quoted.Quotes.reflectModule.SymbolMethods.typeRef", |
| 69 | + "scala.quoted.Quotes.reflectModule.TypeReprMethods.substituteTypes", |
| 70 | + "scala.quoted.Quotes.reflectModule.TypeReprMethods.typeArgs", |
| 71 | + "scala.quoted.Quotes.reflectModule.TypeTreeModule.ref", |
| 72 | + // Can be stabilized in 3.2.0 (unsure) or later |
| 73 | + "scala.quoted.Quotes.reflectModule.CompilationInfoModule.XmacroSettings", |
| 74 | + // Cant be stabilized yet. |
| 75 | + // Need newClass variant that can add constructor parameters. |
| 76 | + // Need experimental annotation macros to check that design works. |
| 77 | + "scala.quoted.Quotes.reflectModule.ClassDefModule.apply", |
| 78 | + "scala.quoted.Quotes.reflectModule.SymbolModule.newClass", |
| 79 | +) |
| 80 | + |
| 81 | + |
| 82 | +@main def Test = { |
| 83 | + val inspector = new Inspector { |
| 84 | + def inspect(using Quotes)(tastys: List[Tasty[quotes.type]]): Unit = { |
| 85 | + import quotes.reflect.* |
| 86 | + val experimentalAnnot = Symbol.requiredClass("scala.annotation.experimental") |
| 87 | + object AccumulateExperimentalDefs extends TreeAccumulator[Set[Symbol]]: |
| 88 | + def foldTree(expDefs: Set[Symbol], tree: Tree)(owner: Symbol): Set[Symbol] = |
| 89 | + tree match |
| 90 | + case tree: Definition if tree.symbol.hasAnnotation(experimentalAnnot) => foldOverTree(expDefs + tree.symbol, tree)(owner) |
| 91 | + case _ => foldOverTree(expDefs, tree)(owner) |
| 92 | + |
| 93 | + val experimentalDefinitionsSyms = tastys.foldLeft(Set.empty[Symbol]) { (acc, tasty) => |
| 94 | + AccumulateExperimentalDefs.foldTree(acc, tasty.ast)(Symbol.spliceOwner) |
| 95 | + } |
| 96 | + val experimentalDefinitions = experimentalDefinitionsSyms.map(_.fullName) |
| 97 | + val missingFromList = experimentalDefinitions -- experimentalDefinitionInLibrary |
| 98 | + val missingInLibrary = experimentalDefinitionInLibrary -- experimentalDefinitions |
| 99 | + assert(missingFromList.isEmpty, |
| 100 | + s"""Failed @experimental definitions check |
| 101 | + | |
| 102 | + |Found @experimental definition in library not listed: |
| 103 | + |${missingFromList.toSeq.sorted.mkString("\n")} |
| 104 | + | |
| 105 | + |If added new experimental defintions to the library, add them to the list in tests/run-custom-args/tasty-inspector/stdlibExperimentalDefinitions.scala |
| 106 | + | |
| 107 | + |Test only: sbt "scala3-bootstrapped/testCompilation tests/run-custom-args/tasty-inspector/stdlibExperimentalDefinitions.scala" |
| 108 | + |""".stripMargin |
| 109 | + ) |
| 110 | + assert(missingInLibrary.isEmpty, |
| 111 | + s"""Failed @experimental definitions check |
| 112 | + | |
| 113 | + |Listed @experimental definition was not found in the library |
| 114 | + |${missingInLibrary.toSeq.sorted.mkString("\n")} |
| 115 | + | |
| 116 | + |If experimental definition was removed or stabilized, remove from the list in tests/run-custom-args/tasty-inspector/stdlibExperimentalDefinitions.scala |
| 117 | + | |
| 118 | + |Test only: sbt "scala3-bootstrapped/testCompilation tests/run-custom-args/tasty-inspector/stdlibExperimentalDefinitions.scala" |
| 119 | + |""".stripMargin |
| 120 | + ) |
| 121 | + } |
| 122 | + } |
| 123 | + |
| 124 | + // Artefact of the current test infrastructure |
| 125 | + // TODO improve infrastructure to avoid needing this code on each test |
| 126 | + val libJarClasspath = dotty.tools.dotc.util.ClasspathFromClassloader(this.getClass.getClassLoader).split(java.io.File.pathSeparator).find(x => x.contains("scala3-library-bootstrapped") && x.endsWith(".jar")).get |
| 127 | + |
| 128 | + TastyInspector.inspectTastyFilesInJar(libJarClasspath)(inspector) |
| 129 | +} |
0 commit comments