diff --git a/.github/Dockerfile b/.github/Dockerfile index d56ec6a59f2d..59d46fd169d9 100644 --- a/.github/Dockerfile +++ b/.github/Dockerfile @@ -15,7 +15,8 @@ RUN apt-get update && \ openjdk-17-jdk-headless \ openjdk-21-jdk-headless && \ (curl -fsSL https://deb.nodesource.com/setup_18.x | bash -) && \ - apt-get install -y nodejs + apt-get install -y nodejs && \ + apt-get install -y zip unzip # Install sbt diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 97c4a9d75277..9cd0f0b3899c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -48,7 +48,7 @@ jobs: test_non_bootstrapped: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2023-11-07 + image: lampepfl/dotty:2024-10-18 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -100,7 +100,7 @@ jobs: test: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2023-11-07 + image: lampepfl/dotty:2024-10-18 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -175,7 +175,7 @@ jobs: uses: actions/checkout@v4 - name: Test - run: sbt ";scala3-bootstrapped/compile; scala3-bootstrapped/testCompilation" + run: sbt ";scala3-bootstrapped/compile; scala3-bootstrapped/testCompilation; scala3-presentation-compiler-bootstrapped/test; scala3-language-server/test" shell: cmd - name: build binary @@ -230,7 +230,7 @@ jobs: name: MiMa runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2023-11-07 + image: lampepfl/dotty:2024-10-18 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -276,7 +276,7 @@ jobs: community_build_a: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2023-11-07 + image: lampepfl/dotty:2024-10-18 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -330,7 +330,7 @@ jobs: community_build_b: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2023-11-07 + image: lampepfl/dotty:2024-10-18 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -384,7 +384,7 @@ jobs: community_build_c: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2023-11-07 + image: lampepfl/dotty:2024-10-18 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -438,7 +438,7 @@ jobs: test_sbt: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2023-11-07 + image: lampepfl/dotty:2024-10-18 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -483,7 +483,7 @@ jobs: test_java8: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2023-11-07 + image: lampepfl/dotty:2024-10-18 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -539,7 +539,7 @@ jobs: publish_nightly: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2023-11-07 + image: lampepfl/dotty:2024-10-18 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -580,6 +580,14 @@ jobs: echo "This build version: $ver" echo "THISBUILD_VERSION=$ver" >> $GITHUB_ENV + - name: Check is version matching pattern + shell: bash + run: | + if ! grep -Eo "3\.[0-9]+\.[0-9]+-RC[0-9]+-bin-[0-9]{8}-[a-zA-Z0-9]{7}-NIGHTLY" <<< "${{ env.THISBUILD_VERSION }}"; then + echo "Version used by compiler to publish nightly release does not match expected pattern" + exit 1 + fi + - name: Check whether not yet published id: not_yet_published continue-on-error: true @@ -594,7 +602,7 @@ jobs: nightly_documentation: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2023-11-07 + image: lampepfl/dotty:2024-10-18 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -648,7 +656,7 @@ jobs: contents: write # for actions/create-release to create a release runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2023-11-07 + image: lampepfl/dotty:2024-10-18 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -685,6 +693,16 @@ jobs: - name: Add SBT proxy repositories run: cp -vf .github/workflows/repositories /root/.sbt/ ; true + - name: Check compiler version + shell: bash + run : | + version=$(./project/scripts/sbt "print scala3-compiler-bootstrapped/version" | tail -n1) + echo "This build version: ${version}" + if [ "${version}" != "${{ env.RELEASE_TAG }}" ]; then + echo "Compiler version for this build '${version}', does not match tag: ${{ env.RELEASE_TAG }}" + exit 1 + fi + - name: Prepare Release run: | ./project/scripts/sbt dist/packArchive @@ -740,7 +758,7 @@ jobs: open_issue_on_failure: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2023-11-07 + image: lampepfl/dotty:2024-10-18 needs: [nightly_documentation, test_windows_full] # The `failure()` expression is true iff at least one of the dependencies # of this job (including transitive dependencies) has failed. diff --git a/community-build/community-projects/scala-collection-compat b/community-build/community-projects/scala-collection-compat index b39b4b64732d..c9d3a8b160a3 160000 --- a/community-build/community-projects/scala-collection-compat +++ b/community-build/community-projects/scala-collection-compat @@ -1 +1 @@ -Subproject commit b39b4b64732d9dd5e0f065e4180f656237ac4444 +Subproject commit c9d3a8b160a35c9915816dd84a1063e18db4a84a diff --git a/community-build/community-projects/stdLib213 b/community-build/community-projects/stdLib213 index fcc67cd56c67..b6f70d2347f2 160000 --- a/community-build/community-projects/stdLib213 +++ b/community-build/community-projects/stdLib213 @@ -1 +1 @@ -Subproject commit fcc67cd56c67851bf31019ec25ccb09d08b9561b +Subproject commit b6f70d2347f2857695e5c0fe544b0f921544b02a diff --git a/community-build/src/scala/dotty/communitybuild/projects.scala b/community-build/src/scala/dotty/communitybuild/projects.scala index a425f38b117e..0fed6aa783b4 100644 --- a/community-build/src/scala/dotty/communitybuild/projects.scala +++ b/community-build/src/scala/dotty/communitybuild/projects.scala @@ -492,8 +492,8 @@ object projects: lazy val scalaCollectionCompat = SbtCommunityProject( project = "scala-collection-compat", - sbtTestCommand = "compat30/test", - sbtPublishCommand = "compat30/publishLocal", + sbtTestCommand = "compat3/test", + sbtPublishCommand = "compat3/publishLocal", ) lazy val scalaJava8Compat = SbtCommunityProject( diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 6863618bacfc..f2bb972726d8 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -19,6 +19,7 @@ import printing.Formatting.hl import config.Printers import scala.annotation.internal.sharable +import dotty.tools.dotc.util.SrcPos object desugar { import untpd.* @@ -934,8 +935,8 @@ object desugar { paramss match case rightParam :: paramss1 => // `rightParam` must have a single parameter and without `given` flag - def badRightAssoc(problem: String) = - report.error(em"right-associative extension method $problem", mdef.srcPos) + def badRightAssoc(problem: String, pos: SrcPos) = + report.error(em"right-associative extension method $problem", pos) extParamss ++ mdef.paramss rightParam match @@ -951,11 +952,23 @@ object desugar { // // If you change the names of the clauses below, also change them in right-associative-extension-methods.md val (leftTyParamsAndLeadingUsing, leftParamAndTrailingUsing) = extParamss.span(isUsingOrTypeParamClause) + + val names = (for ps <- mdef.paramss; p <- ps yield p.name).toSet[Name] + + val tt = new untpd.UntypedTreeTraverser: + def traverse(tree: Tree)(using Context): Unit = tree match + case tree: Ident if names.contains(tree.name) => + badRightAssoc(s"cannot have a forward reference to ${tree.name}", tree.srcPos) + case _ => traverseChildren(tree) + + for ts <- leftParamAndTrailingUsing; t <- ts do + tt.traverse(t) + leftTyParamsAndLeadingUsing ::: rightTyParams ::: rightParam :: leftParamAndTrailingUsing ::: paramss1 else - badRightAssoc("cannot start with using clause") + badRightAssoc("cannot start with using clause", mdef.srcPos) case _ => - badRightAssoc("must start with a single parameter") + badRightAssoc("must start with a single parameter", mdef.srcPos) case _ => // no value parameters, so not an infix operator. extParamss ++ mdef.paramss diff --git a/compiler/src/dotty/tools/dotc/config/Properties.scala b/compiler/src/dotty/tools/dotc/config/Properties.scala index 1e9cc82112af..4ea058d2cca8 100644 --- a/compiler/src/dotty/tools/dotc/config/Properties.scala +++ b/compiler/src/dotty/tools/dotc/config/Properties.scala @@ -10,7 +10,7 @@ import java.io.IOException import java.util.jar.Attributes.{ Name => AttributeName } import java.nio.charset.StandardCharsets -/** Loads `library.properties` from the jar. */ +/** Loads `compiler.properties` from the jar. */ object Properties extends PropertiesTrait { protected def propCategory: String = "compiler" protected def pickJarBasedOn: Class[PropertiesTrait] = classOf[PropertiesTrait] diff --git a/compiler/src/dotty/tools/dotc/core/Phases.scala b/compiler/src/dotty/tools/dotc/core/Phases.scala index e3e28139a150..5fd2e276adec 100644 --- a/compiler/src/dotty/tools/dotc/core/Phases.scala +++ b/compiler/src/dotty/tools/dotc/core/Phases.scala @@ -333,15 +333,20 @@ object Phases { for unit <- units do given unitCtx: Context = runCtx.fresh.setPhase(this.start).setCompilationUnit(unit).withRootImports if ctx.run.enterUnit(unit) then - try run - catch case ex: Throwable if !ctx.run.enrichedErrorMessage => - println(ctx.run.enrichErrorMessage(s"unhandled exception while running $phaseName on $unit")) - throw ex + try + run + buf += unitCtx.compilationUnit + catch + case _: CompilationUnit.SuspendException => // this unit will be run again in `Run#compileSuspendedUnits` + case ex: Throwable if !ctx.run.enrichedErrorMessage => + println(ctx.run.enrichErrorMessage(s"unhandled exception while running $phaseName on $unit")) + throw ex finally ctx.run.advanceUnit() - buf += unitCtx.compilationUnit end if end for - buf.result() + val res = buf.result() + ctx.run.nn.checkSuspendedUnits(res) + res end runOn /** Convert a compilation unit's tree to a string; can be overridden */ diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 51e690e9a899..0123f023472f 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -140,6 +140,9 @@ object Types extends TypeUtils { !t.isPermanentlyInstantiated || test(t.permanentInst, theAcc) case t: LazyRef => !t.completed || test(t.ref, theAcc) + case t: ParamRef => + (t: Type).mightBeProvisional = false // break cycles + test(t.underlying, theAcc) case _ => (if theAcc != null then theAcc else ProAcc()).foldOver(false, t) end if diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala index b9edb147be9d..6f0d88c9a71e 100644 --- a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala @@ -363,8 +363,8 @@ object JavaParsers { def annotation(): Option[Tree] = { def classOrId(): Tree = val id = qualId() - if in.lookaheadToken == CLASS then - in.nextToken() + if in.token == DOT && in.lookaheadToken == CLASS then + accept(DOT) accept(CLASS) TypeApply( Select( diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 6267461185c2..2fa0745ab98e 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -429,6 +429,14 @@ object Parsers { finally inEnum = saved } + private var inMatchPattern = false + private def withinMatchPattern[T](body: => T): T = { + val saved = inMatchPattern + inMatchPattern = true + try body + finally inMatchPattern = saved + } + private var staged = StageKind.None def withinStaged[T](kind: StageKind)(op: => T): T = { val saved = staged @@ -1857,7 +1865,7 @@ object Parsers { if isSimpleLiteral then SingletonTypeTree(simpleLiteral()) else if in.token == USCORE then - if ctx.settings.YkindProjector.value == "underscores" then + if ctx.settings.YkindProjector.value == "underscores" && !inMatchPattern then val start = in.skipToken() Ident(tpnme.USCOREkw).withSpan(Span(start, in.lastOffset, start)) else @@ -2883,7 +2891,7 @@ object Parsers { def caseClause(exprOnly: Boolean = false): CaseDef = atSpan(in.offset) { val (pat, grd) = inSepRegion(InCase) { accept(CASE) - (pattern(), guard()) + (withinMatchPattern(pattern()), guard()) } CaseDef(pat, grd, atSpan(accept(ARROW)) { if exprOnly then @@ -2907,7 +2915,7 @@ object Parsers { val start = in.skipToken() Ident(tpnme.WILDCARD).withSpan(Span(start, in.lastOffset, start)) case _ => - rejectWildcardType(infixType()) + withinMatchPattern(rejectWildcardType(infixType())) } } CaseDef(pat, EmptyTree, atSpan(accept(ARROW)) { diff --git a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala index bfeb426d6f9a..ff0aac879752 100644 --- a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala +++ b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala @@ -214,6 +214,8 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe case UnusedSymbolID // errorNumber: 198 case TailrecNestedCallID //errorNumber: 199 - unused in LTS case FinalLocalDefID // errorNumber: 200 + case NonNamedArgumentInJavaAnnotationID // errorNumber: 201 - unused in LTS + case QuotedTypeMissingID // errorNumber: 202 def errorNumber = ordinal - 1 diff --git a/compiler/src/dotty/tools/dotc/reporting/MessageKind.scala b/compiler/src/dotty/tools/dotc/reporting/MessageKind.scala index 10ad4f83d93d..bb02a08d2e46 100644 --- a/compiler/src/dotty/tools/dotc/reporting/MessageKind.scala +++ b/compiler/src/dotty/tools/dotc/reporting/MessageKind.scala @@ -22,6 +22,7 @@ enum MessageKind: case Compatibility case PotentialIssue case UnusedSymbol + case Staging /** Human readable message that will end up being shown to the user. * NOTE: This is only used in the situation where you have multiple words @@ -39,5 +40,6 @@ enum MessageKind: case MatchCaseUnreachable => "Match case Unreachable" case PotentialIssue => "Potential Issue" case UnusedSymbol => "Unused Symbol" + case Staging => "Staging Issue" case kind => kind.toString end MessageKind diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index b8df9c466a2b..74bdb0bb52dc 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -107,6 +107,9 @@ end CyclicMsg abstract class ReferenceMsg(errorId: ErrorMessageID)(using Context) extends Message(errorId): def kind = MessageKind.Reference +abstract class StagingMessage(errorId: ErrorMessageID)(using Context) extends Message(errorId): + override final def kind = MessageKind.Staging + abstract class EmptyCatchOrFinallyBlock(tryBody: untpd.Tree, errNo: ErrorMessageID)(using Context) extends SyntaxMsg(errNo) { def explain(using Context) = { @@ -1797,13 +1800,25 @@ class SuperCallsNotAllowedInlineable(symbol: Symbol)(using Context) } class NotAPath(tp: Type, usage: String)(using Context) extends TypeMsg(NotAPathID): - def msg(using Context) = i"$tp is not a valid $usage, since it is not an immutable path" + def msg(using Context) = i"$tp is not a valid $usage, since it is not an immutable path" + inlineParamAddendum def explain(using Context) = i"""An immutable path is | - a reference to an immutable value, or | - a reference to `this`, or | - a selection of an immutable path with an immutable value.""" + def inlineParamAddendum(using Context) = + val sym = tp.termSymbol + if sym.isAllOf(Flags.InlineParam) then + i""" + |Inline parameters are not considered immutable paths and cannot be used as + |singleton types. + | + |Hint: Removing the `inline` qualifier from the `${sym.name}` parameter + |may help resolve this issue.""" + else "" + + class WrongNumberOfParameters(tree: untpd.Tree, foundCount: Int, pt: Type, expectedCount: Int)(using Context) extends SyntaxMsg(WrongNumberOfParametersID) { def msg(using Context) = s"Wrong number of parameters, expected: $expectedCount" @@ -3153,3 +3168,20 @@ object UnusedSymbol { def privateMembers(using Context): UnusedSymbol = new UnusedSymbol(i"unused private member") def patVars(using Context): UnusedSymbol = new UnusedSymbol(i"unused pattern variable") } + +final class QuotedTypeMissing(tpe: Type)(using Context) extends StagingMessage(QuotedTypeMissingID): + + private def witness = defn.QuotedTypeClass.typeRef.appliedTo(tpe) + + override protected def msg(using Context): String = + i"Reference to $tpe within quotes requires a given ${witness} in scope" + + override protected def explain(using Context): String = + i"""Referencing `$tpe` inside a quoted expression requires a `${witness}` to be in scope. + |Since Scala is subject to erasure at runtime, the type information will be missing during the execution of the code. + |`${witness}` is therefore needed to carry `$tpe`'s type information into the quoted code. + |Without an implicit `${witness}`, the type `$tpe` cannot be properly referenced within the expression. + |To resolve this, ensure that a `${witness}` is available, either through a context-bound or explicitly. + |""" + +end QuotedTypeMissing diff --git a/compiler/src/dotty/tools/dotc/staging/HealType.scala b/compiler/src/dotty/tools/dotc/staging/HealType.scala index 5a26803c8137..a73f884fbac9 100644 --- a/compiler/src/dotty/tools/dotc/staging/HealType.scala +++ b/compiler/src/dotty/tools/dotc/staging/HealType.scala @@ -1,17 +1,19 @@ package dotty.tools.dotc package staging -import dotty.tools.dotc.core.Contexts.* -import dotty.tools.dotc.core.Decorators.* -import dotty.tools.dotc.core.Flags.* -import dotty.tools.dotc.core.StdNames.* -import dotty.tools.dotc.core.Symbols.* -import dotty.tools.dotc.core.Types.* -import dotty.tools.dotc.staging.StagingLevel.* -import dotty.tools.dotc.staging.QuoteTypeTags.* +import reporting.* -import dotty.tools.dotc.typer.Implicits.SearchFailureType -import dotty.tools.dotc.util.SrcPos +import core.Contexts.* +import core.Decorators.* +import core.Flags.* +import core.StdNames.* +import core.Symbols.* +import core.Types.* +import StagingLevel.* +import QuoteTypeTags.* + +import typer.Implicits.SearchFailureType +import util.SrcPos class HealType(pos: SrcPos)(using Context) extends TypeMap { @@ -98,9 +100,7 @@ class HealType(pos: SrcPos)(using Context) extends TypeMap { pos) tp case _ => - report.error(em"""Reference to $tp within quotes requires a given $reqType in scope. - | - |""", pos) + report.error(QuotedTypeMissing(tp), pos) tp } diff --git a/compiler/src/dotty/tools/dotc/transform/ArrayApply.scala b/compiler/src/dotty/tools/dotc/transform/ArrayApply.scala index 98ca8f2e2b5b..1a6ec307e289 100644 --- a/compiler/src/dotty/tools/dotc/transform/ArrayApply.scala +++ b/compiler/src/dotty/tools/dotc/transform/ArrayApply.scala @@ -76,7 +76,7 @@ class ArrayApply extends MiniPhase { tree.args match // (a, b, c) ~> new ::(a, new ::(b, new ::(c, Nil))) but only for reference types case StripAscription(Apply(wrapArrayMeth, List(StripAscription(rest: JavaSeqLiteral)))) :: Nil - if defn.WrapArrayMethods().contains(wrapArrayMeth.symbol) => + if rest.elems.isEmpty || defn.WrapArrayMethods().contains(wrapArrayMeth.symbol) => Some(rest.elems) case _ => None else None diff --git a/compiler/src/dotty/tools/dotc/transform/Inlining.scala b/compiler/src/dotty/tools/dotc/transform/Inlining.scala index 2215a580dccd..72c763ef155a 100644 --- a/compiler/src/dotty/tools/dotc/transform/Inlining.scala +++ b/compiler/src/dotty/tools/dotc/transform/Inlining.scala @@ -31,13 +31,7 @@ class Inlining extends MacroTransform { override def run(using Context): Unit = if ctx.compilationUnit.needsInlining || ctx.compilationUnit.hasMacroAnnotations then - try super.run - catch case _: CompilationUnit.SuspendException => () - - override def runOn(units: List[CompilationUnit])(using Context): List[CompilationUnit] = - val newUnits = super.runOn(units).filterNot(_.suspended) - ctx.run.nn.checkSuspendedUnits(newUnits) - newUnits + super.run override def checkPostCondition(tree: Tree)(using Context): Unit = tree match { diff --git a/compiler/src/dotty/tools/dotc/transform/Recheck.scala b/compiler/src/dotty/tools/dotc/transform/Recheck.scala index 5963a98f50f2..2eebc2347eec 100644 --- a/compiler/src/dotty/tools/dotc/transform/Recheck.scala +++ b/compiler/src/dotty/tools/dotc/transform/Recheck.scala @@ -39,10 +39,13 @@ object Recheck: val addRecheckedTypes = new TreeMap: override def transform(tree: Tree)(using Context): Tree = - val tree1 = super.transform(tree) - tree.getAttachment(RecheckedType) match - case Some(tpe) => tree1.withType(tpe) - case None => tree1 + try + val tree1 = super.transform(tree) + tree.getAttachment(RecheckedType) match + case Some(tpe) => tree1.withType(tpe) + case None => tree1 + catch + case _:TypeError => tree extension (sym: Symbol) diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 6bfbea0ace1a..ea350437f20d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -708,7 +708,7 @@ object Checking { report.error(ValueClassesMayNotDefineNonParameterField(clazz, stat.symbol), stat.srcPos) case _: DefDef if stat.symbol.isConstructor => report.error(ValueClassesMayNotDefineASecondaryConstructor(clazz, stat.symbol), stat.srcPos) - case _: MemberDef | _: Import | EmptyTree => + case _: MemberDef | _: Import | _: Export | EmptyTree => // ok case _ => report.error(ValueClassesMayNotContainInitalization(clazz), stat.srcPos) diff --git a/compiler/src/scala/quoted/runtime/impl/printers/Extractors.scala b/compiler/src/scala/quoted/runtime/impl/printers/Extractors.scala index eac85244d97b..726f2daf1788 100644 --- a/compiler/src/scala/quoted/runtime/impl/printers/Extractors.scala +++ b/compiler/src/scala/quoted/runtime/impl/printers/Extractors.scala @@ -177,6 +177,8 @@ object Extractors { this += "Alternatives(" ++= patterns += ")" case TypedOrTest(tree, tpt) => this += "TypedOrTest(" += tree += ", " += tpt += ")" + case tree => + this += s"" } def visitConstant(x: Constant): this.type = x match { @@ -239,6 +241,8 @@ object Extractors { this += "NoPrefix()" case MatchCase(pat, rhs) => this += "MatchCase(" += pat += ", " += rhs += ")" + case tp => + this += s"" } def visitSignature(sig: Signature): this.type = { diff --git a/compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala b/compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala index db6027460a02..017ee7eecb7e 100644 --- a/compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala +++ b/compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala @@ -1150,8 +1150,19 @@ object SourceCode { case tp: TypeRef if tp.typeSymbol == Symbol.requiredClass("scala.") => this += "_*" case _ => - printType(tp) - inSquare(printTypesOrBounds(args, ", ")) + if !fullNames && args.lengthCompare(2) == 0 && tp.typeSymbol.flags.is(Flags.Infix) then + val lhs = args(0) + val rhs = args(1) + this += "(" + printType(lhs) + this += " " + printType(tp) + this += " " + printType(rhs) + this += ")" + else + printType(tp) + inSquare(printTypesOrBounds(args, ", ")) } case AnnotatedType(tp, annot) => @@ -1287,7 +1298,9 @@ object SourceCode { val sym = annot.tpe.typeSymbol sym != Symbol.requiredClass("scala.forceInline") && sym.maybeOwner != Symbol.requiredPackage("scala.annotation.internal") - case x => cannotBeShownAsSource(x.show(using Printer.TreeStructure)) + case x => + cannotBeShownAsSource(x.show(using Printer.TreeStructure)) + false } printAnnotations(annots) if (annots.nonEmpty) this += " " @@ -1462,8 +1475,8 @@ object SourceCode { } } - private def cannotBeShownAsSource(x: String): Nothing = - throw new Exception(s"$x does not have a source representation") + private def cannotBeShownAsSource(x: String): this.type = + this += s"<$x does not have a source representation>" private object SpecialOp { def unapply(arg: Tree): Option[(String, List[Term])] = arg match { diff --git a/compiler/test/dotty/tools/backend/jvm/ArrayApplyOptTest.scala b/compiler/test/dotty/tools/backend/jvm/ArrayApplyOptTest.scala index 37e7d5316f9d..bf8ec32ed81e 100644 --- a/compiler/test/dotty/tools/backend/jvm/ArrayApplyOptTest.scala +++ b/compiler/test/dotty/tools/backend/jvm/ArrayApplyOptTest.scala @@ -161,6 +161,42 @@ class ArrayApplyOptTest extends DottyBytecodeTest { } } + @Test def emptyListApplyAvoidsIntermediateArray = + checkApplyAvoidsIntermediateArray("EmptyList"): + """import scala.collection.immutable.Nil + |class Foo { + | def meth1: List[String] = List() + | def meth2: List[String] = Nil + |} + """.stripMargin + + @Test def emptyRefListApplyAvoidsIntermediateArray = + checkApplyAvoidsIntermediateArray("EmptyListOfRef"): + """import scala.collection.immutable.Nil + |class Foo { + | def meth1: List[String] = List[String]() + | def meth2: List[String] = Nil + |} + """.stripMargin + + @Test def emptyPrimitiveListApplyAvoidsIntermediateArray = + checkApplyAvoidsIntermediateArray("EmptyListOfInt"): + """import scala.collection.immutable.Nil + |class Foo { + | def meth1: List[Int] = List() + | def meth2: List[Int] = Nil + |} + """.stripMargin + + @Test def primitiveListApplyAvoidsIntermediateArray = + checkApplyAvoidsIntermediateArray("ListOfInt"): + """import scala.collection.immutable.{ ::, Nil } + |class Foo { + | def meth1: List[Int] = List(1, 2, 3) + | def meth2: List[Int] = new ::(1, new ::(2, new ::(3, Nil))) + |} + """.stripMargin + @Test def testListApplyAvoidsIntermediateArray = { checkApplyAvoidsIntermediateArray("List"): """import scala.collection.immutable.{ ::, Nil } diff --git a/docs/_spec/Gemfile.lock b/docs/_spec/Gemfile.lock index b8e54fb6b4cb..c703a87bf993 100644 --- a/docs/_spec/Gemfile.lock +++ b/docs/_spec/Gemfile.lock @@ -41,7 +41,7 @@ GEM sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) - webrick (1.8.1) + webrick (1.8.2) PLATFORMS ruby diff --git a/project/Build.scala b/project/Build.scala index 6cc860718d5a..198a4f23646d 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -124,8 +124,8 @@ object Build { * scala-library. */ def stdlibVersion(implicit mode: Mode): String = mode match { - case NonBootstrapped => "2.13.14" - case Bootstrapped => "2.13.14" + case NonBootstrapped => "2.13.15" + case Bootstrapped => "2.13.15" } val dottyOrganization = "org.scala-lang" @@ -582,9 +582,9 @@ object Build { libraryDependencies ++= Seq( "org.scala-lang.modules" % "scala-asm" % "9.7.0-scala-2", // used by the backend Dependencies.compilerInterface, - "org.jline" % "jline-reader" % "3.25.1", // used by the REPL - "org.jline" % "jline-terminal" % "3.25.1", - "org.jline" % "jline-terminal-jna" % "3.25.1", // needed for Windows + "org.jline" % "jline-reader" % "3.27.0", // used by the REPL + "org.jline" % "jline-terminal" % "3.27.0", + "org.jline" % "jline-terminal-jna" % "3.27.0", // needed for Windows ("io.get-coursier" %% "coursier" % "2.0.16" % Test).cross(CrossVersion.for3Use2_13), ), @@ -1150,7 +1150,7 @@ object Build { BuildInfoPlugin.buildInfoDefaultSettings lazy val presentationCompilerSettings = { - val mtagsVersion = "1.3.4" + val mtagsVersion = "1.3.5" Seq( libraryDependencies ++= Seq( "org.lz4" % "lz4-java" % "1.8.0", @@ -1160,7 +1160,7 @@ object Build { .exclude("org.eclipse.lsp4j","org.eclipse.lsp4j.jsonrpc"), "org.eclipse.lsp4j" % "org.eclipse.lsp4j" % "0.20.1", ), - libraryDependencies += ("org.scalameta" % "mtags-shared_2.13.14" % mtagsVersion % SourceDeps), + libraryDependencies += ("org.scalameta" % "mtags-shared_2.13.15" % mtagsVersion % SourceDeps), ivyConfigurations += SourceDeps.hide, transitiveClassifiers := Seq("sources"), Compile / scalacOptions ++= Seq("-Yexplicit-nulls", "-Ysafe-init"), diff --git a/project/scripts/check-cla.sh b/project/scripts/check-cla.sh index 1a91363f5079..3ccfc48dee02 100755 --- a/project/scripts/check-cla.sh +++ b/project/scripts/check-cla.sh @@ -5,16 +5,16 @@ echo "Pull request submitted by $AUTHOR"; if [ "$AUTHOR" = "github-actions[bot]" ] ; then echo "CLA check for $AUTHOR successful"; else - signed=$(curl -s "https://www.lightbend.com/contribute/cla/scala/check/$AUTHOR" | jq -r ".signed"); + signed=$(curl -L -s "https://contribute.akka.io/contribute/cla/scala/check/$AUTHOR" | jq -r ".signed"); if [ "$signed" = "true" ] ; then echo "CLA check for $AUTHOR successful"; else echo "CLA check for $AUTHOR failed"; echo "Please sign the Scala CLA to contribute to the Scala compiler."; - echo "Go to https://www.lightbend.com/contribute/cla/scala and then"; + echo "Go to https://contribute.akka.io/contribute/cla/scala and then"; echo "comment on the pull request to ask for a new check."; echo ""; - echo "Check if CLA is signed: https://www.lightbend.com/contribute/cla/scala/check/$AUTHOR"; + echo "Check if CLA is signed: https://contribute.akka.io/contribute/cla/scala/check/$AUTHOR"; exit 1; fi; fi; diff --git a/scaladoc-testcases/src/tests/opaqueTypes.scala b/scaladoc-testcases/src/tests/opaqueTypes.scala index 33cc7ab9ff91..c248632092bd 100644 --- a/scaladoc-testcases/src/tests/opaqueTypes.scala +++ b/scaladoc-testcases/src/tests/opaqueTypes.scala @@ -6,4 +6,8 @@ opaque type Permissions = Int opaque type PermissionChoice = Int -//opaque type Permission <: Permissions & PermissionChoice = Int TODO: #112 \ No newline at end of file +//opaque type Permission <: Permissions & PermissionChoice = Int TODO: #112 + +object Foo: + opaque type Bar + = Int \ No newline at end of file diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala index 880979852ef6..4514cb42c9c3 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala @@ -314,7 +314,7 @@ trait ClassLikeSupport: def parseObject(classDef: ClassDef, signatureOnly: Boolean = false): Member = mkClass(classDef)( // All objects are final so we do not need final modifier! - modifiers = classDef.symbol.getExtraModifiers().filter(_ != Modifier.Final), + modifiers = classDef.symbol.getExtraModifiers().filter(mod => mod != Modifier.Final && mod != Modifier.Opaque), signatureOnly = signatureOnly ) diff --git a/tests/neg/21538.check b/tests/neg/21538.check new file mode 100644 index 000000000000..0e799bef3611 --- /dev/null +++ b/tests/neg/21538.check @@ -0,0 +1,11 @@ +-- [E083] Type Error: tests/neg/21538.scala:3:45 ----------------------------------------------------------------------- +3 |inline def foo[V](inline value: V)(using Bar[value.type]) : Unit = {} // error + | ^^^^^^^^^^ + | (value : V) is not a valid singleton type, since it is not an immutable path + | Inline parameters are not considered immutable paths and cannot be used as + | singleton types. + | + | Hint: Removing the `inline` qualifier from the `value` parameter + | may help resolve this issue. + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg/21538.scala b/tests/neg/21538.scala new file mode 100644 index 000000000000..761e9cde678a --- /dev/null +++ b/tests/neg/21538.scala @@ -0,0 +1,3 @@ +trait Bar[T] +given [T]: Bar[T] with {} +inline def foo[V](inline value: V)(using Bar[value.type]) : Unit = {} // error \ No newline at end of file diff --git a/tests/neg/i16815.check b/tests/neg/i16815.check new file mode 100644 index 000000000000..8f2f5c57d405 --- /dev/null +++ b/tests/neg/i16815.check @@ -0,0 +1,28 @@ +-- Error: tests/neg/i16815.scala:3:37 ---------------------------------------------------------------------------------- +3 |extension [C1 >: Chain <: Chain](c2: c1.Tail) // error + | ^^ + | right-associative extension method cannot have a forward reference to c1 +-- Error: tests/neg/i16815.scala:6:24 ---------------------------------------------------------------------------------- +6 |extension [C1](c2: (C1, C2)) // error + | ^^ + | right-associative extension method cannot have a forward reference to C2 +-- Error: tests/neg/i16815.scala:9:19 ---------------------------------------------------------------------------------- +9 |extension [C1](c2: C2) // error + | ^^ + | right-associative extension method cannot have a forward reference to C2 +-- Error: tests/neg/i16815.scala:12:24 --------------------------------------------------------------------------------- +12 |extension [C1](c2: (C1, C2, C3)) // error // error + | ^^ + | right-associative extension method cannot have a forward reference to C2 +-- Error: tests/neg/i16815.scala:12:28 --------------------------------------------------------------------------------- +12 |extension [C1](c2: (C1, C2, C3)) // error // error + | ^^ + | right-associative extension method cannot have a forward reference to C3 +-- Error: tests/neg/i16815.scala:15:48 --------------------------------------------------------------------------------- +15 |extension [C1](str: String)(using z: (str.type, C2)) // error + | ^^ + | right-associative extension method cannot have a forward reference to C2 +-- Error: tests/neg/i16815.scala:19:31 --------------------------------------------------------------------------------- +19 |extension [D1 <: Int](D2: (D1, D2)) // error + | ^^ + | right-associative extension method cannot have a forward reference to D2 diff --git a/tests/neg/i16815.scala b/tests/neg/i16815.scala new file mode 100644 index 000000000000..595f75e40df4 --- /dev/null +++ b/tests/neg/i16815.scala @@ -0,0 +1,20 @@ +trait Chain { type Tail <: Chain } + +extension [C1 >: Chain <: Chain](c2: c1.Tail) // error + def ra1_:[C2 <: C1](c1: C1): C2 = ??? + +extension [C1](c2: (C1, C2)) // error + def ra2_:[C2 <: C1](c1: (C1, C2)): C2 = ??? + +extension [C1](c2: C2) // error + def ra3_:[C2 <: C1](c1: C1): C2 = ??? + +extension [C1](c2: (C1, C2, C3)) // error // error + def ra4_:[C2 <: C1, C3 <: C1](c1: (C1, C2)): C2 = ??? + +extension [C1](str: String)(using z: (str.type, C2)) // error + def ra5_:[C2 <: Int](c1: C1): C2 = ??? + +type D2 = String +extension [D1 <: Int](D2: (D1, D2)) // error + def sa2_:[D2 <: D1](D1: (D1, D2)): D2 = ??? diff --git a/tests/neg/i21696.check b/tests/neg/i21696.check new file mode 100644 index 000000000000..9195263040b3 --- /dev/null +++ b/tests/neg/i21696.check @@ -0,0 +1,13 @@ +-- [E202] Staging Issue Error: tests/neg/i21696.scala:7:52 ------------------------------------------------------------- +7 |def foo[T](using Quotes): Expr[Thing[T]] = '{ Thing[T]() } // error + | ^ + | Reference to T within quotes requires a given scala.quoted.Type[T] in scope + |--------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | Referencing `T` inside a quoted expression requires a `scala.quoted.Type[T]` to be in scope. + | Since Scala is subject to erasure at runtime, the type information will be missing during the execution of the code. + | `scala.quoted.Type[T]` is therefore needed to carry `T`'s type information into the quoted code. + | Without an implicit `scala.quoted.Type[T]`, the type `T` cannot be properly referenced within the expression. + | To resolve this, ensure that a `scala.quoted.Type[T]` is available, either through a context-bound or explicitly. + --------------------------------------------------------------------------------------------------------------------- diff --git a/tests/neg/i21696.scala b/tests/neg/i21696.scala new file mode 100644 index 000000000000..7ec30a8a2e41 --- /dev/null +++ b/tests/neg/i21696.scala @@ -0,0 +1,7 @@ +//> using options -explain + +import scala.quoted.{Expr, Quotes} + +case class Thing[T]() + +def foo[T](using Quotes): Expr[Thing[T]] = '{ Thing[T]() } // error diff --git a/tests/pos-macros/i18517/Caller.scala b/tests/pos-macros/i18517/Caller.scala new file mode 100644 index 000000000000..3f5ce9eee903 --- /dev/null +++ b/tests/pos-macros/i18517/Caller.scala @@ -0,0 +1,17 @@ +package dummy + +trait BG { + val description: { type Structure } + type Structure = description.Structure +} + +abstract class Caller extends BG { + type Foo >: this.type <: this.type + + transparent inline def generate2() = + ${Macro.impl() } + + final val description = { + generate2() + } +} diff --git a/tests/pos-macros/i18517/Macro.scala b/tests/pos-macros/i18517/Macro.scala new file mode 100644 index 000000000000..d18b07e910a5 --- /dev/null +++ b/tests/pos-macros/i18517/Macro.scala @@ -0,0 +1,7 @@ +package dummy + +import scala.quoted.* + +object Macro: + def impl()(using quotes:Quotes) : Expr[Any] = + '{ null } diff --git a/tests/pos-macros/i18517/User.scala b/tests/pos-macros/i18517/User.scala new file mode 100644 index 000000000000..8216c581937b --- /dev/null +++ b/tests/pos-macros/i18517/User.scala @@ -0,0 +1,6 @@ +package dummy + +trait User: + final def bar(cell:Any) : Unit = + (cell: cell.type) match + case c: (Caller & cell.type) => () diff --git a/tests/pos-macros/skolem/Macro_1.scala b/tests/pos-macros/skolem/Macro_1.scala new file mode 100644 index 000000000000..65b14cffbc5b --- /dev/null +++ b/tests/pos-macros/skolem/Macro_1.scala @@ -0,0 +1,10 @@ +import scala.quoted.* + +object Macro { + + def impl(expr: Expr[Any])(using Quotes): Expr[Unit] = + println(expr.show) + '{ () } + + inline def macr(inline x: Any): Unit = ${impl('x)} +} diff --git a/tests/pos-macros/skolem/Test_2.scala b/tests/pos-macros/skolem/Test_2.scala new file mode 100644 index 000000000000..e243b8844c23 --- /dev/null +++ b/tests/pos-macros/skolem/Test_2.scala @@ -0,0 +1,9 @@ +trait Foo: + val x: Int + def ho(p: x.type => x.type): Unit = () + +object Test { + var f: Foo = ??? + Macro.macr: + f.ho(arg => arg) +} diff --git a/tests/pos/14952.scala b/tests/pos/14952.scala new file mode 100644 index 000000000000..5e4fd1c9a5ee --- /dev/null +++ b/tests/pos/14952.scala @@ -0,0 +1,9 @@ +//> using options -Ykind-projector:underscores + +import Tuple.* + +type LiftP[F[_], T] <: Tuple = + T match { + case _ *: _ => F[Head[T]] *: LiftP[F, Tail[T]] + case _ => EmptyTuple + } diff --git a/tests/pos/21400.scala b/tests/pos/21400.scala new file mode 100644 index 000000000000..28a061883913 --- /dev/null +++ b/tests/pos/21400.scala @@ -0,0 +1,7 @@ +//> using options -Ykind-projector:underscores + +import scala.compiletime.ops.int.S + +type IndexOf[T <: Tuple, E] <: Int = T match + case E *: _ => 0 + case _ *: es => 1 // S[IndexOf[es, E]] diff --git a/tests/pos/21400b.scala b/tests/pos/21400b.scala new file mode 100644 index 000000000000..6426de9b0f94 --- /dev/null +++ b/tests/pos/21400b.scala @@ -0,0 +1,10 @@ +//> using options -Ykind-projector:underscores + +import scala.quoted.Type +import scala.quoted.Quotes + +def x[A](t: Type[A])(using Quotes): Boolean = t match + case '[_ *: _] => + true + case _ => + false diff --git a/tests/pos/dep-poly-class.scala b/tests/pos/dep-poly-class.scala new file mode 100644 index 000000000000..3615b699ff3a --- /dev/null +++ b/tests/pos/dep-poly-class.scala @@ -0,0 +1,9 @@ +trait A: + type B + +class CCPoly[T <: A](a: T, b: a.B) + +object Test: + def test(): Unit = + val aa: A { type B = Int } = new A { type B = Int } + val x: CCPoly[aa.type] = CCPoly(aa, 1) diff --git a/tests/pos/i20026/J.java b/tests/pos/i20026/J.java new file mode 100644 index 000000000000..e950024ed913 --- /dev/null +++ b/tests/pos/i20026/J.java @@ -0,0 +1,4 @@ +package p; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class J { } diff --git a/tests/pos/i20026/S.scala b/tests/pos/i20026/S.scala new file mode 100644 index 000000000000..7da04d6b6bbe --- /dev/null +++ b/tests/pos/i20026/S.scala @@ -0,0 +1 @@ +class S diff --git a/tests/pos/i20026/TestInstance.java b/tests/pos/i20026/TestInstance.java new file mode 100644 index 000000000000..8db79ad88d89 --- /dev/null +++ b/tests/pos/i20026/TestInstance.java @@ -0,0 +1,15 @@ +package p; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +public @interface TestInstance { + enum Lifecycle { PER_CLASS, PER_METHOD; } + Lifecycle value(); +} diff --git a/tests/run-macros/i19905.check b/tests/run-macros/i19905.check index 36ba7772bfdb..47e9d86e3662 100644 --- a/tests/run-macros/i19905.check +++ b/tests/run-macros/i19905.check @@ -1,3 +1,3 @@ -java.lang.Exception: NoPrefix() does not have a source representation -java.lang.Exception: NoPrefix() does not have a source representation + + NoPrefix() diff --git a/tests/run-macros/type-print.check b/tests/run-macros/type-print.check new file mode 100644 index 000000000000..6ded89ec4e88 --- /dev/null +++ b/tests/run-macros/type-print.check @@ -0,0 +1,12 @@ +List[Int] +scala.collection.immutable.List[scala.Int] +scala.collection.immutable.List[scala.Int] +AppliedType(TypeRef(ThisType(TypeRef(NoPrefix(), "immutable")), "List"), List(TypeRef(TermRef(ThisType(TypeRef(NoPrefix(), "")), "scala"), "Int"))) ++[3, *[a, b]] +scala.compiletime.ops.int.+[3, scala.compiletime.ops.int.*[a, b]] +scala.compiletime.ops.int.+[3, scala.compiletime.ops.int.*[a, b]] +AppliedType(TypeRef(TermRef(TermRef(TermRef(TermRef(ThisType(TypeRef(NoPrefix(), "")), "scala"), "compiletime"), "ops"), "int"), "+"), List(ConstantType(IntConstant(3)), AppliedType(TypeRef(TermRef(TermRef(TermRef(TermRef(ThisType(TypeRef(NoPrefix(), "")), "scala"), "compiletime"), "ops"), "int"), "*"), List(TermRef(NoPrefix(), "a"), TermRef(NoPrefix(), "b"))))) +*[+[3, a], b] +scala.compiletime.ops.int.*[scala.compiletime.ops.int.+[3, a], b] +scala.compiletime.ops.int.*[scala.compiletime.ops.int.+[3, a], b] +AppliedType(TypeRef(TermRef(TermRef(TermRef(TermRef(ThisType(TypeRef(NoPrefix(), "")), "scala"), "compiletime"), "ops"), "int"), "*"), List(AppliedType(TypeRef(TermRef(TermRef(TermRef(TermRef(ThisType(TypeRef(NoPrefix(), "")), "scala"), "compiletime"), "ops"), "int"), "+"), List(ConstantType(IntConstant(3)), TermRef(NoPrefix(), "a"))), TermRef(NoPrefix(), "b"))) diff --git a/tests/run-macros/type-print/Macro_1.scala b/tests/run-macros/type-print/Macro_1.scala new file mode 100644 index 000000000000..c0dd57e33018 --- /dev/null +++ b/tests/run-macros/type-print/Macro_1.scala @@ -0,0 +1,29 @@ +import scala.quoted.* + +inline def printTypeShort[T]: String = + ${ printTypeShortImpl[T] } + +inline def printType[T]: String = + ${ printTypeImpl[T] } + +inline def printTypeAnsi[T]: String = + ${ printTypeAnsiImpl[T] } + +inline def printTypeStructure[T]: String = + ${ printTypeStructureImpl[T] } + +def printTypeShortImpl[T: Type](using Quotes): Expr[String] = + import quotes.reflect.* + Expr(Printer.TypeReprShortCode.show(TypeRepr.of[T])) + +def printTypeImpl[T: Type](using Quotes): Expr[String] = + import quotes.reflect.* + Expr(Printer.TypeReprCode.show(TypeRepr.of[T])) + +def printTypeAnsiImpl[T: Type](using Quotes): Expr[String] = + import quotes.reflect.* + Expr(Printer.TypeReprAnsiCode.show(TypeRepr.of[T])) + +def printTypeStructureImpl[T: Type](using Quotes): Expr[String] = + import quotes.reflect.* + Expr(Printer.TypeReprStructure.show(TypeRepr.of[T])) diff --git a/tests/run-macros/type-print/Test_2.scala b/tests/run-macros/type-print/Test_2.scala new file mode 100644 index 000000000000..f2ea6c3ba8b1 --- /dev/null +++ b/tests/run-macros/type-print/Test_2.scala @@ -0,0 +1,15 @@ +import scala.compiletime.ops.int.* + +inline def printAll[T]: Unit = + println(printTypeShort[T]) + println(printType[T]) + println(printTypeAnsi[T]) + println(printTypeStructure[T]) + +@main +def Test: Unit = + printAll[List[Int]] + val a = 1 + val b = 2 + printAll[3 + a.type * b.type] + printAll[(3 + a.type) * b.type] diff --git a/tests/run/export-anyval.check b/tests/run/export-anyval.check new file mode 100644 index 000000000000..1c2f472bb006 --- /dev/null +++ b/tests/run/export-anyval.check @@ -0,0 +1 @@ +Hello from export \ No newline at end of file diff --git a/tests/run/export-anyval.scala b/tests/run/export-anyval.scala new file mode 100644 index 000000000000..26fb2230781d --- /dev/null +++ b/tests/run/export-anyval.scala @@ -0,0 +1,12 @@ +class Foo(val x: String) + + +class Bar(val y: Foo) extends AnyVal: + export y.* + def foo: String = x +end Bar + +@main def Test = + val a = Bar(Foo("Hello from export")) + println(a.foo) +