diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index db2a66b8b234..0bb2943f581f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -26,10 +26,10 @@ on: - cron: '0 3 * * *' # Every day at 3 AM workflow_dispatch: -# Cancels any in-progress runs within the same group identified by workflow name and GH reference (branch or tag) +# Cancels any in-progress runs within the same group identified by workflow name and GH reference (branch or tag) # For example it would: # - terminate previous PR CI execution after pushing more changes to the same PR branch -# - terminate previous on-push CI run after merging new PR to main +# - terminate previous on-push CI run after merging new PR to main concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} diff --git a/.github/workflows/lts-backport.yaml b/.github/workflows/lts-backport.yaml index 33cdc8d07f6c..f8b930707c69 100644 --- a/.github/workflows/lts-backport.yaml +++ b/.github/workflows/lts-backport.yaml @@ -15,7 +15,7 @@ jobs: with: fetch-depth: 0 - uses: coursier/cache-action@v6 - - uses: VirtusLab/scala-cli-setup@v1.7.0 + - uses: VirtusLab/scala-cli-setup@v1.7.1 - run: scala-cli ./project/scripts/addToBackportingProject.scala -- ${{ github.sha }} env: GRAPHQL_API_TOKEN: ${{ secrets.GRAPHQL_API_TOKEN }} diff --git a/.gitmodules b/.gitmodules index 8f87e992013a..6c3e826c4fa5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,9 +19,6 @@ [submodule "community-build/community-projects/fastparse"] path = community-build/community-projects/fastparse url = https://github.com/dotty-staging/fastparse -[submodule "community-build/community-projects/stdLib213"] - path = community-build/community-projects/stdLib213 - url = https://github.com/dotty-staging/scala213 [submodule "community-build/community-projects/sourcecode"] path = community-build/community-projects/sourcecode url = https://github.com/dotty-staging/sourcecode diff --git a/changelogs/3.7.0-RC1.md b/changelogs/3.7.0-RC1.md new file mode 100644 index 000000000000..e895cfc324e0 --- /dev/null +++ b/changelogs/3.7.0-RC1.md @@ -0,0 +1,266 @@ +# Highlights of the release + +- Add `@scala.annotation.internal.preview` annotation and `-preview` flag. [#22317](https://github.com/scala/scala3/pull/22317) +- Make SIP-52 `@publicInBinary` a stable feature in 3.7 [#22591](https://github.com/scala/scala3/pull/22591) +- Make SIP-58 - `Named Tuples` a stable feature in 3.7 [#22753](https://github.com/scala/scala3/pull/22753) +- Make SIP-62 - `Better Fors` a preview feature in 3.7 [#22776](https://github.com/scala/scala3/pull/22776) +- Implement SIP-61 `@unroll` annotation as experimental [#21693](https://github.com/scala/scala3/pull/21693) +- Upgrade Scala 2 Standard Library to 2.13.16 [#22386](https://github.com/scala/scala3/pull/22386) +- Upgrade Scala.js to 1.18.1. [#22397](https://github.com/scala/scala3/pull/22397) +- Upgrade Scala CLI to 1.7.0 [#22735](https://github.com/scala/scala3/pull/22735) +- Expression Compiler is now part of Scala 3 compiler [#22597](https://github.com/scala/scala3/pull/22597) +- Quotes API: Added `apply` methods to import selectors [#22457](https://github.com/scala/scala3/pull/22457) +- Quotes API: Implement experimental `summonIgnoring` method [#22417](https://github.com/scala/scala3/pull/22417) +- Quotes API: Add class parameters, flags, and privateWithin and annotations to experimental `newClass` methods [#21880](https://github.com/scala/scala3/pull/21880) +- Experimental: Capture Calculus - Inferring `tracked` modifier [#21628](https://github.com/scala/scala3/pull/21628) +- Presentation Compiler: Show inferred type on holes in hover [#21423](https://github.com/scala/scala3/pull/21423) +- JVM Backend: Fix #15736 blocking Scala 3 on Android [#22632](https://github.com/scala/scala3/pull/22632) +- REPL: add flag to quit after evaluating init script [#22636](https://github.com/scala/scala3/pull/22636) +- REPL: implement :jar (deprecate :require) [#22343](https://github.com/scala/scala3/pull/22343) +- Linting: Improvements to -Wunused and -Wconf [#20894](https://github.com/scala/scala3/pull/20894) +- Implicit parameters warn at call site without `using` keyword [#22441](https://github.com/scala/scala3/pull/22441) +- Minimal support for dependent case classes [#21698](https://github.com/scala/scala3/pull/21698) + +# Other changes and fixes + +## Annotations + +- Lift arguments of explicitly constructed annotations [#22553](https://github.com/scala/scala3/pull/22553) +- Fix copy of annotation on `@main` methods [#22582](https://github.com/scala/scala3/pull/22582) +- `@publicInBinary` has now effect on secondary constructors [#22630](https://github.com/scala/scala3/pull/22630) +- Fix mapping of annotations [#22407](https://github.com/scala/scala3/pull/22407) + +## Backend: Scala.js + +- Emit `js.NewArray` IR nodes when possible. [#22446](https://github.com/scala/scala3/pull/22446) + +## Classpath + +- Fix empty ClassPath attribute in one or more classpath jars causes crash [#22462](https://github.com/scala/scala3/pull/22462) + +## Documentation + +- Improve the usage of inclusive language [#22360](https://github.com/scala/scala3/pull/22360) + +## Erasure + +- Handle type aliases in contextFunctionResultTypeAfter [#21517](https://github.com/scala/scala3/pull/21517) +- Align erasure of `Array[Nothing]` and `Array[Null]` with Scala 2 [#22517](https://github.com/scala/scala3/pull/22517) + +## Desugering + +- Under `betterFors` don't drop the trailing `map` if it would result in a different type (also drop `_ => ()`) [#22619](https://github.com/scala/scala3/pull/22619) + +## Experimental: Capture Checking + +- Canonicalize capture variable subtype comparisons [#22299](https://github.com/scala/scala3/pull/22299) +- Permit Capture Refs for Uninitialized Type and Term Params in BiTypeMap [#22451](https://github.com/scala/scala3/pull/22451) +- Fix maximal capability handling and expand aliases [#22341](https://github.com/scala/scala3/pull/22341) + +## Experimental: Modularity + +- Widen skolem types when adding parent refinements [#22488](https://github.com/scala/scala3/pull/22488) + +## Experimental: Global Initialization Checker + +- Refactor the abstract domain of global init checker to compile http4s [#22179](https://github.com/scala/scala3/pull/22179) +- Fix global init checking crash when using a value defined in by-name closure [#22625](https://github.com/scala/scala3/pull/22625) + +## Experimentals + +- Expand value references to packages to their underlying package objects [#22011](https://github.com/scala/scala3/pull/22011) + +## Implicits + +- Restrict implicit args to using [#22458](https://github.com/scala/scala3/pull/22458) + +## Linting + +- Suppress spurious Suppression [#22383](https://github.com/scala/scala3/pull/22383) +- CheckUnused checks span.exists before testing its parts [#22504](https://github.com/scala/scala3/pull/22504) +- Don't warn retainedBody [#22510](https://github.com/scala/scala3/pull/22510) +- Handle Typeable [#22663](https://github.com/scala/scala3/pull/22663) +- Nowarn public implicit val class params [#22664](https://github.com/scala/scala3/pull/22664) +- Exclude synthetic this.m, Any.m from import lookup [#22695](https://github.com/scala/scala3/pull/22695) +- Warn unused member of anonymous class [#22729](https://github.com/scala/scala3/pull/22729) +- Ignore params to default arg getters [#22749](https://github.com/scala/scala3/pull/22749) +- Lazy val def member is pattern var [#22750](https://github.com/scala/scala3/pull/22750) +- Restore resolving prefixes of implicit Ident [#22751](https://github.com/scala/scala3/pull/22751) +- No warning for parameter of overriding method [#22757](https://github.com/scala/scala3/pull/22757) +- Dealias before checking for member in lint [#22708](https://github.com/scala/scala3/pull/22708) +- Warn on bad extensions of aliases [#22362](https://github.com/scala/scala3/pull/22362) +- Warn universal extensions on opaque types [#22502](https://github.com/scala/scala3/pull/22502) +- Discourage default arg for extension receiver [#22492](https://github.com/scala/scala3/pull/22492) +- Rename on import is never wildcard [#22712](https://github.com/scala/scala3/pull/22712) +- Collect nowarn symbols instead of skipping them [#22766](https://github.com/scala/scala3/pull/22766) + +## Match Types + +- Handle NoType in TypeComparer.disjointnessBoundary [#21520](https://github.com/scala/scala3/pull/21520) + +## Named Tuples + +- Special case NamedTuple.From for arguments derived from Tuple [#22449](https://github.com/scala/scala3/pull/22449) +- Generate mirrors for named tuples [#22469](https://github.com/scala/scala3/pull/22469) + +## Opaque Types + +- Fix stack overflow errors when generating opaque type proxies [#22479](https://github.com/scala/scala3/pull/22479) +- Fix inline proxy generation for opaque types referencing other opaque types [#22381](https://github.com/scala/scala3/pull/22381) +- Fix opaque types leaking rhs when inlined and found in type params (and a related stale symbol issue) [#22655](https://github.com/scala/scala3/pull/22655) + +## Overloading + +- Make overload pruning based on result types less aggressive [#21744](https://github.com/scala/scala3/pull/21744) + +## Parser + +- Fix annotations being not expected in the middle of an array type by java parser [#22391](https://github.com/scala/scala3/pull/22391) +- No outdent at eof [#22435](https://github.com/scala/scala3/pull/22435) +- Allow observing an indent after conditional [#22611](https://github.com/scala/scala3/pull/22611) +- Correctly detect colon lambda eol indent for optional brace of argument [#22477](https://github.com/scala/scala3/pull/22477) + +## Pattern Matching + +- Avoid crash in uninhab check in Space [#22601](https://github.com/scala/scala3/pull/22601) +- Account for named tuples in space subtraction [#22658](https://github.com/scala/scala3/pull/22658) +- Check exhaustivity of any case class [#22604](https://github.com/scala/scala3/pull/22604) + +## Presentation Compiler + +- Add enum type param support in sourceSymbol [#18603](https://github.com/scala/scala3/pull/18603) +- Map name position to desugared version of named context bound [#22374](https://github.com/scala/scala3/pull/22374) +- Hover and go to definition for named tuples [#22202](https://github.com/scala/scala3/pull/22202) +- Completions: do not complete package [#20532](https://github.com/scala/scala3/pull/20532) +- Print parens for single method argument only if a direct tuple type [#21510](https://github.com/scala/scala3/pull/21510) +- Improvement: use heuristic to figure out `nameSpan` if `pointDelta` too big [#22484](https://github.com/scala/scala3/pull/22484) +- Fix inferredTypeEdits for symbols [#22485](https://github.com/scala/scala3/pull/22485) +- Fix: Only fallback to the definition of a synthetic valdef if it is zero extent [#22551](https://github.com/scala/scala3/pull/22551) +- Better LSP completions inside of backticks [#22555](https://github.com/scala/scala3/pull/22555) +- Don't search for members in pc info when irrelevant [#22674](https://github.com/scala/scala3/pull/22674) +- Backport from Metals [#22426](https://github.com/scala/scala3/pull/22426) +- Backport from Metals [#22491](https://github.com/scala/scala3/pull/22491) +- Backport from Metals [#22665](https://github.com/scala/scala3/pull/22665) + +## Runner + +- Upgrade Scala CLI to [1.7.0 highlights](https://github.com/VirtusLab/scala-cli/releases/tag/v1.7.0) + - Switch to scalameta/scalafmt images of scalafmt 3.9.1+ [#3502](https://github.com/VirtusLab/scala-cli/pull/3502) + - Support the `--test` command line option for `run` subcommand [#3519](https://github.com/VirtusLab/scala-cli/pull/3519) + - Support the `--test` command line option for `package` subcommand [#3519](https://github.com/VirtusLab/scala-cli/pull/3519) + - Detect objects with main class in scripts [#3479](https://github.com/VirtusLab/scala-cli/pull/3479) + - Support for Scala.js 1.18.2 [#3454](https://github.com/VirtusLab/scala-cli/pull/3454) + - Support for Scala Native 0.5.7 [#3527](https://github.com/VirtusLab/scala-cli/pull/3527) + - Add support for running a main method from the test scope [#3502](https://github.com/VirtusLab/scala-cli/pull/3502) + +## Quotes + +- Add a check for correct Array shape in quotes.reflect.ClassOfConstant [#22033](https://github.com/scala/scala3/pull/22033) +- Fix issue with static `this` references erroring in quoted code [#22618](https://github.com/scala/scala3/pull/22618) +- Fix #21721: make case TypeBlock(_,_) not match non-type Block [#21722](https://github.com/scala/scala3/pull/21722) +- Make Ref.apply() return trees usable in the largest scope possible [#22240](https://github.com/scala/scala3/pull/22240) +- Make sure Block does not incorrectly match a TypeBlock [#22716](https://github.com/scala/scala3/pull/22716) +- Do not approximate prefixes when using memberType in reflect API [#22448](https://github.com/scala/scala3/pull/22448) +- Bring back pattern match exhaustivity checking for macros [#22622](https://github.com/scala/scala3/pull/22622) + +## REPL + +- REPL: JLine 3.29.0 (was 3.27.1) [#22679](https://github.com/scala/scala3/pull/22679) +- Repl: emit warning for the `:sh` command [#22694](https://github.com/scala/scala3/pull/22694) +- Add warning for :kind command [#22572](https://github.com/scala/scala3/pull/22572) + +## Reporting + +- Filter help renders box border [#22434](https://github.com/scala/scala3/pull/22434) +- Register nowarn when inlining [#22682](https://github.com/scala/scala3/pull/22682) +- Rule out exports of member of the current class [#22545](https://github.com/scala/scala3/pull/22545) + +## Scaladoc + +- Render `@deprecated` correctly even when named arguments weren't used [#21925](https://github.com/scala/scala3/pull/21925) +- Remove DRI from Scaladoc warnings [#22330](https://github.com/scala/scala3/pull/22330) + +## SemanticDB + +- Don't add `()` to semanticdb symbol for java variables [#22573](https://github.com/scala/scala3/pull/22573) +- Fix compiler crash when using betasty with missing java classfiles [#22599](https://github.com/scala/scala3/pull/22599) + +## Transform + +- Check only stable qual for import prefix [#22633](https://github.com/scala/scala3/pull/22633) +- Treat static vals as enclosures in lambdalift [#22452](https://github.com/scala/scala3/pull/22452) +- Record calls to constructors in lambdaLift [#22487](https://github.com/scala/scala3/pull/22487) +- Only check logicalOwners for methods, and not for classes, when looking for proxies [#22356](https://github.com/scala/scala3/pull/22356) +- Add error-checking when fetching rhs of trees from TASTy [#22565](https://github.com/scala/scala3/pull/22565) + +## Typer + +- Root of Java select must be class or rooted package [#21800](https://github.com/scala/scala3/pull/21800) +- Check if a prefix is valid before selecting from a type [#22368](https://github.com/scala/scala3/pull/22368) +- Preserve hard unions in widenSingletons [#22369](https://github.com/scala/scala3/pull/22369) +- Constructor proxy is restricted if class is protected [#22563](https://github.com/scala/scala3/pull/22563) +- Constructor companion gets privateWithin [#22627](https://github.com/scala/scala3/pull/22627) +- Revert lambda cleanup [#22697](https://github.com/scala/scala3/pull/22697) +- Avoid infinite recursion when looking for suggestions [#22361](https://github.com/scala/scala3/pull/22361) +- Fix cyclic check, regardless of definition order [#22342](https://github.com/scala/scala3/pull/22342) +- Avoid inf recursion in provablyDisjointClasses [#22489](https://github.com/scala/scala3/pull/22489) + +## Value Classes + +- Allow private members when computing the denotation of a NamedType [#22549](https://github.com/scala/scala3/pull/22549) + +## Other changes + +- Remove locale dependent FileSystemException check [#21633](https://github.com/scala/scala3/pull/21633) + +# Contributors + +Thank you to all the contributors who made this release possible 🎉 + +According to `git shortlog -sn --no-merges 3.6.4..3.7.0-RC1` these are: + +``` + 59 Martin Odersky + 43 Som Snytt + 33 Adrien Piquerez + 32 Hamza Remmal + 21 Wojciech Mazur + 19 aherlihy + 19 kasiaMarek + 15 Jan Chyb + 13 Dale Wijnand + 11 Kacper Korban + 10 EnzeXing + 7 Guillaume Martres + 7 Matt Bovel + 7 Oliver Bračevac + 7 noti0na1 + 6 Sébastien Doeraene + 5 HarrisL2 + 5 Jamie Thompson + 5 dependabot[bot] + 4 Joel Wilsson + 4 Seth Tisue + 3 Piotr Chabelski + 3 Roman Janusz + 3 anna herlihy + 2 David Hua + 1 Alec Theriault + 1 Daisy Li + 1 Daniel Thoma + 1 Dmitrii Naumenko + 1 Felix Herrmann + 1 He-Pin(kerr) + 1 João Ferreira + 1 Jędrzej Rochala + 1 Katarzyna Marek + 1 Kenji Yoshida + 1 Niklas Fiekas + 1 Rocco Mathijn Andela + 1 Vadim Chelyshov + 1 Yichen Xu + 1 adpi2 + 1 fan-tom + 1 philwalk + 1 rochala +``` diff --git a/changelogs/3.7.0-RC2.md b/changelogs/3.7.0-RC2.md new file mode 100644 index 000000000000..d97aaf5c9812 --- /dev/null +++ b/changelogs/3.7.0-RC2.md @@ -0,0 +1,27 @@ +# Backported changes + +- Backport "Check trailing blank line at EOF for OUTDENT" to 3.7.0 [#22942](https://github.com/scala/scala3/pull/22942) +- Backport "Fail compilation if multiple conflicting top-level private defs/vals are in the same package" to 3.7 [#22932](https://github.com/scala/scala3/pull/22932) +- Backport "Deprecate `Yno-kind-polymorphism`" to 3.7 [#22931](https://github.com/scala/scala3/pull/22931) +- Backport "Revert unconditional lint of Inlined expansion" to 3.7 [#22930](https://github.com/scala/scala3/pull/22930) +- Backport "Bump Scala CLI to v1.7.1 (was v1.7.0)" to 3.7 [#22929](https://github.com/scala/scala3/pull/22929) +- Backport "Fix #22794: Emit the definition of Arrays.newArray even though it's a primitive." to 3.7.0 [#22801](https://github.com/scala/scala3/pull/22801) + +# Reverted changes + +- Revert "Make overload pruning based on result types less aggressive" in 3.7.0 [#22940](https://github.com/scala/scala3/pull/22940) + +# Contributors + +Thank you to all the contributors who made this release possible 🎉 + +According to `git shortlog -sn --no-merges 3.7.0-RC1..3.7.0-RC2` these are: + +``` + 4 Som Snytt + 4 Wojciech Mazur + 1 Jan Chyb + 1 Piotr Chabelski + 1 Sébastien Doeraene + 1 Yichen Xu +``` diff --git a/changelogs/3.7.0-RC3.md b/changelogs/3.7.0-RC3.md new file mode 100644 index 000000000000..3408fbf56d59 --- /dev/null +++ b/changelogs/3.7.0-RC3.md @@ -0,0 +1,16 @@ +# Backported changes + +- Backport "Two fixes to NamedTuple pattern matching" to 3.7.0 [#22995](https://github.com/scala/scala3/pull/22995) +- Backport "changes to scala.caps in preparation to make Capability stable" to 3.7.0 [#22967](https://github.com/scala/scala3/pull/22967) + +# Contributors + +Thank you to all the contributors who made this release possible 🎉 + +According to `git shortlog -sn --no-merges 3.7.0-RC2..3.7.0-RC3` these are: + +``` + 4 Martin Odersky + 2 Wojciech Mazur + 1 Natsu Kagami +``` diff --git a/changelogs/3.7.0-RC4.md b/changelogs/3.7.0-RC4.md new file mode 100644 index 000000000000..2b39d025541f --- /dev/null +++ b/changelogs/3.7.0-RC4.md @@ -0,0 +1,15 @@ +# Backported changes + +- Backport "Upgrade to Scala.js 1.19.0." to 3.7 [#23035](https://github.com/scala/scala3/pull/23035) + + +# Contributors + +Thank you to all the contributors who made this release possible 🎉 + +According to `git shortlog -sn --no-merges 3.7.0-RC3..3.7.0-RC4` these are: + +``` + 2 Sébastien Doeraene + 1 Tomasz Godzik +``` diff --git a/changelogs/3.7.0.md b/changelogs/3.7.0.md new file mode 100644 index 000000000000..8cfe9c75116f --- /dev/null +++ b/changelogs/3.7.0.md @@ -0,0 +1,279 @@ +# Highlights of the release + +- Add `@scala.annotation.internal.preview` annotation and `-preview` flag. [#22317](https://github.com/scala/scala3/pull/22317) +- Make SIP-52 `@publicInBinary` a stable feature in 3.7 [#22591](https://github.com/scala/scala3/pull/22591) +- Make SIP-58 - `Named Tuples` a stable feature in 3.7 [#22753](https://github.com/scala/scala3/pull/22753) +- Make SIP-62 - `Better Fors` a preview feature in 3.7 [#22776](https://github.com/scala/scala3/pull/22776) +- Implement SIP-61 `@unroll` annotation as experimental [#21693](https://github.com/scala/scala3/pull/21693) +- Upgrade Scala 2 Standard Library to 2.13.16 [#22386](https://github.com/scala/scala3/pull/22386) +- Upgrade Scala.js to 1.19.0 [#23026](https://github.com/scala/scala3/pull/23026) +- Upgrade Scala CLI to 1.7.1 [#22843](https://github.com/scala/scala3/pull/22843) +- Expression Compiler is now part of Scala 3 compiler [#22597](https://github.com/scala/scala3/pull/22597) +- Quotes API: Added `apply` methods to import selectors [#22457](https://github.com/scala/scala3/pull/22457) +- Quotes API: Implement experimental `summonIgnoring` method [#22417](https://github.com/scala/scala3/pull/22417) +- Quotes API: Add class parameters, flags, and privateWithin and annotations to experimental `newClass` methods [#21880](https://github.com/scala/scala3/pull/21880) +- Experimental: Capture Calculus - Inferring `tracked` modifier [#21628](https://github.com/scala/scala3/pull/21628) +- Presentation Compiler: Show inferred type on holes in hover [#21423](https://github.com/scala/scala3/pull/21423) +- JVM Backend: Fix #15736 blocking Scala 3 on Android [#22632](https://github.com/scala/scala3/pull/22632) +- REPL: add flag to quit after evaluating init script [#22636](https://github.com/scala/scala3/pull/22636) +- REPL: implement :jar (deprecate :require) [#22343](https://github.com/scala/scala3/pull/22343) +- Linting: Improvements to -Wunused and -Wconf [#20894](https://github.com/scala/scala3/pull/20894) +- Implicit parameters warn at call site without `using` keyword [#22441](https://github.com/scala/scala3/pull/22441) +- Support for dependent case classes [#21698](https://github.com/scala/scala3/pull/21698) +- Deprecate `Yno-kind-polymorphism` [#22814](https://github.com/scala/scala3/pull/22814) + +# Other changes and fixes + +## Annotations + +- Lift arguments of explicitly constructed annotations [#22553](https://github.com/scala/scala3/pull/22553) +- Fix copy of annotation on `@main` methods [#22582](https://github.com/scala/scala3/pull/22582) +- `@publicInBinary` has now effect on secondary constructors [#22630](https://github.com/scala/scala3/pull/22630) +- Fix mapping of annotations [#22407](https://github.com/scala/scala3/pull/22407) + +## Backend: Scala.js + +- Emit `js.NewArray` IR nodes when possible. [#22446](https://github.com/scala/scala3/pull/22446) +- Fix #22794: Emit the definition of Arrays.newArray even though it's a primitive [#22797](https://github.com/scala/scala3/pull/22797) + +## Classpath + +- Fix empty ClassPath attribute in one or more classpath jars causes crash [#22462](https://github.com/scala/scala3/pull/22462) + +## Documentation + +- Improve the usage of inclusive language [#22360](https://github.com/scala/scala3/pull/22360) + +## Erasure + +- Handle type aliases in contextFunctionResultTypeAfter [#21517](https://github.com/scala/scala3/pull/21517) +- Align erasure of `Array[Nothing]` and `Array[Null]` with Scala 2 [#22517](https://github.com/scala/scala3/pull/22517) + +## Desugering + +- Under `betterFors` don't drop the trailing `map` if it would result in a different type (also drop `_ => ()`) [#22619](https://github.com/scala/scala3/pull/22619) + +## Experimental: Capture Checking + +- Canonicalize capture variable subtype comparisons [#22299](https://github.com/scala/scala3/pull/22299) +- Permit Capture Refs for Uninitialized Type and Term Params in BiTypeMap [#22451](https://github.com/scala/scala3/pull/22451) +- Fix maximal capability handling and expand aliases [#22341](https://github.com/scala/scala3/pull/22341) + +## Experimental: Modularity + +- Widen skolem types when adding parent refinements [#22488](https://github.com/scala/scala3/pull/22488) + +## Experimental: Global Initialization Checker + +- Refactor the abstract domain of global init checker to compile http4s [#22179](https://github.com/scala/scala3/pull/22179) +- Fix global init checking crash when using a value defined in by-name closure [#22625](https://github.com/scala/scala3/pull/22625) + +## Experimentals + +- Expand value references to packages to their underlying package objects [#22011](https://github.com/scala/scala3/pull/22011) + +## Implicits + +- Restrict implicit args to using [#22458](https://github.com/scala/scala3/pull/22458) + +## Linting + +- Suppress spurious Suppression [#22383](https://github.com/scala/scala3/pull/22383) +- CheckUnused checks span.exists before testing its parts [#22504](https://github.com/scala/scala3/pull/22504) +- Don't warn retainedBody [#22510](https://github.com/scala/scala3/pull/22510) +- Handle Typeable [#22663](https://github.com/scala/scala3/pull/22663) +- Nowarn public implicit val class params [#22664](https://github.com/scala/scala3/pull/22664) +- Exclude synthetic this.m, Any.m from import lookup [#22695](https://github.com/scala/scala3/pull/22695) +- Warn unused member of anonymous class [#22729](https://github.com/scala/scala3/pull/22729) +- Ignore params to default arg getters [#22749](https://github.com/scala/scala3/pull/22749) +- Lazy val def member is pattern var [#22750](https://github.com/scala/scala3/pull/22750) +- Restore resolving prefixes of implicit Ident [#22751](https://github.com/scala/scala3/pull/22751) +- No warning for parameter of overriding method [#22757](https://github.com/scala/scala3/pull/22757) +- Dealias before checking for member in lint [#22708](https://github.com/scala/scala3/pull/22708) +- Warn on bad extensions of aliases [#22362](https://github.com/scala/scala3/pull/22362) +- Warn universal extensions on opaque types [#22502](https://github.com/scala/scala3/pull/22502) +- Discourage default arg for extension receiver [#22492](https://github.com/scala/scala3/pull/22492) +- Rename on import is never wildcard [#22712](https://github.com/scala/scala3/pull/22712) +- Collect nowarn symbols instead of skipping them [#22766](https://github.com/scala/scala3/pull/22766) +- Revert unconditional lint of Inlined expansion [#22815](https://github.com/scala/scala3/pull/22815) + +## Match Types + +- Handle NoType in TypeComparer.disjointnessBoundary [#21520](https://github.com/scala/scala3/pull/21520) + +## Named Tuples + +- Special case NamedTuple.From for arguments derived from Tuple [#22449](https://github.com/scala/scala3/pull/22449) +- Generate mirrors for named tuples [#22469](https://github.com/scala/scala3/pull/22469) +- Two fixes to NamedTuple pattern matching [#22953](https://github.com/scala/scala3/pull/22953) + +## Opaque Types + +- Fix stack overflow errors when generating opaque type proxies [#22479](https://github.com/scala/scala3/pull/22479) +- Fix inline proxy generation for opaque types referencing other opaque types [#22381](https://github.com/scala/scala3/pull/22381) +- Fix opaque types leaking rhs when inlined and found in type params (and a related stale symbol issue) [#22655](https://github.com/scala/scala3/pull/22655) + +## Overloading + +- Make overload pruning based on result types less aggressive [#21744](https://github.com/scala/scala3/pull/21744) +- Fail compilation if multiple conflicting top-level private defs/vals are in the same package [#22759](https://github.com/scala/scala3/pull/22759) + +## Parser + +- Fix annotations being not expected in the middle of an array type by java parser [#22391](https://github.com/scala/scala3/pull/22391) +- No outdent at eof [#22435](https://github.com/scala/scala3/pull/22435) +- Allow observing an indent after conditional [#22611](https://github.com/scala/scala3/pull/22611) +- Correctly detect colon lambda eol indent for optional brace of argument [#22477](https://github.com/scala/scala3/pull/22477) + +## Pattern Matching + +- Avoid crash in uninhab check in Space [#22601](https://github.com/scala/scala3/pull/22601) +- Account for named tuples in space subtraction [#22658](https://github.com/scala/scala3/pull/22658) +- Check exhaustivity of any case class [#22604](https://github.com/scala/scala3/pull/22604) + +## Presentation Compiler + +- Add enum type param support in sourceSymbol [#18603](https://github.com/scala/scala3/pull/18603) +- Map name position to desugared version of named context bound [#22374](https://github.com/scala/scala3/pull/22374) +- Hover and go to definition for named tuples [#22202](https://github.com/scala/scala3/pull/22202) +- Completions: do not complete package [#20532](https://github.com/scala/scala3/pull/20532) +- Print parens for single method argument only if a direct tuple type [#21510](https://github.com/scala/scala3/pull/21510) +- Improvement: use heuristic to figure out `nameSpan` if `pointDelta` too big [#22484](https://github.com/scala/scala3/pull/22484) +- Fix inferredTypeEdits for symbols [#22485](https://github.com/scala/scala3/pull/22485) +- Fix: Only fallback to the definition of a synthetic valdef if it is zero extent [#22551](https://github.com/scala/scala3/pull/22551) +- Better LSP completions inside of backticks [#22555](https://github.com/scala/scala3/pull/22555) +- Don't search for members in pc info when irrelevant [#22674](https://github.com/scala/scala3/pull/22674) +- Backport from Metals [#22426](https://github.com/scala/scala3/pull/22426) +- Backport from Metals [#22491](https://github.com/scala/scala3/pull/22491) +- Backport from Metals [#22665](https://github.com/scala/scala3/pull/22665) + +## Runner + +- Upgrade Scala CLI to [1.7.1 highlights](https://github.com/VirtusLab/scala-cli/releases/tag/v1.7.1) + - Switch to scalameta/scalafmt images of scalafmt 3.9.1+ [#3502](https://github.com/VirtusLab/scala-cli/pull/3502) + - Support the `--test` command line option for `run` subcommand [#3519](https://github.com/VirtusLab/scala-cli/pull/3519) + - Support the `--test` command line option for `package` subcommand [#3519](https://github.com/VirtusLab/scala-cli/pull/3519) + - Detect objects with main class in scripts [#3479](https://github.com/VirtusLab/scala-cli/pull/3479) + - Support for Scala.js 1.18.2 [#3454](https://github.com/VirtusLab/scala-cli/pull/3454) + - Support for Scala Native 0.5.7 [#3527](https://github.com/VirtusLab/scala-cli/pull/3527) + - Add support for running a main method from the test scope [#3502](https://github.com/VirtusLab/scala-cli/pull/3502) + +## Quotes + +- Add a check for correct Array shape in quotes.reflect.ClassOfConstant [#22033](https://github.com/scala/scala3/pull/22033) +- Fix issue with static `this` references erroring in quoted code [#22618](https://github.com/scala/scala3/pull/22618) +- Fix #21721: make case TypeBlock(_,_) not match non-type Block [#21722](https://github.com/scala/scala3/pull/21722) +- Make Ref.apply() return trees usable in the largest scope possible [#22240](https://github.com/scala/scala3/pull/22240) +- Make sure Block does not incorrectly match a TypeBlock [#22716](https://github.com/scala/scala3/pull/22716) +- Do not approximate prefixes when using memberType in reflect API [#22448](https://github.com/scala/scala3/pull/22448) +- Bring back pattern match exhaustivity checking for macros [#22622](https://github.com/scala/scala3/pull/22622) + +## REPL + +- REPL: JLine 3.29.0 (was 3.27.1) [#22679](https://github.com/scala/scala3/pull/22679) +- Repl: emit warning for the `:sh` command [#22694](https://github.com/scala/scala3/pull/22694) +- Add warning for :kind command [#22572](https://github.com/scala/scala3/pull/22572) +- Check trailing blank line at EOF for OUTDENT [#22855](https://github.com/scala/scala3/pull/22855) + +## Reporting + +- Filter help renders box border [#22434](https://github.com/scala/scala3/pull/22434) +- Register nowarn when inlining [#22682](https://github.com/scala/scala3/pull/22682) +- Rule out exports of member of the current class [#22545](https://github.com/scala/scala3/pull/22545) + +## Standard Library + +- Changes in preparation to make `caps.Capability` stable [#22849](https://github.com/scala/scala3/pull/22849) +- Mitigate change in status of scala.caps [#22956](https://github.com/scala/scala3/pull/22956) + +## Scaladoc + +- Render `@deprecated` correctly even when named arguments weren't used [#21925](https://github.com/scala/scala3/pull/21925) +- Remove DRI from Scaladoc warnings [#22330](https://github.com/scala/scala3/pull/22330) + +## SemanticDB + +- Don't add `()` to semanticdb symbol for java variables [#22573](https://github.com/scala/scala3/pull/22573) +- Fix compiler crash when using betasty with missing java classfiles [#22599](https://github.com/scala/scala3/pull/22599) + +## Transform + +- Check only stable qual for import prefix [#22633](https://github.com/scala/scala3/pull/22633) +- Treat static vals as enclosures in lambdalift [#22452](https://github.com/scala/scala3/pull/22452) +- Record calls to constructors in lambdaLift [#22487](https://github.com/scala/scala3/pull/22487) +- Only check logicalOwners for methods, and not for classes, when looking for proxies [#22356](https://github.com/scala/scala3/pull/22356) +- Add error-checking when fetching rhs of trees from TASTy [#22565](https://github.com/scala/scala3/pull/22565) + +## Typer + +- Root of Java select must be class or rooted package [#21800](https://github.com/scala/scala3/pull/21800) +- Check if a prefix is valid before selecting from a type [#22368](https://github.com/scala/scala3/pull/22368) +- Preserve hard unions in widenSingletons [#22369](https://github.com/scala/scala3/pull/22369) +- Constructor proxy is restricted if class is protected [#22563](https://github.com/scala/scala3/pull/22563) +- Constructor companion gets privateWithin [#22627](https://github.com/scala/scala3/pull/22627) +- Revert lambda cleanup [#22697](https://github.com/scala/scala3/pull/22697) +- Avoid infinite recursion when looking for suggestions [#22361](https://github.com/scala/scala3/pull/22361) +- Fix cyclic check, regardless of definition order [#22342](https://github.com/scala/scala3/pull/22342) +- Avoid inf recursion in provablyDisjointClasses [#22489](https://github.com/scala/scala3/pull/22489) + +## Value Classes + +- Allow private members when computing the denotation of a NamedType [#22549](https://github.com/scala/scala3/pull/22549) + +## Other changes + +- Remove locale dependent FileSystemException check [#21633](https://github.com/scala/scala3/pull/21633) + +# Contributors + +Thank you to all the contributors who made this release possible 🎉 + +According to `git shortlog -sn --no-merges 3.6.4..3.7.0` these are: + +``` + 63 Martin Odersky + 47 Som Snytt + 33 Adrien Piquerez + 32 Hamza Remmal + 29 Wojciech Mazur + 19 aherlihy + 19 kasiaMarek + 16 Jan Chyb + 13 Dale Wijnand + 11 Kacper Korban + 10 EnzeXing + 9 Sébastien Doeraene + 7 Guillaume Martres + 7 Matt Bovel + 7 Oliver Bračevac + 7 noti0na1 + 5 HarrisL2 + 5 Jamie Thompson + 5 dependabot[bot] + 4 Joel Wilsson + 4 Piotr Chabelski + 4 Seth Tisue + 3 Roman Janusz + 3 anna herlihy + 2 David Hua + 2 Tomasz Godzik + 2 Yichen Xu + 1 Alec Theriault + 1 Daisy Li + 1 Daniel Thoma + 1 Dmitrii Naumenko + 1 Felix Herrmann + 1 He-Pin(kerr) + 1 João Ferreira + 1 Jędrzej Rochala + 1 Katarzyna Marek + 1 Kenji Yoshida + 1 Natsu Kagami + 1 Niklas Fiekas + 1 Rocco Mathijn Andela + 1 Vadim Chelyshov + 1 adpi2 + 1 fan-tom + 1 philwalk + 1 rochala +``` diff --git a/community-build/community-projects/scalatest b/community-build/community-projects/scalatest index d6eeedbfc1e0..ab674686d089 160000 --- a/community-build/community-projects/scalatest +++ b/community-build/community-projects/scalatest @@ -1 +1 @@ -Subproject commit d6eeedbfc1e04f2eff55506f07f93f448cc21407 +Subproject commit ab674686d089f13da2e29c3b78fe6c3ab0211189 diff --git a/community-build/community-projects/scas b/community-build/community-projects/scas index 83d0f62bbc57..acaad1055738 160000 --- a/community-build/community-projects/scas +++ b/community-build/community-projects/scas @@ -1 +1 @@ -Subproject commit 83d0f62bbc57691e509f07186b34847bafe4b96e +Subproject commit acaad1055738dbbcae7b18e6c6c2fc95f06eb7d6 diff --git a/community-build/community-projects/stdLib213 b/community-build/community-projects/stdLib213 deleted file mode 160000 index 3f6bdaeafde1..000000000000 --- a/community-build/community-projects/stdLib213 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3f6bdaeafde17d790023cc3f299b81eaaf876ca3 diff --git a/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala b/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala index 5c2ea408413c..6181d4c3ddec 100644 --- a/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala +++ b/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala @@ -95,6 +95,7 @@ class CommunityBuildTestC: @Test def sourcecode = projects.sourcecode.run() @Test def specs2 = projects.specs2.run() + // @Test def stdLib213 = projects.stdLib213.run() @Test def ujson = projects.ujson.run() @Test def upickle = projects.upickle.run() @Test def utest = projects.utest.run() diff --git a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala index deaad2d51dbc..8ffc9637a001 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala @@ -26,7 +26,7 @@ import dotty.tools.dotc.util.SourcePosition import dotty.tools.dotc.report import dotty.tools.sjs.ir -import dotty.tools.sjs.ir.{ClassKind, Position, Names => jsNames, Trees => js, Types => jstpe} +import dotty.tools.sjs.ir.{ClassKind, Position, Trees => js, Types => jstpe, WellKnownNames => jswkn} import dotty.tools.sjs.ir.Names.{ClassName, LocalName, MethodName, SimpleMethodName} import dotty.tools.sjs.ir.OriginalName import dotty.tools.sjs.ir.OriginalName.NoOriginalName @@ -133,7 +133,7 @@ class JSCodeGen()(using genCtx: Context) { def currentThisType: jstpe.Type = { currentThisTypeNullable match { case tpe @ jstpe.ClassType(cls, _) => - jstpe.BoxedClassToPrimType.getOrElse(cls, tpe.toNonNullable) + jswkn.BoxedClassToPrimType.getOrElse(cls, tpe.toNonNullable) case tpe @ jstpe.AnyType => // We are in a JS class, in which even `this` is nullable tpe @@ -424,7 +424,7 @@ class JSCodeGen()(using genCtx: Context) { val staticInitializerStats = reflectInit ::: staticModuleInit if (staticInitializerStats.nonEmpty) - List(genStaticConstructorWithStats(ir.Names.StaticInitializerName, js.Block(staticInitializerStats))) + List(genStaticConstructorWithStats(jswkn.StaticInitializerName, js.Block(staticInitializerStats))) else Nil } @@ -453,7 +453,7 @@ class JSCodeGen()(using genCtx: Context) { originalName, ClassKind.Class, None, - Some(js.ClassIdent(ir.Names.ObjectClass)), + Some(js.ClassIdent(jswkn.ObjectClass)), Nil, None, None, @@ -574,7 +574,7 @@ class JSCodeGen()(using genCtx: Context) { if (staticFields.nonEmpty) { generatedMethods += - genStaticConstructorWithStats(ir.Names.ClassInitializerName, genLoadModule(companionModuleClass)) + genStaticConstructorWithStats(jswkn.ClassInitializerName, genLoadModule(companionModuleClass)) } (staticFields, staticExports) @@ -1000,7 +1000,7 @@ class JSCodeGen()(using genCtx: Context) { val fqcnArg = js.StringLiteral(sym.fullName.toString) val runtimeClassArg = js.ClassOf(toTypeRef(sym.info)) val loadModuleFunArg = - js.Closure(arrow = true, Nil, Nil, None, genLoadModule(sym), Nil) + js.Closure(js.ClosureFlags.arrow, Nil, Nil, None, jstpe.AnyType, genLoadModule(sym), Nil) val stat = genApplyMethod( genLoadModule(jsdefn.ReflectModule), @@ -1035,7 +1035,7 @@ class JSCodeGen()(using genCtx: Context) { val paramTypesArray = js.JSArrayConstr(parameterTypes) - val newInstanceFun = js.Closure(arrow = true, Nil, formalParams, None, { + val newInstanceFun = js.Closure(js.ClosureFlags.arrow, Nil, formalParams, None, jstpe.AnyType, { js.New(encodeClassName(sym), encodeMethodSym(ctor), actualParams) }, Nil) @@ -1557,7 +1557,7 @@ class JSCodeGen()(using genCtx: Context) { def jsParams = params.map(genParamDef(_)) - if (primitives.isPrimitive(sym)) { + if (primitives.isPrimitive(sym) && sym != defn.newArrayMethod) { None } else if (sym.is(Deferred) && currentClassSym.isNonNativeJSClass) { // scala-js/#4409: Do not emit abstract methods in non-native JS classes @@ -2389,7 +2389,7 @@ class JSCodeGen()(using genCtx: Context) { // Make new class def with static members val newClassDef = { implicit val pos = originalClassDef.pos - val parent = js.ClassIdent(jsNames.ObjectClass) + val parent = js.ClassIdent(jswkn.ObjectClass) js.ClassDef(originalClassDef.name, originalClassDef.originalName, ClassKind.AbstractJSType, None, Some(parent), interfaces = Nil, jsSuperClass = None, jsNativeLoadSpec = None, fields = Nil, @@ -2427,7 +2427,7 @@ class JSCodeGen()(using genCtx: Context) { js.VarRef(selfIdent.name)(jstpe.AnyType) def memberLambda(params: List[js.ParamDef], restParam: Option[js.ParamDef], body: js.Tree)(implicit pos: ir.Position): js.Closure = - js.Closure(arrow = false, captureParams = Nil, params, restParam, body, captureValues = Nil) + js.Closure(js.ClosureFlags.function, captureParams = Nil, params, restParam, jstpe.AnyType, body, captureValues = Nil) val fieldDefinitions = jsFieldDefs.toList.map { fdef => implicit val pos = fdef.pos @@ -2539,7 +2539,8 @@ class JSCodeGen()(using genCtx: Context) { beforeSuper ::: superCall ::: afterSuper } - val closure = js.Closure(arrow = true, jsClassCaptures, Nil, None, + // Wrap everything in a lambda, for namespacing + val closure = js.Closure(js.ClosureFlags.arrow, jsClassCaptures, Nil, None, jstpe.AnyType, js.Block(inlinedCtorStats, selfRef), jsSuperClassValue :: args) js.JSFunctionApply(closure, Nil) } @@ -3350,7 +3351,7 @@ class JSCodeGen()(using genCtx: Context) { // Sanity check: we can handle Ints and Strings (including `null`s), but nothing else genSelector.tpe match { - case jstpe.IntType | jstpe.ClassType(jsNames.BoxedStringClass, _) | jstpe.NullType | jstpe.NothingType => + case jstpe.IntType | jstpe.ClassType(jswkn.BoxedStringClass, _) | jstpe.NullType | jstpe.NothingType => // ok case _ => abortMatch(s"Invalid selector type ${genSelector.tpe}") @@ -3514,6 +3515,8 @@ class JSCodeGen()(using genCtx: Context) { atPhase(elimRepeatedPhase)(samMethod.info.paramInfoss.flatten.exists(_.isRepeatedParam)) } } + val isFunctionXXL = + funInterfaceSym.name == tpnme.FunctionXXL && funInterfaceSym.owner == defn.ScalaRuntimePackageClass val formalParamNames = sym.info.paramNamess.flatten.drop(envSize) val formalParamTypes = sym.info.paramInfoss.flatten.drop(envSize) @@ -3523,8 +3526,11 @@ class JSCodeGen()(using genCtx: Context) { val formalAndActualParams = formalParamNames.lazyZip(formalParamTypes).lazyZip(formalParamRepeateds).map { (name, tpe, repeated) => + val formalTpe = + if (isFunctionXXL) jstpe.ArrayType(ObjectArrayTypeRef, nullable = true) + else jstpe.AnyType val formalParam = js.ParamDef(freshLocalIdent(name), - OriginalName(name.toString), jstpe.AnyType, mutable = false) + OriginalName(name.toString), formalTpe, mutable = false) val actualParam = if (repeated) genJSArrayToVarArgs(formalParam.ref)(tree.sourcePos) else unbox(formalParam.ref, tpe) @@ -3559,10 +3565,11 @@ class JSCodeGen()(using genCtx: Context) { if (isThisFunction) { val thisParam :: otherParams = formalParams: @unchecked js.Closure( - arrow = false, + js.ClosureFlags.function, formalCaptures, otherParams, restParam, + jstpe.AnyType, js.Block( js.VarDef(thisParam.name, thisParam.originalName, thisParam.ptpe, mutable = false, @@ -3570,23 +3577,32 @@ class JSCodeGen()(using genCtx: Context) { genBody), actualCaptures) } else { - val closure = js.Closure(arrow = true, formalCaptures, formalParams, restParam, genBody, actualCaptures) + val closure = js.Closure(js.ClosureFlags.typed, formalCaptures, + formalParams, restParam, jstpe.AnyType, genBody, actualCaptures) if (!funInterfaceSym.exists || defn.isFunctionClass(funInterfaceSym)) { val formalCount = formalParams.size - val cls = ClassName("scala.scalajs.runtime.AnonFunction" + formalCount) - val ctorName = MethodName.constructor( - jstpe.ClassRef(ClassName("scala.scalajs.js.Function" + formalCount)) :: Nil) - js.New(cls, js.MethodIdent(ctorName), List(closure)) - } else if (funInterfaceSym.name == tpnme.FunctionXXL && funInterfaceSym.owner == defn.ScalaRuntimePackageClass) { - val cls = ClassName("scala.scalajs.runtime.AnonFunctionXXL") - val ctorName = MethodName.constructor( - jstpe.ClassRef(ClassName("scala.scalajs.js.Function1")) :: Nil) - js.New(cls, js.MethodIdent(ctorName), List(closure)) + val descriptor = js.NewLambda.Descriptor( + superClass = encodeClassName(defn.AbstractFunctionClass(formalCount)), + interfaces = Nil, + methodName = MethodName(applySimpleMethodName, List.fill(formalCount)(jswkn.ObjectRef), jswkn.ObjectRef), + paramTypes = List.fill(formalCount)(jstpe.AnyType), + resultType = jstpe.AnyType + ) + js.NewLambda(descriptor, closure)(encodeClassType(defn.FunctionSymbol(formalCount)).toNonNullable) + } else if (isFunctionXXL) { + val descriptor = js.NewLambda.Descriptor( + superClass = jswkn.ObjectClass, + interfaces = List(encodeClassName(defn.FunctionXXLClass)), + methodName = MethodName(applySimpleMethodName, List(ObjectArrayTypeRef), jswkn.ObjectRef), + paramTypes = List(jstpe.ArrayType(ObjectArrayTypeRef, nullable = true)), + resultType = jstpe.AnyType + ) + js.NewLambda(descriptor, closure)(encodeClassType(funInterfaceSym).toNonNullable) } else { assert(funInterfaceSym.isJSType, s"Invalid functional interface $funInterfaceSym reached the back-end") - closure + closure.copy(flags = js.ClosureFlags.arrow) } } } @@ -3699,8 +3715,8 @@ class JSCodeGen()(using genCtx: Context) { } private def genThrowClassCastException()(implicit pos: Position): js.Tree = { - js.UnaryOp(js.UnaryOp.Throw, js.New(jsNames.ClassCastExceptionClass, - js.MethodIdent(jsNames.NoArgConstructorName), Nil)) + js.UnaryOp(js.UnaryOp.Throw, js.New(jswkn.ClassCastExceptionClass, + js.MethodIdent(jswkn.NoArgConstructorName), Nil)) } /** Gen JS code for an isInstanceOf test (for reference types only) */ @@ -3987,7 +4003,7 @@ class JSCodeGen()(using genCtx: Context) { case arg: js.JSGlobalRef => js.JSTypeOfGlobalRef(arg) case _ => js.JSUnaryOp(js.JSUnaryOp.typeof, arg) } - js.AsInstanceOf(typeofExpr, jstpe.ClassType(jsNames.BoxedStringClass, nullable = true)) + js.AsInstanceOf(typeofExpr, jstpe.ClassType(jswkn.BoxedStringClass, nullable = true)) case STRICT_EQ => // js.special.strictEquals(arg1, arg2) @@ -4235,7 +4251,7 @@ class JSCodeGen()(using genCtx: Context) { "literal classOf[T] expressions (typically compiler-generated). " + "Other uses are not supported in Scala.js.", otherTree.sourcePos) - (jstpe.AnyType, jstpe.ClassRef(jsNames.ObjectClass)) + (jstpe.AnyType, jstpe.ClassRef(jswkn.ObjectClass)) } // Gen the actual args, downcasting them to the formal param types @@ -4870,16 +4886,17 @@ object JSCodeGen { private val JSObjectClassName = ClassName("scala.scalajs.js.Object") private val JavaScriptExceptionClassName = ClassName("scala.scalajs.js.JavaScriptException") - private val ObjectClassRef = jstpe.ClassRef(ir.Names.ObjectClass) + private val ObjectArrayTypeRef = jstpe.ArrayTypeRef(jswkn.ObjectRef, 1) + private val applySimpleMethodName = SimpleMethodName("apply") private val newSimpleMethodName = SimpleMethodName("new") - private val selectedValueMethodName = MethodName("selectedValue", Nil, ObjectClassRef) + private val selectedValueMethodName = MethodName("selectedValue", Nil, jswkn.ObjectRef) private val JLRArrayNewInstanceMethodName = - MethodName("newInstance", List(jstpe.ClassRef(jsNames.ClassClass), jstpe.ArrayTypeRef(jstpe.IntRef, 1)), ObjectClassRef) + MethodName("newInstance", List(jstpe.ClassRef(jswkn.ClassClass), jstpe.ArrayTypeRef(jstpe.IntRef, 1)), jswkn.ObjectRef) - private val ObjectArgConstructorName = MethodName.constructor(List(ObjectClassRef)) + private val ObjectArgConstructorName = MethodName.constructor(List(jswkn.ObjectRef)) private val thisOriginalName = OriginalName("this") diff --git a/compiler/src/dotty/tools/backend/sjs/JSEncoding.scala b/compiler/src/dotty/tools/backend/sjs/JSEncoding.scala index b3d28b73d81c..959a05fd6c43 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSEncoding.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSEncoding.scala @@ -16,7 +16,7 @@ import StdNames.* import dotty.tools.dotc.transform.sjs.JSSymUtils.* import dotty.tools.sjs.ir -import dotty.tools.sjs.ir.{Trees => js, Types => jstpe} +import dotty.tools.sjs.ir.{Trees => js, Types => jstpe, WellKnownNames => jswkn} import dotty.tools.sjs.ir.Names.{LocalName, LabelName, SimpleFieldName, FieldName, SimpleMethodName, MethodName, ClassName} import dotty.tools.sjs.ir.OriginalName import dotty.tools.sjs.ir.OriginalName.NoOriginalName @@ -235,7 +235,7 @@ object JSEncoding { def encodeDynamicImportForwarderIdent(params: List[Symbol])(using Context, ir.Position): js.MethodIdent = { val paramTypeRefs = params.map(sym => paramOrResultTypeRef(sym.info)) - val resultTypeRef = jstpe.ClassRef(ir.Names.ObjectClass) + val resultTypeRef = jstpe.ClassRef(jswkn.ObjectClass) val methodName = MethodName(dynamicImportForwarderSimpleName, paramTypeRefs, resultTypeRef) js.MethodIdent(methodName) } @@ -282,7 +282,7 @@ object JSEncoding { * - scala.Null to scala.runtime.Null$. */ if (sym1 == defn.BoxedUnitClass) - ir.Names.BoxedUnitClass + jswkn.BoxedUnitClass else if (sym1 == defn.NothingClass) ScalaRuntimeNothingClassName else if (sym1 == defn.NullClass) @@ -326,6 +326,9 @@ object JSEncoding { case typeRef: jstpe.ArrayTypeRef => jstpe.ArrayType(typeRef, nullable = true) + + case typeRef: jstpe.TransientTypeRef => + throw AssertionError(s"Unexpected transient type ref $typeRef for ${typeRefInternal._2}") } } @@ -359,7 +362,7 @@ object JSEncoding { */ def nonClassTypeRefToTypeRef(sym: Symbol): (jstpe.TypeRef, Symbol) = { //assert(sym.isType && isCompilingArray, sym) - (jstpe.ClassRef(ir.Names.ObjectClass), defn.ObjectClass) + (jstpe.ClassRef(jswkn.ObjectClass), defn.ObjectClass) } tp.widenDealias match { diff --git a/compiler/src/dotty/tools/backend/sjs/JSExportsGen.scala b/compiler/src/dotty/tools/backend/sjs/JSExportsGen.scala index 42205f9b70c2..425710c6be9a 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSExportsGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSExportsGen.scala @@ -22,8 +22,7 @@ import TypeErasure.ErasedValueType import dotty.tools.dotc.util.{SourcePosition, SrcPos} import dotty.tools.dotc.report -import dotty.tools.sjs.ir.{Position, Names => jsNames, Trees => js, Types => jstpe} -import dotty.tools.sjs.ir.Names.DefaultModuleID +import dotty.tools.sjs.ir.{Position, Names => jsNames, Trees => js, Types => jstpe, WellKnownNames => jswkn} import dotty.tools.sjs.ir.OriginalName.NoOriginalName import dotty.tools.sjs.ir.Position.NoPosition import dotty.tools.sjs.ir.Trees.OptimizerHints @@ -87,7 +86,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) { symForAnnot.annotations.collect { case annot if annot.symbol == jsdefn.JSExportTopLevelAnnot => val jsName = annot.argumentConstantString(0).get - val moduleID = annot.argumentConstantString(1).getOrElse(DefaultModuleID) + val moduleID = annot.argumentConstantString(1).getOrElse(jswkn.DefaultModuleID) TopLevelExportInfo(moduleID, jsName)(annot.tree.sourcePos) } } @@ -947,8 +946,8 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) { case jstpe.FloatType => PrimitiveTypeTest(jstpe.FloatType, 7) case jstpe.DoubleType => PrimitiveTypeTest(jstpe.DoubleType, 8) - case jstpe.ClassType(Names.BoxedUnitClass, _) => PrimitiveTypeTest(jstpe.UndefType, 0) - case jstpe.ClassType(Names.BoxedStringClass, _) => PrimitiveTypeTest(jstpe.StringType, 9) + case jstpe.ClassType(jswkn.BoxedUnitClass, _) => PrimitiveTypeTest(jstpe.UndefType, 0) + case jstpe.ClassType(jswkn.BoxedStringClass, _) => PrimitiveTypeTest(jstpe.StringType, 9) case jstpe.ClassType(_, _) => InstanceOfTypeTest(tpe) case jstpe.ArrayType(_, _) => InstanceOfTypeTest(tpe) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 1c86ba069433..c235143e97f1 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -1953,9 +1953,9 @@ object desugar { /** Create tree for for-comprehension `` or * `` where mapName and flatMapName are chosen * corresponding to whether this is a for-do or a for-yield. - * If sourceVersion >= 3.7 are enabled, the creation performs the following rewrite rules: + * If betterFors are enabled, the creation performs the following rewrite rules: * - * 1. if sourceVersion >= 3.7: + * 1. if betterFors is enabled: * * for () do E ==> E * or @@ -1986,13 +1986,13 @@ object desugar { * ==> * for (P <- G.withFilter (P => E); ...) ... * - * 6. For any N, if sourceVersion >= 3.7: + * 6. For any N, if betterFors is enabled: * * for (P <- G; P_1 = E_1; ... P_N = E_N; P1 <- G1; ...) ... * ==> * G.flatMap (P => for (P_1 = E_1; ... P_N = E_N; ...)) * - * 7. For any N, if sourceVersion >= 3.7: + * 7. For any N, if betterFors is enabled: * * for (P <- G; P_1 = E_1; ... P_N = E_N) ... * ==> @@ -2013,7 +2013,7 @@ object desugar { * If any of the P_i are variable patterns, the corresponding `x_i @ P_i` is not generated * and the variable constituting P_i is used instead of x_i * - * 9. For any N, if sourceVersion >= 3.7: + * 9. For any N, if betterFors is enabled: * * for (P_1 = E_1; ... P_N = E_N; ...) * ==> @@ -2157,7 +2157,7 @@ object desugar { case _ => false def markTrailingMap(aply: Apply, gen: GenFrom, selectName: TermName): Unit = - if sourceVersion.isAtLeast(`3.7`) + if sourceVersion.enablesBetterFors && selectName == mapName && gen.checkMode != GenCheckMode.Filtered // results of withFilter have the wrong type && (deepEquals(gen.pat, body) || deepEquals(body, Tuple(Nil))) @@ -2165,7 +2165,7 @@ object desugar { aply.putAttachment(TrailingForMap, ()) enums match { - case Nil if sourceVersion.isAtLeast(`3.7`) => body + case Nil if sourceVersion.enablesBetterFors => body case (gen: GenFrom) :: Nil => val aply = Apply(rhsSelect(gen, mapName), makeLambda(gen, body)) markTrailingMap(aply, gen, mapName) @@ -2174,7 +2174,7 @@ object desugar { val cont = makeFor(mapName, flatMapName, rest, body) Apply(rhsSelect(gen, flatMapName), makeLambda(gen, cont)) case (gen: GenFrom) :: rest - if sourceVersion.isAtLeast(`3.7`) + if sourceVersion.enablesBetterFors && rest.dropWhile(_.isInstanceOf[GenAlias]).headOption.forall(e => e.isInstanceOf[GenFrom]) // possible aliases followed by a generator or end of for && !rest.takeWhile(_.isInstanceOf[GenAlias]).exists(a => isNestedGivenPattern(a.asInstanceOf[GenAlias].pat)) => val cont = makeFor(mapName, flatMapName, rest, body) @@ -2202,9 +2202,9 @@ object desugar { makeFor(mapName, flatMapName, vfrom1 :: rest1, body) case (gen: GenFrom) :: test :: rest => val filtered = Apply(rhsSelect(gen, nme.withFilter), makeLambda(gen, test)) - val genFrom = GenFrom(gen.pat, filtered, if sourceVersion.isAtLeast(`3.7`) then GenCheckMode.Filtered else GenCheckMode.Ignore) + val genFrom = GenFrom(gen.pat, filtered, if sourceVersion.enablesBetterFors then GenCheckMode.Filtered else GenCheckMode.Ignore) makeFor(mapName, flatMapName, genFrom :: rest, body) - case GenAlias(_, _) :: _ if sourceVersion.isAtLeast(`3.7`) => + case GenAlias(_, _) :: _ if sourceVersion.enablesBetterFors => val (valeqs, rest) = enums.span(_.isInstanceOf[GenAlias]) val pats = valeqs.map { case GenAlias(pat, _) => pat } val rhss = valeqs.map { case GenAlias(_, rhs) => rhs } diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index 2acfc4cf86e3..57c74d90b45d 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -518,6 +518,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { def scalaUnit(implicit src: SourceFile): Select = scalaDot(tpnme.Unit) def scalaAny(implicit src: SourceFile): Select = scalaDot(tpnme.Any) + def capsInternalDot(name: Name)(using SourceFile): Select = + Select(Select(scalaDot(nme.caps), nme.internal), name) + def captureRoot(using Context): Select = Select(scalaDot(nme.caps), nme.CAPTURE_ROOT) @@ -525,7 +528,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { Annotated(parent, New(scalaAnnotationDot(annotName), List(refs))) def makeCapsOf(tp: RefTree)(using Context): Tree = - TypeApply(Select(scalaDot(nme.caps), nme.capsOf), tp :: Nil) + TypeApply(capsInternalDot(nme.capsOf), tp :: Nil) // Capture set variable `[C^]` becomes: `[C >: CapSet <: CapSet^{cap}]` def makeCapsBound()(using Context): TypeBoundsTree = diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index c6c0ab47de52..4ee4d17cd63e 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -443,7 +443,8 @@ private sealed trait YSettings: val YwithBestEffortTasty: Setting[Boolean] = BooleanSetting(ForkSetting, "Ywith-best-effort-tasty", "Allow to compile using best-effort tasty files. If such file is used, the compiler will stop after the pickler phase.") // Experimental language features - val YnoKindPolymorphism: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-kind-polymorphism", "Disable kind polymorphism.") + @deprecated(message = "This flag has no effect and will be removed in a future version.", since = "3.7.0") + val YnoKindPolymorphism: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-kind-polymorphism", "Disable kind polymorphism. (This flag has no effect)", deprecation = Deprecation.removed()) val YexplicitNulls: Setting[Boolean] = BooleanSetting(ForkSetting, "Yexplicit-nulls", "Make reference types non-nullable. Nullable types can be expressed with unions: e.g. String|Null.") val YnoFlexibleTypes: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-flexible-types", "Disable turning nullable Java return types and parameter types into flexible types, which behave like abstract types with a nullable lower bound and non-nullable upper bound.") val YcheckInitGlobal: Setting[Boolean] = BooleanSetting(ForkSetting, "Ysafe-init-global", "Check safe initialization of global objects.") diff --git a/compiler/src/dotty/tools/dotc/config/SourceVersion.scala b/compiler/src/dotty/tools/dotc/config/SourceVersion.scala index 199350949233..30a88fb79f2a 100644 --- a/compiler/src/dotty/tools/dotc/config/SourceVersion.scala +++ b/compiler/src/dotty/tools/dotc/config/SourceVersion.scala @@ -3,6 +3,8 @@ package dotc package config import core.Decorators.* +import core.Contexts.* +import Feature.isPreviewEnabled import util.Property enum SourceVersion: @@ -35,6 +37,7 @@ enum SourceVersion: def enablesClauseInterleaving = isAtLeast(`3.6`) def enablesNewGivens = isAtLeast(`3.6`) def enablesNamedTuples = isAtLeast(`3.7`) + def enablesBetterFors(using Context) = isAtLeast(`3.7`) && isPreviewEnabled object SourceVersion extends Property.Key[SourceVersion]: def defaultSourceVersion = `3.7` diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index f89bc8691e2d..e44bfcee2cf7 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -449,10 +449,7 @@ class Definitions { @tu lazy val AnyKindClass: ClassSymbol = { val cls = newCompleteClassSymbol(ScalaPackageClass, tpnme.AnyKind, AbstractFinal | Permanent, Nil, newScope(0)) - if (!ctx.settings.YnoKindPolymorphism.value) - // Enable kind-polymorphism by exposing scala.AnyKind - cls.entered - cls + cls.entered } def AnyKindType: TypeRef = AnyKindClass.typeRef @@ -996,17 +993,19 @@ class Definitions { @tu lazy val LabelClass: Symbol = requiredClass("scala.util.boundary.Label") @tu lazy val BreakClass: Symbol = requiredClass("scala.util.boundary.Break") - @tu lazy val CapsModule: Symbol = requiredModule("scala.caps") + @tu lazy val CapsModule: Symbol = requiredPackage("scala.caps") @tu lazy val captureRoot: TermSymbol = CapsModule.requiredValue("cap") @tu lazy val Caps_Capability: TypeSymbol = CapsModule.requiredType("Capability") @tu lazy val Caps_CapSet: ClassSymbol = requiredClass("scala.caps.CapSet") - @tu lazy val Caps_reachCapability: TermSymbol = CapsModule.requiredMethod("reachCapability") - @tu lazy val Caps_capsOf: TermSymbol = CapsModule.requiredMethod("capsOf") + @tu lazy val CapsInternalModule: Symbol = requiredModule("scala.caps.internal") + @tu lazy val Caps_reachCapability: TermSymbol = CapsInternalModule.requiredMethod("reachCapability") + @tu lazy val Caps_capsOf: TermSymbol = CapsInternalModule.requiredMethod("capsOf") @tu lazy val Caps_Exists: ClassSymbol = requiredClass("scala.caps.Exists") @tu lazy val CapsUnsafeModule: Symbol = requiredModule("scala.caps.unsafe") @tu lazy val Caps_unsafeAssumePure: Symbol = CapsUnsafeModule.requiredMethod("unsafeAssumePure") @tu lazy val Caps_ContainsTrait: TypeSymbol = CapsModule.requiredType("Contains") - @tu lazy val Caps_containsImpl: TermSymbol = CapsModule.requiredMethod("containsImpl") + @tu lazy val Caps_ContainsModule: Symbol = requiredModule("scala.caps.Contains") + @tu lazy val Caps_containsImpl: TermSymbol = Caps_ContainsModule.requiredMethod("containsImpl") /** The same as CaptureSet.universal but generated implicitly for references of Capability subtypes */ @tu lazy val universalCSImpliedByCapability = CaptureSet(captureRoot.termRef) @@ -1066,7 +1065,7 @@ class Definitions { @tu lazy val UncheckedStableAnnot: ClassSymbol = requiredClass("scala.annotation.unchecked.uncheckedStable") @tu lazy val UncheckedVarianceAnnot: ClassSymbol = requiredClass("scala.annotation.unchecked.uncheckedVariance") @tu lazy val UncheckedCapturesAnnot: ClassSymbol = requiredClass("scala.annotation.unchecked.uncheckedCaptures") - @tu lazy val UntrackedCapturesAnnot: ClassSymbol = requiredClass("scala.caps.untrackedCaptures") + @tu lazy val UntrackedCapturesAnnot: ClassSymbol = requiredClass("scala.caps.unsafe.untrackedCaptures") @tu lazy val UseAnnot: ClassSymbol = requiredClass("scala.caps.use") @tu lazy val VolatileAnnot: ClassSymbol = requiredClass("scala.volatile") @tu lazy val LanguageFeatureMetaAnnot: ClassSymbol = requiredClass("scala.annotation.meta.languageFeature") @@ -2090,7 +2089,12 @@ class Definitions { */ @tu lazy val ccExperimental: Set[Symbol] = Set( CapsModule, CapsModule.moduleClass, PureClass, + Caps_Capability, // TODO: Remove when Capability is stabilized RequiresCapabilityAnnot, + captureRoot, Caps_CapSet, Caps_ContainsTrait, Caps_ContainsModule, Caps_ContainsModule.moduleClass, UseAnnot, + Caps_Exists, + CapsUnsafeModule, CapsUnsafeModule.moduleClass, + CapsInternalModule, CapsInternalModule.moduleClass, RetainsAnnot, RetainsCapAnnot, RetainsByNameAnnot) /** Experimental language features defined in `scala.runtime.stdLibPatches.language.experimental`. diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index 39297697f29a..6a9d70a19f49 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -78,7 +78,7 @@ object SymbolLoaders { * and give them `completer` as type. */ def enterPackage(owner: Symbol, pname: TermName, completer: (TermSymbol, ClassSymbol) => PackageLoader)(using Context): Symbol = { - val preExisting = owner.info.decls lookup pname + val preExisting = owner.info.decls.lookup(pname) if (preExisting != NoSymbol) // Some jars (often, obfuscated ones) include a package and // object with the same name. Rather than render them unusable, @@ -95,6 +95,18 @@ object SymbolLoaders { s"Resolving package/object name conflict in favor of object ${preExisting.fullName}. The package will be inaccessible.") return NoSymbol } + else if pname == nme.caps && owner == defn.ScalaPackageClass then + // `scala.caps`` was an object until 3.6, it is a package from 3.7. Without special handling + // this would cause a TypeError to be thrown below if a build has several versions of the + // Scala standard library on the classpath. This was the case for 29 projects in OpenCB. + // These projects should be updated. But until that's the case we issue a warning instead + // of a hard failure. + report.warning( + em"""$owner contains object and package with same name: $pname. + |This indicates that there are several versions of the Scala standard library on the classpath. + |The build should be reconfigured so that only one version of the standard library is on the classpath.""") + owner.info.decls.openForMutations.unlink(preExisting) + owner.info.decls.openForMutations.unlink(preExisting.moduleClass) else throw TypeError( em"""$owner contains object and package with same name: $pname diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 821c7833a737..c8ede8bfdec2 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -641,6 +641,32 @@ object Symbols extends SymUtils { newClassSymbol(owner, name, flags, completer, privateWithin, coord, compUnitInfo) } + /** Same as the other `newNormalizedClassSymbol` except that `parents` can be a function returning a list of arbitrary + * types which get normalized into type refs and parameter bindings and annotations can be assigned in the completer. + */ + def newNormalizedClassSymbol( + owner: Symbol, + name: TypeName, + flags: FlagSet, + parentTypes: Symbol => List[Type], + selfInfo: Type, + privateWithin: Symbol, + annotations: List[Tree], + coord: Coord, + compUnitInfo: CompilationUnitInfo | Null)(using Context): ClassSymbol = { + def completer = new LazyType { + def complete(denot: SymDenotation)(using Context): Unit = { + val cls = denot.asClass.classSymbol + val decls = newScope + val parents = parentTypes(cls).map(_.dealias) + assert(parents.nonEmpty && !parents.head.typeSymbol.is(dotc.core.Flags.Trait), "First parent must be a class") + denot.info = ClassInfo(owner.thisType, cls, parents, decls, selfInfo) + denot.annotations = annotations.map(Annotations.Annotation(_)) + } + } + newClassSymbol(owner, name, flags, completer, privateWithin, coord, compUnitInfo) + } + def newRefinedClassSymbol(coord: Coord = NoCoord)(using Context): ClassSymbol = newCompleteClassSymbol(ctx.owner, tpnme.REFINE_CLASS, NonMember, parents = Nil, newScope, coord = coord) @@ -718,6 +744,34 @@ object Symbols extends SymUtils { privateWithin, coord, compUnitInfo) } + /** Same as `newNormalizedModuleSymbol` except that `parents` can be a function returning a list of arbitrary + * types which get normalized into type refs and parameter bindings. + */ + def newNormalizedModuleSymbol( + owner: Symbol, + name: TermName, + modFlags: FlagSet, + clsFlags: FlagSet, + parentTypes: ClassSymbol => List[Type], + decls: Scope, + privateWithin: Symbol, + coord: Coord, + compUnitInfo: CompilationUnitInfo | Null)(using Context): TermSymbol = { + def completer(module: Symbol) = new LazyType { + def complete(denot: SymDenotation)(using Context): Unit = { + val cls = denot.asClass.classSymbol + val decls = newScope + val parents = parentTypes(cls).map(_.dealias) + assert(parents.nonEmpty && !parents.head.typeSymbol.is(dotc.core.Flags.Trait), "First parent must be a class") + denot.info = ClassInfo(owner.thisType, cls, parents, decls, TermRef(owner.thisType, module)) + } + } + newModuleSymbol( + owner, name, modFlags, clsFlags, + (module, modcls) => completer(module), + privateWithin, coord, compUnitInfo) + } + /** Create a package symbol with associated package class * from its non-info fields and a lazy type for loading the package's members. */ diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index cc0471d40213..0139ff2c865e 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -369,8 +369,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling } compareWild case tp2: LazyRef => - isBottom(tp1) - || !tp2.evaluating && recur(tp1, tp2.ref) + isBottom(tp1) || !tp2.evaluating && recur(tp1, tp2.ref) case CapturingType(_, _) => secondTry case tp2: AnnotatedType if !tp2.isRefining => @@ -493,7 +492,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling // If `tp1` is in train of being evaluated, don't force it // because that would cause an assertionError. Return false instead. // See i859.scala for an example where we hit this case. - tp2.isAny + tp2.isRef(AnyClass, skipRefined = false) || !tp1.evaluating && recur(tp1.ref, tp2) case AndType(tp11, tp12) => if tp11.stripTypeVar eq tp12.stripTypeVar then recur(tp11, tp2) diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index a7f41a71d7ce..e3168ca5a27d 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -124,7 +124,7 @@ object TypeOps: } def isLegalPrefix(pre: Type)(using Context): Boolean = - pre.isStable + pre.isStable || !ctx.phase.isTyper /** Implementation of Types#simplified */ def simplify(tp: Type, theMap: SimplifyMap | Null)(using Context): Type = { diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 7c0c89da97ee..15b295af963e 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -98,8 +98,12 @@ object Types extends TypeUtils { // ----- Tests ----------------------------------------------------- // // debug only: a unique identifier for a type -// val uniqId = { nextId = nextId + 1; nextId } -// if uniqId == 19555 then trace.dumpStack() +// val uniqId = { +// nextId = nextId + 1 +// if (nextId == 19555) +// println("foo") +// nextId +// } /** A cache indicating whether the type was still provisional, last time we checked */ @sharable private var mightBeProvisional = true @@ -5575,25 +5579,24 @@ object Types extends TypeUtils { } def & (that: TypeBounds)(using Context): TypeBounds = - val lo1 = this.lo.stripLazyRef - val lo2 = that.lo.stripLazyRef - val hi1 = this.hi.stripLazyRef - val hi2 = that.hi.stripLazyRef - // This will try to preserve the FromJavaObjects type in upper bounds. // For example, (? <: FromJavaObjects | Null) & (? <: Any), // we want to get (? <: FromJavaObjects | Null) intead of (? <: Any), // because we may check the result <:< (? <: Object | Null) later. - if hi1.containsFromJavaObject && (hi1 frozen_<:< hi2) && (lo2 frozen_<:< lo1) then + if this.hi.containsFromJavaObject + && (this.hi frozen_<:< that.hi) + && (that.lo frozen_<:< this.lo) then // FromJavaObject in tp1.hi guarantees tp2.hi <:< tp1.hi // prefer tp1 if FromJavaObject is in its hi this - else if hi2.containsFromJavaObject && (hi2 frozen_<:< hi1) && (lo1 frozen_<:< lo2) then + else if that.hi.containsFromJavaObject + && (that.hi frozen_<:< this.hi) + && (this.lo frozen_<:< that.lo) then // Similarly, prefer tp2 if FromJavaObject is in its hi that - else if (lo1 frozen_<:< lo2) && (hi2 frozen_<:< hi1) then that - else if (lo2 frozen_<:< lo1) && (hi1 frozen_<:< hi2) then this - else TypeBounds(lo1 | lo2, hi1 & hi2) + else if (this.lo frozen_<:< that.lo) && (that.hi frozen_<:< this.hi) then that + else if (that.lo frozen_<:< this.lo) && (this.hi frozen_<:< that.hi) then this + else TypeBounds(this.lo | that.lo, this.hi & that.hi) def | (that: TypeBounds)(using Context): TypeBounds = if ((this.lo frozen_<:< that.lo) && (that.hi frozen_<:< this.hi)) this @@ -5602,7 +5605,7 @@ object Types extends TypeUtils { override def & (that: Type)(using Context): Type = that match { case that: TypeBounds => this & that - case _ => super.&(that) + case _ => super.& (that) } override def | (that: Type)(using Context): Type = that match { diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index f87f0d957325..20eb6e9b33fa 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -2956,7 +2956,7 @@ object Parsers { /** Enumerators ::= Generator {semi Enumerator | Guard} */ def enumerators(): List[Tree] = - if sourceVersion.isAtLeast(`3.7`) then + if sourceVersion.enablesBetterFors then aliasesUntilGenerator() ++ enumeratorsRest() else generator() :: enumeratorsRest() diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index ed20c189796b..6ae2f7999d33 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -603,6 +603,20 @@ object Scanners { lastWidth = r.knownWidth newlineIsSeparating = r.isInstanceOf[InBraces] + // can emit OUTDENT if line is not non-empty blank line at EOF + inline def isTrailingBlankLine: Boolean = + token == EOF && { + val end = buf.length - 1 // take terminal NL as empty last line + val prev = buf.lastIndexWhere(!isWhitespace(_), end = end) + prev < 0 || end - prev > 0 && isLineBreakChar(buf(prev)) + } + + inline def canDedent: Boolean = + lastToken != INDENT + && !isLeadingInfixOperator(nextWidth) + && !statCtdTokens.contains(lastToken) + && !isTrailingBlankLine + if newlineIsSeparating && canEndStatTokens.contains(lastToken) && canStartStatTokens.contains(token) @@ -615,9 +629,8 @@ object Scanners { || nextWidth == lastWidth && (indentPrefix == MATCH || indentPrefix == CATCH) && token != CASE then if currentRegion.isOutermost then if nextWidth < lastWidth then currentRegion = topLevelRegion(nextWidth) - else if !isLeadingInfixOperator(nextWidth) && !statCtdTokens.contains(lastToken) && lastToken != INDENT then + else if canDedent then currentRegion match - case _ if token == EOF => // no OUTDENT at EOF case r: Indented => insert(OUTDENT, offset) handleNewIndentWidth(r.enclosing, ir => @@ -671,13 +684,16 @@ object Scanners { reset() if atEOL then token = COLONeol - // consume => and insert if applicable + // consume => and insert if applicable. Used to detect colon arrow: x => def observeArrowIndented(): Unit = if isArrow && indentSyntax then peekAhead() - val atEOL = isAfterLineEnd || token == EOF + val atEOL = isAfterLineEnd + val atEOF = token == EOF reset() - if atEOL then + if atEOF then + token = EOF + else if atEOL then val nextWidth = indentWidth(next.offset) val lastWidth = currentRegion.indentWidth if lastWidth < nextWidth then diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index e90aeb217362..53e9a2c2098b 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -187,10 +187,11 @@ class PlainPrinter(_ctx: Context) extends Printer { homogenize(tp) match { case tp: TypeType => toTextRHS(tp) + case tp: TermRef if tp.isRootCapability => + toTextCaptureRef(tp) case tp: TermRef if !tp.denotationIsCurrent && !homogenizedView // always print underlying when testing picklers - && !tp.isRootCapability || tp.symbol.is(Module) || tp.symbol.name == nme.IMPORT => toTextRef(tp) ~ ".type" diff --git a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala index 24763abc21b4..2ee3ea825edc 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckUnused.scala @@ -145,9 +145,10 @@ class CheckUnused private (phaseMode: PhaseMode, suffix: String) extends MiniPha refInfos.inlined.push(tree.call.srcPos) ctx override def transformInlined(tree: Inlined)(using Context): tree.type = - transformAllDeep(tree.expansion) // traverse expansion with nonempty inlined stack to avoid registering defs + //transformAllDeep(tree.expansion) // traverse expansion with nonempty inlined stack to avoid registering defs val _ = refInfos.inlined.pop() - transformAllDeep(tree.call) + if !tree.call.isEmpty && phaseMode.eq(PhaseMode.Aggregate) then + transformAllDeep(tree.call) tree override def prepareForBind(tree: Bind)(using Context): Context = diff --git a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala index 8d01d2415340..8fc9f02c1e38 100644 --- a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala +++ b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala @@ -19,10 +19,14 @@ import NameKinds.OuterSelectName import StdNames.* import config.Feature import inlines.Inlines.inInlineMethod +import util.Property object FirstTransform { val name: String = "firstTransform" val description: String = "some transformations to put trees into a canonical form" + + /** Attachment key for named argument patterns */ + val WasNamedArg: Property.StickyKey[Unit] = Property.StickyKey() } /** The first tree transform @@ -38,6 +42,7 @@ object FirstTransform { */ class FirstTransform extends MiniPhase with SymTransformer { thisPhase => import ast.tpd.* + import FirstTransform.* override def phaseName: String = FirstTransform.name @@ -156,7 +161,13 @@ class FirstTransform extends MiniPhase with SymTransformer { thisPhase => override def transformOther(tree: Tree)(using Context): Tree = tree match { case tree: Export => EmptyTree - case tree: NamedArg => transformAllDeep(tree.arg) + case tree: NamedArg => + val res = transformAllDeep(tree.arg) + if ctx.mode.is(Mode.Pattern) then + // Need to keep NamedArg status for pattern matcher to work correctly when faced + // with single-element named tuples. + res.pushAttachment(WasNamedArg, ()) + res case tree => if (tree.isType) toTypeTree(tree) else tree } diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index 250d4844d2b3..e2505144abda 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -386,9 +386,20 @@ object PatternMatcher { } else letAbstract(get) { getResult => - val selectors = - if (args.tail.isEmpty) ref(getResult) :: Nil - else productSelectors(getResult.info).map(ref(getResult).select(_)) + def isUnaryNamedTupleSelectArg(arg: Tree) = + get.tpe.widenDealias.isNamedTupleType + && arg.removeAttachment(FirstTransform.WasNamedArg).isDefined + // Special case: Normally, we pull out the argument wholesale if + // there is only one. But if the argument is a named argument for + // a single-element named tuple, we have to select the field instead. + // NamedArg trees are eliminated in FirstTransform but for named arguments + // of patterns we add a WasNamedArg attachment, which is used to guide the + // logic here. See i22900.scala for test cases. + val selectors = args match + case arg :: Nil if !isUnaryNamedTupleSelectArg(arg) => + ref(getResult) :: Nil + case _ => + productSelectors(getResult.info).map(ref(getResult).select(_)) matchArgsPlan(selectors, args, onSuccess) } } diff --git a/compiler/src/dotty/tools/dotc/transform/Recheck.scala b/compiler/src/dotty/tools/dotc/transform/Recheck.scala index 8936c460de81..bd87ebd8abe1 100644 --- a/compiler/src/dotty/tools/dotc/transform/Recheck.scala +++ b/compiler/src/dotty/tools/dotc/transform/Recheck.scala @@ -219,10 +219,10 @@ abstract class Recheck extends Phase, SymTransformer: sharpen: Denotation => Denotation)(using Context): Type = if name.is(OuterSelectName) then tree.tpe else - val pre = ta.maybeSkolemizePrefix(qualType, name) + //val pre = ta.maybeSkolemizePrefix(qualType, name) val mbr = sharpen( - qualType.findMember(name, pre, + qualType.findMember(name, qualType, excluded = if tree.symbol.is(Private) then EmptyFlags else Private )).suchThat(tree.symbol == _) val newType = tree.tpe match diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index c35dc80c04a5..90262bc5da85 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -854,30 +854,34 @@ object TreeChecker { val phases = ctx.base.allPhases.toList val treeChecker = new LocalChecker(previousPhases(phases)) + def reportMalformedMacroTree(msg: String | Null, err: Throwable) = + val stack = + if !ctx.settings.Ydebug.value then "\nstacktrace available when compiling with `-Ydebug`" + else if err.getStackTrace == null then " no stacktrace" + else err.getStackTrace.nn.mkString(" ", " \n", "") + report.error( + em"""Malformed tree was found while expanding macro with -Xcheck-macros. + |The tree does not conform to the compiler's tree invariants. + | + |Macro was: + |${scala.quoted.runtime.impl.QuotesImpl.showDecompiledTree(original)} + | + |The macro returned: + |${scala.quoted.runtime.impl.QuotesImpl.showDecompiledTree(expansion)} + | + |Error: + |$msg + |$stack + |""", + original + ) + try treeChecker.typed(expansion)(using checkingCtx) catch case err: java.lang.AssertionError => - val stack = - if !ctx.settings.Ydebug.value then "\nstacktrace available when compiling with `-Ydebug`" - else if err.getStackTrace == null then " no stacktrace" - else err.getStackTrace.nn.mkString(" ", " \n", "") - - report.error( - em"""Malformed tree was found while expanding macro with -Xcheck-macros. - |The tree does not conform to the compiler's tree invariants. - | - |Macro was: - |${scala.quoted.runtime.impl.QuotesImpl.showDecompiledTree(original)} - | - |The macro returned: - |${scala.quoted.runtime.impl.QuotesImpl.showDecompiledTree(expansion)} - | - |Error: - |${err.getMessage} - |$stack - |""", - original - ) + reportMalformedMacroTree(err.getMessage(), err) + case err: UnhandledError => + reportMalformedMacroTree(err.diagnostic.message, err) private[TreeChecker] def previousPhases(phases: List[Phase])(using Context): List[Phase] = phases match { case (phase: MegaPhase) :: phases1 => diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 30b892ece470..ab5885e6278c 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -279,7 +279,7 @@ object SpaceEngine { || unappResult <:< ConstantType(Constant(true)) // only for unapply || (unapp.symbol.is(Synthetic) && unapp.symbol.owner.linkedClass.is(Case)) // scala2 compatibility || unapplySeqTypeElemTp(unappResult).exists // only for unapplySeq - || isProductMatch(unappResult, argLen) + || isProductMatch(unappResult.stripNamedTuple, argLen) || extractorMemberType(unappResult, nme.isEmpty, NoSourcePosition) <:< ConstantType(Constant(false)) || unappResult.derivesFrom(defn.NonEmptyTupleClass) || unapp.symbol == defn.TupleXXL_unapplySeq // Fixes TupleXXL.unapplySeq which returns Some but declares Option diff --git a/compiler/src/dotty/tools/dotc/transform/sjs/PrepJSExports.scala b/compiler/src/dotty/tools/dotc/transform/sjs/PrepJSExports.scala index 5aa35a277cb5..43b29a224564 100644 --- a/compiler/src/dotty/tools/dotc/transform/sjs/PrepJSExports.scala +++ b/compiler/src/dotty/tools/dotc/transform/sjs/PrepJSExports.scala @@ -21,7 +21,7 @@ import dotty.tools.backend.sjs.JSDefinitions.jsdefn import JSExportUtils.* import JSSymUtils.* -import dotty.tools.sjs.ir.Names.DefaultModuleID +import dotty.tools.sjs.ir.WellKnownNames.DefaultModuleID import dotty.tools.sjs.ir.Trees.TopLevelExportDef.isValidTopLevelExportName object PrepJSExports { diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 71fc250d0710..058cd2de332c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -2119,27 +2119,16 @@ trait Applications extends Compatibility { def resolveOverloaded(alts: List[TermRef], pt: Type)(using Context): List[TermRef] = record("resolveOverloaded") - /** Is `alt` a method or polytype whose approximated result type after the first value parameter + /** Is `alt` a method or polytype whose result type after the first value parameter * section conforms to the expected type `resultType`? If `resultType` * is a `IgnoredProto`, pick the underlying type instead. - * - * Using an approximated result type is necessary to avoid false negatives - * due to incomplete type inference such as in tests/pos/i21410.scala and tests/pos/i21410b.scala. */ def resultConforms(altSym: Symbol, altType: Type, resultType: Type)(using Context): Boolean = resultType.revealIgnored match { case resultType: ValueType => altType.widen match { - case tp: PolyType => resultConforms(altSym, tp.resultType, resultType) - case tp: MethodType => - val wildRes = wildApprox(tp.resultType) - - class ResultApprox extends AvoidWildcardsMap: - // Avoid false negatives by approximating to a lower bound - variance = -1 - - val approx = ResultApprox()(wildRes) - constrainResult(altSym, approx, resultType) + case tp: PolyType => resultConforms(altSym, instantiateWithTypeVars(tp), resultType) + case tp: MethodType => constrainResult(altSym, tp.resultType, resultType) case _ => true } case _ => true @@ -2511,7 +2500,6 @@ trait Applications extends Compatibility { if t.exists && alt.symbol.exists then val (trimmed, skipped) = trimParamss(t.stripPoly, alt.symbol.rawParamss) val mappedSym = alt.symbol.asTerm.copy(info = t) - mappedSym.annotations = alt.symbol.annotations mappedSym.rawParamss = trimmed val (pre, totalSkipped) = mappedAltInfo(alt.symbol) match case Some((pre, prevSkipped)) => diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index ec07fefc64ab..2d6817f74ff7 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -1036,6 +1036,8 @@ trait Checking { pats.forall(recur(_, pt)) case Typed(arg, tpt) => check(pat, pt) && recur(arg, pt) + case NamedArg(name, pat) => + recur(pat, pt) case Ident(nme.WILDCARD) => true case pat: QuotePattern => diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 0442c72af6f0..89dc4cf53472 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -134,7 +134,7 @@ class Namer { typer: Typer => * The logic here is very subtle and fragile due to the fact that * we are not allowed to force anything. */ - def checkNoConflict(name: Name, isPrivate: Boolean, span: Span)(using Context): Name = + def checkNoConflict(name: Name, span: Span)(using Context): Name = val owner = ctx.owner var conflictsDetected = false @@ -169,7 +169,7 @@ class Namer { typer: Typer => def preExisting = ctx.effectiveScope.lookup(name) if (!owner.isClass || name.isTypeName) && preExisting.exists then conflict(preExisting) - else if owner.isPackageObject && !isPrivate && name != nme.CONSTRUCTOR then + else if owner.isPackageObject && name != nme.CONSTRUCTOR then checkNoConflictIn(owner.owner) for pkgObj <- pkgObjs(owner.owner) if pkgObj != owner do checkNoConflictIn(pkgObj) @@ -249,7 +249,7 @@ class Namer { typer: Typer => var flags = checkFlags(tree.mods.flags) if ctx.settings.YcompileScala2Library.value then flags |= Scala2x - val name = checkNoConflict(tree.name, flags.is(Private), tree.span).asTypeName + val name = checkNoConflict(tree.name, tree.span).asTypeName val cls = createOrRefine[ClassSymbol](tree, name, flags, ctx.owner, cls => adjustIfModule(new ClassCompleter(cls, tree)(ctx), tree), @@ -258,7 +258,7 @@ class Namer { typer: Typer => cls case tree: MemberDef => var flags = checkFlags(tree.mods.flags) - val name = checkNoConflict(tree.name, flags.is(Private), tree.span) + val name = checkNoConflict(tree.name, tree.span) tree match case tree: ValOrDefDef => if tree.isInstanceOf[ValDef] && !flags.is(Param) && name.endsWith("_=") then @@ -1264,7 +1264,7 @@ class Namer { typer: Typer => val hasDefaults = sym.hasDefaultParams // compute here to ensure HasDefaultParams and NoDefaultParams flags are set val forwarder = if mbr.isType then - val forwarderName = checkNoConflict(alias.toTypeName, isPrivate = false, span) + val forwarderName = checkNoConflict(alias.toTypeName, span) var target = pathType.select(sym) if target.typeParams.nonEmpty then target = target.etaExpand @@ -1320,7 +1320,7 @@ class Namer { typer: Typer => (EmptyFlags, mbrInfo) var mbrFlags = MandatoryExportTermFlags | maybeStable | (sym.flags & RetainedExportTermFlags) if pathMethod.exists then mbrFlags |= ExtensionMethod - val forwarderName = checkNoConflict(alias, isPrivate = false, span) + val forwarderName = checkNoConflict(alias, span) newSymbol(cls, forwarderName, mbrFlags, mbrInfo, coord = span) forwarder.info = avoidPrivateLeaks(forwarder) diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 28af86344621..4d16a342f484 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -12,6 +12,7 @@ import collection.mutable import reporting.* import Checking.{checkNoPrivateLeaks, checkNoWildcard} import cc.CaptureSet +import transform.Splicer trait TypeAssigner { import tpd.* @@ -301,7 +302,10 @@ trait TypeAssigner { if fntpe.isResultDependent then safeSubstMethodParams(fntpe, args.tpes) else fntpe.resultType // fast path optimization else - errorType(em"wrong number of arguments at ${ctx.phase.prev} for $fntpe: ${fn.tpe}, expected: ${fntpe.paramInfos.length}, found: ${args.length}", tree.srcPos) + val erroringPhase = + if Splicer.inMacroExpansion then i"${ctx.phase} (while expanding macro)" + else ctx.phase.prev.toString + errorType(em"wrong number of arguments at $erroringPhase for $fntpe: ${fn.tpe}, expected: ${fntpe.paramInfos.length}, found: ${args.length}", tree.srcPos) case err: ErrorType => err case t => diff --git a/compiler/src/dotty/tools/dotc/util/Chars.scala b/compiler/src/dotty/tools/dotc/util/Chars.scala index 916bdfa9dca3..e68c48903a63 100644 --- a/compiler/src/dotty/tools/dotc/util/Chars.scala +++ b/compiler/src/dotty/tools/dotc/util/Chars.scala @@ -50,7 +50,7 @@ object Chars: } /** Is character a whitespace character (but not a new line)? */ - def isWhitespace(c: Char): Boolean = + inline def isWhitespace(c: Char): Boolean = c == ' ' || c == '\t' || c == CR /** Can character form part of a doc comment variable $xxx? */ diff --git a/compiler/src/dotty/tools/repl/ReplDriver.scala b/compiler/src/dotty/tools/repl/ReplDriver.scala index 0b67c36492ae..6f682ac96a1a 100644 --- a/compiler/src/dotty/tools/repl/ReplDriver.scala +++ b/compiler/src/dotty/tools/repl/ReplDriver.scala @@ -188,7 +188,7 @@ class ReplDriver(settings: Array[String], /* complete = */ false // if true adds space when completing ) } - val comps = completions(line.cursor, line.line, state) + val comps = completionsWithSignatures(line.cursor, line.line, state) candidates.addAll(comps.map(_.label).distinct.map(makeCandidate).asJava) val lineWord = line.word() comps.filter(c => c.label == lineWord && c.symbols.nonEmpty) match @@ -275,8 +275,22 @@ class ReplDriver(settings: Array[String], else label + @deprecated("Use completionsWithSignatures instead", "3.4.2") + protected final def completions(cursor: Int, expr: String, state0: State): List[Candidate] = + completionsWithSignatures(cursor, expr, state0).map: c => + new Candidate( + /* value = */ c.label, + /* displ = */ stripBackTicks(c.label), // displayed value + /* group = */ null, // can be used to group completions together + /* descr = */ null, // TODO use for documentation? + /* suffix = */ null, + /* key = */ null, + /* complete = */ false // if true adds space when completing + ) + end completions + /** Extract possible completions at the index of `cursor` in `expr` */ - protected final def completions(cursor: Int, expr: String, state0: State): List[Completion] = + protected final def completionsWithSignatures(cursor: Int, expr: String, state0: State): List[Completion] = if expr.startsWith(":") then ParseResult.commands.collect { case command if command._1.startsWith(expr) => Completion(command._1, "", List()) @@ -295,7 +309,7 @@ class ReplDriver(settings: Array[String], try Completion.completions(srcPos)._2 catch case NonFatal(_) => Nil } .getOrElse(Nil) - end completions + end completionsWithSignatures protected def interpret(res: ParseResult)(using state: State): State = { res match { diff --git a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala index 1c420dd93b29..a93e010ddc34 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala @@ -25,6 +25,8 @@ import scala.quoted.runtime.impl.printers.* import scala.reflect.TypeTest import dotty.tools.dotc.core.NameKinds.ExceptionBinderName import dotty.tools.dotc.transform.TreeChecker +import dotty.tools.dotc.core.Names +import dotty.tools.dotc.util.Spans.NoCoord object QuotesImpl { @@ -241,9 +243,35 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler object ClassDef extends ClassDefModule: def apply(cls: Symbol, parents: List[Tree], body: List[Statement]): ClassDef = - val untpdCtr = untpd.DefDef(nme.CONSTRUCTOR, Nil, tpd.TypeTree(dotc.core.Symbols.defn.UnitClass.typeRef), tpd.EmptyTree) + val paramsDefs: List[untpd.ParamClause] = + cls.primaryConstructor.paramSymss.map { paramSym => + if paramSym.headOption.map(_.isType).getOrElse(false) then + paramSym.map(sym => TypeDef(sym)) + else + paramSym.map(ValDef(_, None)) + } + def throwError() = + throw new RuntimeException( + "Symbols necessary for creation of the ClassDef tree could not be found." + ) + val paramsAccessDefs: List[untpd.ParamClause] = + cls.primaryConstructor.paramSymss.map { paramSym => + if paramSym.headOption.map(_.isType).getOrElse(false) then + paramSym.map { symm => + def isParamAccessor(memberSym: Symbol) = memberSym.flags.is(Flags.Param) && memberSym.name == symm.name + TypeDef(cls.typeMembers.find(isParamAccessor).getOrElse(throwError())) + } + else + paramSym.map { symm => + def isParam(memberSym: Symbol) = memberSym.flags.is(Flags.ParamAccessor) && memberSym.name == symm.name + ValDef(cls.fieldMembers.find(isParam).getOrElse(throwError()), None) + } + } + + val termSymbol: dotc.core.Symbols.TermSymbol = cls.primaryConstructor.asTerm + val untpdCtr = untpd.DefDef(nme.CONSTRUCTOR, paramsDefs, tpd.TypeTree(dotc.core.Symbols.defn.UnitClass.typeRef), tpd.EmptyTree) val ctr = ctx.typeAssigner.assignType(untpdCtr, cls.primaryConstructor) - tpd.ClassDefWithParents(cls.asClass, ctr, parents, body) + tpd.ClassDefWithParents(cls.asClass, ctr, parents, paramsAccessDefs.flatten ++ body) def copy(original: Tree)(name: String, constr: DefDef, parents: List[Tree], selfOpt: Option[ValDef], body: List[Statement]): ClassDef = { val dotc.ast.Trees.TypeDef(_, originalImpl: tpd.Template) = original: @unchecked @@ -2655,8 +2683,134 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler for sym <- decls(cls) do cls.enter(sym) cls - def newModule(owner: Symbol, name: String, modFlags: Flags, clsFlags: Flags, parents: List[TypeRepr], decls: Symbol => List[Symbol], privateWithin: Symbol): Symbol = - assert(parents.nonEmpty && !parents.head.typeSymbol.is(dotc.core.Flags.Trait), "First parent must be a class") + def newClass( + owner: Symbol, + name: String, + parents: Symbol => List[TypeRepr], + decls: Symbol => List[Symbol], + selfType: Option[TypeRepr], + clsFlags: Flags, + clsPrivateWithin: Symbol, + conParams: List[(String, TypeRepr)] + ): Symbol = + val (conParamNames, conParamTypes) = conParams.unzip + newClass( + owner, + name, + parents, + decls, + selfType, + clsFlags, + clsPrivateWithin, + Nil, + conMethodType = res => MethodType(conParamNames)(_ => conParamTypes, _ => res), + conFlags = Flags.EmptyFlags, + conPrivateWithin = Symbol.noSymbol, + conParamFlags = List(for i <- conParamNames yield Flags.EmptyFlags), + conParamPrivateWithins = List(for i <- conParamNames yield Symbol.noSymbol) + ) + + def newClass( + owner: Symbol, + name: String, + parents: Symbol => List[TypeRepr], + decls: Symbol => List[Symbol], + selfType: Option[TypeRepr], + clsFlags: Flags, + clsPrivateWithin: Symbol, + clsAnnotations: List[Term], + conMethodType: TypeRepr => MethodOrPoly, + conFlags: Flags, + conPrivateWithin: Symbol, + conParamFlags: List[List[Flags]], + conParamPrivateWithins: List[List[Symbol]] + ) = + assert(!clsPrivateWithin.exists || clsPrivateWithin.isType, "clsPrivateWithin must be a type symbol or `Symbol.noSymbol`") + assert(!conPrivateWithin.exists || conPrivateWithin.isType, "consPrivateWithin must be a type symbol or `Symbol.noSymbol`") + checkValidFlags(clsFlags.toTypeFlags, Flags.validClassFlags) + checkValidFlags(conFlags.toTermFlags, Flags.validClassConstructorFlags) + val cls = dotc.core.Symbols.newNormalizedClassSymbol( + owner, + name.toTypeName, + clsFlags, + parents, + selfType.getOrElse(Types.NoType), + clsPrivateWithin, + clsAnnotations, + NoCoord, + compUnitInfo = null + ) + val methodType: MethodOrPoly = conMethodType(cls.typeRef) + def throwShapeException() = throw new Exception("Shapes of conMethodType and conParamFlags differ.") + def checkMethodOrPolyShape(checkedMethodType: TypeRepr, clauseIdx: Int): Unit = + checkedMethodType match + case PolyType(params, _, res) if clauseIdx == 0 => + if (conParamFlags.length < clauseIdx) throwShapeException() + if (conParamFlags(clauseIdx).length != params.length) throwShapeException() + checkMethodOrPolyShape(res, clauseIdx + 1) + case PolyType(_, _, _) => throw new Exception("Clause interleaving not supported for constructors") + case MethodType(params, _, res) => + if (conParamFlags.length <= clauseIdx) throwShapeException() + if (conParamFlags(clauseIdx).length != params.length) throwShapeException() + checkMethodOrPolyShape(res, clauseIdx + 1) + case other => + xCheckMacroAssert( + other.typeSymbol == cls, + "Incorrect type returned from the innermost PolyOrMethod." + ) + (other, methodType) match + case (AppliedType(tycon, args), pt: PolyType) => + xCheckMacroAssert( + args.length == pt.typeParams.length && + args.zip(pt.typeParams).forall { + case (arg, param) => arg == param.paramRef + }, + "Constructor result type does not correspond to the declared type parameters" + ) + case _ => + xCheckMacroAssert( + !(other.isInstanceOf[AppliedType] || methodType.isInstanceOf[PolyType]), + "AppliedType has to be the innermost resultTypeExp result if and only if conMethodType returns a PolyType" + ) + checkMethodOrPolyShape(methodType, clauseIdx = 0) + + cls.enter(dotc.core.Symbols.newSymbol(cls, nme.CONSTRUCTOR, Flags.Synthetic | Flags.Method | conFlags, methodType, conPrivateWithin, dotty.tools.dotc.util.Spans.NoCoord)) + + case class ParamSymbolData(name: String, tpe: TypeRepr, isTypeParam: Boolean, clauseIdx: Int, elementIdx: Int) + def getParamSymbolsData(methodType: TypeRepr, clauseIdx: Int): List[ParamSymbolData] = + methodType match + case MethodType(paramInfosExp, resultTypeExp, res) => + paramInfosExp.zip(resultTypeExp).zipWithIndex.map { case ((name, tpe), elementIdx) => + ParamSymbolData(name, tpe, isTypeParam = false, clauseIdx, elementIdx) + } ++ getParamSymbolsData(res, clauseIdx + 1) + case pt @ PolyType(paramNames, paramBounds, res) => + paramNames.zip(paramBounds).zipWithIndex.map {case ((name, tpe), elementIdx) => + ParamSymbolData(name, tpe, isTypeParam = true, clauseIdx, elementIdx) + } ++ getParamSymbolsData(res, clauseIdx + 1) + case result => + List() + // Maps PolyType indexes to type parameter symbol typerefs + val paramRefMap = collection.mutable.HashMap[Int, Symbol]() + val paramRefRemapper = new Types.TypeMap { + def apply(tp: Types.Type) = tp match { + case pRef: ParamRef if pRef.binder == methodType => paramRefMap(pRef.paramNum).typeRef + case _ => mapOver(tp) + } + } + for case ParamSymbolData(name, tpe, isTypeParam, clauseIdx, elementIdx) <- getParamSymbolsData(methodType, 0) do + if isTypeParam then + checkValidFlags(conParamFlags(clauseIdx)(elementIdx).toTypeFlags, Flags.validClassTypeParamFlags) + val symbol = dotc.core.Symbols.newSymbol(cls, name.toTypeName, Flags.Param | Flags.Deferred | Flags.Private | Flags.PrivateLocal | Flags.Local | conParamFlags(clauseIdx)(elementIdx), tpe, conParamPrivateWithins(clauseIdx)(elementIdx)) + paramRefMap.addOne(elementIdx, symbol) + cls.enter(symbol) + else + checkValidFlags(conParamFlags(clauseIdx)(elementIdx).toTermFlags, Flags.validClassTermParamFlags) + val fixedType = paramRefRemapper(tpe) + cls.enter(dotc.core.Symbols.newSymbol(cls, name.toTermName, Flags.ParamAccessor | conParamFlags(clauseIdx)(elementIdx), fixedType, conParamPrivateWithins(clauseIdx)(elementIdx))) + for sym <- decls(cls) do cls.enter(sym) + cls + + def newModule(owner: Symbol, name: String, modFlags: Flags, clsFlags: Flags, parents: Symbol => List[TypeRepr], decls: Symbol => List[Symbol], privateWithin: Symbol): Symbol = assert(!privateWithin.exists || privateWithin.isType, "privateWithin must be a type symbol or `Symbol.noSymbol`") val mod = dotc.core.Symbols.newNormalizedModuleSymbol( owner, @@ -2665,7 +2819,10 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler clsFlags | dotc.core.Flags.ModuleClassCreationFlags, parents, dotc.core.Scopes.newScope, - privateWithin) + privateWithin, + NoCoord, + compUnitInfo = null + ) val cls = mod.moduleClass.asClass cls.enter(dotc.core.Symbols.newConstructor(cls, dotc.core.Flags.Synthetic, Nil, Nil)) for sym <- decls(cls) do cls.enter(sym) @@ -3063,6 +3220,18 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler // Keep: aligned with Quotes's `newTypeAlias` doc private[QuotesImpl] def validTypeAliasFlags: Flags = Private | Protected | Override | Final | Infix | Local + // Keep: aligned with Quotes's `newClass` + private[QuotesImpl] def validClassFlags: Flags = Private | Protected | PrivateLocal | Local | Final | Trait | Abstract | Open + + // Keep: aligned with Quote's 'newClass' + private[QuotesImpl] def validClassConstructorFlags: Flags = Synthetic | Method | Private | Protected | PrivateLocal | Local + + // Keep: aligned with Quotes's `newClass` + private[QuotesImpl] def validClassTypeParamFlags: Flags = Param | Deferred | Private | PrivateLocal | Local + + // Keep: aligned with Quotes's `newClass` + private[QuotesImpl] def validClassTermParamFlags: Flags = ParamAccessor | Private | Protected | PrivateLocal | Local + end Flags given FlagsMethods: FlagsMethods with diff --git a/compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala b/compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala index 64a0ff9db9ec..7c7a688eccb2 100644 --- a/compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala +++ b/compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala @@ -1379,13 +1379,13 @@ object SourceCode { printTypeTree(bounds.low) else bounds.low match { - case Inferred() => + case Inferred() if bounds.low.tpe.typeSymbol == TypeRepr.of[Nothing].typeSymbol => case low => this += " >: " printTypeTree(low) } bounds.hi match { - case Inferred() => this + case Inferred() if bounds.hi.tpe.typeSymbol == TypeRepr.of[Any].typeSymbol => this case hi => this += " <: " printTypeTree(hi) diff --git a/compiler/test-resources/scripting/envtestNu.sc b/compiler/test-resources/scripting/envtestNu.sc new file mode 100755 index 000000000000..fe4cd7851b0a --- /dev/null +++ b/compiler/test-resources/scripting/envtestNu.sc @@ -0,0 +1,2 @@ +// MIGRATION: Scala CLI expects `*.sc` files to be straight-line code + println("Hello " + util.Properties.propOrNull("key")) diff --git a/compiler/test-resources/scripting/scriptPathNu.sc b/compiler/test-resources/scripting/scriptPathNu.sc new file mode 100755 index 000000000000..bb3e459654b9 --- /dev/null +++ b/compiler/test-resources/scripting/scriptPathNu.sc @@ -0,0 +1,13 @@ +#!/usr/bin/env bin/scala + +// THIS FILE IS RAN WITH SCALA CLI, which wraps scripts exposing scriptPath and args variables + +args.zipWithIndex.foreach { case (arg,i) => printf("arg %d: [%s]\n",i,arg) } + +if !scriptPath.endsWith("scriptPathNu.sc") then + printf( s"incorrect script.path defined as [$scriptPath]") +else + printf("scriptPath: %s\n", scriptPath) // report the value + +extension(s: String) + def norm: String = s.replace('\\', '/') diff --git a/compiler/test-resources/scripting/showArgsNu.sc b/compiler/test-resources/scripting/showArgsNu.sc new file mode 100755 index 000000000000..f4c1aa6af257 --- /dev/null +++ b/compiler/test-resources/scripting/showArgsNu.sc @@ -0,0 +1,6 @@ +#!/usr/bin/env bin/scala + +// precise output format expected by BashScriptsTests.scala +// MIGRATION: Scala CLI expects `*.sc` files to be straight-line code +for (a,i) <- args.zipWithIndex do + printf(s"arg %2d:[%s]\n",i,a) diff --git a/compiler/test-resources/scripting/sqlDateErrorNu.sc b/compiler/test-resources/scripting/sqlDateErrorNu.sc new file mode 100755 index 000000000000..a6f1bd50297d --- /dev/null +++ b/compiler/test-resources/scripting/sqlDateErrorNu.sc @@ -0,0 +1,6 @@ +#!/usr/bin/env bin/scala + +// def main(args: Array[String]): Unit = { MIGRATION: Scala CLI expects `*.sc` files to be straight-line code + println(new java.sql.Date(100L)) + System.err.println("SCALA_OPTS="+Option(System.getenv("SCALA_OPTS")).getOrElse("")) +// } diff --git a/compiler/test/dotc/neg-best-effort-pickling.excludelist b/compiler/test/dotc/neg-best-effort-pickling.excludelist index 13fd5669dd8a..52371ecf17a5 100644 --- a/compiler/test/dotc/neg-best-effort-pickling.excludelist +++ b/compiler/test/dotc/neg-best-effort-pickling.excludelist @@ -18,6 +18,7 @@ i20317a.scala # recursion limit exceeded i11226.scala # missing type i974.scala # cyclic reference i13864.scala # missing symbol in pickling +type-params.scala # recursion limit exceeded # semantic db generation fails in the first compilation i15158.scala # cyclic reference - stack overflow diff --git a/compiler/test/dotc/pos-test-pickling.excludelist b/compiler/test/dotc/pos-test-pickling.excludelist index 23c79affada0..07c157793f5d 100644 --- a/compiler/test/dotc/pos-test-pickling.excludelist +++ b/compiler/test/dotc/pos-test-pickling.excludelist @@ -24,7 +24,6 @@ t5031_2.scala i16997.scala i7414.scala i17588.scala -i8300.scala i9804.scala i13433.scala i16649-irrefutable.scala diff --git a/compiler/test/dotty/tools/debug/DebugTests.scala b/compiler/test/dotty/tools/debug/DebugTests.scala index 95bf5a2e52a6..e8f744286ba4 100644 --- a/compiler/test/dotty/tools/debug/DebugTests.scala +++ b/compiler/test/dotty/tools/debug/DebugTests.scala @@ -18,7 +18,8 @@ class DebugTests: implicit val testGroup: TestGroup = TestGroup("debug") CompilationTest.aggregateTests( compileFile("tests/debug-custom-args/eval-explicit-nulls.scala", TestConfiguration.explicitNullsOptions), - compileFilesInDir("tests/debug", TestConfiguration.defaultOptions) + compileFilesInDir("tests/debug", TestConfiguration.defaultOptions), + compileFilesInDir("tests/debug-preview", TestConfiguration.defaultOptions.and("-preview")) ).checkDebug() object DebugTests extends ParallelTesting: diff --git a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala index d32b28647c32..0592cbbed1be 100644 --- a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala +++ b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala @@ -511,6 +511,16 @@ class ReplCompilerTests extends ReplTest: val all = lines() assertTrue(hints.forall(hint => all.exists(_.contains(hint)))) + @Test def `i22844 regression colon eol`: Unit = initially: + run: + """|println: + | "hello, world" + |""".stripMargin // outdent, but this test does not exercise the bug + assertEquals(List("hello, world"), lines()) + + @Test def `i22844b regression colon arrow eol`: Unit = contextually: + assertTrue(ParseResult.isIncomplete("List(42).map: x =>")) + object ReplCompilerTests: private val pattern = Pattern.compile("\\r[\\n]?|\\n"); diff --git a/compiler/test/dotty/tools/repl/ReplTest.scala b/compiler/test/dotty/tools/repl/ReplTest.scala index a0975d603ae1..9741a8dee450 100644 --- a/compiler/test/dotty/tools/repl/ReplTest.scala +++ b/compiler/test/dotty/tools/repl/ReplTest.scala @@ -42,7 +42,7 @@ extends ReplDriver(options, new PrintStream(out, true, StandardCharsets.UTF_8.na /** Returns the `(, )`*/ def tabComplete(src: String)(implicit state: State): List[String] = - completions(src.length, src, state).map(_.label).sorted.distinct + completionsWithSignatures(src.length, src, state).map(_.label).sorted.distinct extension [A](state: State) infix def andThen(op: State ?=> A): A = op(using state) diff --git a/compiler/test/dotty/tools/scripting/ScriptingTests.scala b/compiler/test/dotty/tools/scripting/ScriptingTests.scala index 8d07cb137917..4dc193f0efe4 100644 --- a/compiler/test/dotty/tools/scripting/ScriptingTests.scala +++ b/compiler/test/dotty/tools/scripting/ScriptingTests.scala @@ -51,7 +51,10 @@ class ScriptingTests: */ @Test def scriptingMainTests = assumeFalse("Scripts do not yet support Scala 2 library TASTy", Properties.usingScalaLibraryTasty) - for (scriptFile, scriptArgs) <- scalaFilesWithArgs(".sc") do + for + (scriptFile, scriptArgs) <- scalaFilesWithArgs(".sc") + if !scriptFile.getName().endsWith("Nu.sc") + do showScriptUnderTest(scriptFile) val unexpectedJar = script2jar(scriptFile) unexpectedJar.delete @@ -70,7 +73,10 @@ class ScriptingTests: */ @Test def scriptingJarTest = assumeFalse("Scripts do not yet support Scala 2 library TASTy", Properties.usingScalaLibraryTasty) - for (scriptFile, scriptArgs) <- scalaFilesWithArgs(".sc") do + for + (scriptFile, scriptArgs) <- scalaFilesWithArgs(".sc") + if !scriptFile.getName().endsWith("Nu.sc") + do showScriptUnderTest(scriptFile) val expectedJar = script2jar(scriptFile) expectedJar.delete diff --git a/compiler/test/dotty/tools/vulpix/FileFilter.scala b/compiler/test/dotty/tools/vulpix/FileFilter.scala index b59b4d4f209d..7bb098e1903e 100644 --- a/compiler/test/dotty/tools/vulpix/FileFilter.scala +++ b/compiler/test/dotty/tools/vulpix/FileFilter.scala @@ -23,4 +23,8 @@ object FileFilter { object NoFilter extends FileFilter { def accept(file: String) = true } + + object ExcludeDotFiles extends FileFilter { + def accept(file: String) = !file.startsWith(".") + } } diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala index 12a53a19931d..7656acb38f70 100644 --- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala +++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala @@ -1423,7 +1423,7 @@ trait ParallelTesting extends RunnerOrchestration { self => private def compilationTargets(sourceDir: JFile, fileFilter: FileFilter = FileFilter.NoFilter): (List[JFile], List[JFile]) = sourceDir.listFiles.foldLeft((List.empty[JFile], List.empty[JFile])) { case ((dirs, files), f) => if (!fileFilter.accept(f.getName)) (dirs, files) - else if (f.isDirectory) (f :: dirs, files) + else if (f.isDirectory && FileFilter.ExcludeDotFiles.accept(f.getName)) (f :: dirs, files) else if (isSourceFile(f)) (dirs, f :: files) else (dirs, files) } diff --git a/dist/bin-native-overrides/cli-common-platform b/dist/bin-native-overrides/cli-common-platform new file mode 100644 index 000000000000..1a11c770f91a --- /dev/null +++ b/dist/bin-native-overrides/cli-common-platform @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +if [[ ${cygwin-} || ${mingw-} || ${msys-} ]]; then + SCALA_CLI_VERSION="" + # iterate through lines in VERSION_SRC + while IFS= read -r line; do + # if line starts with "version:=" then extract the version + if [[ "$line" == cli_version:=* ]]; then + SCALA_CLI_VERSION="${line#cli_version:=}" + break + fi + done < "$PROG_HOME/EXTRA_PROPERTIES" + SCALA_CLI_CMD_BASH=("\"$PROG_HOME/bin/scala-cli\"" "--cli-version \"$SCALA_CLI_VERSION\"") +else + SCALA_CLI_CMD_BASH=("\"$PROG_HOME/bin/scala-cli\"") +fi diff --git a/dist/bin-native-overrides/cli-common-platform.bat b/dist/bin-native-overrides/cli-common-platform.bat new file mode 100644 index 000000000000..d1c4f1c4716b --- /dev/null +++ b/dist/bin-native-overrides/cli-common-platform.bat @@ -0,0 +1,22 @@ +@echo off + +setlocal enabledelayedexpansion + +set "_SCALA_CLI_VERSION=" +@rem read for cli_version:=_SCALA_CLI_VERSION in EXTRA_PROPERTIES file +FOR /F "usebackq delims=" %%G IN ("%_PROG_HOME%\EXTRA_PROPERTIES") DO ( + SET "line=%%G" + IF "!line:~0,13!"=="cli_version:=" ( + SET "_SCALA_CLI_VERSION=!line:~13!" + GOTO :foundCliVersion + ) +) + +@REM we didn't find it, so we should fail +echo "ERROR: cli_version not found in EXTRA_PROPERTIES file" +exit /b 1 + +:foundCliVersion +endlocal & set "SCALA_CLI_VERSION=%_SCALA_CLI_VERSION%" + +set SCALA_CLI_CMD_WIN="%_PROG_HOME%\bin\scala-cli.exe" "--cli-version" "%SCALA_CLI_VERSION%" diff --git a/dist/bin/cli-common b/dist/bin/cli-common new file mode 100644 index 000000000000..d295d58916da --- /dev/null +++ b/dist/bin/cli-common @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +#/*-------------------------------------------------------------------------- +# * Credits: This script is based on the script generated by sbt-pack. +# *--------------------------------------------------------------------------*/ + +# save terminal settings +saved_stty=$(stty -g 2>/dev/null) +# clear on error so we don't later try to restore them +if [[ ! $? ]]; then + saved_stty="" +fi + +# restore stty settings (echo in particular) +function restoreSttySettings() { + stty $saved_stty + saved_stty="" +} + +scala_exit_status=127 +function onExit() { + [[ "$saved_stty" != "" ]] && restoreSttySettings + exit $scala_exit_status +} + +#/*-------------------------------------------------------------------------- +# * SECTION FOR JAVA COMMAND +# *--------------------------------------------------------------------------*/ + +# to reenable echo if we are interrupted before completing. +trap onExit INT TERM EXIT + +unset cygwin mingw msys darwin conemu + +# COLUMNS is used together with command line option '-pageWidth'. +if command -v tput >/dev/null 2>&1; then + export COLUMNS="$(tput -Tdumb cols)" +fi + +case "`uname`" in + CYGWIN*) cygwin=true + ;; + MINGW*) mingw=true + ;; + MSYS*) msys=true + ;; + Darwin*) darwin=true + if [ -z "$JAVA_VERSION" ] ; then + JAVA_VERSION="CurrentJDK" + else + echo "Using Java version: $JAVA_VERSION" 1>&2 + fi + if [ -z "$JAVA_HOME" ] ; then + JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/${JAVA_VERSION}/Home + fi + JAVACMD="`which java`" + ;; +esac + +unset CYGPATHCMD +if [[ ${cygwin-} || ${mingw-} || ${msys-} ]]; then + # ConEmu terminal is incompatible with jna-5.*.jar + [[ (${CONEMUANSI-} || ${ConEmuANSI-}) ]] && conemu=true + # cygpath is used by various windows shells: cygwin, git-sdk, gitbash, msys, etc. + CYGPATHCMD=`which cygpath 2>/dev/null` + case "$TERM" in + rxvt* | xterm* | cygwin*) + stty -icanon min 1 -echo + JAVA_OPTS="$JAVA_OPTS -Djline.terminal=unix" + ;; + esac +fi + +# Resolve JAVA_HOME from javac command path +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" -a -f "$javaExecutable" -a ! "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + javaExecutable="`readlink -f \"$javaExecutable\"`" + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "${JAVACMD-}" ] ; then + if [ -n "${JAVA_HOME-}" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." + echo " We cannot execute $JAVACMD" + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSPATH_SUFFIX="" +# Path separator used in EXTRA_CLASSPATH +PSEP=":" + +# translate paths to Windows-mixed format before running java +if [ -n "${CYGPATHCMD-}" ]; then + [ -n "${PROG_HOME-}" ] && + PROG_HOME=`"$CYGPATHCMD" -am "$PROG_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`"$CYGPATHCMD" -am "$JAVA_HOME"` + CLASSPATH_SUFFIX=";" + PSEP=";" +elif [[ ${mingw-} || ${msys-} ]]; then + # For Mingw / Msys, convert paths from UNIX format before anything is touched + [ -n "$PROG_HOME" ] && + PROG_HOME="`(cd "$PROG_HOME"; pwd -W | sed 's|/|\\\\|g')`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd -W | sed 's|/|\\\\|g')`" + CLASSPATH_SUFFIX=";" + PSEP=";" +fi + +#/*-------------------------------------------------- +# * The code below is for Dotty +# *-------------------------------------------------*/ + +find_lib () { + for lib in "$PROG_HOME"/lib/$1 ; do + if [[ -f "$lib" ]]; then + if [ -n "$CYGPATHCMD" ]; then + "$CYGPATHCMD" -am "$lib" + elif [[ $mingw || $msys ]]; then + echo "$lib" | sed 's|/|\\\\|g' + else + echo "$lib" + fi + return + fi + done +} + +SCALA_CLI_JAR="$PROG_HOME/etc/scala-cli.jar" + +declare -a scala_args + +addScala () { + scala_args+=("'$1'") +} diff --git a/dist/bin/cli-common-platform b/dist/bin/cli-common-platform new file mode 100644 index 000000000000..a5906e882bb4 --- /dev/null +++ b/dist/bin/cli-common-platform @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +SCALA_CLI_CMD_BASH=("\"$JAVACMD\"" "-jar \"$PROG_HOME/bin/scala-cli.jar\"") diff --git a/dist/bin/cli-common-platform.bat b/dist/bin/cli-common-platform.bat new file mode 100644 index 000000000000..99103266c1d9 --- /dev/null +++ b/dist/bin/cli-common-platform.bat @@ -0,0 +1,5 @@ +@echo off + +@rem we need to escape % in the java command path, for some reason this doesnt work in common.bat +set "_JAVACMD=!_JAVACMD:%%=%%%%!" +set SCALA_CLI_CMD_WIN="%_JAVACMD%" "-jar" "%_PROG_HOME%\bin\scala-cli.jar" \ No newline at end of file diff --git a/dist/bin/common-shared b/dist/bin/common-shared new file mode 100644 index 000000000000..8c85993a5283 --- /dev/null +++ b/dist/bin/common-shared @@ -0,0 +1,139 @@ +#!/usr/bin/env bash + +# Common options for both scala-cli and java based launchers + +#/*-------------------------------------------------------------------------- +# * Credits: This script is based on the script generated by sbt-pack. +# *--------------------------------------------------------------------------*/ + +# save terminal settings +saved_stty=$(stty -g 2>/dev/null) +# clear on error so we don't later try to restore them +if [[ ! $? ]]; then + saved_stty="" +fi + +# restore stty settings (echo in particular) +function restoreSttySettings() { + stty $saved_stty + saved_stty="" +} + +scala_exit_status=127 +function onExit() { + [[ "$saved_stty" != "" ]] && restoreSttySettings + exit $scala_exit_status +} + +# to reenable echo if we are interrupted before completing. +trap onExit INT TERM EXIT + +unset cygwin mingw msys darwin conemu + +# COLUMNS is used together with command line option '-pageWidth'. +if command -v tput >/dev/null 2>&1; then + export COLUMNS="$(tput -Tdumb cols)" +fi + +case "`uname`" in + CYGWIN*) cygwin=true + ;; + MINGW*) mingw=true + ;; + MSYS*) msys=true + ;; + Darwin*) darwin=true + if [ -z "$JAVA_VERSION" ] ; then + JAVA_VERSION="CurrentJDK" + else + echo "Using Java version: $JAVA_VERSION" 1>&2 + fi + if [ -z "$JAVA_HOME" ] ; then + JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/${JAVA_VERSION}/Home + fi + JAVACMD="`which java`" + ;; +esac + +unset CYGPATHCMD +if [[ ${cygwin-} || ${mingw-} || ${msys-} ]]; then + # ConEmu terminal is incompatible with jna-5.*.jar + [[ (${CONEMUANSI-} || ${ConEmuANSI-}) ]] && conemu=true + # cygpath is used by various windows shells: cygwin, git-sdk, gitbash, msys, etc. + CYGPATHCMD=`which cygpath 2>/dev/null` + case "$TERM" in + rxvt* | xterm* | cygwin*) + stty -icanon min 1 -echo + JAVA_OPTS="$JAVA_OPTS -Djline.terminal=unix" + ;; + esac +fi + +# Resolve JAVA_HOME from javac command path +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" -a -f "$javaExecutable" -a ! "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + javaExecutable="`readlink -f \"$javaExecutable\"`" + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "${JAVACMD-}" ] ; then + if [ -n "${JAVA_HOME-}" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." + echo " We cannot execute $JAVACMD" + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSPATH_SUFFIX="" +# Path separator used in EXTRA_CLASSPATH +PSEP=":" +PROG_HOME_URI="file://$PROG_HOME" + +# translate paths to Windows-mixed format before running java +if [ -n "${CYGPATHCMD-}" ]; then + [ -n "${PROG_HOME-}" ] && + PROG_HOME=`"$CYGPATHCMD" -am "$PROG_HOME"` + PROG_HOME_URI="file:///$PROG_HOME" # Add extra root dir prefix + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`"$CYGPATHCMD" -am "$JAVA_HOME"` + CLASSPATH_SUFFIX=";" + PSEP=";" +elif [[ ${mingw-} || ${msys-} ]]; then + # For Mingw / Msys, convert paths from UNIX format before anything is touched + [ -n "$PROG_HOME" ] && + PROG_HOME="`(cd "$PROG_HOME"; pwd -W | sed 's|/|\\\\|g')`" + PROG_HOME_URI="file:///$PROG_HOME" # Add extra root dir prefix + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd -W | sed 's|/|\\\\|g')`" + CLASSPATH_SUFFIX=";" + PSEP=";" +fi + +declare -a scala_args +addScala () { + scala_args+=("'$1'") +} diff --git a/docs/_docs/reference/other-new-features/kind-polymorphism.md b/docs/_docs/reference/other-new-features/kind-polymorphism.md index e452ee8384f9..4bb1e659dfe9 100644 --- a/docs/_docs/reference/other-new-features/kind-polymorphism.md +++ b/docs/_docs/reference/other-new-features/kind-polymorphism.md @@ -43,5 +43,4 @@ It is declared `abstract` and `final`, so it can be neither instantiated nor ext `AnyKind` plays a special role in Scala's subtype system: It is a supertype of all other types no matter what their kind is. It is also assumed to be kind-compatible with all other types. Furthermore, `AnyKind` is treated as a higher-kinded type (so it cannot be used as a type of values), but at the same time it has no type parameters (so it cannot be instantiated). -**Note:** This feature is considered experimental but stable and it can be disabled under compiler flag -(i.e. `-Yno-kind-polymorphism`). +**Note:** This feature is now stable. The compiler flag `-Yno-kind-polymorphism` is deprecated as of 3.7.0, has no effect (is ignored), and will be removed in a future version. diff --git a/docs/_docs/reference/changed-features/better-fors.md b/docs/_docs/reference/preview/better-fors.md similarity index 93% rename from docs/_docs/reference/changed-features/better-fors.md rename to docs/_docs/reference/preview/better-fors.md index 36355f0faa88..d5fd32da9a1e 100644 --- a/docs/_docs/reference/changed-features/better-fors.md +++ b/docs/_docs/reference/preview/better-fors.md @@ -1,10 +1,10 @@ --- layout: doc-page title: "Better fors" -nightlyOf: https://docs.scala-lang.org/scala3/reference/changed-features/better-fors.html +nightlyOf: https://docs.scala-lang.org/scala3/reference/preview/better-fors.html --- -Starting in Scala `3.7`, the usability of `for`-comprehensions is improved. +Starting in Scala `3.7` under `-preview` mode, the usability of `for`-comprehensions is improved. The biggest user facing change is the new ability to start `for`-comprehensions with aliases. This means that the following previously invalid code is now valid: diff --git a/docs/_docs/reference/preview/overview.md b/docs/_docs/reference/preview/overview.md new file mode 100644 index 000000000000..ec8d36bdfd25 --- /dev/null +++ b/docs/_docs/reference/preview/overview.md @@ -0,0 +1,24 @@ +--- +layout: doc-page +title: "Preview" +nightlyOf: https://docs.scala-lang.org/scala3/reference/preview/overview.html +--- + +## Preview language features + +New Scala language features or standard library APIs are initially introduced as experimental, but once they become fully implemented and accepted by the [SIP](https://docs.scala-lang.org/sips/) these can become a preview features. + +Preview language features and APIs are guaranteed to be standardized in some next Scala minor release, but allow the compiler team to introduce small, possibly binary incompatible, changes based on the community feedback. +These can be used by early adopters who can accept the possibility of binary compatibility breakage. For instance, preview features could be used in some internal tool or application. On the other hand, preview features are discouraged in publicly available libraries. + +More information about preview featues can be found in [preview defintions guide](../other-new-features/preview-defs.md) + +### `-preview` compiler flag + +This flag enables the use of all preview language feature in the project. + + +## List of available preview features + +* [`better-fors`](./better-fors.md): Enables new for-comprehension behaviour under SIP-62 under `-source:3.7` or later + diff --git a/docs/sidebar.yml b/docs/sidebar.yml index ca58e21587eb..aecd974326ab 100644 --- a/docs/sidebar.yml +++ b/docs/sidebar.yml @@ -116,7 +116,6 @@ subsection: - page: reference/changed-features/lazy-vals-init.md - page: reference/changed-features/main-functions.md - page: reference/changed-features/interpolation-escapes.md - - page: reference/changed-features/better-fors.md - title: Dropped Features index: reference/dropped-features/dropped-features.md subsection: @@ -140,6 +139,11 @@ subsection: - page: reference/dropped-features/nonlocal-returns.md - page: reference/dropped-features/this-qualifier.md - page: reference/dropped-features/wildcard-init.md + - title: Preview Features + directory: preview + index: reference/preview/overview.md + subsection: + - page: reference/preview/better-fors.md - title: Experimental Features directory: experimental index: reference/experimental/overview.md diff --git a/library-js/src/scala/scalajs/runtime/AnonFunctionXXL.scala b/library-js/src/scala/scalajs/runtime/AnonFunctionXXL.scala index 87208573eff9..aa08afdce323 100644 --- a/library-js/src/scala/scalajs/runtime/AnonFunctionXXL.scala +++ b/library-js/src/scala/scalajs/runtime/AnonFunctionXXL.scala @@ -1,8 +1,25 @@ package scala.scalajs.runtime -import scala.scalajs.js - -@inline -final class AnonFunctionXXL(f: js.Function1[IArray[Object], Object]) extends scala.runtime.FunctionXXL { - override def apply(xs: IArray[Object]): Object = f(xs) -} +/* Before Scala.js 1.19, this class was concrete. It had a 1-argument + * constructor taking a js.Function[Array[Object], Object], and its `apply()` + * method called that function. This was similar to the `AnonFunctionN` classes + * of the Scala.js library (shared between Scala 2 and 3). + * + * In Scala.js 1.19, we introduced `NewLambda` nodes, which superseded these + * specialized classes with a compilation mode that is more efficient on Wasm. + * However, libraries compiled with earlier versions still contain references + * to `AnonFunctionXXL`. + * + * The IR deserializer patches allocations of the form + * New(AnonFunctionXXL, ctor, closure :: Nil) + * into + * NewLambda(AnonFunctionXXL, ..., (xs: Array[Object]) => closure(xs)) + * + * When the `closure` is directly a JS `Closure` with the right signature + * (which is supposed to be always, as far as our codegens were concerned), + * it rewrites that as + * NewLambda(AnonFunctionXXL, ..., (closureParam: Array[Object]) => closureBody) + * which provides the best performance for old code. + */ +@deprecated("used by the codegen before Scala.js 1.19", since = "3.7.0") +sealed abstract class AnonFunctionXXL extends scala.runtime.FunctionXXL diff --git a/library/src/scala/caps.scala b/library/src/scala/caps.scala deleted file mode 100644 index c35b3b55e813..000000000000 --- a/library/src/scala/caps.scala +++ /dev/null @@ -1,69 +0,0 @@ -package scala - -import annotation.{experimental, compileTimeOnly, retainsCap} - -@experimental object caps: - - trait Capability extends Any - - /** The universal capture reference */ - val cap: Capability = new Capability() {} - - /** The universal capture reference (deprecated) */ - @deprecated("Use `cap` instead") - val `*`: Capability = cap - - @deprecated("Use `Capability` instead") - type Cap = Capability - - /** Carrier trait for capture set type parameters */ - trait CapSet extends Any - - /** A type constraint expressing that the capture set `C` needs to contain - * the capability `R` - */ - sealed trait Contains[+C >: CapSet <: CapSet @retainsCap, R <: Singleton] - - /** The only implementation of `Contains`. The constraint that `{R} <: C` is - * added separately by the capture checker. - */ - given containsImpl[C >: CapSet <: CapSet @retainsCap, R <: Singleton]: Contains[C, R]() - - /** A wrapper indicating a type variable in a capture argument list of a - * @retains annotation. E.g. `^{x, Y^}` is represented as `@retains(x, capsOf[Y])`. - */ - @compileTimeOnly("Should be be used only internally by the Scala compiler") - def capsOf[CS >: CapSet <: CapSet @retainsCap]: Any = ??? - - /** Reach capabilities x* which appear as terms in @retains annotations are encoded - * as `caps.reachCapability(x)`. When converted to CaptureRef types in capture sets - * they are represented as `x.type @annotation.internal.reachCapability`. - */ - extension (x: Any) def reachCapability: Any = x - - /** A trait to allow expressing existential types such as - * - * (x: Exists) => A ->{x} B - */ - sealed trait Exists extends Capability - - /** This should go into annotations. For now it is here, so that we - * can experiment with it quickly between minor releases - */ - final class untrackedCaptures extends annotation.StaticAnnotation - - /** This should go into annotations. For now it is here, so that we - * can experiment with it quickly between minor releases - */ - final class use extends annotation.StaticAnnotation - - object unsafe: - - extension [T](x: T) - /** A specific cast operation to remove a capture set. - * If argument is of type `T^C`, assume it is of type `T` instead. - * Calls to this method are treated specially by the capture checker. - */ - def unsafeAssumePure: T = x - - end unsafe diff --git a/library/src/scala/caps/package.scala b/library/src/scala/caps/package.scala new file mode 100644 index 000000000000..3705a6137be8 --- /dev/null +++ b/library/src/scala/caps/package.scala @@ -0,0 +1,106 @@ +package scala +package caps + +import annotation.{experimental, compileTimeOnly, retainsCap} + +/** + * Base trait for classes that represent capabilities in the + * [object-capability model](https://en.wikipedia.org/wiki/Object-capability_model). + * + * A capability is a value representing a permission, access right, resource or effect. + * Capabilities are typically passed to code as parameters; they should not be global objects. + * Often, they come with access restrictions such as scoped lifetimes or limited sharing. + * + * An example is the [[scala.util.boundary.Label Label]] class in [[scala.util.boundary]]. + * It represents a capability in the sense that it gives permission to [[scala.util.boundary.break break]] + * to the enclosing boundary represented by the `Label`. It has a scoped lifetime, since breaking to + * a `Label` after the associated `boundary` was exited gives a runtime exception. + * + * [[Capability]] has a formal meaning when + * [[scala.language.experimental.captureChecking Capture Checking]] + * is turned on. + * But even without capture checking, extending this trait can be useful for documenting the intended purpose + * of a class. + */ +@experimental +trait Capability extends Any + +/** The universal capture reference. */ +@experimental +object cap extends Capability + +/** Carrier trait for capture set type parameters */ +@experimental +trait CapSet extends Any + +/** A type constraint expressing that the capture set `C` needs to contain + * the capability `R` + */ +@experimental +sealed trait Contains[+C >: CapSet <: CapSet @retainsCap, R <: Singleton] + +@experimental +object Contains: + /** The only implementation of `Contains`. The constraint that `{R} <: C` is + * added separately by the capture checker. + */ + @experimental + given containsImpl[C >: CapSet <: CapSet @retainsCap, R <: Singleton]: Contains[C, R]() + +/** An annotation on parameters `x` stating that the method's body makes + * use of the reach capability `x*`. Consequently, when calling the method + * we need to charge the deep capture set of the actual argiment to the + * environment. + * + * Note: This should go into annotations. For now it is here, so that we + * can experiment with it quickly between minor releases + */ +@experimental +final class use extends annotation.StaticAnnotation + +/** A trait to allow expressing existential types such as + * + * (x: Exists) => A ->{x} B + */ +@experimental +sealed trait Exists extends Capability + +@experimental +object internal: + + /** A wrapper indicating a type variable in a capture argument list of a + * @retains annotation. E.g. `^{x, Y^}` is represented as `@retains(x, capsOf[Y])`. + */ + @compileTimeOnly("Should be be used only internally by the Scala compiler") + def capsOf[CS >: CapSet <: CapSet @retainsCap]: Any = ??? + + /** Reach capabilities x* which appear as terms in @retains annotations are encoded + * as `caps.reachCapability(x)`. When converted to CaptureRef types in capture sets + * they are represented as `x.type @annotation.internal.reachCapability`. + */ + extension (x: Any) def reachCapability: Any = x + +@experimental +object unsafe: + /** + * Marks the constructor parameter as untracked. + * The capture set of this parameter will not be included in + * the capture set of the constructed object. + * + * @note This should go into annotations. For now it is here, so that we + * can experiment with it quickly between minor releases + */ + final class untrackedCaptures extends annotation.StaticAnnotation + + extension [T](x: T) + /** A specific cast operation to remove a capture set. + * If argument is of type `T^C`, assume it is of type `T` instead. + * Calls to this method are treated specially by the capture checker. + */ + def unsafeAssumePure: T = x + + /** A wrapper around code for which separation checks are suppressed. + */ + def unsafeAssumeSeparate(op: Any): op.type = op + +end unsafe diff --git a/library/src/scala/quoted/Quotes.scala b/library/src/scala/quoted/Quotes.scala index 8f7a069eaff5..a96785ce2741 100644 --- a/library/src/scala/quoted/Quotes.scala +++ b/library/src/scala/quoted/Quotes.scala @@ -3815,7 +3815,8 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching => /** The class Symbol of a global class definition */ def classSymbol(fullName: String): Symbol - /** Generates a new class symbol for a class with a parameterless constructor. + /** Generates a new class symbol for a class with a public parameterless constructor. + * For more settings, look to the other newClass methods. * * Example usage: * ``` @@ -3843,7 +3844,7 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching => * } * ``` * - * @param parent The owner of the class + * @param owner The owner of the class * @param name The name of the class * @param parents The parent classes of the class. The first parent must not be a trait. * @param decls The member declarations of the class provided the symbol of this class @@ -3856,8 +3857,181 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching => * @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be * direct or indirect children of the reflection context's owner. */ - // TODO: add flags and privateWithin - @experimental def newClass(parent: Symbol, name: String, parents: List[TypeRepr], decls: Symbol => List[Symbol], selfType: Option[TypeRepr]): Symbol + @experimental def newClass(owner: Symbol, name: String, parents: List[TypeRepr], decls: Symbol => List[Symbol], selfType: Option[TypeRepr]): Symbol + + /** Generates a new class symbol for a class with a public single term clause constructor. + * + * Example usage: + * ``` + * val name = "myClass" + * def decls(cls: Symbol): List[Symbol] = + * List(Symbol.newMethod(cls, "foo", MethodType(Nil)(_ => Nil, _ => TypeRepr.of[Unit]))) + * val parents = List(TypeTree.of[Object]) + * val cls = Symbol.newClass( + * Symbol.spliceOwner, + * name, + * parents = _ => parents.map(_.tpe), + * decls, + * selfType = None, + * clsFlags = Flags.EmptyFlags, + * Symbol.noSymbol, + * List(("idx", TypeRepr.of[Int]), ("str", TypeRepr.of[String])) + * ) + * + * val fooSym = cls.declaredMethod("foo").head + * val idxSym = cls.fieldMember("idx") + * val strSym = cls.fieldMember("str") + * val fooDef = DefDef(fooSym, argss => + * Some('{println(s"Foo method call with (${${Ref(idxSym).asExpr}}, ${${Ref(strSym).asExpr}})")}.asTerm) + * ) + * val clsDef = ClassDef(cls, parents, body = List(fooDef)) + * val newCls = Apply(Select(New(TypeIdent(cls)), cls.primaryConstructor), List('{0}.asTerm, '{string}.asTerm)) + * + * Block(List(clsDef), Apply(Select(newCls, cls.methodMember("foo")(0)), Nil)).asExprOf[Unit] + * ``` + * construct the equivalent to + * ``` + * '{ + * class myClass(idx: Int, str: String) extends Object { + * def foo() = + * println(s"Foo method call with $idx, $str") + * } + * new myClass(0, "string").foo() + * } + * ``` + * @param owner The owner of the class + * @param name The name of the class + * @param parents Function returning the parent classes of the class. The first parent must not be a trait. + * Takes the constructed class symbol as an argument. Calling `cls.typeRef.asType` as part of this function will lead to cyclic reference errors. + * @param clsFlags extra flags with which the class symbol should be constructed. + * @param clsPrivateWithin the symbol within which this new class symbol should be private. May be noSymbol. + * @param conParams constructor parameter pairs of names and types. + * + * Parameters assigned by the constructor can be obtained via `classSymbol.memberField`. + * This symbol starts without an accompanying definition. + * It is the meta-programmer's responsibility to provide exactly one corresponding definition by passing + * this symbol to the ClassDef constructor. + * + * @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be + * direct or indirect children of the reflection context's owner. + */ + @experimental def newClass( + owner: Symbol, + name: String, + parents: Symbol => List[TypeRepr], + decls: Symbol => List[Symbol], + selfType: Option[TypeRepr], + clsFlags: Flags, + clsPrivateWithin: Symbol, + conParams: List[(String, TypeRepr)] + ): Symbol + + /** Generates a new class symbol with a constructor of the shape signified by a passed PolyOrMethod parameter. + * + * Example usage: + * ``` + * val name = "myClass" + * def decls(cls: Symbol): List[Symbol] = + * List(Symbol.newMethod(cls, "getParam", MethodType(Nil)(_ => Nil, _ => cls.typeMember("T").typeRef))) + * val conMethodType = + * (classType: TypeRepr) => PolyType(List("T"))(_ => List(TypeBounds.empty), polyType => + * MethodType(List("param"))((_: MethodType) => List(polyType.param(0)), (_: MethodType) => + * AppliedType(classType, List(polyType.param(0))) + * ) + * ) + * val cls = Symbol.newClass( + * Symbol.spliceOwner, + * name, + * parents = _ => List(TypeRepr.of[Object]), + * decls, + * selfType = None, + * clsFlags = Flags.EmptyFlags, + * clsPrivateWithin = Symbol.noSymbol, + * clsAnnotations = Nil, + * conMethodType, + * conFlags = Flags.EmptyFlags, + * conPrivateWithin = Symbol.noSymbol, + * conParamFlags = List(List(Flags.EmptyFlags), List(Flags.EmptyFlags)), + * conParamPrivateWithins = List(List(Symbol.noSymbol), List(Symbol.noSymbol)) + * ) + * + * val getParamSym = cls.declaredMethod("getParam").head + * def getParamRhs(): Option[Term] = + * val paramValue = This(cls).select(cls.fieldMember("param")).asExpr + * Some('{ println("Calling getParam"); $paramValue }.asTerm) + * val getParamDef = DefDef(getParamSym, _ => getParamRhs()) + * + * val clsDef = ClassDef(cls, List(TypeTree.of[Object]), body = List(getParamDef)) + * val newCls = + * Apply( + * Select( + * Apply( + * TypeApply(Select(New(TypeIdent(cls)), cls.primaryConstructor), List(TypeTree.of[String])), + * List(Expr("test").asTerm) + * ), + * cls.methodMember("getParam").head + * ), + * Nil + * ) + * + * Block(List(clsDef), newCls).asExpr + * ``` + * constructs the equivalent to + * ``` + * '{ + * class myClass[T](val param: T) extends Object { + * def getParam: T = + * println("Calling getParam") + * param + * } + * new myClass[String]("test").getParam() + * } + * ``` + * + * @param owner The owner of the class + * @param name The name of the class + * @param parents Function returning the parent classes of the class. The first parent must not be a trait + * Takes the constructed class symbol as an argument. Calling `cls.typeRef.asType` as part of this function will lead to cyclic reference errors. + * @param decls The member declarations of the class provided the symbol of this class + * @param selfType The self type of the class if it has one + * @param clsFlags extra flags with which the class symbol should be constructed. Can be `Private` | `Protected` | `PrivateLocal` | `Local` | `Final` | `Trait` | `Abstract` | `Open` + * @param clsPrivateWithin the symbol within which this new class symbol should be private. May be noSymbol + * @param clsAnnotations annotations of the class + * @param conMethodType Function returning MethodOrPoly type representing the type of the constructor. + * Takes the result type as parameter which must be returned from the innermost MethodOrPoly and have type parameters applied if those are used. + * PolyType may only represent the first clause of the constructor. + * @param conFlags extra flags with which the constructor symbol should be constructed. Can be `Synthetic` | `Method` | `Private` | `Protected` | `PrivateLocal` | `Local` + * @param conPrivateWithin the symbol within which the constructor for this new class symbol should be private. May be noSymbol. + * @param conParamFlags extra flags with which the constructor parameter symbols should be constructed. Must match the shape of `conMethodType`. + * For type parameters those can be `Param` | `Deferred` | `Private` | `PrivateLocal` | `Local`. + * For term parameters those can be `ParamAccessor` | `Private` | `Protected` | `PrivateLocal` | `Local` + * @param conParamPrivateWithins the symbols within which the constructor parameters should be private. Must match the shape of `conMethodType`. Can consist of noSymbol. + * + * Term and type parameters assigned by the constructor can be obtained via `classSymbol.memberField`/`classSymbol.memberType`. + * This symbol starts without an accompanying definition. + * It is the meta-programmer's responsibility to provide exactly one corresponding definition by passing + * this symbol to the ClassDef constructor. + * + * @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be + * direct or indirect children of the reflection context's owner. + */ + // Keep doc aligned with QuotesImpl's validFlags: `clsFlags` with `validClassFlags`, `conFlags` with `validClassConstructorFlags`, + // conParamFlags with `validClassTypeParamFlags` and `validClassTermParamFlags` + @experimental def newClass( + owner: Symbol, + name: String, + parents: Symbol => List[TypeRepr], + decls: Symbol => List[Symbol], + selfType: Option[TypeRepr], + clsFlags: Flags, + clsPrivateWithin: Symbol, + clsAnnotations: List[Term], + conMethodType: TypeRepr => MethodOrPoly, + conFlags: Flags, + conPrivateWithin: Symbol, + conParamFlags: List[List[Flags]], + conParamPrivateWithins: List[List[Symbol]] + ): Symbol /** Generates a new module symbol with an associated module class symbol, * this is equivalent to an `object` declaration in source code. @@ -3874,7 +4048,7 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching => * def decls(cls: Symbol): List[Symbol] = * List(Symbol.newMethod(cls, "run", MethodType(Nil)(_ => Nil, _ => TypeRepr.of[Unit]), Flags.EmptyFlags, Symbol.noSymbol)) * - * val mod = Symbol.newModule(Symbol.spliceOwner, moduleName, Flags.EmptyFlags, Flags.EmptyFlags, parents.map(_.tpe), decls, Symbol.noSymbol) + * val mod = Symbol.newModule(Symbol.spliceOwner, moduleName, Flags.EmptyFlags, Flags.EmptyFlags, _ => parents.map(_.tpe), decls, Symbol.noSymbol) * val cls = mod.moduleClass * val runSym = cls.declaredMethod("run").head * @@ -3902,7 +4076,7 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching => * @param name The name of the class * @param modFlags extra flags with which the module symbol should be constructed * @param clsFlags extra flags with which the module class symbol should be constructed - * @param parents The parent classes of the class. The first parent must not be a trait. + * @param parents A function that takes the symbol of the module class as input and returns the parent classes of the class. The first parent must not be a trait. * @param decls A function that takes the symbol of the module class as input and return the symbols of its declared members * @param privateWithin the symbol within which this new method symbol should be private. May be noSymbol. * @@ -3915,7 +4089,7 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching => * * @syntax markdown */ - @experimental def newModule(owner: Symbol, name: String, modFlags: Flags, clsFlags: Flags, parents: List[TypeRepr], decls: Symbol => List[Symbol], privateWithin: Symbol): Symbol + @experimental def newModule(owner: Symbol, name: String, modFlags: Flags, clsFlags: Flags, parents: Symbol => List[TypeRepr], decls: Symbol => List[Symbol], privateWithin: Symbol): Symbol /** Generates a new method symbol with the given parent, name and type. * diff --git a/library/src/scala/runtime/stdLibPatches/language.scala b/library/src/scala/runtime/stdLibPatches/language.scala index 556df0e2759a..8899f734aece 100644 --- a/library/src/scala/runtime/stdLibPatches/language.scala +++ b/library/src/scala/runtime/stdLibPatches/language.scala @@ -140,7 +140,7 @@ object language: * @see [[https://github.com/scala/improvement-proposals/pull/79]] */ @compileTimeOnly("`betterFors` can only be used at compile time in import statements") - @deprecated("The `experimental.betterFors` language import is no longer needed since the feature is now standard", since = "3.7") + @deprecated("The `experimental.betterFors` language import no longer has any effect, the feature is being stablised and can be enabled using `-preview` flag", since = "3.7") object betterFors /** Experimental support for package object values diff --git a/presentation-compiler/test/dotty/tools/pc/tests/tokens/SemanticTokensSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/tokens/SemanticTokensSuite.scala index ca0b98de46f8..200f74537591 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/tokens/SemanticTokensSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/tokens/SemanticTokensSuite.scala @@ -1,10 +1,14 @@ package dotty.tools.pc.tests.tokens import dotty.tools.pc.base.BaseSemanticTokensSuite +import java.nio.file.Path import org.junit.Test class SemanticTokensSuite extends BaseSemanticTokensSuite: + // -preview required for `for-comprehension` test + override protected def scalacOptions(classpath: Seq[Path]): Seq[String] = + super.scalacOptions(classpath) ++ Seq("-preview") @Test def `class, object, var, val(readonly), method, type, parameter, String(single-line)` = check( diff --git a/project/Build.scala b/project/Build.scala index 4a86ae3e9e19..2d9242aa5d1a 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -123,7 +123,7 @@ object Build { * During release candidate cycle incremented by the release officer before publishing a subsequent RC version; * During final, stable release is set exactly to `developedVersion`. */ - val baseVersion = s"$developedVersion-RC1" + val baseVersion = developedVersion /** The version of TASTY that should be emitted, checked in runtime test * For defails on how TASTY version should be set see related discussions: @@ -141,7 +141,7 @@ object Build { * - in release candidate branch is experimental if {patch == 0} * - in stable release is always non-experimetnal */ - val expectedTastyVersion = "28.7-experimental-1" + val expectedTastyVersion = "28.7" checkReleasedTastyVersion() /** Final version of Scala compiler, controlled by environment variables. */ @@ -189,7 +189,7 @@ object Build { val mimaPreviousLTSDottyVersion = "3.3.0" /** Version of Scala CLI to download */ - val scalaCliLauncherVersion = "1.7.0" + val scalaCliLauncherVersion = "1.7.1" /** Version of Coursier to download for initializing the local maven repo of Scala command */ val coursierJarVersion = "2.1.24" @@ -452,7 +452,7 @@ object Build { "Automatic-Module-Name" -> s"${dottyOrganization.replaceAll("-",".")}.${moduleName.value.replaceAll("-",".")}" ), - // add extraDevelocityCacheInputFiles in cache key components + // add extraDevelocityCacheInputFiles in cache key components Compile / compile / buildcache.develocityTaskCacheKeyComponents += (Compile / extraDevelocityCacheInputFiles / outputFileStamps).taskValue, Test / test / buildcache.develocityTaskCacheKeyComponents += @@ -1692,7 +1692,6 @@ object Build { "compliantNullPointers" -> (sems.nullPointers == CheckedBehavior.Compliant), "compliantStringIndexOutOfBounds" -> (sems.stringIndexOutOfBounds == CheckedBehavior.Compliant), "compliantModuleInit" -> (sems.moduleInit == CheckedBehavior.Compliant), - "strictFloats" -> sems.strictFloats, "productionMode" -> sems.productionMode, "esVersion" -> linkerConfig.esFeatures.esVersion.edition, "useECMAScript2015Semantics" -> linkerConfig.esFeatures.useECMAScript2015Semantics, diff --git a/project/MiMaFilters.scala b/project/MiMaFilters.scala index 8427b4398c5f..3e6a36f62819 100644 --- a/project/MiMaFilters.scala +++ b/project/MiMaFilters.scala @@ -16,6 +16,10 @@ object MiMaFilters { ProblemFilters.exclude[MissingClassProblem]("scala.annotation.internal.preview"), ProblemFilters.exclude[MissingFieldProblem]("scala.runtime.stdLibPatches.language#experimental.packageObjectValues"), ProblemFilters.exclude[MissingClassProblem]("scala.runtime.stdLibPatches.language$experimental$packageObjectValues$"), + + // Scala.js-only class + ProblemFilters.exclude[FinalClassProblem]("scala.scalajs.runtime.AnonFunctionXXL"), + ProblemFilters.exclude[DirectMissingMethodProblem]("scala.scalajs.runtime.AnonFunctionXXL.this"), ), // Additions since last LTS @@ -89,6 +93,13 @@ object MiMaFilters { // Breaking changes since last reference version Build.mimaPreviousDottyVersion -> // Seq.empty, // We should never break backwards compatibility Seq( + // Scala.js-only class, which is subject to IR deserializatiation hacks to preserve bincompat. + // It's OK. Scala.js did the same: + // https://github.com/scala-js/scala-js/blob/v1.19.0/project/BinaryIncompatibilities.scala#L66-L71 + ProblemFilters.exclude[AbstractClassProblem]("scala.scalajs.runtime.AnonFunctionXXL"), + ProblemFilters.exclude[DirectMissingMethodProblem]("scala.scalajs.runtime.AnonFunctionXXL.this"), + ProblemFilters.exclude[DirectMissingMethodProblem]("scala.scalajs.runtime.AnonFunctionXXL.apply"), + // `ReversedMissingMethodProblem`s are acceptable. See comment in `Breaking changes since last LTS`. ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule.FlexibleType"), ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule.FlexibleTypeTypeTest"), diff --git a/project/Modes.scala b/project/Modes.scala index eddb5a3f1a7b..fcc13dea8a89 100644 --- a/project/Modes.scala +++ b/project/Modes.scala @@ -1,4 +1,4 @@ -import sbt.{Project, ProjectReference, SettingsDefinition} +import sbt.{Project, ProjectReference, SettingsDefinition, Plugins} object Modes { @@ -25,5 +25,9 @@ object Modes { def bootstrappedDependsOn(s: sbt.ClasspathDep[ProjectReference]*)(implicit mode: Mode): Project = if (mode == NonBootstrapped) project else project.dependsOn(s: _*) + /** Plugins only if the mode is bootstrapped */ + def bootstrappedEnablePlugins(ns: Plugins*)(implicit mode: Mode): Project = + if (mode == NonBootstrapped) project else project.enablePlugins(ns: _*) + } } diff --git a/project/plugins.sbt b/project/plugins.sbt index 9b9b90913228..da70069d8290 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -6,7 +6,7 @@ libraryDependencySchemes += "org.scala-lang.modules" %% "scala-xml" % VersionScheme.Always -addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.18.1") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.19.0") addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.21") diff --git a/sbt-test/scalajs/backward-compat/build.sbt b/sbt-test/scalajs/backward-compat/build.sbt new file mode 100644 index 000000000000..3f82b8529b16 --- /dev/null +++ b/sbt-test/scalajs/backward-compat/build.sbt @@ -0,0 +1,5 @@ +enablePlugins(ScalaJSPlugin) + +scalaVersion := sys.props("plugin.scalaVersion") + +libraryDependencies += "org.scalameta" %%% "munit" % "1.1.0" diff --git a/sbt-test/scalajs/backward-compat/project/plugins.sbt b/sbt-test/scalajs/backward-compat/project/plugins.sbt new file mode 100644 index 000000000000..b30c6e8c5ec8 --- /dev/null +++ b/sbt-test/scalajs/backward-compat/project/plugins.sbt @@ -0,0 +1,2 @@ + +addSbtPlugin("org.scala-js" % "sbt-scalajs" % sys.props("plugin.scalaJSVersion")) diff --git a/sbt-test/scalajs/backward-compat/src/test/scala/NewArrayIssue22794Test.scala b/sbt-test/scalajs/backward-compat/src/test/scala/NewArrayIssue22794Test.scala new file mode 100644 index 000000000000..0385b537bfe4 --- /dev/null +++ b/sbt-test/scalajs/backward-compat/src/test/scala/NewArrayIssue22794Test.scala @@ -0,0 +1,5 @@ +class NewArrayIssue22794Test extends munit.FunSuite { + test("foo") { + assert(2 + 2 == 4) + } +} diff --git a/sbt-test/scalajs/backward-compat/test b/sbt-test/scalajs/backward-compat/test new file mode 100644 index 000000000000..dfffb838b4b3 --- /dev/null +++ b/sbt-test/scalajs/backward-compat/test @@ -0,0 +1 @@ +> test diff --git a/scala2-library-cc/src/scala/collection/immutable/LazyListIterable.scala b/scala2-library-cc/src/scala/collection/immutable/LazyListIterable.scala index 28ce8da104aa..7a63fbb4f248 100644 --- a/scala2-library-cc/src/scala/collection/immutable/LazyListIterable.scala +++ b/scala2-library-cc/src/scala/collection/immutable/LazyListIterable.scala @@ -24,7 +24,7 @@ import scala.language.implicitConversions import scala.runtime.Statics import language.experimental.captureChecking import annotation.unchecked.uncheckedCaptures -import caps.untrackedCaptures +import caps.unsafe.untrackedCaptures /** This class implements an immutable linked list. We call it "lazy" * because it computes its elements only when they are needed. diff --git a/tasty/src/dotty/tools/tasty/TastyFormat.scala b/tasty/src/dotty/tools/tasty/TastyFormat.scala index de3700c667a4..4c1453243450 100644 --- a/tasty/src/dotty/tools/tasty/TastyFormat.scala +++ b/tasty/src/dotty/tools/tasty/TastyFormat.scala @@ -340,7 +340,7 @@ object TastyFormat { * is able to read final TASTy documents if the file's * `MinorVersion` is strictly less than the current value. */ - final val ExperimentalVersion: Int = 1 + final val ExperimentalVersion: Int = 0 /**This method implements a binary relation (`<:<`) between two TASTy versions. * diff --git a/tests/debug-preview/eval-in-for-comprehension.check b/tests/debug-preview/eval-in-for-comprehension.check new file mode 100644 index 000000000000..6e91c891ebdb --- /dev/null +++ b/tests/debug-preview/eval-in-for-comprehension.check @@ -0,0 +1,27 @@ +break Test$ 5 // in main +eval list(0) +result 1 +// TODO can we remove debug line in adapted methods? +break Test$ 5 // in main$$anonfun$adapted$1 +break Test$ 6 // in main$$anonfun$1 +eval list(0) +result 1 +eval x +result 1 +break Test$ 7 // in main$$anonfun$1$$anonfun$1 +eval x + y +result 2 + +break Test$ 11 // in main$$anonfun$2 +eval x +result 1 + +break Test$ 13 // in main +eval list(0) +result 1 +break Test$ 13 // in main$$anonfun$4 + +break Test$ 14 // in main +eval list(0) +result 1 +break Test$ 14 // in main$$anonfun$5 diff --git a/tests/debug-preview/eval-in-for-comprehension.scala b/tests/debug-preview/eval-in-for-comprehension.scala new file mode 100644 index 000000000000..0ea86fbb0302 --- /dev/null +++ b/tests/debug-preview/eval-in-for-comprehension.scala @@ -0,0 +1,14 @@ +object Test: + def main(args: Array[String]): Unit = + val list = List(1) + for + x <- list + y <- list + z = x + y + yield x + for + x <- list + if x == 1 + yield x + for x <- list yield x + for x <- list do println(x) \ No newline at end of file diff --git a/tests/debug/eval-in-for-comprehension.check b/tests/debug/eval-in-for-comprehension.check index 6e91c891ebdb..fb0d62135efb 100644 --- a/tests/debug/eval-in-for-comprehension.check +++ b/tests/debug/eval-in-for-comprehension.check @@ -8,9 +8,16 @@ eval list(0) result 1 eval x result 1 +break Test$ 6 // in main$$anonfun$1$$anonfun$adapted$1 break Test$ 7 // in main$$anonfun$1$$anonfun$1 eval x + y result 2 +// TODO this line position does not make any sense +break Test$ 6 // in main$$anonfun$1$$anonfun$1 +break Test$ 7 // in main$$anonfun$1$$anonfun$1 +break Test$ 6 // in main$$anonfun$1$$anonfun$2 +break Test$ 6 // in main$$anonfun$1$$anonfun$2 +break Test$ 7 // in main$$anonfun$1$$anonfun$2 break Test$ 11 // in main$$anonfun$2 eval x diff --git a/tests/disabled/neg-custom-args/captures/capt-wf.scala b/tests/disabled/neg-custom-args/captures/capt-wf.scala index bfe349747776..302202064ac0 100644 --- a/tests/disabled/neg-custom-args/captures/capt-wf.scala +++ b/tests/disabled/neg-custom-args/captures/capt-wf.scala @@ -1,7 +1,7 @@ // No longer valid class C -type Cap = C @retains(caps.*) -type Top = Any @retains(caps.*) +type Cap = C @retains(caps.cap) +type Top = Any @retains(caps.cap) type T = (x: Cap) => List[String @retains(x)] => Unit // error val x: (x: Cap) => Array[String @retains(x)] = ??? // error diff --git a/tests/disabled/neg-custom-args/captures/try2.scala b/tests/disabled/neg-custom-args/captures/try2.scala index 876dc1ec12f1..43e17d8c9eef 100644 --- a/tests/disabled/neg-custom-args/captures/try2.scala +++ b/tests/disabled/neg-custom-args/captures/try2.scala @@ -5,7 +5,7 @@ import annotation.ability @ability erased val canThrow: * = ??? class CanThrow[E <: Exception] extends Retains[canThrow.type] -type Top = Any @retains(caps.*) +type Top = Any @retains(caps.cap) infix type throws[R, E <: Exception] = (erased CanThrow[E]) ?=> R diff --git a/tests/neg-custom-args/captures/capt1.check b/tests/neg-custom-args/captures/capt1.check index acf8faa7a969..15fe32fc7653 100644 --- a/tests/neg-custom-args/captures/capt1.check +++ b/tests/neg-custom-args/captures/capt1.check @@ -36,15 +36,15 @@ -- Error: tests/neg-custom-args/captures/capt1.scala:34:16 ------------------------------------------------------------- 34 | val z2 = h[() -> Cap](() => x) // error // error | ^^^^^^^^^ - | Type variable X of method h cannot be instantiated to () -> (ex$15: caps.Exists) -> C^{ex$15} since - | the part C^{ex$15} of that type captures the root capability `cap`. + | Type variable X of method h cannot be instantiated to () -> (ex$15: scala.caps.Exists) -> C^{ex$15} since + | the part C^{ex$15} of that type captures the root capability `cap`. -- Error: tests/neg-custom-args/captures/capt1.scala:34:30 ------------------------------------------------------------- 34 | val z2 = h[() -> Cap](() => x) // error // error | ^ - | reference (x : C^) is not included in the allowed capture set {} - | of an enclosing function literal with expected type () -> (ex$15: caps.Exists) -> C^{ex$15} + | reference (x : C^) is not included in the allowed capture set {} + | of an enclosing function literal with expected type () -> (ex$15: scala.caps.Exists) -> C^{ex$15} -- Error: tests/neg-custom-args/captures/capt1.scala:36:13 ------------------------------------------------------------- 36 | val z3 = h[(() -> Cap) @retains(x)](() => x)(() => C()) // error | ^^^^^^^^^^^^^^^^^^^^^^^ - | Type variable X of method h cannot be instantiated to box () ->{x} (ex$20: caps.Exists) -> C^{ex$20} since - | the part C^{ex$20} of that type captures the root capability `cap`. + |Type variable X of method h cannot be instantiated to box () ->{x} (ex$20: scala.caps.Exists) -> C^{ex$20} since + |the part C^{ex$20} of that type captures the root capability `cap`. diff --git a/tests/neg-custom-args/captures/cc-poly-1.check b/tests/neg-custom-args/captures/cc-poly-1.check index ea486f55a61f..0ac35b532916 100644 --- a/tests/neg-custom-args/captures/cc-poly-1.check +++ b/tests/neg-custom-args/captures/cc-poly-1.check @@ -1,12 +1,12 @@ -- [E057] Type Mismatch Error: tests/neg-custom-args/captures/cc-poly-1.scala:12:6 ------------------------------------- 12 | f[Any](D()) // error | ^ - | Type argument Any does not conform to upper bound caps.CapSet^ + | Type argument Any does not conform to upper bound scala.caps.CapSet^ | | longer explanation available when compiling with `-explain` -- [E057] Type Mismatch Error: tests/neg-custom-args/captures/cc-poly-1.scala:13:6 ------------------------------------- 13 | f[String](D()) // error | ^ - | Type argument String does not conform to upper bound caps.CapSet^ + | Type argument String does not conform to upper bound scala.caps.CapSet^ | | longer explanation available when compiling with `-explain` diff --git a/tests/neg-custom-args/captures/cc-this2.check b/tests/neg-custom-args/captures/cc-this2.check index 6cb3010d6174..dc61fe2e0396 100644 --- a/tests/neg-custom-args/captures/cc-this2.check +++ b/tests/neg-custom-args/captures/cc-this2.check @@ -2,7 +2,7 @@ -- Error: tests/neg-custom-args/captures/cc-this2/D_2.scala:3:8 -------------------------------------------------------- 3 | this: D^ => // error | ^^ - |reference (caps.cap : caps.Capability) captured by this self type is not included in the allowed capture set {} of pure base class class C + | reference cap captured by this self type is not included in the allowed capture set {} of pure base class class C -- [E058] Type Mismatch Error: tests/neg-custom-args/captures/cc-this2/D_2.scala:2:6 ----------------------------------- 2 |class D extends C: // error | ^ diff --git a/tests/neg-custom-args/captures/exception-definitions.check b/tests/neg-custom-args/captures/exception-definitions.check index 3f2b15f312b9..67f0f3b72cbb 100644 --- a/tests/neg-custom-args/captures/exception-definitions.check +++ b/tests/neg-custom-args/captures/exception-definitions.check @@ -1,7 +1,7 @@ -- Error: tests/neg-custom-args/captures/exception-definitions.scala:3:8 ----------------------------------------------- 3 | self: Err^ => // error | ^^^^ - |reference (caps.cap : caps.Capability) captured by this self type is not included in the allowed capture set {} of pure base class class Throwable + |reference cap captured by this self type is not included in the allowed capture set {} of pure base class class Throwable -- Error: tests/neg-custom-args/captures/exception-definitions.scala:7:12 ---------------------------------------------- 7 | val x = c // error | ^ diff --git a/tests/neg-custom-args/captures/existential-mapping.check b/tests/neg-custom-args/captures/existential-mapping.check index 30836bc427cf..43f4e97e6a2a 100644 --- a/tests/neg-custom-args/captures/existential-mapping.check +++ b/tests/neg-custom-args/captures/existential-mapping.check @@ -5,84 +5,84 @@ -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:9:25 --------------------------- 9 | val _: (x: C^) -> C = x1 // error | ^^ - | Found: (x1 : (x: C^) -> (ex$3: caps.Exists) -> C^{ex$3}) + | Found: (x1 : (x: C^) -> (ex$3: scala.caps.Exists) -> C^{ex$3}) | Required: (x: C^) -> C | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:12:20 -------------------------- 12 | val _: C^ -> C = x2 // error | ^^ - | Found: (x2 : C^ -> (ex$7: caps.Exists) -> C^{ex$7}) + | Found: (x2 : C^ -> (ex$7: scala.caps.Exists) -> C^{ex$7}) | Required: C^ -> C | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:15:30 -------------------------- 15 | val _: A^ -> (x: C^) -> C = x3 // error | ^^ - | Found: (x3 : A^ -> (x: C^) -> (ex$11: caps.Exists) -> C^{ex$11}) + | Found: (x3 : A^ -> (x: C^) -> (ex$11: scala.caps.Exists) -> C^{ex$11}) | Required: A^ -> (x: C^) -> C | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:18:25 -------------------------- 18 | val _: A^ -> C^ -> C = x4 // error | ^^ - | Found: (x4 : A^ -> C^ -> (ex$19: caps.Exists) -> C^{ex$19}) + | Found: (x4 : A^ -> C^ -> (ex$19: scala.caps.Exists) -> C^{ex$19}) | Required: A^ -> C^ -> C | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:21:30 -------------------------- 21 | val _: A^ -> (x: C^) -> C = x5 // error | ^^ - | Found: (x5 : A^ -> (x: C^) -> (ex$27: caps.Exists) -> C^{ex$27}) + | Found: (x5 : A^ -> (x: C^) -> (ex$27: scala.caps.Exists) -> C^{ex$27}) | Required: A^ -> (x: C^) -> C | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:24:30 -------------------------- 24 | val _: A^ -> (x: C^) => C = x6 // error | ^^ - | Found: (x6 : A^ -> (ex$36: caps.Exists) -> (x: C^) ->{ex$36} (ex$35: caps.Exists) -> C^{ex$35}) - | Required: A^ -> (ex$39: caps.Exists) -> (x: C^) ->{ex$39} C + | Found: (x6 : A^ -> (ex$36: scala.caps.Exists) -> (x: C^) ->{ex$36} (ex$35: scala.caps.Exists) -> C^{ex$35}) + | Required: A^ -> (ex$39: scala.caps.Exists) -> (x: C^) ->{ex$39} C | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:27:25 -------------------------- 27 | val _: (x: C^) => C = y1 // error | ^^ - | Found: (y1 : (x: C^) => (ex$41: caps.Exists) -> C^{ex$41}) + | Found: (y1 : (x: C^) => (ex$41: scala.caps.Exists) -> C^{ex$41}) | Required: (x: C^) => C | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:30:20 -------------------------- 30 | val _: C^ => C = y2 // error | ^^ - | Found: (y2 : C^ => (ex$45: caps.Exists) -> C^{ex$45}) + | Found: (y2 : C^ => (ex$45: scala.caps.Exists) -> C^{ex$45}) | Required: C^ => C | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:33:30 -------------------------- 33 | val _: A^ => (x: C^) => C = y3 // error | ^^ - | Found: (y3 : A^ => (ex$50: caps.Exists) -> (x: C^) ->{ex$50} (ex$49: caps.Exists) -> C^{ex$49}) - | Required: A^ => (ex$53: caps.Exists) -> (x: C^) ->{ex$53} C + | Found: (y3 : A^ => (ex$50: scala.caps.Exists) -> (x: C^) ->{ex$50} (ex$49: scala.caps.Exists) -> C^{ex$49}) + | Required: A^ => (ex$53: scala.caps.Exists) -> (x: C^) ->{ex$53} C | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:36:25 -------------------------- 36 | val _: A^ => C^ => C = y4 // error | ^^ - | Found: (y4 : A^ => (ex$56: caps.Exists) -> C^ ->{ex$56} (ex$55: caps.Exists) -> C^{ex$55}) - | Required: A^ => (ex$59: caps.Exists) -> C^ ->{ex$59} C + | Found: (y4 : A^ => (ex$56: scala.caps.Exists) -> C^ ->{ex$56} (ex$55: scala.caps.Exists) -> C^{ex$55}) + | Required: A^ => (ex$59: scala.caps.Exists) -> C^ ->{ex$59} C | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:39:30 -------------------------- 39 | val _: A^ => (x: C^) -> C = y5 // error | ^^ - | Found: (y5 : A^ => (x: C^) -> (ex$61: caps.Exists) -> C^{ex$61}) + | Found: (y5 : A^ => (x: C^) -> (ex$61: scala.caps.Exists) -> C^{ex$61}) | Required: A^ => (x: C^) -> C | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/existential-mapping.scala:42:30 -------------------------- 42 | val _: A^ => (x: C^) => C = y6 // error | ^^ - | Found: (y6 : A^ => (ex$70: caps.Exists) -> (x: C^) ->{ex$70} (ex$69: caps.Exists) -> C^{ex$69}) - | Required: A^ => (ex$73: caps.Exists) -> (x: C^) ->{ex$73} C + | Found: (y6 : A^ => (ex$70: scala.caps.Exists) -> (x: C^) ->{ex$70} (ex$69: scala.caps.Exists) -> C^{ex$69}) + | Required: A^ => (ex$73: scala.caps.Exists) -> (x: C^) ->{ex$73} C | | longer explanation available when compiling with `-explain` diff --git a/tests/neg-custom-args/captures/i21313.check b/tests/neg-custom-args/captures/i21313.check index 37b944a97d68..f76f4bc6871e 100644 --- a/tests/neg-custom-args/captures/i21313.check +++ b/tests/neg-custom-args/captures/i21313.check @@ -5,7 +5,7 @@ -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/i21313.scala:15:12 --------------------------------------- 15 | ac1.await(src2) // error | ^^^^ - | Found: (src2 : Source[Int, caps.CapSet^{ac2}]^?) - | Required: Source[Int, caps.CapSet^{ac1}]^ + | Found: (src2 : Source[Int, scala.caps.CapSet^{ac2}]^?) + | Required: Source[Int, scala.caps.CapSet^{ac1}]^ | | longer explanation available when compiling with `-explain` diff --git a/tests/neg-custom-args/captures/i21401.check b/tests/neg-custom-args/captures/i21401.check index e7483e10bfa6..05378bf57f23 100644 --- a/tests/neg-custom-args/captures/i21401.check +++ b/tests/neg-custom-args/captures/i21401.check @@ -21,7 +21,7 @@ -- Error: tests/neg-custom-args/captures/i21401.scala:17:52 ------------------------------------------------------------ 17 | val x: Boxed[IO^] = leaked[Boxed[IO^], Boxed[IO^] -> Boxed[IO^]](x => x) // error // error | ^^^^^^^^^^^^^^^^^^^^^^^^ - |Type variable X of value leaked cannot be instantiated to Boxed[box IO^] -> (ex$20: caps.Exists) -> Boxed[box IO^{ex$20}] since + |Type variable X of value leaked cannot be instantiated to Boxed[box IO^] -> (ex$20: scala.caps.Exists) -> Boxed[box IO^{ex$20}] since |the part box IO^{ex$20} of that type captures the root capability `cap`. -- Error: tests/neg-custom-args/captures/i21401.scala:18:21 ------------------------------------------------------------ 18 | val y: IO^{x*} = x.unbox // error diff --git a/tests/neg-custom-args/captures/i21614.check b/tests/neg-custom-args/captures/i21614.check index f4967253455f..2d1de6c57a0b 100644 --- a/tests/neg-custom-args/captures/i21614.check +++ b/tests/neg-custom-args/captures/i21614.check @@ -8,10 +8,10 @@ -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/i21614.scala:15:12 --------------------------------------- 15 | files.map(new Logger(_)) // error, Q: can we improve the error message? | ^^^^^^^^^^^^^ - | Found: (_$1: box File^{files*}) ->{files*} (ex$16: caps.Exists) -> box Logger{val f: File^{_$1}}^{ex$16} - | Required: (_$1: box File^{files*}) => box Logger{val f: File^?}^? + |Found: (_$1: box File^{files*}) ->{files*} (ex$16: scala.caps.Exists) -> box Logger{val f: File^{_$1}}^{ex$16} + |Required: (_$1: box File^{files*}) => box Logger{val f: File^?}^? | - | Note that the universal capability `cap` - | cannot be included in capture set ? + |Note that the universal capability `cap` + |cannot be included in capture set ? | | longer explanation available when compiling with `-explain` diff --git a/tests/neg-custom-args/captures/lazylist.check b/tests/neg-custom-args/captures/lazylist.check index 65fed0c4ec7e..bc95a445f3f4 100644 --- a/tests/neg-custom-args/captures/lazylist.check +++ b/tests/neg-custom-args/captures/lazylist.check @@ -29,7 +29,7 @@ -- [E007] Type Mismatch Error: tests/neg-custom-args/captures/lazylist.scala:41:42 ------------------------------------- 41 | val ref4c: LazyList[Int]^{cap1, ref3} = ref4 // error | ^^^^ - | Found: (ref4 : lazylists.LazyList[Int]^{cap3, ref1, ref2}) + | Found: (ref4 : lazylists.LazyList[Int]^{cap3, cap2, ref1, cap1}) | Required: lazylists.LazyList[Int]^{cap1, ref3} | | longer explanation available when compiling with `-explain` diff --git a/tests/neg-custom-args/captures/leaked-curried.check b/tests/neg-custom-args/captures/leaked-curried.check index be11aedd74ae..d6b9c46f71e0 100644 --- a/tests/neg-custom-args/captures/leaked-curried.check +++ b/tests/neg-custom-args/captures/leaked-curried.check @@ -1,10 +1,10 @@ -- Error: tests/neg-custom-args/captures/leaked-curried.scala:14:20 ---------------------------------------------------- 14 | () => () => io // error | ^^ - | reference (io : Cap^) is not included in the allowed capture set {} - | of an enclosing function literal with expected type () -> () ->{io} (ex$7: caps.Exists) -> Cap^{ex$7} + | reference (io : Cap^) is not included in the allowed capture set {} + | of an enclosing function literal with expected type () -> () ->{io} (ex$7: scala.caps.Exists) -> Cap^{ex$7} -- Error: tests/neg-custom-args/captures/leaked-curried.scala:17:20 ---------------------------------------------------- 17 | () => () => io // error | ^^ - | reference (io : Cap^) is not included in the allowed capture set {} - | of an enclosing function literal with expected type () -> () ->{io} (ex$15: caps.Exists) -> Cap^{ex$15} + | reference (io : Cap^) is not included in the allowed capture set {} + | of an enclosing function literal with expected type () -> () ->{io} (ex$15: scala.caps.Exists) -> Cap^{ex$15} diff --git a/tests/neg-macros/i19842-a.check b/tests/neg-macros/i19842-a.check index 30b295cd05a5..af628c566c15 100644 --- a/tests/neg-macros/i19842-a.check +++ b/tests/neg-macros/i19842-a.check @@ -9,8 +9,8 @@ | | at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8) | at dotty.tools.dotc.transform.TreeChecker$.checkParents(TreeChecker.scala:210) - | at scala.quoted.runtime.impl.QuotesImpl$reflect$ClassDef$.module(QuotesImpl.scala:257) - | at scala.quoted.runtime.impl.QuotesImpl$reflect$ClassDef$.module(QuotesImpl.scala:256) + | at scala.quoted.runtime.impl.QuotesImpl$reflect$ClassDef$.module(QuotesImpl.scala:285) + | at scala.quoted.runtime.impl.QuotesImpl$reflect$ClassDef$.module(QuotesImpl.scala:284) | at Macros$.makeSerializer(Macro.scala:25) | |--------------------------------------------------------------------------------------------------------------------- diff --git a/tests/neg-macros/i19842-a/Macro.scala b/tests/neg-macros/i19842-a/Macro.scala index 18a1bc16045f..14b7c3f24a1a 100644 --- a/tests/neg-macros/i19842-a/Macro.scala +++ b/tests/neg-macros/i19842-a/Macro.scala @@ -16,7 +16,7 @@ object Macros { name, Flags.Implicit, Flags.EmptyFlags, - List(TypeRepr.of[Object], TypeRepr.of[Serializer[T]]), + _ => List(TypeRepr.of[Object], TypeRepr.of[Serializer[T]]), _ => Nil, Symbol.noSymbol ) diff --git a/tests/neg-macros/i19842-b.check b/tests/neg-macros/i19842-b.check index d84d916acb66..b402006c2d4b 100644 --- a/tests/neg-macros/i19842-b.check +++ b/tests/neg-macros/i19842-b.check @@ -9,8 +9,8 @@ | | at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8) | at dotty.tools.dotc.transform.TreeChecker$.checkParents(TreeChecker.scala:210) - | at scala.quoted.runtime.impl.QuotesImpl$reflect$ClassDef$.module(QuotesImpl.scala:257) - | at scala.quoted.runtime.impl.QuotesImpl$reflect$ClassDef$.module(QuotesImpl.scala:256) + | at scala.quoted.runtime.impl.QuotesImpl$reflect$ClassDef$.module(QuotesImpl.scala:285) + | at scala.quoted.runtime.impl.QuotesImpl$reflect$ClassDef$.module(QuotesImpl.scala:284) | at Macros$.makeSerializer(Macro.scala:27) | |--------------------------------------------------------------------------------------------------------------------- diff --git a/tests/neg-macros/i19842-b/Macro.scala b/tests/neg-macros/i19842-b/Macro.scala index f1399d328f49..8b43faab76dd 100644 --- a/tests/neg-macros/i19842-b/Macro.scala +++ b/tests/neg-macros/i19842-b/Macro.scala @@ -18,7 +18,7 @@ object Macros { name, Flags.Implicit, Flags.EmptyFlags, - List(TypeRepr.of[Object], TypeRepr.of[Serializer[T]]), + _ => List(TypeRepr.of[Object], TypeRepr.of[Serializer[T]]), _ => Nil, Symbol.noSymbol ) diff --git a/tests/neg-macros/newClassParamsMissingArgument.check b/tests/neg-macros/newClassParamsMissingArgument.check new file mode 100644 index 000000000000..2a6b53bd2d79 --- /dev/null +++ b/tests/neg-macros/newClassParamsMissingArgument.check @@ -0,0 +1,32 @@ + +-- Error: tests/neg-macros/newClassParamsMissingArgument/Test_2.scala:4:2 ---------------------------------------------- +4 | makeClass("foo") // error // error + | ^^^^^^^^^^^^^^^^ + |wrong number of arguments at inlining (while expanding macro) for (idx: Int): foo: (foo# : (idx: Int): foo), expected: 1, found: 0 +-- Error: tests/neg-macros/newClassParamsMissingArgument/Test_2.scala:4:11 --------------------------------------------- +4 | makeClass("foo") // error // error + | ^^^^^^^^^^^^^^^^ + |Malformed tree was found while expanding macro with -Xcheck-macros. + |The tree does not conform to the compiler's tree invariants. + | + |Macro was: + |scala.quoted.runtime.Expr.splice[java.lang.Object](((contextual$1: scala.quoted.Quotes) ?=> Macro_1$package.inline$makeClassExpr(scala.quoted.runtime.Expr.quote[scala.Predef.String]("foo").apply(using contextual$1))(contextual$1))) + | + |The macro returned: + |{ + | class foo(val idx: scala.Int) extends java.lang.Object + | + | (new foo(): java.lang.Object) + |} + | + |Error: + |missing argument for parameter idx of constructor foo in class foo: (idx: Int): foo + | + |stacktrace available when compiling with `-Ydebug` + |--------------------------------------------------------------------------------------------------------------------- + |Inline stack trace + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + |This location contains code that was inlined from Macro_1.scala:5 +5 |inline def makeClass(inline name: String): Object = ${ makeClassExpr('name) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + --------------------------------------------------------------------------------------------------------------------- diff --git a/tests/neg-macros/newClassParamsMissingArgument/Macro_1.scala b/tests/neg-macros/newClassParamsMissingArgument/Macro_1.scala new file mode 100644 index 000000000000..a0ee5a899e62 --- /dev/null +++ b/tests/neg-macros/newClassParamsMissingArgument/Macro_1.scala @@ -0,0 +1,24 @@ +//> using options -experimental + +import scala.quoted._ + +inline def makeClass(inline name: String): Object = ${ makeClassExpr('name) } +private def makeClassExpr(nameExpr: Expr[String])(using Quotes): Expr[Object] = { + import quotes.reflect.* + + val name = nameExpr.valueOrAbort + val parents = List(TypeTree.of[Object]) + def decls(cls: Symbol): List[Symbol] = Nil + + val cls = Symbol.newClass(Symbol.spliceOwner, name, parents = _ => parents.map(_.tpe), decls, selfType = None, Flags.EmptyFlags, Symbol.noSymbol, List(("idx", TypeRepr.of[Int]))) + + val clsDef = ClassDef(cls, parents, body = Nil) + val newCls = Typed(Apply(Select(New(TypeIdent(cls)), cls.primaryConstructor), Nil), TypeTree.of[Object]) + + Block(List(clsDef), newCls).asExprOf[Object] + + // '{ + // class `name`(idx: Int) + // new `name` + // } +} diff --git a/tests/neg-macros/newClassParamsMissingArgument/Test_2.scala b/tests/neg-macros/newClassParamsMissingArgument/Test_2.scala new file mode 100644 index 000000000000..8d7142f7bd72 --- /dev/null +++ b/tests/neg-macros/newClassParamsMissingArgument/Test_2.scala @@ -0,0 +1,5 @@ +//> using options -experimental + +@main def Test: Unit = { + makeClass("foo") // error // error +} diff --git a/tests/neg/6314-6.check b/tests/neg/6314-6.check index df988f1db9dd..7d6bd182173d 100644 --- a/tests/neg/6314-6.check +++ b/tests/neg/6314-6.check @@ -4,7 +4,7 @@ |object creation impossible, since def apply(fa: String): Int in trait XX in object Test3 is not defined |(Note that | parameter String in def apply(fa: String): Int in trait XX in object Test3 does not match - | parameter Test3.Bar[X & (X & Y)] in def apply(fa: Test3.Bar[X & YY.this.Foo]): Test3.Bar[Y & YY.this.Foo] in trait YY in object Test3 + | parameter Test3.Bar[X & Object with Test3.YY {...}#Foo] in def apply(fa: Test3.Bar[X & YY.this.Foo]): Test3.Bar[Y & YY.this.Foo] in trait YY in object Test3 | ) -- Error: tests/neg/6314-6.scala:52:3 ---------------------------------------------------------------------------------- 52 | (new YY {}).boom // error: object creation impossible @@ -12,5 +12,5 @@ |object creation impossible, since def apply(fa: String): Int in trait XX in object Test4 is not defined |(Note that | parameter String in def apply(fa: String): Int in trait XX in object Test4 does not match - | parameter Test4.Bar[X & (X & Y)] in def apply(fa: Test4.Bar[X & YY.this.FooAlias]): Test4.Bar[Y & YY.this.FooAlias] in trait YY in object Test4 + | parameter Test4.Bar[X & Object with Test4.YY {...}#FooAlias] in def apply(fa: Test4.Bar[X & YY.this.FooAlias]): Test4.Bar[Y & YY.this.FooAlias] in trait YY in object Test4 | ) diff --git a/tests/neg/i15474.check b/tests/neg/i15474.check deleted file mode 100644 index 3205f703cd50..000000000000 --- a/tests/neg/i15474.check +++ /dev/null @@ -1,31 +0,0 @@ --- Error: tests/neg/i15474.scala:6:39 ---------------------------------------------------------------------------------- -6 | given c: Conversion[ String, Int ] = _.toInt // error - | ^ - | Result of implicit search for ?{ toInt: ? } will change. - | Current result Test2.c will be no longer eligible - | because it is not defined before the search position. - | Result with new rules: augmentString. - | To opt into the new rules, compile with `-source future` or use - | the `scala.language.future` language import. - | - | To fix the problem without the language import, you could try one of the following: - | - use a `given ... with` clause as the enclosing given, - | - rearrange definitions so that Test2.c comes earlier, - | - use an explicit conversion, - | - use an import to get extension method into scope. - | This will be an error in Scala 3.5 and later. --- Error: tests/neg/i15474.scala:12:56 --------------------------------------------------------------------------------- -12 | given Ordering[Price] = summon[Ordering[BigDecimal]] // error - | ^ - | Result of implicit search for Ordering[BigDecimal] will change. - | Current result Prices.Price.given_Ordering_Price will be no longer eligible - | because it is not defined before the search position. - | Result with new rules: scala.math.Ordering.BigDecimal. - | To opt into the new rules, compile with `-source future` or use - | the `scala.language.future` language import. - | - | To fix the problem without the language import, you could try one of the following: - | - use a `given ... with` clause as the enclosing given, - | - rearrange definitions so that Prices.Price.given_Ordering_Price comes earlier, - | - use an explicit argument. - | This will be an error in Scala 3.5 and later. diff --git a/tests/neg/i22721.check b/tests/neg/i22721.check new file mode 100644 index 000000000000..44b0749f3262 --- /dev/null +++ b/tests/neg/i22721.check @@ -0,0 +1,6 @@ +-- [E161] Naming Error: tests/neg/i22721/test2.scala:3:12 -------------------------------------------------------------- +3 |private def foobar: Int = 0 // error + |^^^^^^^^^^^^^^^^^^^^^^^^^^^ + |foobar is already defined as method foobar in tests/neg/i22721/test1.scala + | + |Note that overloaded methods must all be defined in the same group of toplevel definitions diff --git a/tests/neg/i22721/test1.scala b/tests/neg/i22721/test1.scala new file mode 100644 index 000000000000..b3f1b1fba690 --- /dev/null +++ b/tests/neg/i22721/test1.scala @@ -0,0 +1,4 @@ +package example + +private def foobar: String = "foo" +object test1 { def x = foobar } diff --git a/tests/neg/i22721/test2.scala b/tests/neg/i22721/test2.scala new file mode 100644 index 000000000000..c70a42894dcd --- /dev/null +++ b/tests/neg/i22721/test2.scala @@ -0,0 +1,4 @@ +package example + +private def foobar: Int = 0 // error +object test2 { def x = foobar } diff --git a/tests/neg/i22890.check b/tests/neg/i22890.check new file mode 100644 index 000000000000..f5e37b10dac2 --- /dev/null +++ b/tests/neg/i22890.check @@ -0,0 +1,7 @@ +-- [E161] Naming Error: tests/neg/i22890/caps_1.java:3:0 --------------------------------------------------------------- +3 |class caps { // error: caps is already defined as package caps + |^ + |caps is already defined as package scala.caps +package scala contains object and package with same name: caps. +This indicates that there are several versions of the Scala standard library on the classpath. +The build should be reconfigured so that only one version of the standard library is on the classpath. diff --git a/tests/neg/i22890/Test_2.scala b/tests/neg/i22890/Test_2.scala new file mode 100644 index 000000000000..4545d5ab94ae --- /dev/null +++ b/tests/neg/i22890/Test_2.scala @@ -0,0 +1,3 @@ +@main def Test = + println("hello") +// nopos-warn diff --git a/tests/neg/i22890/caps_1.java b/tests/neg/i22890/caps_1.java new file mode 100644 index 000000000000..9bc804829932 --- /dev/null +++ b/tests/neg/i22890/caps_1.java @@ -0,0 +1,5 @@ +package scala; + +class caps { // error: caps is already defined as package caps + static public void foo() {} +} \ No newline at end of file diff --git a/tests/neg/i6225.scala b/tests/neg/i6225.scala index bb936c9a79b1..148a484fd0f1 100644 --- a/tests/neg/i6225.scala +++ b/tests/neg/i6225.scala @@ -1,4 +1,4 @@ -object O1 { // error: cannot be instantiated +object O1 { type A[X] = X opaque type T = A // error: opaque type alias must be fully applied } diff --git a/tests/neg/no-kind-polymorphism-anykind.scala b/tests/neg/no-kind-polymorphism-anykind.scala deleted file mode 100644 index b14491468d00..000000000000 --- a/tests/neg/no-kind-polymorphism-anykind.scala +++ /dev/null @@ -1,3 +0,0 @@ -//> using options -Yno-kind-polymorphism - -trait Foo[T <: AnyKind] // error: Not found: type AnyKind diff --git a/tests/neg/toplevel-overload/moredefs_1.scala b/tests/neg/toplevel-overload/moredefs_1.scala index 5ba8cfc52078..74cdd3ac1bb6 100644 --- a/tests/neg/toplevel-overload/moredefs_1.scala +++ b/tests/neg/toplevel-overload/moredefs_1.scala @@ -2,4 +2,4 @@ trait B def f(x: B) = s"B" // error: has already been compiled -private def g(): Unit = () // OK, since it is private \ No newline at end of file +private def g(): Unit = () // error: has already been compiled (def is visible in package) \ No newline at end of file diff --git a/tests/neg/type-params.check b/tests/neg/type-params.check new file mode 100644 index 000000000000..e1eefb4c6fe9 --- /dev/null +++ b/tests/neg/type-params.check @@ -0,0 +1,103 @@ +-- [E053] Type Error: tests/neg/type-params.scala:14:13 ---------------------------------------------------------------- +14 | type t = x[x] // error + | ^^^^ + | x does not take type parameters + | + | longer explanation available when compiling with `-explain` +-- [E053] Type Error: tests/neg/type-params.scala:16:13 ---------------------------------------------------------------- +16 | val foo: s[Int] // error + | ^^^^^^ + | s does not take type parameters + | + | longer explanation available when compiling with `-explain` +-- Error: tests/neg/type-params.scala:21:26 ---------------------------------------------------------------------------- +21 | object mp extends Monad[Tuple2] // error + | ^^^^^^ + | Type argument [T1, T2] =>> (T1, T2) does not have the same kind as its bound [x] +-- Error: tests/neg/type-params.scala:24:26 ---------------------------------------------------------------------------- +24 | trait ms1 extends Monad[String] // error + | ^^^^^^ + | Type argument String does not have the same kind as its bound [x] +-- Error: tests/neg/type-params.scala:25:29 ---------------------------------------------------------------------------- +25 | trait ms2[t] extends Monad[t] // error + | ^ + | Type argument t does not have the same kind as its bound [x] +-- Error: tests/neg/type-params.scala:26:35 ---------------------------------------------------------------------------- +26 | trait ms3[m[_], t] extends Monad[m[t]] // error -- added to check regression on bug + | ^^^^ + | Type argument m[t] does not have the same kind as its bound [x] +-- Error: tests/neg/type-params.scala:31:31 ---------------------------------------------------------------------------- +31 | trait Bar2[m[_]] extends Foo[m] // error check that m is properly recognized as kind *->*, while * is expected + | ^ + | Type argument m does not have the same kind as its bound +-- [E053] Type Error: tests/neg/type-params.scala:37:20 ---------------------------------------------------------------- +37 |class t1701 extends java.lang.Cloneable[String, Option, Int] // error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | Cloneable does not take type parameters + | + | longer explanation available when compiling with `-explain` +-- [E053] Type Error: tests/neg/type-params.scala:39:24 ---------------------------------------------------------------- +39 |trait t0842[T] { def m: this.type[T] = this } // error + | ^^^^^^^^^^^^ + | (t0842.this : t0842[T]) does not take type parameters + | + | longer explanation available when compiling with `-explain` +-- [E134] Type Error: tests/neg/type-params.scala:45:10 ---------------------------------------------------------------- +45 | println(a[A]) // error + | ^ + | None of the overloaded alternatives of method apply in trait Function1 with types + | (v1: t278.this.A): Unit + | (): Unit + | match type arguments [t278.this.A] and expected type Any +-- [E120] Naming Error: tests/neg/type-params.scala:44:6 --------------------------------------------------------------- +44 | def a = (p: A) => () // error + | ^ + | Double definition: + | def a: () => Unit in trait t278 at line 43 and + | def a: t278.this.A => Unit in trait t278 at line 44 + | have the same type after erasure. + | + | Consider adding a @targetName annotation to one of the conflicting definitions + | for disambiguation. +-- Error: tests/neg/type-params.scala:4:7 ------------------------------------------------------------------------------ +4 | "".==[Int] // error + | ^^^^^^^^^^ + | method == in class Any does not take type parameters +-- Error: tests/neg/type-params.scala:5:17 ----------------------------------------------------------------------------- +5 | ("": AnyRef).==[Int] // error + | ^^^^^^^^^^^^^^^^^^^^ + | method == in class Any does not take type parameters +-- Error: tests/neg/type-params.scala:6:17 ----------------------------------------------------------------------------- +6 | ("": Object).==[Int] // error + | ^^^^^^^^^^^^^^^^^^^^ + | method == in class Any does not take type parameters +-- Error: tests/neg/type-params.scala:9:14 ----------------------------------------------------------------------------- +9 | classOf[Int][Int] // error + | ^^^^^^^^^^^^^^^^^ + | illegal repeated type application + | You might have meant something like: + | classOf[Int, Int] +-- [E140] Cyclic Error: tests/neg/type-params.scala:34:11 -------------------------------------------------------------- +34 | def g[X, A[X] <: A[X]](x: A[X]) = x // error // error + | ^ + | illegal cyclic type reference: upper bound ... of type A refers back to the type itself + | + | Run with -explain-cyclic for more details. +-- [E053] Type Error: tests/neg/type-params.scala:34:28 ---------------------------------------------------------------- +34 | def g[X, A[X] <: A[X]](x: A[X]) = x // error // error + | ^^^^ + | A does not take type parameters + | + | longer explanation available when compiling with `-explain` +-- [E140] Cyclic Error: tests/neg/type-params.scala:35:8 --------------------------------------------------------------- +35 | def f[C[X] <: C[X]](l: C[_]) = l.x // error // error + | ^ + | illegal cyclic type reference: upper bound ... of type C refers back to the type itself + | + | Run with -explain-cyclic for more details. +-- [E053] Type Error: tests/neg/type-params.scala:35:25 ---------------------------------------------------------------- +35 | def f[C[X] <: C[X]](l: C[_]) = l.x // error // error + | ^^^^ + | C does not take type parameters + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg/type-params.scala b/tests/neg/type-params.scala new file mode 100644 index 000000000000..2803141f3b85 --- /dev/null +++ b/tests/neg/type-params.scala @@ -0,0 +1,45 @@ + +def `t8219 Any == is not overloaded in error message`: Unit = + // Scala 2 once defined AnyRef == and Any == as overloaded. Spec defines only Any ==. + "".==[Int] // error + ("": AnyRef).==[Int] // error + ("": Object).==[Int] // error + +def `extra type arg to class literal` = + classOf[Int][Int] // error + +class `various ancient kindedness`: + + class WellKinded[x]: + type t = x[x] // error + trait WellKindedBounded[s <: Throwable]: + val foo: s[Int] // error + class WellKindedWrongSyntax[s <: List] // must be s[x] <: List[x] ? + + class Monad[m[x]] + + object mp extends Monad[Tuple2] // error + + // expecting types of kind *->* + trait ms1 extends Monad[String] // error + trait ms2[t] extends Monad[t] // error + trait ms3[m[_], t] extends Monad[m[t]] // error -- added to check regression on bug + + // expecting types of kind * + trait Foo[x] + trait Bar1[m[_]] extends Foo[m[Int]] // check that m[Int] is properly recognized as kind-* + trait Bar2[m[_]] extends Foo[m] // error check that m is properly recognized as kind *->*, while * is expected + +def `t2918 t5093 detect cyclic error` = + def g[X, A[X] <: A[X]](x: A[X]) = x // error // error + def f[C[X] <: C[X]](l: C[_]) = l.x // error // error + +class t1701 extends java.lang.Cloneable[String, Option, Int] // error + +trait t0842[T] { def m: this.type[T] = this } // error + +trait t278: + class A + def a = () => () + def a = (p: A) => () // error + println(a[A]) // error diff --git a/tests/pending/neg/i16451.scala b/tests/pending/neg/i16451.scala new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/pos-custom-args/captures/untracked-captures.scala b/tests/pos-custom-args/captures/untracked-captures.scala index 7a090a5dd24f..f02dee607c01 100644 --- a/tests/pos-custom-args/captures/untracked-captures.scala +++ b/tests/pos-custom-args/captures/untracked-captures.scala @@ -1,4 +1,5 @@ -import caps.untrackedCaptures +import caps.unsafe.untrackedCaptures + class LL[+A] private (@untrackedCaptures lazyState: () => LL.State[A]^): private val res = lazyState() diff --git a/tests/pos-macros/newClassExtendsWithSymbolInParent/Macro_1.scala b/tests/pos-macros/newClassExtendsWithSymbolInParent/Macro_1.scala new file mode 100644 index 000000000000..569d8e0c25be --- /dev/null +++ b/tests/pos-macros/newClassExtendsWithSymbolInParent/Macro_1.scala @@ -0,0 +1,40 @@ +//> using options -experimental + +import scala.quoted.* + +transparent inline def makeClass(inline name: String): Foo[_] = ${ makeClassExpr('name) } +private def makeClassExpr(nameExpr: Expr[String])(using Quotes): Expr[Foo[_]] = { + import quotes.reflect.* + + val name = nameExpr.valueOrAbort + + // using asType on the passed Symbol leads to cyclic reference errors + def parents(cls: Symbol) = + List(AppliedType(TypeRepr.typeConstructorOf(Class.forName("Foo")), List(TypeIdent(cls).tpe))) + def decls(cls: Symbol): List[Symbol] = Nil + + val cls = Symbol.newClass(Symbol.spliceOwner, name, parents, decls, selfType = None, Flags.EmptyFlags, Symbol.noSymbol, conParams = Nil) + + val parentsWithSym = + cls.typeRef.asType match + case '[t] => + List(Apply(TypeApply(Select(New(TypeTree.of[Foo[t]]), TypeRepr.of[Foo[t]].typeSymbol.primaryConstructor), List(TypeTree.of[t])), List())) + val clsDef = ClassDef(cls, parentsWithSym, body = Nil) + + val newCls = cls.typeRef.asType match + case '[t] => + Typed(Apply(Select(New(TypeIdent(cls)), cls.primaryConstructor), Nil), TypeTree.of[Foo[t]]) + + cls.typeRef.asType match + case '[t] => + Block(List(clsDef), newCls).asExprOf[Foo[t]] + + // '{ + // class Name() extends Foo[Name.type]() + // new Name() + // } +} + +class Foo[X]() { self: X => + def getSelf: X = self +} diff --git a/tests/pos-macros/newClassExtendsWithSymbolInParent/Test_2.scala b/tests/pos-macros/newClassExtendsWithSymbolInParent/Test_2.scala new file mode 100644 index 000000000000..bb48bfadd96b --- /dev/null +++ b/tests/pos-macros/newClassExtendsWithSymbolInParent/Test_2.scala @@ -0,0 +1,6 @@ +//> using options -experimental + +@main def Test: Unit = { + val foo = makeClass("Bar") + foo.getSelf +} diff --git a/tests/pos/13633.scala b/tests/pos/13633.scala index 8883ef98d0be..ca0f7e68e81e 100644 --- a/tests/pos/13633.scala +++ b/tests/pos/13633.scala @@ -21,7 +21,7 @@ object Sums extends App: type Reverse[A] = ReverseLoop[A, EmptyTuple] - type PlusTri[A, B, C] <: Tuple = (A, B, C) match + type PlusTri[A, B, C] = (A, B, C) match case (false, false, false) => (false, false) case (true, false, false) | (false, true, false) | (false, false, true) => (false, true) case (true, true, false) | (true, false, true) | (false, true, true) => (true, false) diff --git a/tests/pos/Tuple.Drop.scala b/tests/pos/Tuple.Drop.scala deleted file mode 100644 index 9b88cc227966..000000000000 --- a/tests/pos/Tuple.Drop.scala +++ /dev/null @@ -1,7 +0,0 @@ -import compiletime.ops.int.* - -type Drop[T <: Tuple, N <: Int] <: Tuple = N match - case 0 => T - case S[n1] => T match - case EmptyTuple => EmptyTuple - case x *: xs => Drop[xs, n1] diff --git a/tests/pos/Tuple.Elem.scala b/tests/pos/Tuple.Elem.scala deleted file mode 100644 index 81494485c321..000000000000 --- a/tests/pos/Tuple.Elem.scala +++ /dev/null @@ -1,7 +0,0 @@ -import compiletime.ops.int.* - -type Elem[T <: Tuple, I <: Int] = T match - case h *: tail => - I match - case 0 => h - case S[j] => Elem[tail, j] diff --git a/tests/pos/better-fors-given.scala b/tests/pos/better-fors-given.scala index e4d64bbb30f3..6f70c5549469 100644 --- a/tests/pos/better-fors-given.scala +++ b/tests/pos/better-fors-given.scala @@ -1,3 +1,5 @@ +//> using options -preview + @main def Test: Unit = for x <- Option(23 -> "abc") diff --git a/tests/pos/better-fors-i21804.scala b/tests/pos/better-fors-i21804.scala index 7c8c753bf7c3..85ffb87b0296 100644 --- a/tests/pos/better-fors-i21804.scala +++ b/tests/pos/better-fors-i21804.scala @@ -1,4 +1,5 @@ -import scala.language.experimental.betterFors +//> using options -preview +// import scala.language.experimental.betterFors case class Container[A](val value: A) { def map[B](f: A => B): Container[B] = Container(f(value)) diff --git a/tests/pos/caps-universal.scala b/tests/pos/caps-universal.scala index 014955caaa87..3451866ed8f3 100644 --- a/tests/pos/caps-universal.scala +++ b/tests/pos/caps-universal.scala @@ -3,7 +3,7 @@ import annotation.retains val id: Int -> Int = (x: Int) => x val foo: Int => Int = id -val bar: (Int -> Int) @retains(caps.*) = foo +val bar: (Int -> Int) @retains(caps.cap) = foo diff --git a/tests/pos/deprecated-no-kind-polymorphism-anykind.scala b/tests/pos/deprecated-no-kind-polymorphism-anykind.scala new file mode 100644 index 000000000000..1697acaca6f9 --- /dev/null +++ b/tests/pos/deprecated-no-kind-polymorphism-anykind.scala @@ -0,0 +1,5 @@ +// This test is kept as a placeholder for historical reasons. +// The -Yno-kind-polymorphism flag is now deprecated and has no effect. +// Kind polymorphism with AnyKind is always enabled. + +trait Foo[T <: AnyKind] // This now works as AnyKind is always defined diff --git a/tests/pos/given-loop-prevention.scala b/tests/pos/given-loop-prevention.scala deleted file mode 100644 index f02559af1e82..000000000000 --- a/tests/pos/given-loop-prevention.scala +++ /dev/null @@ -1,14 +0,0 @@ -//> using options -Xfatal-warnings -source 3.4 - -class Foo - -object Bar { - given Foo with {} - given List[Foo] = List(summon[Foo]) // ok -} - -object Baz { - @annotation.nowarn - given List[Foo] = List(summon[Foo]) // gives a warning, which is suppressed - given Foo with {} -} diff --git a/tests/pos/i17222.2.scala b/tests/pos/i17222.2.scala deleted file mode 100644 index 34db494750c4..000000000000 --- a/tests/pos/i17222.2.scala +++ /dev/null @@ -1,30 +0,0 @@ -import scala.compiletime.* - -trait Reader[-In, Out] - -trait A: - type T - type F[X] - type Q = F[T] - -object Reader: - - given [X]: Reader[A { type Q = X }, X] with {} - -object Test: - - trait B[X] extends A: - type T = X - - trait C extends A: - type F[X] = X - - trait D[X] extends B[X] with C - - val d = new D[Int] {} - val bc = new B[Int] with C - - summonAll[(Reader[d.type, Int], Reader[d.type, Int])] // works - summonAll[(Reader[bc.type, Int], Reader[bc.type, Int])] // error - summonInline[Reader[d.type, Int]] // works - summonInline[Reader[bc.type, Int]] // works?? diff --git a/tests/pos/i17222.3.scala b/tests/pos/i17222.3.scala deleted file mode 100644 index 7ca85f65278f..000000000000 --- a/tests/pos/i17222.3.scala +++ /dev/null @@ -1,39 +0,0 @@ -import scala.compiletime.* - -trait Reader[-In, Out] - -trait A: - type T - type F[X] - type Q = F[T] - -object Reader: - - given [X]: Reader[A { type Q = X }, X] with {} - -object Test: - - trait B[X] extends A: - type T = X - - trait C extends A: - type F[X] = X - - trait D[X] extends B[X] with C - - val d = new D[Int] {} - val bc = new B[Int] with C - - case class Box[T](value: T) - - /** compiletime.summonAll, but with one case */ - inline def summonOne[T <: Box[?]]: T = - val res = - inline erasedValue[T] match - case _: Box[t] => summonInline[t] - end match - Box(res).asInstanceOf[T] - end summonOne - - summonOne[Box[Reader[d.type, Int]]] // works - summonOne[Box[Reader[bc.type, Int]]] // errors diff --git a/tests/pos/i17222.4.scala b/tests/pos/i17222.4.scala deleted file mode 100644 index 209425d47915..000000000000 --- a/tests/pos/i17222.4.scala +++ /dev/null @@ -1,71 +0,0 @@ -import scala.compiletime.* - -trait Reader[-In, Out] - -trait A: - type T - type F[X] - type Q = F[T] - -given [X]: Reader[A { type Q = X }, X] with {} - -case class Box[T](x: T) - -/** compiletime.summonAll, but with one case */ -inline def summonOne[T]: T = - val res = - inline erasedValue[T] match - case _: Box[t] => summonInline[t] - end match - Box(res).asInstanceOf[T] -end summonOne - - -@main def main = - - - trait B[X] extends A: - type T = X - - trait C extends A: - type F[X] = X - - - val bc = new B[Int] with C - - summonOne[Box[Reader[bc.type, Int]]] // errors - - - val bc2: A { type Q = Int } = new B[Int] with C - - summonOne[Box[Reader[bc2.type, Int]]] // works - - - object BC extends B[Int] with C - - summonOne[Box[Reader[BC.type, Int]]] // works - - - val a = new A: - type T = Int - type F[X] = X - - summonOne[Box[Reader[a.type, Int]]] // works - - - val b = new B[Int]: - type F[X] = X - - summonOne[Box[Reader[b.type, Int]]] // works - - - val ac = new A with C: - type T = Int - - summonOne[Box[Reader[ac.type, Int]]] // works - - - trait D[X] extends B[X] with C - val d = new D[Int] {} - - summonOne[Box[Reader[d.type, Int]]] // works diff --git a/tests/pos/i17222.5.scala b/tests/pos/i17222.5.scala deleted file mode 100644 index dc608e94235c..000000000000 --- a/tests/pos/i17222.5.scala +++ /dev/null @@ -1,26 +0,0 @@ -import scala.compiletime.* - -trait Reader[-In, Out] - -trait A: - type T - type F[X] - type Q = F[T] - -given [X]: Reader[A { type Q = X }, X] with {} - -case class Box[T](x: T) - -inline def summonOne[T]: T = - summonInline[T] -end summonOne - -@main def main = - trait B[X] extends A: - type T = X - trait C extends A: - type F[X] = X - - val bc = new B[Int] with C - summonInline[Reader[bc.type, Int]] // (I) Works - summonOne[Reader[bc.type, Int]] // (II) Errors diff --git a/tests/pos/i17222.8.scala b/tests/pos/i17222.8.scala deleted file mode 100644 index a415a78e0703..000000000000 --- a/tests/pos/i17222.8.scala +++ /dev/null @@ -1,18 +0,0 @@ -import scala.compiletime.* - -trait A: - type F - type Q = F - -trait Reader[-In, Out] -object Reader: - given [X]: Reader[A { type Q = X }, X] with {} - -class Test: - //type BC = A { type F = Int } & A // ok - type BC = A & A { type F = Int } // fail, also ok when manually de-aliased - - inline def summonOne: Unit = summonInline[Reader[BC, Int]] - - def t1(): Unit = summonInline[Reader[BC, Int]] // ok - def t2(): Unit = summonOne // error diff --git a/tests/pos/i17222.scala b/tests/pos/i17222.scala deleted file mode 100644 index 2af9fc2861a8..000000000000 --- a/tests/pos/i17222.scala +++ /dev/null @@ -1,33 +0,0 @@ -import scala.deriving.Mirror -import scala.compiletime.* - -trait Reader[-In, Out] - -trait A: - type T - type F[X] - type Q = F[T] - -object Reader: - - given [X]: Reader[A { type Q = X }, X] with {} - - type Map2[Tup1 <: Tuple, Tup2 <: Tuple, F[_, _]] <: Tuple = (Tup1, Tup2) match - case (h1 *: t1, h2 *: t2) => F[h1, h2] *: Map2[t1, t2, F] - case (EmptyTuple, EmptyTuple) => EmptyTuple - - inline given productReader[In <: Product, Out <: Product](using mi: Mirror.ProductOf[In])(using mo: Mirror.ProductOf[Out]): Reader[In, Out] = - summonAll[Map2[mi.MirroredElemTypes, mo.MirroredElemTypes, Reader]] - ??? - -object Test: - - trait B[X] extends A: - type T = X - - trait C extends A: - type F[X] = X - - val bc = new B[Int] with C - - summon[Reader[(bc.type, bc.type), (Int, Int)]] // fails diff --git a/tests/pos/i19710.scala b/tests/pos/i19710.scala deleted file mode 100644 index 03fd1e2d80b3..000000000000 --- a/tests/pos/i19710.scala +++ /dev/null @@ -1,11 +0,0 @@ -import scala.util.NotGiven - -type HasName1 = [n] =>> [x] =>> x match { - case n => true - case _ => false - } -@main def Test = { - summon[HasName1["foo"]["foo"] =:= true] - summon[NotGiven[HasName1["foo"]["bar"] =:= true]] - summon[Tuple.Filter[(1, "foo", 2, "bar"), HasName1["foo"]] =:= Tuple1["foo"]] // error -} diff --git a/tests/pos/i21320.scala b/tests/pos/i21320.scala new file mode 100644 index 000000000000..0a7e0d1941d1 --- /dev/null +++ b/tests/pos/i21320.scala @@ -0,0 +1,73 @@ +import scala.deriving.* +import scala.compiletime.* + +trait ConfigMonoid[T]: + def zero: T + def orElse(main: T, defaults: T): T + +object ConfigMonoid: + given option[T]: ConfigMonoid[Option[T]] = ??? + + inline def zeroTuple[C <: Tuple]: Tuple = + inline erasedValue[C] match + case _: EmptyTuple => EmptyTuple + case _: (t *: ts) => + summonInline[ConfigMonoid[t]].zero *: zeroTuple[ts] + + inline def valueTuple[C <: Tuple, T](index: Int, main: T, defaults: T): Tuple = + inline erasedValue[C] match + case _: EmptyTuple => EmptyTuple + case _: (t *: ts) => + def get(v: T) = v.asInstanceOf[Product].productElement(index).asInstanceOf[t] + summonInline[ConfigMonoid[t]].orElse(get(main), get(defaults)) *: valueTuple[ts, T]( + index + 1, + main, + defaults + ) + + inline given derive[T](using m: Mirror.ProductOf[T]): ConfigMonoid[T] = + new ConfigMonoid[T]: + def zero: T = m.fromProduct(zeroTuple[m.MirroredElemTypes]) + def orElse(main: T, defaults: T): T = m.fromProduct(valueTuple[m.MirroredElemTypes, T](0, main, defaults)) + + + +final case class PublishOptions( + v1: Option[String] = None, + v2: Option[String] = None, + v3: Option[String] = None, + v4: Option[String] = None, + v5: Option[String] = None, + v6: Option[String] = None, + v7: Option[String] = None, + v8: Option[String] = None, + v9: Option[String] = None, + ci: PublishContextualOptions = PublishContextualOptions(), +) +object PublishOptions: + implicit val monoid: ConfigMonoid[PublishOptions] = ConfigMonoid.derive + +final case class PublishContextualOptions( + v1: Option[String] = None, + v2: Option[String] = None, + v3: Option[String] = None, + v4: Option[String] = None, + v5: Option[String] = None, + v6: Option[String] = None, + v7: Option[String] = None, + v8: Option[String] = None, + v9: Option[String] = None, + v10: Option[String] = None, + v11: Option[String] = None, + v12: Option[String] = None, + v13: Option[String] = None, + v14: Option[String] = None, + v15: Option[String] = None, + v16: Option[String] = None, + v17: Option[String] = None, + v18: Option[String] = None, + v19: Option[String] = None, + v20: Option[String] = None +) +object PublishContextualOptions: + given monoid: ConfigMonoid[PublishContextualOptions] = ConfigMonoid.derive \ No newline at end of file diff --git a/tests/pos/i21410.scala b/tests/pos/i21410.scala deleted file mode 100644 index c3ba3ea862bc..000000000000 --- a/tests/pos/i21410.scala +++ /dev/null @@ -1,12 +0,0 @@ -class A -object Test: - type F[X] <: Any = X match - case A => Int - - def foo[T](x: String): T = ??? - def foo[U](x: U): F[U] = ??? - - val x1 = foo(A()) - val y: Int = x1 - - val x2: Int = foo(A()) // error diff --git a/tests/pos/i21410b.scala b/tests/pos/i21410b.scala deleted file mode 100644 index a17ad59bc59e..000000000000 --- a/tests/pos/i21410b.scala +++ /dev/null @@ -1,10 +0,0 @@ -object Test: - def foo[T](x: Option[T]): T = ??? - def foo[T <: Tuple](x: T): Tuple.Map[T, List] = ??? - - val tup: (Int, String) = (1, "") - - val x = foo(tup) - val y: (List[Int], List[String]) = x - - val x2: (List[Int], List[String]) = foo(tup) // error diff --git a/tests/pos/i21410c.scala b/tests/pos/i21410c.scala deleted file mode 100644 index 21f69fec20fa..000000000000 --- a/tests/pos/i21410c.scala +++ /dev/null @@ -1,11 +0,0 @@ -class AppliedPIso[A, B]() -case class User(age: Int) - -object Test: - extension [From, To](from: From) - def focus(): AppliedPIso[From, From] = ??? - transparent inline def focus(inline lambda: (From => To)): Any = ??? - - - val u = User(1) - val ap: AppliedPIso[User, User] = u.focus(_.age) // error diff --git a/tests/run-macros/annot-add-global-object/Macro_1.scala b/tests/run-macros/annot-add-global-object/Macro_1.scala index 031d6e33fefe..b928cf23c2e8 100644 --- a/tests/run-macros/annot-add-global-object/Macro_1.scala +++ b/tests/run-macros/annot-add-global-object/Macro_1.scala @@ -14,7 +14,7 @@ class addClass extends MacroAnnotation: def decls(cls: Symbol): List[Symbol] = List(Symbol.newMethod(cls, "run", MethodType(Nil)(_ => Nil, _ => TypeRepr.of[Unit]), Flags.EmptyFlags, Symbol.noSymbol)) - val mod = Symbol.newModule(Symbol.spliceOwner, Symbol.freshName("Bar"), Flags.EmptyFlags, Flags.EmptyFlags, parents.map(_.tpe), decls, Symbol.noSymbol) + val mod = Symbol.newModule(Symbol.spliceOwner, Symbol.freshName("Bar"), Flags.EmptyFlags, Flags.EmptyFlags, _ => parents.map(_.tpe), decls, Symbol.noSymbol) val cls = mod.moduleClass val runSym = cls.declaredMethod("run").head diff --git a/tests/run-macros/annot-add-local-object/Macro_1.scala b/tests/run-macros/annot-add-local-object/Macro_1.scala index 3d47fafd599a..bbdfbfd287d4 100644 --- a/tests/run-macros/annot-add-local-object/Macro_1.scala +++ b/tests/run-macros/annot-add-local-object/Macro_1.scala @@ -14,7 +14,7 @@ class addClass extends MacroAnnotation: def decls(cls: Symbol): List[Symbol] = List(Symbol.newMethod(cls, "run", MethodType(Nil)(_ => Nil, _ => TypeRepr.of[Unit]), Flags.EmptyFlags, Symbol.noSymbol)) - val mod = Symbol.newModule(Symbol.spliceOwner, "Baz", Flags.EmptyFlags, Flags.EmptyFlags, parents.map(_.tpe), decls, Symbol.noSymbol) + val mod = Symbol.newModule(Symbol.spliceOwner, "Baz", Flags.EmptyFlags, Flags.EmptyFlags, _ => parents.map(_.tpe), decls, Symbol.noSymbol) val cls = mod.moduleClass val runSym = cls.declaredMethod("run").head diff --git a/tests/run-macros/annot-add-nested-object/Macro_1.scala b/tests/run-macros/annot-add-nested-object/Macro_1.scala index ce6cbaa67a57..cfc4691e95c9 100644 --- a/tests/run-macros/annot-add-nested-object/Macro_1.scala +++ b/tests/run-macros/annot-add-nested-object/Macro_1.scala @@ -14,7 +14,7 @@ class addClass extends MacroAnnotation: def decls(cls: Symbol): List[Symbol] = List(Symbol.newMethod(cls, "run", MethodType(Nil)(_ => Nil, _ => TypeRepr.of[Unit]), Flags.EmptyFlags, Symbol.noSymbol)) - val mod = Symbol.newModule(Symbol.spliceOwner, Symbol.freshName("Bar"), Flags.EmptyFlags, Flags.EmptyFlags, parents.map(_.tpe), decls, Symbol.noSymbol) + val mod = Symbol.newModule(Symbol.spliceOwner, Symbol.freshName("Bar"), Flags.EmptyFlags, Flags.EmptyFlags, _ => parents.map(_.tpe), decls, Symbol.noSymbol) val cls = mod.moduleClass val runSym = cls.declaredMethod("run").head diff --git a/tests/run-macros/newClassAnnotation.check b/tests/run-macros/newClassAnnotation.check new file mode 100644 index 000000000000..433c40f72180 --- /dev/null +++ b/tests/run-macros/newClassAnnotation.check @@ -0,0 +1,7 @@ +{ + @JavaAnnot("string in a java annotation") @ScalaAnnotation("string in a scala annotation") class name() extends java.lang.Object + + (new name(): scala.Any) +} +class Test_2$package$name$1 +string in a java annotation diff --git a/tests/run-macros/newClassAnnotation/JavaAnnot.java b/tests/run-macros/newClassAnnotation/JavaAnnot.java new file mode 100644 index 000000000000..2c815478c198 --- /dev/null +++ b/tests/run-macros/newClassAnnotation/JavaAnnot.java @@ -0,0 +1,5 @@ +import java.lang.annotation.*; +public @Retention(RetentionPolicy.RUNTIME) +@interface JavaAnnot { + public String value(); +} \ No newline at end of file diff --git a/tests/run-macros/newClassAnnotation/Macro_1.scala b/tests/run-macros/newClassAnnotation/Macro_1.scala new file mode 100644 index 000000000000..c7631317675b --- /dev/null +++ b/tests/run-macros/newClassAnnotation/Macro_1.scala @@ -0,0 +1,56 @@ +//> using options -experimental + +import scala.quoted.* +import scala.annotation.StaticAnnotation + +class ScalaAnnotation(value: String) extends StaticAnnotation + +inline def makeClass(inline name: String): Any = ${ makeClassExpr('name) } +private def makeClassExpr(nameExpr: Expr[String])(using Quotes): Expr[Any] = { + import quotes.reflect.* + + val name = nameExpr.valueOrAbort + def decls(cls: Symbol): List[Symbol] = Nil + val conMethodType = (classType: TypeRepr) => MethodType(Nil)((_: MethodType) => Nil, (_: MethodType) => classType) + + val javaAnnotSym = TypeRepr.of[JavaAnnot].typeSymbol + val scalaAnnotSym = TypeRepr.of[ScalaAnnotation].typeSymbol + + val javaAnnotationDef = Apply(Select(New(TypeIdent(javaAnnotSym)), javaAnnotSym.primaryConstructor), List(Literal(StringConstant("string in a java annotation")))) + val scalaAnnotationDef = Apply(Select(New(TypeIdent(scalaAnnotSym)), scalaAnnotSym.primaryConstructor), List(Literal(StringConstant("string in a scala annotation")))) + + val cls = Symbol.newClass( + Symbol.spliceOwner, + name, + parents = _ => List(TypeRepr.of[Object]), + decls, + selfType = None, + clsFlags = Flags.EmptyFlags, + clsPrivateWithin = Symbol.noSymbol, + clsAnnotations = List(javaAnnotationDef, scalaAnnotationDef), + conMethodType, + conFlags = Flags.EmptyFlags, + conPrivateWithin = Symbol.noSymbol, + conParamFlags = List(List()), + conParamPrivateWithins = List(List()) + ) + + val clsDef = ClassDef(cls, List(TypeTree.of[Object]), body = Nil) + val newCls = + Typed( + Apply( + Select(New(TypeIdent(cls)), cls.primaryConstructor), + Nil + ), + TypeTree.of[Any] + ) + + val res = Block(List(clsDef), newCls).asExpr + + Expr.ofTuple(res, Expr(res.show)) + + // { + // @JavaAnnot("string in a java annotation") @ScalaAnnotation("string in a scala annotation") class name() extends java.lang.Object + // (new name(): scala.Any) + // } +} diff --git a/tests/run-macros/newClassAnnotation/Test_2.scala b/tests/run-macros/newClassAnnotation/Test_2.scala new file mode 100644 index 000000000000..a824259eba09 --- /dev/null +++ b/tests/run-macros/newClassAnnotation/Test_2.scala @@ -0,0 +1,7 @@ +//> using options -experimental + +@main def Test = + val (cls, str) = makeClass("name") + println(str) + println(cls.getClass) + println(cls.getClass.getAnnotation(classOf[JavaAnnot]).value) diff --git a/tests/run-macros/newClassExtendsJavaClass.check b/tests/run-macros/newClassExtendsJavaClass.check new file mode 100644 index 000000000000..bd07b5536ebc --- /dev/null +++ b/tests/run-macros/newClassExtendsJavaClass.check @@ -0,0 +1,2 @@ +class Main_2$package$foo$1 +22 diff --git a/tests/run-macros/newClassExtendsJavaClass/JavaClass.java b/tests/run-macros/newClassExtendsJavaClass/JavaClass.java new file mode 100644 index 000000000000..8a02cf294a01 --- /dev/null +++ b/tests/run-macros/newClassExtendsJavaClass/JavaClass.java @@ -0,0 +1,9 @@ +class JavaClass { + T value; + public JavaClass(T value) { + this.value = value; + } + public T getT() { + return value; + } +} \ No newline at end of file diff --git a/tests/run-macros/newClassExtendsJavaClass/Macro_1.scala b/tests/run-macros/newClassExtendsJavaClass/Macro_1.scala new file mode 100644 index 000000000000..c342c78da796 --- /dev/null +++ b/tests/run-macros/newClassExtendsJavaClass/Macro_1.scala @@ -0,0 +1,24 @@ +//> using options -experimental + +import scala.quoted.* + +transparent inline def makeClass(inline name: String): JavaClass[Int] = ${ makeClassExpr('name) } +private def makeClassExpr(nameExpr: Expr[String])(using Quotes): Expr[JavaClass[Int]] = { + import quotes.reflect.* + + val name = nameExpr.valueOrAbort + val parents = List(TypeTree.of[JavaClass[Int]]) + def decls(cls: Symbol): List[Symbol] = Nil + + val cls = Symbol.newClass(Symbol.spliceOwner, name, parents = _ => parents.map(_.tpe), decls, selfType = None, Flags.EmptyFlags, Symbol.noSymbol, List(("idx", TypeRepr.of[Int]))) + + val parentsWithSym = List(Apply(TypeApply(Select(New(TypeTree.of[JavaClass[Int]]), TypeRepr.of[JavaClass].typeSymbol.primaryConstructor), List(TypeTree.of[Int])), List(Ref(cls.fieldMember("idx"))))) + val clsDef = ClassDef(cls, parentsWithSym, body = Nil) + val newCls = Typed(Apply(Select(New(TypeIdent(cls)), cls.primaryConstructor), List(Literal(IntConstant(22)))), TypeTree.of[JavaClass[Int]]) + + Block(List(clsDef), newCls).asExprOf[JavaClass[Int]] + // '{ + // class `name`(idx: Int) extends JavaClass[Int](idx) + // new `name`(22) + // } +} \ No newline at end of file diff --git a/tests/run-macros/newClassExtendsJavaClass/Main_2.scala b/tests/run-macros/newClassExtendsJavaClass/Main_2.scala new file mode 100644 index 000000000000..b41c22427c8e --- /dev/null +++ b/tests/run-macros/newClassExtendsJavaClass/Main_2.scala @@ -0,0 +1,7 @@ +//> using options -experimental + +@main def Test: Unit = { + val cls = makeClass("foo") + println(cls.getClass) + println(cls.getT()) +} diff --git a/tests/run-macros/newClassParams.check b/tests/run-macros/newClassParams.check new file mode 100644 index 000000000000..314cd012f3e5 --- /dev/null +++ b/tests/run-macros/newClassParams.check @@ -0,0 +1 @@ +Foo method call with (10, test) diff --git a/tests/run-macros/newClassParams/Macro_1.scala b/tests/run-macros/newClassParams/Macro_1.scala new file mode 100644 index 000000000000..6ec48e24ebe3 --- /dev/null +++ b/tests/run-macros/newClassParams/Macro_1.scala @@ -0,0 +1,42 @@ +//> using options -experimental + +import scala.quoted._ + +inline def makeClassAndCall(inline name: String, idx: Int, str: String): Unit = ${ makeClassAndCallExpr('name, 'idx, 'str) } +private def makeClassAndCallExpr(nameExpr: Expr[String], idxExpr: Expr[Int], strExpr: Expr[String])(using Quotes): Expr[Unit] = { + import quotes.reflect.* + + val name = nameExpr.valueOrAbort + + def decls(cls: Symbol): List[Symbol] = + List(Symbol.newMethod(cls, "foo", MethodType(Nil)(_ => Nil, _ => TypeRepr.of[Unit]))) + val parents = List(TypeTree.of[Object]) + val cls = Symbol.newClass( + Symbol.spliceOwner, + name, + parents = _ => parents.map(_.tpe), + decls, + selfType = None, + clsFlags = Flags.EmptyFlags, + Symbol.noSymbol, + List(("idx", TypeRepr.of[Int]), ("str", TypeRepr.of[String])) + ) + + val fooSym = cls.declaredMethod("foo").head + val idxSym = cls.fieldMember("idx") + val strSym = cls.fieldMember("str") + val fooDef = DefDef(fooSym, argss => + Some('{println(s"Foo method call with (${${Ref(idxSym).asExpr}}, ${${Ref(strSym).asExpr}})")}.asTerm) + ) + val clsDef = ClassDef(cls, parents, body = List(fooDef)) + val newCls = Apply(Select(New(TypeIdent(cls)), cls.primaryConstructor), List(idxExpr.asTerm, strExpr.asTerm)) + + Block(List(clsDef), Apply(Select(newCls, cls.methodMember("foo")(0)), Nil)).asExprOf[Unit] + + // '{ + // class `name`(idx: Int, str: String) { + // def foo() = println("Foo method call with ($idx, $str)") + // } + // new `name`(`idx`, `str`) + // } +} diff --git a/tests/run-macros/newClassParams/Test_2.scala b/tests/run-macros/newClassParams/Test_2.scala new file mode 100644 index 000000000000..64762f17b92f --- /dev/null +++ b/tests/run-macros/newClassParams/Test_2.scala @@ -0,0 +1,5 @@ +//> using options -experimental + +@main def Test: Unit = { + makeClassAndCall("bar", 10, "test") +} diff --git a/tests/run-macros/newClassParamsExtendsClassParams.check b/tests/run-macros/newClassParamsExtendsClassParams.check new file mode 100644 index 000000000000..86d844c7d00f --- /dev/null +++ b/tests/run-macros/newClassParamsExtendsClassParams.check @@ -0,0 +1,4 @@ +Calling Foo.foo with i = 22 +class Test_2$package$foo$1 +Calling Foo.foo with i = 22 +class Test_2$package$bar$1 diff --git a/tests/run-macros/newClassParamsExtendsClassParams/Macro_1.scala b/tests/run-macros/newClassParamsExtendsClassParams/Macro_1.scala new file mode 100644 index 000000000000..de35a4dfa206 --- /dev/null +++ b/tests/run-macros/newClassParamsExtendsClassParams/Macro_1.scala @@ -0,0 +1,29 @@ +//> using options -experimental + +import scala.quoted._ + +inline def makeClass(inline name: String): Foo = ${ makeClassExpr('name) } +private def makeClassExpr(nameExpr: Expr[String])(using Quotes): Expr[Foo] = { + import quotes.reflect.* + + val name = nameExpr.valueOrAbort + val parents = List('{ new Foo(1) }.asTerm) + def decls(cls: Symbol): List[Symbol] = Nil + + val cls = Symbol.newClass(Symbol.spliceOwner, name, parents = _ => parents.map(_.tpe), decls, selfType = None, Flags.EmptyFlags, Symbol.noSymbol, List(("idx", TypeRepr.of[Int]))) + + val parentsWithSym = List(Apply(Select(New(TypeTree.of[Foo]), TypeRepr.of[Foo].typeSymbol.primaryConstructor), List(Ref(cls.fieldMember("idx"))))) + val clsDef = ClassDef(cls, parentsWithSym, body = Nil) + val newCls = Typed(Apply(Select(New(TypeIdent(cls)), cls.primaryConstructor), List(Literal(IntConstant(22)))), TypeTree.of[Foo]) + + Block(List(clsDef), newCls).asExprOf[Foo] + + // '{ + // class `name`(idx: Int) extends Foo(idx) + // new `name`(22) + // } +} + +class Foo(i: Int) { + def foo(): Unit = println(s"Calling Foo.foo with i = $i") +} diff --git a/tests/run-macros/newClassParamsExtendsClassParams/Test_2.scala b/tests/run-macros/newClassParamsExtendsClassParams/Test_2.scala new file mode 100644 index 000000000000..6e902825fdc6 --- /dev/null +++ b/tests/run-macros/newClassParamsExtendsClassParams/Test_2.scala @@ -0,0 +1,10 @@ +//> using options -experimental + +@main def Test: Unit = { + val foo: Foo = makeClass("foo") + foo.foo() + println(foo.getClass) + val bar: Foo = makeClass("bar") + bar.foo() + println(bar.getClass) +} diff --git a/tests/run-macros/newClassTraitAndAbstract.check b/tests/run-macros/newClassTraitAndAbstract.check new file mode 100644 index 000000000000..65e8c6435722 --- /dev/null +++ b/tests/run-macros/newClassTraitAndAbstract.check @@ -0,0 +1,14 @@ +class Test_2$package$anon$1 +{ + trait foo[A, B <: scala.Int](val param1: A, val param2: B) extends java.lang.Object + class anon() extends java.lang.Object with foo[java.lang.String, scala.Int]("a", 1) + + (new anon(): scala.Any) +} +class Test_2$package$anon$2 +{ + abstract class bar[A, B <: scala.Int](val param1: A, val param2: B) extends java.lang.Object + class anon() extends bar[java.lang.String, scala.Int]("a", 1) + + (new anon(): scala.Any) +} diff --git a/tests/run-macros/newClassTraitAndAbstract/Macro_1.scala b/tests/run-macros/newClassTraitAndAbstract/Macro_1.scala new file mode 100644 index 000000000000..56cd320085db --- /dev/null +++ b/tests/run-macros/newClassTraitAndAbstract/Macro_1.scala @@ -0,0 +1,99 @@ +//> using options -experimental + +import scala.quoted.* + +transparent inline def makeTrait(inline name: String): Any = ${ makeTraitExpr('name) } +transparent inline def makeAbstractClass(inline name: String): Any = ${ makeAbstractClassExpr('name) } + +private def makeTraitExpr(name: Expr[String])(using Quotes): Expr[Any] = { + makeClassExpr(name, quotes.reflect.Flags.Trait, List(quotes.reflect.TypeTree.of[Object])) + // '{ + // trait `name`[A, B <: Int](param1: A, param2: B) + // class anon() extends `name`[String, Int]("a", 1) + // new $anon() + // } +} + +private def makeAbstractClassExpr(name: Expr[String])(using Quotes): Expr[Any] = { + makeClassExpr(name, quotes.reflect.Flags.Abstract, Nil) + // '{ + // abstract class `name`[A, B <: Int](param1: A, param2: B) + // class anon() extends `name`[String, Int]("a", 1) + // new $anon() + // } +} + +private def makeClassExpr(using Quotes)( + nameExpr: Expr[String], clsFlags: quotes.reflect.Flags, childExtraParents: List[quotes.reflect.TypeTree] + ): Expr[Any] = { + import quotes.reflect.* + + val name = nameExpr.valueOrAbort + def decls(cls: Symbol): List[Symbol] = Nil + val conMethodType = + (classType: TypeRepr) => PolyType(List("A", "B"))( + _ => List(TypeBounds.empty, TypeBounds.upper(TypeRepr.of[Int])), + polyType => MethodType(List("param1", "param2"))((_: MethodType) => List(polyType.param(0), polyType.param(1)), (_: MethodType) => + AppliedType(classType, List(polyType.param(0), polyType.param(1))) + ) + ) + + val traitSymbol = Symbol.newClass( + Symbol.spliceOwner, + name, + parents = _ => List(TypeRepr.of[Object]), + decls, + selfType = None, + clsFlags, + clsPrivateWithin = Symbol.noSymbol, + clsAnnotations = Nil, + conMethodType, + conFlags = Flags.EmptyFlags, + conPrivateWithin = Symbol.noSymbol, + conParamFlags = List(List(Flags.EmptyFlags, Flags.EmptyFlags), List(Flags.EmptyFlags, Flags.EmptyFlags)), + conParamPrivateWithins = List(List(Symbol.noSymbol, Symbol.noSymbol), List(Symbol.noSymbol, Symbol.noSymbol)) + ) + val traitDef = ClassDef(traitSymbol, List(TypeTree.of[Object]), body = Nil) + + val traitTypeTree = Applied(TypeIdent(traitSymbol), List(TypeTree.of[String], TypeTree.of[Int])) + val clsSymbol = Symbol.newClass( + Symbol.spliceOwner, + "anon", + parents = _ => childExtraParents.map(_.tpe) ++ List(traitTypeTree.tpe), + decls = _ => Nil, + selfType = None, + clsFlags = Flags.EmptyFlags, + clsPrivateWithin = Symbol.noSymbol, + clsAnnotations = Nil, + conMethodType = (classType: TypeRepr) => MethodType(Nil)(_ => Nil, _ => classType), + conFlags = Flags.EmptyFlags, + conPrivateWithin = Symbol.noSymbol, + conParamFlags = List(List()), + conParamPrivateWithins = List(List(Symbol.noSymbol, Symbol.noSymbol), List(Symbol.noSymbol, Symbol.noSymbol)) + ) + val obj = '{new java.lang.Object()}.asTerm match + case Inlined(_, _, term) => term + + val parentsWithSym = childExtraParents ++ List( + Apply( + TypeApply( + Select(New(traitTypeTree), traitSymbol.primaryConstructor), + List(TypeTree.of[String], TypeTree.of[Int]) + ), + List(Expr("a").asTerm, Expr(1).asTerm) + ) + ) + val clsDef = ClassDef(clsSymbol, parentsWithSym, body = Nil) + + val newCls = + Typed( + Apply( + Select(New(TypeIdent(clsSymbol)), clsSymbol.primaryConstructor), + Nil + ), + TypeTree.of[Any] + ) + val res = Block(List(traitDef), Block(List(clsDef), newCls)).asExpr + + Expr.ofTuple(res, Expr(res.show)) +} diff --git a/tests/run-macros/newClassTraitAndAbstract/Test_2.scala b/tests/run-macros/newClassTraitAndAbstract/Test_2.scala new file mode 100644 index 000000000000..5b6512a49010 --- /dev/null +++ b/tests/run-macros/newClassTraitAndAbstract/Test_2.scala @@ -0,0 +1,11 @@ +//> using options -experimental + +@main def Test: Unit = { + val (cls1, show1) = makeTrait("foo") + println(cls1.getClass) + println(show1) + + val (cls2, show2) = makeAbstractClass("bar") + println(cls2.getClass) + println(show2) +} diff --git a/tests/run-macros/newClassTypeParams.check b/tests/run-macros/newClassTypeParams.check new file mode 100644 index 000000000000..8c400039681c --- /dev/null +++ b/tests/run-macros/newClassTypeParams.check @@ -0,0 +1,6 @@ +class Test_2$package$foo$1 +{ + class foo[A, B <: scala.Int](val param1: A, val param2: B) extends java.lang.Object + + (new foo[java.lang.String, scala.Int]("test", 1): scala.Any) +} diff --git a/tests/run-macros/newClassTypeParams/Macro_1.scala b/tests/run-macros/newClassTypeParams/Macro_1.scala new file mode 100644 index 000000000000..2efb31610c73 --- /dev/null +++ b/tests/run-macros/newClassTypeParams/Macro_1.scala @@ -0,0 +1,53 @@ +//> using options -experimental + +import scala.quoted.* + +transparent inline def makeClass(inline name: String): Any = ${ makeClassExpr('name) } +private def makeClassExpr(nameExpr: Expr[String])(using Quotes): Expr[Any] = { + import quotes.reflect.* + + val name = nameExpr.valueOrAbort + def decls(cls: Symbol): List[Symbol] = Nil + val conMethodType = + (classType: TypeRepr) => PolyType(List("A", "B"))( + _ => List(TypeBounds.empty, TypeBounds.upper(TypeRepr.of[Int])), + polyType => MethodType(List("param1", "param2"))((_: MethodType) => List(polyType.param(0), polyType.param(1)), (_: MethodType) => + AppliedType(classType, List(polyType.param(0), polyType.param(1))) + ) + ) + + val cls = Symbol.newClass( + Symbol.spliceOwner, + name, + parents = _ => List(TypeRepr.of[Object]), + decls, + selfType = None, + clsFlags = Flags.EmptyFlags, + clsPrivateWithin = Symbol.noSymbol, + clsAnnotations = Nil, + conMethodType, + conFlags = Flags.EmptyFlags, + conPrivateWithin = Symbol.noSymbol, + conParamFlags = List(List(Flags.EmptyFlags, Flags.EmptyFlags), List(Flags.EmptyFlags, Flags.EmptyFlags)), + conParamPrivateWithins = List(List(Symbol.noSymbol, Symbol.noSymbol), List(Symbol.noSymbol, Symbol.noSymbol)) + ) + + val clsDef = ClassDef(cls, List(TypeTree.of[Object]), body = Nil) + val newCls = + Typed( + Apply( + TypeApply(Select(New(TypeIdent(cls)), cls.primaryConstructor), List(TypeTree.of[String], TypeTree.of[Int])), + List(Expr("test").asTerm, Expr(1).asTerm) + ), + TypeTree.of[Any] + ) + + val res = Block(List(clsDef), newCls).asExpr + + Expr.ofTuple(res, Expr(res.show)) + + // '{ + // class `name`[A, B <: Int](param1: A, param2: B) + // new `name`[String, Int]("a", 1) + // } +} diff --git a/tests/run-macros/newClassTypeParams/Test_2.scala b/tests/run-macros/newClassTypeParams/Test_2.scala new file mode 100644 index 000000000000..742c0f480a77 --- /dev/null +++ b/tests/run-macros/newClassTypeParams/Test_2.scala @@ -0,0 +1,7 @@ +//> using options -experimental + +@main def Test: Unit = { + val (cls, show) = makeClass("foo") + println(cls.getClass) + println(show) +} diff --git a/tests/run-macros/newClassTypeParamsDoc.check b/tests/run-macros/newClassTypeParamsDoc.check new file mode 100644 index 000000000000..5d3b08bf509c --- /dev/null +++ b/tests/run-macros/newClassTypeParamsDoc.check @@ -0,0 +1,2 @@ +Calling getParam +test diff --git a/tests/run-macros/newClassTypeParamsDoc/Macro_1.scala b/tests/run-macros/newClassTypeParamsDoc/Macro_1.scala new file mode 100644 index 000000000000..9fb81e6f7348 --- /dev/null +++ b/tests/run-macros/newClassTypeParamsDoc/Macro_1.scala @@ -0,0 +1,67 @@ +//> using options -experimental + +import scala.quoted.* + +transparent inline def makeClass(): Any = ${ makeClassExpr } +private def makeClassExpr(using Quotes): Expr[Any] = { + import quotes.reflect.* + + val name = "myClass" + def decls(cls: Symbol): List[Symbol] = + List(Symbol.newMethod(cls, "getParam", MethodType(Nil)(_ => Nil, _ => cls.typeMember("T").typeRef))) + val conMethodType = + (classType: TypeRepr) => PolyType(List("T"))(_ => List(TypeBounds.empty), polyType => + MethodType(List("param"))((_: MethodType) => List(polyType.param(0)), (_: MethodType) => + AppliedType(classType, List(polyType.param(0))) + ) + ) + val cls = Symbol.newClass( + Symbol.spliceOwner, + name, + parents = _ => List(TypeRepr.of[Object]), + decls, + selfType = None, + clsFlags = Flags.EmptyFlags, + clsPrivateWithin = Symbol.noSymbol, + clsAnnotations = Nil, + conMethodType, + conFlags = Flags.EmptyFlags, + conPrivateWithin = Symbol.noSymbol, + conParamFlags = List(List(Flags.EmptyFlags), List(Flags.EmptyFlags)), + conParamPrivateWithins = List(List(Symbol.noSymbol), List(Symbol.noSymbol)) + ) + + val getParamSym = cls.declaredMethod("getParam").head + def getParamRhs(): Option[Term] = + val paramValue = This(cls).select(cls.fieldMember("param")).asExpr + Some('{ println("Calling getParam"); $paramValue }.asTerm) + val getParamDef = DefDef(getParamSym, _ => getParamRhs()) + + val clsDef = ClassDef(cls, List(TypeTree.of[Object]), body = List(getParamDef)) + val appliedTypeTree = Applied(TypeIdent(cls), List(TypeTree.of[String])) + val newCls = + Typed( + Apply( + Select( + Apply( + TypeApply(Select(New(appliedTypeTree), cls.primaryConstructor), List(TypeTree.of[String])), + List(Expr("test").asTerm) + ), + cls.methodMember("getParam").head + ), + Nil + ), + TypeTree.of[String] + ) + + Block(List(clsDef), newCls).asExpr + + // '{ + // class myClass[T](val param: T) { + // def getParam(): T = + // println("Calling getParam") + // param + // } + // new myClass[String]("test").getParam() + // } +} diff --git a/tests/run-macros/newClassTypeParamsDoc/Test_2.scala b/tests/run-macros/newClassTypeParamsDoc/Test_2.scala new file mode 100644 index 000000000000..318db32242fc --- /dev/null +++ b/tests/run-macros/newClassTypeParamsDoc/Test_2.scala @@ -0,0 +1,5 @@ +//> using options -experimental + +@main def Test: Unit = { + println(makeClass()) +} diff --git a/tests/run-macros/tasty-definitions-1.check b/tests/run-macros/tasty-definitions-1.check index 1eba400b6c71..066aeb2eeae4 100644 --- a/tests/run-macros/tasty-definitions-1.check +++ b/tests/run-macros/tasty-definitions-1.check @@ -57,57 +57,31 @@ Function23 Function24 Function25 ContextFunction0 -ContextFunction0 -ContextFunction1 ContextFunction1 ContextFunction2 -ContextFunction2 -ContextFunction3 ContextFunction3 ContextFunction4 -ContextFunction4 -ContextFunction5 ContextFunction5 ContextFunction6 -ContextFunction6 ContextFunction7 -ContextFunction7 -ContextFunction8 ContextFunction8 ContextFunction9 -ContextFunction9 ContextFunction10 -ContextFunction10 -ContextFunction11 ContextFunction11 ContextFunction12 -ContextFunction12 ContextFunction13 -ContextFunction13 -ContextFunction14 ContextFunction14 ContextFunction15 -ContextFunction15 -ContextFunction16 ContextFunction16 ContextFunction17 -ContextFunction17 -ContextFunction18 ContextFunction18 ContextFunction19 -ContextFunction19 ContextFunction20 -ContextFunction20 -ContextFunction21 ContextFunction21 ContextFunction22 -ContextFunction22 ContextFunction23 -ContextFunction23 -ContextFunction24 ContextFunction24 ContextFunction25 -ContextFunction25 class java.lang.Exception: Erased function classes are not supported. Use a refined `scala.PolyFunction` PolyFunction Tuple2 diff --git a/tests/run-macros/tasty-definitions-1/quoted_1.scala b/tests/run-macros/tasty-definitions-1/quoted_1.scala index f5538cb903dc..9a6d6e2edd41 100644 --- a/tests/run-macros/tasty-definitions-1/quoted_1.scala +++ b/tests/run-macros/tasty-definitions-1/quoted_1.scala @@ -60,7 +60,6 @@ object Macros { printout(defn.FunctionClass(i).name) for (i <- 0 to 25) - printout(defn.FunctionClass(i, isContextual = true).name) printout(defn.FunctionClass(i, isImplicit = true).name) // should fail diff --git a/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala b/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala index 0715bedea201..3e7a4868b0cb 100644 --- a/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala +++ b/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala @@ -32,8 +32,19 @@ val experimentalDefinitionInLibrary = Set( "scala.annotation.retainsCap", "scala.annotation.retainsArg", "scala.Pure", - "scala.caps", - "scala.caps$", + "scala.caps.CapSet", + "scala.caps.Capability", + "scala.caps.Contains", + "scala.caps.Contains$", + "scala.caps.Contains$.containsImpl", + "scala.caps.Exists", + "scala.caps.internal", + "scala.caps.internal$", + "scala.caps.cap", + "scala.caps.cap$", + "scala.caps.unsafe", + "scala.caps.unsafe$", + "scala.caps.use", //// New feature: into "scala.annotation.into", diff --git a/tests/run/better-fors-map-elim.scala b/tests/run/better-fors-map-elim.scala index 653984bc8e28..6f4db6573dec 100644 --- a/tests/run/better-fors-map-elim.scala +++ b/tests/run/better-fors-map-elim.scala @@ -1,4 +1,5 @@ -import scala.language.experimental.betterFors +//> using options -preview +// import scala.language.experimental.betterFors class myOptionModule(doOnMap: => Unit) { sealed trait MyOption[+A] { diff --git a/tests/run/better-fors.scala b/tests/run/better-fors.scala index 6b7e74ad9b4f..b0912aacd4dc 100644 --- a/tests/run/better-fors.scala +++ b/tests/run/better-fors.scala @@ -1,3 +1,6 @@ +//> using options -preview +// import scala.language.experimental.betterFors + def for1 = for { a = 1 diff --git a/tests/run/fors.scala b/tests/run/fors.scala index f08b8790cf34..4e802af4c53d 100644 --- a/tests/run/fors.scala +++ b/tests/run/fors.scala @@ -1,3 +1,4 @@ +//> using options -preview //############################################################################ // for-comprehensions (old and new syntax) //############################################################################ diff --git a/tests/run/i22900.check b/tests/run/i22900.check new file mode 100644 index 000000000000..f6636139a701 --- /dev/null +++ b/tests/run/i22900.check @@ -0,0 +1,8 @@ +6 +6 +6 +6 +7 +6 +7 +(6) diff --git a/tests/run/i22900.scala b/tests/run/i22900.scala new file mode 100644 index 000000000000..f7786d32d717 --- /dev/null +++ b/tests/run/i22900.scala @@ -0,0 +1,26 @@ +object NameBaseExtractor { + def unapply(x: Int): Some[(someName: Int)] = Some((someName = x + 3)) +} +object NameBaseExtractor2 { + def unapply(x: Int): Some[(someName: Int, age: Int)] = Some((someName = x + 3, age = x + 4)) +} +@main +def Test = + val x1 = 3 match + case NameBaseExtractor(someName = x) => x + println(x1) + val NameBaseExtractor(someName = x2) = 3 + println(x2) + val NameBaseExtractor((someName = x3)) = 3 + println(x3) + + val NameBaseExtractor2(someName = x4, age = x5) = 3 + println(x4) + println(x5) + + val NameBaseExtractor2((someName = x6, age = x7)) = 3 + println(x6) + println(x7) + + val NameBaseExtractor(y1) = 3 + println(y1) diff --git a/tests/run/i22900a.check b/tests/run/i22900a.check new file mode 100644 index 000000000000..a94217f352f9 --- /dev/null +++ b/tests/run/i22900a.check @@ -0,0 +1,3 @@ +3 +6 +3 diff --git a/tests/run/i22900a.scala b/tests/run/i22900a.scala new file mode 100644 index 000000000000..301deeecdf13 --- /dev/null +++ b/tests/run/i22900a.scala @@ -0,0 +1,15 @@ +case class C(someName: Int) + +object NameBaseExtractor3 { + def unapply(x: Int): Some[C] = Some(C(someName = x + 3)) +} + +@main +def Test = { + val C(someName = xx) = C(3) + println(xx) + val NameBaseExtractor3(C(someName = x)) = 3 + println(x) + C(3) match + case C(someName = xx) => println(xx) +} \ No newline at end of file diff --git a/tests/semanticdb/expect/ForComprehension.expect.scala b/tests/semanticdb/expect/ForComprehension.expect.scala index 864a87c6717c..815b7a93518d 100644 --- a/tests/semanticdb/expect/ForComprehension.expect.scala +++ b/tests/semanticdb/expect/ForComprehension.expect.scala @@ -3,43 +3,43 @@ package example class ForComprehension/*<-example::ForComprehension#*/ { for { a/*<-local0*/ <- List/*->scala::package.List.*/(1) - b/*<-local1*/ <- List/*->scala::package.List.*/(1) + b/*<-local1*//*->local1*/ <- List/*->scala::package.List.*/(1) if b/*->local1*/ >/*->scala::Int#`>`(+3).*/ 1 - c/*<-local2*/ = a/*->local0*/ +/*->scala::Int#`+`(+4).*/ b/*->local1*/ + c/*<-local2*//*->local2*/ = a/*->local0*/ +/*->scala::Int#`+`(+4).*/ b/*->local1*/ } yield (a/*->local0*/, b/*->local1*/, c/*->local2*/) for { - a/*<-local3*/ <- List/*->scala::package.List.*/(1) - b/*<-local4*/ <- List/*->scala::package.List.*/(a/*->local3*/) + a/*<-local4*/ <- List/*->scala::package.List.*/(1) + b/*<-local5*/ <- List/*->scala::package.List.*/(a/*->local4*/) if ( - a/*->local3*/, - b/*->local4*/ + a/*->local4*/, + b/*->local5*/ ) ==/*->scala::Any#`==`().*/ (1, 2) ( - c/*<-local6*/, - d/*<-local7*/ - ) <- List/*->scala::package.List.*/((a/*->local3*/, b/*->local4*/)) + c/*<-local7*/, + d/*<-local8*/ + ) <- List/*->scala::package.List.*/((a/*->local4*/, b/*->local5*/)) if ( - a/*->local3*/, - b/*->local4*/, - c/*->local6*/, - d/*->local7*/ + a/*->local4*/, + b/*->local5*/, + c/*->local7*/, + d/*->local8*/ ) ==/*->scala::Any#`==`().*/ (1, 2, 3, 4) - e/*<-local8*//*->local8*/ = ( - a/*->local3*/, - b/*->local4*/, - c/*->local6*/, - d/*->local7*/ + e/*<-local9*//*->local9*/ = ( + a/*->local4*/, + b/*->local5*/, + c/*->local7*/, + d/*->local8*/ ) - if e/*->local8*/ ==/*->scala::Any#`==`().*/ (1, 2, 3, 4) - f/*<-local9*/ <- List/*->scala::package.List.*/(e/*->local8*/) + if e/*->local9*/ ==/*->scala::Any#`==`().*/ (1, 2, 3, 4) + f/*<-local10*/ <- List/*->scala::package.List.*/(e/*->local9*/) } yield { ( - a/*->local3*/, - b/*->local4*/, - c/*->local6*/, - d/*->local7*/, - e/*->local8*/, - f/*->local9*/ + a/*->local4*/, + b/*->local5*/, + c/*->local7*/, + d/*->local8*/, + e/*->local9*/, + f/*->local10*/ ) } } diff --git a/tests/semanticdb/metac.expect b/tests/semanticdb/metac.expect index c5bb4e645967..f674c6fb4159 100644 --- a/tests/semanticdb/metac.expect +++ b/tests/semanticdb/metac.expect @@ -1661,8 +1661,8 @@ Schema => SemanticDB v4 Uri => ForComprehension.scala Text => empty Language => Scala -Symbols => 12 entries -Occurrences => 51 entries +Symbols => 13 entries +Occurrences => 53 entries Synthetics => 6 entries Symbols: @@ -1671,13 +1671,14 @@ example/ForComprehension#``(). => primary ctor (): ForComprehension local0 => param a: Int local1 => param b: Int local2 => val local c: Int -local3 => param a: Int -local4 => param b: Int -local5 => param x$1: Tuple2[Int, Int] -local6 => val local c: Int -local7 => val local d: Int -local8 => val local e: Tuple4[Int, Int, Int, Int] -local9 => param f: Tuple4[Int, Int, Int, Int] +local3 => param x$1: Tuple2[Int, Int] +local4 => param a: Int +local5 => param b: Int +local6 => param x$1: Tuple2[Int, Int] +local7 => val local c: Int +local8 => val local d: Int +local9 => val local e: Tuple4[Int, Int, Int, Int] +local10 => param f: Tuple4[Int, Int, Int, Int] Occurrences: [0:8..0:15): example <- example/ @@ -1686,51 +1687,53 @@ Occurrences: [4:4..4:5): a <- local0 [4:9..4:13): List -> scala/package.List. [5:4..5:5): b <- local1 +[5:4..5:5): b -> local1 [5:9..5:13): List -> scala/package.List. [6:7..6:8): b -> local1 [6:9..6:10): > -> scala/Int#`>`(+3). [7:4..7:5): c <- local2 +[7:4..7:5): c -> local2 [7:8..7:9): a -> local0 [7:10..7:11): + -> scala/Int#`+`(+4). [7:12..7:13): b -> local1 [8:11..8:12): a -> local0 [8:14..8:15): b -> local1 [8:17..8:18): c -> local2 -[10:4..10:5): a <- local3 +[10:4..10:5): a <- local4 [10:9..10:13): List -> scala/package.List. -[11:4..11:5): b <- local4 +[11:4..11:5): b <- local5 [11:9..11:13): List -> scala/package.List. -[11:14..11:15): a -> local3 -[13:6..13:7): a -> local3 -[14:6..14:7): b -> local4 +[11:14..11:15): a -> local4 +[13:6..13:7): a -> local4 +[14:6..14:7): b -> local5 [15:6..15:8): == -> scala/Any#`==`(). -[17:6..17:7): c <- local6 -[18:6..18:7): d <- local7 +[17:6..17:7): c <- local7 +[18:6..18:7): d <- local8 [19:9..19:13): List -> scala/package.List. -[19:15..19:16): a -> local3 -[19:18..19:19): b -> local4 -[21:6..21:7): a -> local3 -[22:6..22:7): b -> local4 -[23:6..23:7): c -> local6 -[24:6..24:7): d -> local7 +[19:15..19:16): a -> local4 +[19:18..19:19): b -> local5 +[21:6..21:7): a -> local4 +[22:6..22:7): b -> local5 +[23:6..23:7): c -> local7 +[24:6..24:7): d -> local8 [25:6..25:8): == -> scala/Any#`==`(). -[26:4..26:5): e <- local8 -[26:4..26:5): e -> local8 -[27:6..27:7): a -> local3 -[28:6..28:7): b -> local4 -[29:6..29:7): c -> local6 -[30:6..30:7): d -> local7 -[32:7..32:8): e -> local8 +[26:4..26:5): e <- local9 +[26:4..26:5): e -> local9 +[27:6..27:7): a -> local4 +[28:6..28:7): b -> local5 +[29:6..29:7): c -> local7 +[30:6..30:7): d -> local8 +[32:7..32:8): e -> local9 [32:9..32:11): == -> scala/Any#`==`(). -[33:4..33:5): f <- local9 +[33:4..33:5): f <- local10 [33:9..33:13): List -> scala/package.List. -[33:14..33:15): e -> local8 -[36:6..36:7): a -> local3 -[37:6..37:7): b -> local4 -[38:6..38:7): c -> local6 -[39:6..39:7): d -> local7 -[40:6..40:7): e -> local8 -[41:6..41:7): f -> local9 +[33:14..33:15): e -> local9 +[36:6..36:7): a -> local4 +[37:6..37:7): b -> local5 +[38:6..38:7): c -> local7 +[39:6..39:7): d -> local8 +[40:6..40:7): e -> local9 +[41:6..41:7): f -> local10 Synthetics: [4:9..4:13):List => *.apply[Int] diff --git a/tests/untried/neg/class-of-double-targs.check b/tests/untried/neg/class-of-double-targs.check deleted file mode 100644 index f7e2094f9778..000000000000 --- a/tests/untried/neg/class-of-double-targs.check +++ /dev/null @@ -1,4 +0,0 @@ -class-of-double-targs.scala:2: error: expression of type Class[Int](classOf[scala.Int]) does not take type parameters. - classOf[Int][Int] - ^ -one error found diff --git a/tests/untried/neg/class-of-double-targs.scala b/tests/untried/neg/class-of-double-targs.scala deleted file mode 100644 index 26a2fa838136..000000000000 --- a/tests/untried/neg/class-of-double-targs.scala +++ /dev/null @@ -1,3 +0,0 @@ -object Test { - classOf[Int][Int] -} diff --git a/tests/untried/neg/t0842.check b/tests/untried/neg/t0842.check deleted file mode 100644 index 3351aa1174ce..000000000000 --- a/tests/untried/neg/t0842.check +++ /dev/null @@ -1,4 +0,0 @@ -t0842.scala:1: error: A.this.type does not take type parameters -trait A[T] { def m: this.type[T] = this } - ^ -one error found diff --git a/tests/untried/neg/t0842.scala b/tests/untried/neg/t0842.scala deleted file mode 100644 index f32c2ba26d71..000000000000 --- a/tests/untried/neg/t0842.scala +++ /dev/null @@ -1 +0,0 @@ -trait A[T] { def m: this.type[T] = this } diff --git a/tests/untried/neg/t1701.check b/tests/untried/neg/t1701.check deleted file mode 100644 index d603e62e5a6a..000000000000 --- a/tests/untried/neg/t1701.check +++ /dev/null @@ -1,4 +0,0 @@ -t1701.scala:1: error: Cloneable does not take type parameters -class A extends java.lang.Cloneable[String, Option, Int] - ^ -one error found diff --git a/tests/untried/neg/t1701.scala b/tests/untried/neg/t1701.scala deleted file mode 100644 index 7cd6ff9953be..000000000000 --- a/tests/untried/neg/t1701.scala +++ /dev/null @@ -1 +0,0 @@ -class A extends java.lang.Cloneable[String, Option, Int] diff --git a/tests/untried/neg/t278.check b/tests/untried/neg/t278.check deleted file mode 100644 index 405f7d225c17..000000000000 --- a/tests/untried/neg/t278.check +++ /dev/null @@ -1,11 +0,0 @@ -t278.scala:5: error: overloaded method value a with alternatives: - => C.this.A => Unit - => () => Unit - does not take type parameters - println(a[A]) - ^ -t278.scala:4: error: method a is defined twice - conflicting symbols both originated in file 't278.scala' - def a = (p:A) => () - ^ -two errors found diff --git a/tests/untried/neg/t278.scala b/tests/untried/neg/t278.scala deleted file mode 100644 index 39a711bb0985..000000000000 --- a/tests/untried/neg/t278.scala +++ /dev/null @@ -1,6 +0,0 @@ -class C { - class A - def a = () => () - def a = (p:A) => () - println(a[A]) -} diff --git a/tests/untried/neg/t2918.check b/tests/untried/neg/t2918.check deleted file mode 100644 index aae3045e8af7..000000000000 --- a/tests/untried/neg/t2918.check +++ /dev/null @@ -1,10 +0,0 @@ -t2918.scala:2: error: illegal cyclic reference involving type A - def g[X, A[X] <: A[X]](x: A[X]) = x - ^ -t2918.scala:2: error: cyclic aliasing or subtyping involving type A - def g[X, A[X] <: A[X]](x: A[X]) = x - ^ -t2918.scala:2: error: A does not take type parameters - def g[X, A[X] <: A[X]](x: A[X]) = x - ^ -three errors found diff --git a/tests/untried/neg/t2918.scala b/tests/untried/neg/t2918.scala deleted file mode 100644 index ff2be39ae0c4..000000000000 --- a/tests/untried/neg/t2918.scala +++ /dev/null @@ -1,3 +0,0 @@ -object Test { - def g[X, A[X] <: A[X]](x: A[X]) = x -} diff --git a/tests/untried/neg/t5093.check b/tests/untried/neg/t5093.check deleted file mode 100644 index daba46001153..000000000000 --- a/tests/untried/neg/t5093.check +++ /dev/null @@ -1,10 +0,0 @@ -t5093.scala:2: error: illegal cyclic reference involving type C - def f[C[X] <: C[X]](l: C[_]) = l.x - ^ -t5093.scala:2: error: cyclic aliasing or subtyping involving type C - def f[C[X] <: C[X]](l: C[_]) = l.x - ^ -t5093.scala:2: error: C does not take type parameters - def f[C[X] <: C[X]](l: C[_]) = l.x - ^ -three errors found diff --git a/tests/untried/neg/t5093.scala b/tests/untried/neg/t5093.scala deleted file mode 100644 index 9cde364dee4c..000000000000 --- a/tests/untried/neg/t5093.scala +++ /dev/null @@ -1,3 +0,0 @@ -class T { - def f[C[X] <: C[X]](l: C[_]) = l.x -} diff --git a/tests/untried/neg/t8219-any-any-ref-equals.check b/tests/untried/neg/t8219-any-any-ref-equals.check deleted file mode 100644 index 95d2536fba06..000000000000 --- a/tests/untried/neg/t8219-any-any-ref-equals.check +++ /dev/null @@ -1,10 +0,0 @@ -t8219-any-any-ref-equals.scala:5: error: method ==: (x$1: Any)Boolean does not take type parameters. - "".==[Int] - ^ -t8219-any-any-ref-equals.scala:6: error: method ==: (x$1: Any)Boolean does not take type parameters. - ("": AnyRef).==[Int] - ^ -t8219-any-any-ref-equals.scala:7: error: method ==: (x$1: Any)Boolean does not take type parameters. - ("": Object).==[Int] - ^ -three errors found diff --git a/tests/untried/neg/t8219-any-any-ref-equals.scala b/tests/untried/neg/t8219-any-any-ref-equals.scala deleted file mode 100644 index f1b81fa734c1..000000000000 --- a/tests/untried/neg/t8219-any-any-ref-equals.scala +++ /dev/null @@ -1,8 +0,0 @@ -object Test { - // The error message tells us that AnyRef#== and Any#== are overloaded. - // A real class couldn't define such an overload, why do we allow AnyRef - // to do so? - "".==[Int] - ("": AnyRef).==[Int] - ("": Object).==[Int] -} diff --git a/tests/untried/neg/warn-unused-imports.check b/tests/untried/neg/warn-unused-imports.check deleted file mode 100644 index 36c6dd03c38d..000000000000 --- a/tests/untried/neg/warn-unused-imports.check +++ /dev/null @@ -1,33 +0,0 @@ -warn-unused-imports.scala:57: warning: Unused import - import p1.A // warn - ^ -warn-unused-imports.scala:62: warning: Unused import - import p1.{ A, B } // warn on A - ^ -warn-unused-imports.scala:67: warning: Unused import - import p1.{ A, B } // warn on both - ^ -warn-unused-imports.scala:67: warning: Unused import - import p1.{ A, B } // warn on both - ^ -warn-unused-imports.scala:73: warning: Unused import - import c._ // warn - ^ -warn-unused-imports.scala:78: warning: Unused import - import p1._ // warn - ^ -warn-unused-imports.scala:85: warning: Unused import - import c._ // warn - ^ -warn-unused-imports.scala:91: warning: Unused import - import p1.c._ // warn - ^ -warn-unused-imports.scala:98: warning: Unused import - import p1._ // warn - ^ -warn-unused-imports.scala:118: warning: Unused import - import p1.A // warn - ^ -error: No warnings can be incurred under -Xfatal-warnings. -10 warnings found -one error found diff --git a/tests/untried/neg/warn-unused-imports.flags b/tests/untried/neg/warn-unused-imports.flags deleted file mode 100644 index 24db705df164..000000000000 --- a/tests/untried/neg/warn-unused-imports.flags +++ /dev/null @@ -1 +0,0 @@ --Xfatal-warnings -Ywarn-unused-import diff --git a/tests/untried/neg/warn-unused-imports.scala b/tests/untried/neg/warn-unused-imports.scala deleted file mode 100644 index 4b1c1183dcba..000000000000 --- a/tests/untried/neg/warn-unused-imports.scala +++ /dev/null @@ -1,125 +0,0 @@ -class Bippo { - def length: Int = 123 - class Tree -} - -package object p1 { - class A - implicit class B(val s: String) { def bippy = s } - val c: Bippo = new Bippo - type D = String -} -package object p2 { - class A - implicit class B(val s: String) { def bippy = s } - val c: Bippo = new Bippo - type D = Int -} - -trait NoWarn { - { - import p1._ // no warn - println("abc".bippy) - } - - { - import p1._ // no warn - println(new A) - } - - { - import p1.B // no warn - println("abc".bippy) - } - - { - import p1._ // no warn - import c._ // no warn - println(length) - } - - { - import p1._ // no warn - import c._ // no warn - val x: Tree = null - println(x) - } - - { - import p1.D // no warn - val x: D = null - println(x) - } -} - -trait Warn { - { - import p1.A // warn - println(123) - } - - { - import p1.{ A, B } // warn on A - println("abc".bippy) - } - - { - import p1.{ A, B } // warn on both - println(123) - } - - { - import p1._ // no warn (technically this could warn, but not worth the effort to unroll unusedness transitively) - import c._ // warn - println(123) - } - - { - import p1._ // warn - println(123) - } - - { - class Tree - import p1._ // no warn - import c._ // warn - val x: Tree = null - println(x) - } - - { - import p1.c._ // warn - println(123) - } -} - -trait Nested { - { - import p1._ // warn - trait Warn { // warn about unused local trait for good measure - import p2.* - println(new A) - println("abc".bippy) - } - println("") - } - - { - import p1._ // no warn - trait NoWarn { - import p2.B // no warn - println("abc".bippy) - println(new A) - } - println(new NoWarn { }) - } - - { - import p1.A // warn - trait Warn { - import p2.A - println(new A) - } - println(new Warn { }) - } -} diff --git a/tests/untried/neg/warn-unused-privates.check b/tests/untried/neg/warn-unused-privates.check deleted file mode 100644 index d012869c934a..000000000000 --- a/tests/untried/neg/warn-unused-privates.check +++ /dev/null @@ -1,66 +0,0 @@ -warn-unused-privates.scala:2: warning: private constructor in class Bippy is never used - private def this(c: Int) = this(c, c) // warn - ^ -warn-unused-privates.scala:4: warning: private method in class Bippy is never used - private def boop(x: Int) = x+a+b // warn - ^ -warn-unused-privates.scala:6: warning: private val in class Bippy is never used - final private val MILLIS2: Int = 1000 // warn - ^ -warn-unused-privates.scala:13: warning: private val in object Bippy is never used - private val HEY_INSTANCE: Int = 1000 // warn - ^ -warn-unused-privates.scala:35: warning: private val in class Boppy is never used - private val hummer = "def" // warn - ^ -warn-unused-privates.scala:42: warning: private var in trait Accessors is never used - private var v1: Int = 0 // warn - ^ -warn-unused-privates.scala:42: warning: private setter in trait Accessors is never used - private var v1: Int = 0 // warn - ^ -warn-unused-privates.scala:43: warning: private setter in trait Accessors is never used - private var v2: Int = 0 // warn, never set - ^ -warn-unused-privates.scala:44: warning: private var in trait Accessors is never used - private var v3: Int = 0 // warn, never got - ^ -warn-unused-privates.scala:56: warning: private default argument in trait DefaultArgs is never used - private def bippy(x1: Int, x2: Int = 10, x3: Int = 15): Int = x1 + x2 + x3 - ^ -warn-unused-privates.scala:56: warning: private default argument in trait DefaultArgs is never used - private def bippy(x1: Int, x2: Int = 10, x3: Int = 15): Int = x1 + x2 + x3 - ^ -warn-unused-privates.scala:67: warning: local var in method f0 is never used - var x = 1 // warn - ^ -warn-unused-privates.scala:74: warning: local val in method f1 is never used - val b = new Outer // warn - ^ -warn-unused-privates.scala:84: warning: private object in object Types is never used - private object Dongo { def f = this } // warn - ^ -warn-unused-privates.scala:94: warning: local object in method l1 is never used - object HiObject { def f = this } // warn - ^ -warn-unused-privates.scala:78: warning: local var x in method f2 is never set - it could be a val - var x = 100 // warn about it being a var - ^ -warn-unused-privates.scala:85: warning: private class Bar1 in object Types is never used - private class Bar1 // warn - ^ -warn-unused-privates.scala:87: warning: private type Alias1 in object Types is never used - private type Alias1 = String // warn - ^ -warn-unused-privates.scala:95: warning: local class Hi is never used - class Hi { // warn - ^ -warn-unused-privates.scala:99: warning: local class DingDongDoobie is never used - class DingDongDoobie // warn - ^ -warn-unused-privates.scala:102: warning: local type OtherThing is never used - type OtherThing = String // warn - ^ -error: No warnings can be incurred under -Xfatal-warnings. -21 warnings found -one error found diff --git a/tests/untried/neg/warn-unused-privates.flags b/tests/untried/neg/warn-unused-privates.flags deleted file mode 100644 index 25474aefb362..000000000000 --- a/tests/untried/neg/warn-unused-privates.flags +++ /dev/null @@ -1 +0,0 @@ --Ywarn-unused -Xfatal-warnings diff --git a/tests/untried/neg/wellkinded_app.check b/tests/untried/neg/wellkinded_app.check deleted file mode 100644 index d57a0e4b5648..000000000000 --- a/tests/untried/neg/wellkinded_app.check +++ /dev/null @@ -1,4 +0,0 @@ -wellkinded_app.scala:3: error: x does not take type parameters - type t = x[x] - ^ -one error found diff --git a/tests/untried/neg/wellkinded_app.scala b/tests/untried/neg/wellkinded_app.scala deleted file mode 100644 index 7fa3f95a9848..000000000000 --- a/tests/untried/neg/wellkinded_app.scala +++ /dev/null @@ -1,4 +0,0 @@ -// test well-kindedness checks -class WellKinded[x] { - type t = x[x] -} diff --git a/tests/untried/neg/wellkinded_app2.check b/tests/untried/neg/wellkinded_app2.check deleted file mode 100644 index 20a177ea590e..000000000000 --- a/tests/untried/neg/wellkinded_app2.check +++ /dev/null @@ -1,4 +0,0 @@ -wellkinded_app2.scala:3: error: s does not take type parameters - val foo: s[Int] - ^ -one error found diff --git a/tests/untried/neg/wellkinded_app2.scala b/tests/untried/neg/wellkinded_app2.scala deleted file mode 100644 index 7bb4c87f6b17..000000000000 --- a/tests/untried/neg/wellkinded_app2.scala +++ /dev/null @@ -1,4 +0,0 @@ -// test well-kindedness checks -class WellKinded[s <: Throwable] { - val foo: s[Int] -} diff --git a/tests/untried/neg/wellkinded_bounds.check b/tests/untried/neg/wellkinded_bounds.check deleted file mode 100644 index 806eb09a76d7..000000000000 --- a/tests/untried/neg/wellkinded_bounds.check +++ /dev/null @@ -1,4 +0,0 @@ -wellkinded_bounds.scala:2: error: type List takes type parameters -class WellKindedWrongSyntax[s <: List] { // must be s[x] <: List[x] - ^ -one error found diff --git a/tests/untried/neg/wellkinded_bounds.scala b/tests/untried/neg/wellkinded_bounds.scala deleted file mode 100644 index cfa5e74c115f..000000000000 --- a/tests/untried/neg/wellkinded_bounds.scala +++ /dev/null @@ -1,3 +0,0 @@ -// test well-kindedness checks -- syntax error -class WellKindedWrongSyntax[s <: List] { // must be s[x] <: List[x] -} diff --git a/tests/untried/neg/wellkinded_wrongarity.check b/tests/untried/neg/wellkinded_wrongarity.check deleted file mode 100644 index b9f033b4536b..000000000000 --- a/tests/untried/neg/wellkinded_wrongarity.check +++ /dev/null @@ -1,4 +0,0 @@ -wellkinded_wrongarity.scala:5: error: Tuple2 takes two type parameters, expected: one -object mp extends Monad[Tuple2] - ^ -one error found diff --git a/tests/untried/neg/wellkinded_wrongarity.scala b/tests/untried/neg/wellkinded_wrongarity.scala deleted file mode 100644 index 39c7601d53a3..000000000000 --- a/tests/untried/neg/wellkinded_wrongarity.scala +++ /dev/null @@ -1,5 +0,0 @@ -// test well-kindedness checks -- arity error - -class Monad[m[x]] - -object mp extends Monad[Tuple2] diff --git a/tests/untried/neg/wellkinded_wrongarity2.check b/tests/untried/neg/wellkinded_wrongarity2.check deleted file mode 100644 index 922f73381e29..000000000000 --- a/tests/untried/neg/wellkinded_wrongarity2.check +++ /dev/null @@ -1,13 +0,0 @@ -wellkinded_wrongarity2.scala:5: error: String takes no type parameters, expected: one -trait ms1 extends Monad[String] // wrong - ^ -wellkinded_wrongarity2.scala:6: error: t takes no type parameters, expected: one -trait ms2[t] extends Monad[t] // wrong - ^ -wellkinded_wrongarity2.scala:7: error: m[t] takes no type parameters, expected: one -trait ms3[m[_], t] extends Monad[m[t]] // wrong -- added to check regression on bug - ^ -wellkinded_wrongarity2.scala:12: error: type m takes type parameters -trait Bar2[m[_]] extends Foo[m] // check that m is properly recognized as kind *->*, while * is expected - ^ -four errors found diff --git a/tests/untried/neg/wellkinded_wrongarity2.scala b/tests/untried/neg/wellkinded_wrongarity2.scala deleted file mode 100644 index aac617bd8770..000000000000 --- a/tests/untried/neg/wellkinded_wrongarity2.scala +++ /dev/null @@ -1,12 +0,0 @@ -// test well-kindedness checks - -// expecting types of kind *->* -class Monad[m[x]] -trait ms1 extends Monad[String] // wrong -trait ms2[t] extends Monad[t] // wrong -trait ms3[m[_], t] extends Monad[m[t]] // wrong -- added to check regression on bug - -// expecting types of kind * -trait Foo[x] -trait Bar1[m[_]] extends Foo[m[Int]] // check that m[Int] is properly recognized as kind-* -trait Bar2[m[_]] extends Foo[m] // check that m is properly recognized as kind *->*, while * is expected diff --git a/tests/warn/i15503a.scala b/tests/warn/i15503a.scala index 3707b18d316e..884261e140a7 100644 --- a/tests/warn/i15503a.scala +++ b/tests/warn/i15503a.scala @@ -328,3 +328,135 @@ package i22692: type b = AbstractButton type t = swingEvent.AncestorListener + +package ancient: + package p { + class Bippo { + def length: Int = 123 + class Tree + } + } + + package object p1 { + import p._ + class A + implicit class B(val s: String) { def bippy = s } + val c: Bippo = new Bippo + type D = String + } + package object p2 { + import p._ + class A + implicit class B(val s: String) { def bippy = s } + val c: Bippo = new Bippo + type D = Int + } + + trait NoWarn { + { + import p1._ // no warn + println("abc".bippy) + } + + { + import p1._ // no warn + println(new A) + } + + { + import p1.B // no warn + println("abc".bippy) + } + + { + import p1._ // no warn + import c._ // no warn + println(length) + } + + { + import p1._ // no warn + import c._ // no warn + val x: Tree = null + println(x) + } + + { + import p1.D // no warn + val x: D = null + println(x) + } + } + + trait Warn { + { + import p1.A // warn + println(123) + } + + { + import p1.{ A, B } // warn on A + println("abc".bippy) + } + + { + import p1.{ A, B } //warn // warn on both + println(123) + } + + { + import p1._ // no warn (technically this could warn, but not worth the effort to unroll unusedness transitively) + import c._ // warn + println(123) + } + + { + import p1._ // warn + println(123) + } + + { + class Tree + import p1._ // no warn + import c._ // warn + val x: Tree = null + println(x) + } + + { + import p1.c._ // warn + println(123) + } + } + + trait Nested { + { + import p1._ // warn + trait Warn { + import p2.* + println(new A) + println("abc".bippy) + } + println("") + } + + { + import p1._ // no warn + trait NoWarn { + import p2.B // no warn + println("abc".bippy) + println(new A) + } + println(new NoWarn { }) + } + + { + import p1.A // warn + trait Warn { + import p2.A + println(new A) + } + println(new Warn { }) + } + } +end ancient diff --git a/tests/warn/i22899.scala b/tests/warn/i22899.scala new file mode 100644 index 000000000000..ae6544e29286 --- /dev/null +++ b/tests/warn/i22899.scala @@ -0,0 +1,27 @@ +case class CaseClass(a: Int) + +object ProductMatch_CaseClass { + def unapply(int: Int): CaseClass = CaseClass(int) +} + +object ProductMatch_NamedTuple { + def unapply(int: Int): (a: Int) = (a = int) +} + +object NameBasedMatch_CaseClass { + def unapply(int: Int): Some[CaseClass] = Some(CaseClass(int)) +} + +object NameBasedMatch_NamedTuple { + def unapply(int: Int): Some[(a: Int)] = Some((a = int)) +} + +object Test { + val ProductMatch_CaseClass(a = x1) = 1 // ok, was pattern's type (x1 : Int) is more specialized than the right hand side expression's type Int + val ProductMatch_NamedTuple(a = x2) = 2 // ok, was pattern binding uses refutable extractor `org.test.ProductMatch_NamedTuple` + val NameBasedMatch_CaseClass(a = x3) = 3 // ok, was pattern's type (x3 : Int) is more specialized than the right hand side expression's type Int + val NameBasedMatch_NamedTuple(a = x4) = 4 // ok, was pattern's type (x4 : Int) is more specialized than the right hand side expression's type Int + + val CaseClass(a = x5) = CaseClass(5) // ok, was pattern's type (x5 : Int) is more specialized than the right hand side expression's type Int + val (a = x6) = (a = 6) // ok +} \ No newline at end of file