diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md index 52f8010c372e..afbaa8020e07 100644 --- a/.github/ISSUE_TEMPLATE/feature.md +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -1,10 +1,10 @@ --- name: "\U0001F389 Suggest a feature" -about: Please create a feature request here https://github.com/lampepfl/dotty/discussions/new?category=feature-requests +about: Please create a feature request here https://github.com/scala/scala3/discussions/new?category=feature-requests title: '' labels: '' assignees: '' --- -Please create a feature request in the [Dotty Discussions](https://github.com/lampepfl/dotty/discussions/new?category=feature-requests). +Please create a feature request in the [Dotty Discussions](https://github.com/scala/scala3/discussions/new?category=feature-requests). diff --git a/.github/ISSUE_TEMPLATE/improve-error.md b/.github/ISSUE_TEMPLATE/improve-error.md index 918196e1ec53..72d556951e53 100644 --- a/.github/ISSUE_TEMPLATE/improve-error.md +++ b/.github/ISSUE_TEMPLATE/improve-error.md @@ -19,7 +19,7 @@ This code should be self-contained, reproducible (i.e. produces the expected err Ideally, we should be able to just copy this code in a file and run `scalac` (and maybe `scala`) to reproduce the issue. -For a good example, see https://github.com/lampepfl/dotty/issues/18657 +For a good example, see https://github.com/scala/scala3/issues/18657 --> ```Scala @@ -44,12 +44,12 @@ for example: ## Why this Error/Warning was not helpful - + The message was unhelpful because... ## Suggested improvement - + It could be made more helpful by... diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fd1fe30d3fa9..cf375b147793 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -53,7 +53,7 @@ jobs: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || github.event_name == 'push' || ( github.event_name == 'pull_request' @@ -62,14 +62,17 @@ jobs: ) || ( github.event_name == 'workflow_dispatch' - && github.repository == 'lampepfl/dotty' + && github.repository == 'scala/scala3' )" steps: - name: Set JDK 16 as default run: echo "/usr/lib/jvm/java-16-openjdk-amd64/bin" >> $GITHUB_PATH + ## Workaround for https://github.com/actions/runner/issues/2033 (See https://github.com/scala/scala3/pull/19720) - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -102,7 +105,7 @@ jobs: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || github.event_name == 'push' || github.event_name == 'merge_group' || ( @@ -112,7 +115,7 @@ jobs: ) || ( github.event_name == 'workflow_dispatch' - && github.repository == 'lampepfl/dotty' + && github.repository == 'scala/scala3' )" steps: @@ -120,7 +123,9 @@ jobs: run: echo "/usr/lib/jvm/java-16-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -136,7 +141,7 @@ jobs: - name: Cmd Tests run: | - ./project/scripts/sbt ";dist/pack; scala3-bootstrapped/compile; scala3-bootstrapped/test ;sbt-test/scripted scala2-compat/* ;scala2-library-tasty-tests/run ;scala2-library-tasty-tests/test; scala3-compiler-bootstrapped/scala3CompilerCoursierTest:test" + ./project/scripts/sbt ";dist/pack; scala3-bootstrapped/compile; scala3-bootstrapped/test ;sbt-test/scripted scala2-compat/*; scala2-library-tasty-tests/test; scala3-compiler-bootstrapped/scala3CompilerCoursierTest:test" ./project/scripts/cmdTests ./project/scripts/bootstrappedOnlyCmdTests @@ -145,7 +150,10 @@ jobs: ./project/scripts/sbt ";sjsSandbox/run ;sjsSandbox/test ;sjsJUnitTests/test ;set sjsJUnitTests/scalaJSLinkerConfig ~= switchToESModules ;sjsJUnitTests/test ;sjsCompilerTests/test" - name: Test with Scala 2 library TASTy (fast) - run: ./project/scripts/sbt ";set ThisBuild/Build.useScala2LibraryTasty := true ;scala3-bootstrapped/testCompilation i5; scala3-bootstrapped/testCompilation tests/run/typelevel-peano.scala; scala3-bootstrapped/testOnly dotty.tools.backend.jvm.DottyBytecodeTests" # only test a subset of test to avoid doubling the CI execution time + run: ./project/scripts/sbt ";set ThisBuild/Build.scala2Library := Build.Scala2LibraryTasty ;scala3-bootstrapped/testCompilation i5; scala3-bootstrapped/testCompilation tests/run/typelevel-peano.scala; scala3-bootstrapped/testOnly dotty.tools.backend.jvm.DottyBytecodeTests" # only test a subset of test to avoid doubling the CI execution time + + - name: Test with Scala 2 library with CC TASTy (fast) + run: ./project/scripts/sbt "scala2-library-cc/compile; scala2-library-cc-tasty/compile; scala3-bootstrapped/testCompilation i3" test_scala2_library_tasty: runs-on: [self-hosted, Linux] @@ -156,14 +164,14 @@ jobs: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || ( github.event_name == 'pull_request' && contains(github.event.pull_request.body, '[test_scala2_library_tasty]') ) || ( github.event_name == 'workflow_dispatch' - && github.repository == 'lampepfl/dotty' + && github.repository == 'scala/scala3' )" steps: @@ -171,7 +179,9 @@ jobs: run: echo "/usr/lib/jvm/java-16-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -186,7 +196,11 @@ jobs: run: cp -vf .github/workflows/repositories /root/.sbt/ ; true - name: Test with Scala 2 library TASTy - run: ./project/scripts/sbt ";set ThisBuild/Build.useScala2LibraryTasty := true ;scala3-bootstrapped/test" + run: ./project/scripts/sbt ";set ThisBuild/Build.scala2Library := Build.Scala2LibraryTasty ;scala3-bootstrapped/test" + + # TODO test all the test configurations in non-CC library (currently disabled due to bug while loading the library) + # - name: Test with Scala 2 library with CC TASTy + # run: ./project/scripts/sbt ";set ThisBuild/Build.scala2Library := Build.Scala2LibraryCCTasty ;scala3-bootstrapped/test" test_windows_fast: @@ -204,8 +218,10 @@ jobs: steps: - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true shell: cmd + run: | + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Git Checkout uses: actions/checkout@v4 @@ -236,7 +252,7 @@ jobs: test_windows_full: runs-on: [self-hosted, Windows] - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || github.event_name == 'push' || ( github.event_name == 'pull_request' @@ -246,8 +262,10 @@ jobs: steps: - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true shell: cmd + run: | + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Git Checkout uses: actions/checkout@v4 @@ -270,7 +288,7 @@ jobs: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || github.event_name == 'push' || github.event_name == 'merge_group' || ( @@ -280,11 +298,13 @@ jobs: ) || ( github.event_name == 'workflow_dispatch' - && github.repository == 'lampepfl/dotty' + && github.repository == 'scala/scala3' )" steps: - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -316,7 +336,7 @@ jobs: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || github.event_name == 'push' || github.event_name == 'merge_group' || ( @@ -327,12 +347,14 @@ jobs: ) || ( github.event_name == 'workflow_dispatch' - && github.repository == 'lampepfl/dotty' + && github.repository == 'scala/scala3' )" steps: - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -348,6 +370,7 @@ jobs: - name: Test run: | + git config --global --add safe.directory /__w/scala3/scala3 git submodule sync git submodule update --init --recursive --jobs 7 ./project/scripts/sbt "community-build/testOnly dotty.communitybuild.CommunityBuildTestA" @@ -365,7 +388,7 @@ jobs: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || github.event_name == 'push' || github.event_name == 'merge_group' || ( @@ -376,12 +399,14 @@ jobs: ) || ( github.event_name == 'workflow_dispatch' - && github.repository == 'lampepfl/dotty' + && github.repository == 'scala/scala3' )" steps: - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -397,6 +422,7 @@ jobs: - name: Test run: | + git config --global --add safe.directory /__w/scala3/scala3 git submodule sync git submodule update --init --recursive --jobs 7 ./project/scripts/sbt "community-build/testOnly dotty.communitybuild.CommunityBuildTestB" @@ -414,7 +440,7 @@ jobs: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || github.event_name == 'push' || github.event_name == 'merge_group' || ( @@ -425,12 +451,14 @@ jobs: ) || ( github.event_name == 'workflow_dispatch' - && github.repository == 'lampepfl/dotty' + && github.repository == 'scala/scala3' )" steps: - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -446,6 +474,7 @@ jobs: - name: Test run: | + git config --global --add safe.directory /__w/scala3/scala3 git submodule sync git submodule update --init --recursive --jobs 7 ./project/scripts/sbt "community-build/testOnly dotty.communitybuild.CommunityBuildTestC" @@ -463,7 +492,7 @@ jobs: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || github.event_name == 'push' || ( github.event_name == 'pull_request' @@ -472,12 +501,14 @@ jobs: ) || ( github.event_name == 'workflow_dispatch' - && github.repository == 'lampepfl/dotty' + && github.repository == 'scala/scala3' )" steps: - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -504,7 +535,7 @@ jobs: - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || ( github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/') @@ -516,7 +547,7 @@ jobs: ) || ( github.event_name == 'workflow_dispatch' - && github.repository == 'lampepfl/dotty' + && github.repository == 'scala/scala3' )" steps: @@ -524,7 +555,9 @@ jobs: run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -540,7 +573,7 @@ jobs: - name: Test run: | - ./project/scripts/sbt ";dist/pack ;scala3-bootstrapped/compile ;scala3-bootstrapped/test ;sbt-test/scripted scala2-compat/* ;scala2-library-tasty-tests/run ;scala2-library-tasty-tests/test" + ./project/scripts/sbt ";dist/pack ;scala3-bootstrapped/compile ;scala3-bootstrapped/test ;sbt-test/scripted scala2-compat/*; scala2-library-tasty-tests/test" ./project/scripts/cmdTests ./project/scripts/bootstrappedOnlyCmdTests @@ -558,7 +591,7 @@ jobs: - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache needs: [test_non_bootstrapped, test, mima, community_build_a, community_build_b, community_build_c, test_sbt, test_java8] - if: "(github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && github.repository == 'lampepfl/dotty'" + if: "(github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && github.repository == 'scala/scala3'" env: NIGHTLYBUILD: yes PGP_PW: ${{ secrets.PGP_PW }} # PGP passphrase @@ -568,7 +601,9 @@ jobs: steps: - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -609,7 +644,7 @@ jobs: - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache needs: [publish_nightly] - if: "(github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && github.repository == 'lampepfl/dotty'" + if: "(github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && github.repository == 'scala/scala3'" env: NIGHTLYBUILD: yes DOTTY_WEBSITE_BOT_TOKEN: ${{ secrets.BOT_TOKEN }} # If you need to change this: @@ -622,7 +657,9 @@ jobs: steps: - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -638,6 +675,7 @@ jobs: - name: Generate Website run: | + git config --global --add safe.directory /__w/scala3/scala3 ./project/scripts/genDocs -doc-snapshot - name: Deploy Website to dotty-website @@ -672,7 +710,9 @@ jobs: steps: - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 diff --git a/.github/workflows/lts-backport.yaml b/.github/workflows/lts-backport.yaml index 8e8added1c03..090b55b8eaf5 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.1.0 + - uses: VirtusLab/scala-cli-setup@v1.1.2 - run: scala-cli ./project/scripts/addToBackportingProject.scala -- ${{ github.sha }} env: GRAPHQL_API_TOKEN: ${{ secrets.GRAPHQL_API_TOKEN }} diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index f2cd0706cfe7..dde8b0372d52 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -18,7 +18,9 @@ jobs: steps: - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/dotty/dotty + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true - name: Cleanup run: .github/workflows/cleanup.sh diff --git a/.github/workflows/scripts/publish-sdkman.sh b/.github/workflows/scripts/publish-sdkman.sh index 70987bff175b..f959c426e9d8 100755 --- a/.github/workflows/scripts/publish-sdkman.sh +++ b/.github/workflows/scripts/publish-sdkman.sh @@ -10,8 +10,8 @@ set -u # latest stable dotty version -DOTTY_VERSION=$(curl -s https://api.github.com/repos/lampepfl/dotty/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') -DOTTY_URL="https://github.com/lampepfl/dotty/releases/download/$DOTTY_VERSION/scala3-$DOTTY_VERSION.zip" +DOTTY_VERSION=$(curl -s https://api.github.com/repos/scala/scala3/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') +DOTTY_URL="https://github.com/scala/scala3/releases/download/$DOTTY_VERSION/scala3-$DOTTY_VERSION.zip" # checking if dotty version is available if ! curl --output /dev/null --silent --head --fail "$DOTTY_URL"; then diff --git a/MAINTENANCE.md b/MAINTENANCE.md index 1e80f891e987..fd14bab68153 100644 --- a/MAINTENANCE.md +++ b/MAINTENANCE.md @@ -15,11 +15,11 @@ The issue supervisor is responsible for: - Modifying issue labels to best capture information about the issues - Attempting to reproduce the issue (or label “stat:cannot reproduce”) - Further minimizing the issue or asking the reporter of the issue to minimize it correctly (or label “stat:needs minimization”) - - Identifying which issues are of considerable importance and bringing them to the attention of the team during the Dotty meeting, where they can be filtered and added to the [Future Versions](https://github.com/lampepfl/dotty/milestone/46) milestone. + - Identifying which issues are of considerable importance and bringing them to the attention of the team during the Dotty meeting, where they can be filtered and added to the [Future Versions](https://github.com/scala/scala3/milestone/46) milestone. - Identifying if a report is really a feature request and if so, converting it to - a [feature request discussion](https://github.com/lampepfl/dotty/discussions/categories/feature-requests). + a [feature request discussion](https://github.com/scala/scala3/discussions/categories/feature-requests). - Keeping an eye on new -[discussions](https://github.com/lampepfl/dotty/discussions), making sure they +[discussions](https://github.com/scala/scala3/discussions), making sure they don't go unanswered and also correctly labeling new feature requests. Other core teammates are responsible for providing information to the issue supervisor in a timely manner when it is requested if they have that information. diff --git a/NOTICE.md b/NOTICE.md index 64c1ede1a5eb..fd931397a500 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -1,6 +1,6 @@ Dotty (https://dotty.epfl.ch) -Copyright 2012-2023 EPFL -Copyright 2012-2023 Lightbend, Inc. +Copyright 2012-2024 EPFL +Copyright 2012-2024 Lightbend, Inc. Licensed under the Apache License, Version 2.0 (the "License"): http://www.apache.org/licenses/LICENSE-2.0 @@ -104,4 +104,4 @@ major authors were omitted by oversight. [3] https://github.com/sbt/sbt/tree/0.13/compile/interface/src/main/scala/xsbt [4] https://github.com/scoverage/scalac-scoverage-plugin [5] https://github.com/scalameta/metals -[6] https://github.com/lampepfl/dotty/pull/5783/files +[6] https://github.com/scala/scala3/pull/5783/files diff --git a/README.md b/README.md index 1e62e90a1845..6c3212f0676b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ Dotty ===== -[![Dotty CI](https://github.com/lampepfl/dotty/workflows/Dotty/badge.svg?branch=master)](https://github.com/lampepfl/dotty/actions?query=branch%3Amain) +[![Dotty CI](https://github.com/scala/scala3/workflows/Dotty/badge.svg?branch=master)](https://github.com/scala/scala3/actions?query=branch%3Amain) [![Join the chat at https://discord.com/invite/scala](https://img.shields.io/discord/632150470000902164)](https://discord.com/invite/scala) * [Documentation](https://docs.scala-lang.org/scala3/) @@ -23,7 +23,7 @@ other more direct lines of communication such as email. How to Contribute ================= * [Getting Started as Contributor](https://docs.scala-lang.org/scala3/guides/contribution/contribution-intro.html) -* [Issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) +* [Issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) License ======= diff --git a/bench/profiles/compiletime.yml b/bench/profiles/compiletime.yml index fd77df7dfe9a..520af3750aa4 100644 --- a/bench/profiles/compiletime.yml +++ b/bench/profiles/compiletime.yml @@ -1,31 +1,31 @@ charts: - name: "Compile-time sums of constant integer types (generated)" - url: https://github.com/lampepfl/dotty/blob/main/bench/src/main/scala/generateBenchmarks.scala + url: https://github.com/scala/scala3/blob/main/bench/src/main/scala/generateBenchmarks.scala lines: - key: compiletime-sum-constants label: bootstrapped - name: "Compile-time sums of term reference types (generated)" - url: https://github.com/lampepfl/dotty/blob/main/bench/src/main/scala/generateBenchmarks.scala + url: https://github.com/scala/scala3/blob/main/bench/src/main/scala/generateBenchmarks.scala lines: - key: compiletime-sum-termrefs label: bootstrapped - name: "Sums of term references, result type inferred (generated)" - url: https://github.com/lampepfl/dotty/blob/main/bench/src/main/scala/generateBenchmarks.scala + url: https://github.com/scala/scala3/blob/main/bench/src/main/scala/generateBenchmarks.scala lines: - key: compiletime-sum-termrefs-terms label: bootstrapped - name: "Compile-time sums of type applications (generated)" - url: https://github.com/lampepfl/dotty/blob/main/bench/src/main/scala/generateBenchmarks.scala + url: https://github.com/scala/scala3/blob/main/bench/src/main/scala/generateBenchmarks.scala lines: - key: compiletime-sum-applications label: bootstrapped - name: "Compile-time additions inside multiplications (generated)" - url: https://github.com/lampepfl/dotty/blob/main/bench/src/main/scala/generateBenchmarks.scala + url: https://github.com/scala/scala3/blob/main/bench/src/main/scala/generateBenchmarks.scala lines: - key: compiletime-distribute label: bootstrapped @@ -48,4 +48,4 @@ scripts: - measure 6 6 7 1 $PROG_HOME/dotty/bench/tests-generated/compiletime-ops/distribute.scala config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/default.yml b/bench/profiles/default.yml index 22ed6d5f31df..5867816217fe 100644 --- a/bench/profiles/default.yml +++ b/bench/profiles/default.yml @@ -11,4 +11,4 @@ includes: config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/empty.yml b/bench/profiles/empty.yml index ac571e64e831..108150d3934e 100644 --- a/bench/profiles/empty.yml +++ b/bench/profiles/empty.yml @@ -1,19 +1,19 @@ charts: - name: "empty class" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/empty-class.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/empty-class.scala lines: - key: empty-class label: bootstrapped - name: "empty object" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/empty-object.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/empty-object.scala lines: - key: empty-object label: bootstrapped - name: "empty file" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/empty-file.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/empty-file.scala lines: - key: empty-file label: bootstrapped @@ -30,4 +30,4 @@ scripts: - measure $PROG_HOME/dotty/tests/bench/empty-file.scala config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/exhaustivity.yml b/bench/profiles/exhaustivity.yml index af6eb4041f6c..47710f7cb39f 100644 --- a/bench/profiles/exhaustivity.yml +++ b/bench/profiles/exhaustivity.yml @@ -1,54 +1,54 @@ charts: - name: "exhaustivity check" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/patmatexhaust.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/patmatexhaust.scala lines: - key: patmatexhaust label: bootstrapped - name: "exhaustivity I" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/exhaustivity-I.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/exhaustivity-I.scala lines: - key: exhaustivity-I label: bootstrapped - name: "exhaustivity S" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/exhaustivity-S.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/exhaustivity-S.scala lines: - key: exhaustivity-S label: bootstrapped - name: "exhaustivity T" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/exhaustivity-T.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/exhaustivity-T.scala lines: - key: exhaustivity-T label: bootstrapped - name: "exhaustivity V" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/exhaustivity-V.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/exhaustivity-V.scala lines: - key: exhaustivity-V label: bootstrapped - name: "exhaustivity MIPS" - url: https://github.com/lampepfl/dotty/blob/main/tests/patmat/i7186.scala + url: https://github.com/scala/scala3/blob/main/tests/patmat/i7186.scala lines: - key: exhaustivity-mips label: bootstrapped - name: "exhaustivity i12241" - url: https://github.com/lampepfl/dotty/blob/main/tests/patmat/i12241.scala + url: https://github.com/scala/scala3/blob/main/tests/patmat/i12241.scala lines: - key: exhaustivity-i12241 label: bootstrapped - name: "exhaustivity i12358" - url: https://github.com/lampepfl/dotty/blob/main/tests/patmat/i12358.scala + url: https://github.com/scala/scala3/blob/main/tests/patmat/i12358.scala lines: - key: exhaustivity-i12358 label: bootstrapped - name: "exhaustivity i13565" - url: https://github.com/lampepfl/dotty/blob/main/tests/pos/i13565.scala + url: https://github.com/scala/scala3/blob/main/tests/pos/i13565.scala lines: - key: exhaustivity-i13565 label: bootstrapped @@ -83,4 +83,4 @@ scripts: - measure 20 40 3 $PROG_HOME/dotty/tests/pos/i13565.scala config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/implicits.yml b/bench/profiles/implicits.yml index 3e944b5be28b..ff7f8c34b872 100644 --- a/bench/profiles/implicits.yml +++ b/bench/profiles/implicits.yml @@ -1,6 +1,6 @@ charts: - name: "implicit cache I" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/implicit_cache.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/implicit_cache.scala lines: - key: implicit-cache label: bootstrapped @@ -8,7 +8,7 @@ charts: label: from tasty - name: "implicit cache II" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/implicitNums.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/implicitNums.scala lines: - key: implicitNums label: bootstrapped @@ -16,13 +16,13 @@ charts: label: from tasty - name: "implicit scope loop" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/implicit-scope-loop.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/implicit-scope-loop.scala lines: - key: implicit-scope-loop label: bootstrapped - name: "inductive implicits" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/inductive-implicits.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/inductive-implicits.scala lines: - key: inductive-implicits label: bootstrapped @@ -48,4 +48,4 @@ scripts: - source $PROG_HOME/dotty/bench/scripts/implicitNums-from-tasty config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/misc.yml b/bench/profiles/misc.yml index 668f8e60c176..7ef168a0eea9 100644 --- a/bench/profiles/misc.yml +++ b/bench/profiles/misc.yml @@ -1,13 +1,13 @@ charts: - name: "issue #1535" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/i1535.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/i1535.scala lines: - key: i1535 label: bootstrapped - name: "issue #1687" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/i1687.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/i1687.scala lines: - key: i1687 label: bootstrapped diff --git a/bench/profiles/projects.yml b/bench/profiles/projects.yml index f1133d180c54..72e506290bad 100644 --- a/bench/profiles/projects.yml +++ b/bench/profiles/projects.yml @@ -41,4 +41,4 @@ scripts: - source $PROG_HOME/dotty/bench/scripts/stdlib213 config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/pull.yml b/bench/profiles/pull.yml index 163d75a8769d..4760e27daf95 100644 --- a/bench/profiles/pull.yml +++ b/bench/profiles/pull.yml @@ -5,4 +5,4 @@ includes: - empty.yml config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/quotes.yml b/bench/profiles/quotes.yml index afd970543aa1..454cd0dc5faa 100644 --- a/bench/profiles/quotes.yml +++ b/bench/profiles/quotes.yml @@ -1,18 +1,18 @@ charts: - name: "Inline a quote" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/power-macro/PowerInlined-1.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/power-macro/PowerInlined-1.scala lines: - key: power-macro-power-inlined-1 label: bootstrapped - name: "Inline 1k quotes" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/power-macro/PowerInlined-1k.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/power-macro/PowerInlined-1k.scala lines: - key: power-macro-power-inlined-1k label: bootstrapped - name: "Quote String interpolation matching" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/string-interpolation-macro/Test.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/string-interpolation-macro/Test.scala lines: - key: quote-string-interpolation-matching label: bootstrapped @@ -29,4 +29,4 @@ scripts: - source $PROG_HOME/dotty/bench/scripts/quote-string-interpolation-matching config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/sbt.yml b/bench/profiles/sbt.yml index 3ab0e43f3db2..653b10381959 100644 --- a/bench/profiles/sbt.yml +++ b/bench/profiles/sbt.yml @@ -12,4 +12,4 @@ scripts: - measure -with-compiler -Yforce-sbt-phases -with-dotty $(find $PROG_HOME/dotty/compiler/src/dotty -name *.scala -o -name *.java) config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/tuples.yml b/bench/profiles/tuples.yml index 5e41ecf7c80d..24bf76f786cc 100644 --- a/bench/profiles/tuples.yml +++ b/bench/profiles/tuples.yml @@ -1,42 +1,42 @@ charts: - name: "Tuple22 creation with Tuple22.apply" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/tuple22-creation-apply.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/tuple22-creation-apply.scala lines: - key: tuple22-creation-apply label: bootstrapped - name: "Tuple22 creation with *:" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/tuple22-creation-cons.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/tuple22-creation-cons.scala lines: - key: tuple22-creation-cons label: bootstrapped - name: "Tuple22.tail" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/tuple22-tails.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/tuple22-tails.scala lines: - key: tuple22-tails label: bootstrapped - name: "Tuple22.apply" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/tuple22-apply.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/tuple22-apply.scala lines: - key: tuple22-apply label: bootstrapped - name: "Tuple22.size" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/tuple22-size.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/tuple22-size.scala lines: - key: tuple22-size label: bootstrapped - name: "Tuple reverse (Runtime)" - url: https://github.com/lampepfl/dotty/blob/main/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/TupleOps.scala#L59 + url: https://github.com/scala/scala3/blob/main/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/TupleOps.scala#L59 lines: - key: tuple-reverse label: bootstrapped - name: "Tuple flatMap (Runtime)" - url: https://github.com/lampepfl/dotty/blob/main/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/TupleOps.scala#L64 + url: https://github.com/scala/scala3/blob/main/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/TupleOps.scala#L64 lines: - key: tuple-flatMap label: bootstrapped @@ -65,4 +65,4 @@ scripts: - measure-run TupleOps.flatMap config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/typing.yml b/bench/profiles/typing.yml index f6476bca7006..929438cb5a93 100644 --- a/bench/profiles/typing.yml +++ b/bench/profiles/typing.yml @@ -1,6 +1,6 @@ charts: - name: "Find Ref" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/FindRef.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/FindRef.scala lines: - key: find-ref label: bootstrapped @@ -11,4 +11,4 @@ scripts: - measure $PROG_HOME/dotty/tests/bench/FindRef.scala config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/build.sbt b/build.sbt index 9b6ebc194ea0..1712e80405ae 100644 --- a/build.sbt +++ b/build.sbt @@ -17,6 +17,8 @@ val `scala3-bench-micro` = Build.`scala3-bench-micro` val `scala2-library-bootstrapped` = Build.`scala2-library-bootstrapped` val `scala2-library-tasty` = Build.`scala2-library-tasty` val `scala2-library-tasty-tests` = Build.`scala2-library-tasty-tests` +val `scala2-library-cc` = Build.`scala2-library-cc` +val `scala2-library-cc-tasty` = Build.`scala2-library-cc-tasty` val `tasty-core` = Build.`tasty-core` val `tasty-core-bootstrapped` = Build.`tasty-core-bootstrapped` val `tasty-core-scala2` = Build.`tasty-core-scala2` diff --git a/changelogs/3.4.1-RC1.md b/changelogs/3.4.1-RC1.md new file mode 100644 index 000000000000..f374c6768497 --- /dev/null +++ b/changelogs/3.4.1-RC1.md @@ -0,0 +1,190 @@ +# Highlights of the release + +- Add support for `@deprecatedInheritance` [#19082](https://github.com/lampepfl/dotty/pull/19082) +- Avoid generating given definitions that loop [#19282](https://github.com/lampepfl/dotty/pull/19282) + +# Other changes and fixes + +## Coverage + +- Correctly prettify names in coverage info [#18542](https://github.com/lampepfl/dotty/pull/18542) + +## Desugaring + +- Make apply proxies work with overloaded ctors [#19464](https://github.com/lampepfl/dotty/pull/19464) +- Fix possible crash in Desugar [#19567](https://github.com/lampepfl/dotty/pull/19567) + +## Documentation + +- Update `private[this]` deprecation warning and documentation [#19393](https://github.com/lampepfl/dotty/pull/19393) + +## Erasure + +- Make eraseInfo work for classes with EmptyScopes [#19550](https://github.com/lampepfl/dotty/pull/19550) + +## Exports + +- Do not propagate `@tailrec` to exported methods [#19509](https://github.com/lampepfl/dotty/pull/19509) +- Fix retained flags in exports [#19636](https://github.com/lampepfl/dotty/pull/19636) + +## GADTs + +- Only cache base types when gadt state is empty [#19562](https://github.com/lampepfl/dotty/pull/19562) + +## Implicits + +- Run CheckStatic after UncacheGivenAliases [#19318](https://github.com/lampepfl/dotty/pull/19318) +- Add tests to verify that crash is fixed elsewhere. Fixes #19328 [#19329](https://github.com/lampepfl/dotty/pull/19329) +- Don't search for implicit conversions to NoType [#19563](https://github.com/lampepfl/dotty/pull/19563) +- Instantiate argument type vars before implicit search [#19096](https://github.com/lampepfl/dotty/pull/19096) + +## Java Interop + +- Classfile reader: handle JDK 9+ constant types in constant pool [#19533](https://github.com/lampepfl/dotty/pull/19533) + +## Linting + +- Make fatal warnings not fail compilation early & aggregate warns [#19245](https://github.com/lampepfl/dotty/pull/19245) + +## Macro Annotations + +- Check and enter missing symbols in MacroAnnotations only for definitions [#19579](https://github.com/lampepfl/dotty/pull/19579) + +## Match Types + +- Normalize MatchAlias in unrollTupleTypes [#19565](https://github.com/lampepfl/dotty/pull/19565) +- Fix #19445: Remove too-strict test in match type matching. [#19511](https://github.com/lampepfl/dotty/pull/19511) + +## Opaque Types + +- Fix problems with cycle checks [#19453](https://github.com/lampepfl/dotty/pull/19453) + +## Parser + +- Fix(#18265): crash on extension method without type nor RHS [#18743](https://github.com/lampepfl/dotty/pull/18743) +- Warn when @volatile is used on vals [#19462](https://github.com/lampepfl/dotty/pull/19462) +- Fix(#16459) xml parse regression [#19531](https://github.com/lampepfl/dotty/pull/19531) + +## Pattern Matching + +- Fix false unreachable due to opaqueness [#19368](https://github.com/lampepfl/dotty/pull/19368) +- Improve recursive decompose prefix fix [#19375](https://github.com/lampepfl/dotty/pull/19375) +- Allow constraining a parameter to Nothing [#19397](https://github.com/lampepfl/dotty/pull/19397) +- Add a test case, proving i15661 is fixed [#19432](https://github.com/lampepfl/dotty/pull/19432) + +## Presentation Compiler + +- Improvement: Support completions for implicit classes [#19314](https://github.com/lampepfl/dotty/pull/19314) +- Chore: Backport changes from Metals [#19410](https://github.com/lampepfl/dotty/pull/19410) +- Fix goto-def on exported forwarders [#19494](https://github.com/lampepfl/dotty/pull/19494) +- Backport pc changes from metals [#19617](https://github.com/lampepfl/dotty/pull/19617) +- Chore: Backport changes from Metals [#19592](https://github.com/lampepfl/dotty/pull/19592) +- Use comma counting for all signature help types [#19520](https://github.com/lampepfl/dotty/pull/19520) +- Make PC more resilient to crashes [#19488](https://github.com/lampepfl/dotty/pull/19488) +- Make order of renames and missing imports deterministic [#19468](https://github.com/lampepfl/dotty/pull/19468) +- Chore: backport changes from metals [#19452](https://github.com/lampepfl/dotty/pull/19452) +- Improve signature help by more stable position calculation + better named arg support [#19214](https://github.com/lampepfl/dotty/pull/19214) +- Instantiate Type Vars in completion labels of extension methods [#18914](https://github.com/lampepfl/dotty/pull/18914) + +## Quotes + +- Only evaluate transparent inline unapply once [#19380](https://github.com/lampepfl/dotty/pull/19380) +- Update `staging.Compiler.make` documentation [#19428](https://github.com/lampepfl/dotty/pull/19428) +- Error instead of StaleSymbol crash for certain cyclic macro dependencies [#19549](https://github.com/lampepfl/dotty/pull/19549) +- Refine handling of StaleSymbol type errors [#19605](https://github.com/lampepfl/dotty/pull/19605) +- Fix module symbol recovery from `NoClassDefFoundError` [#19645](https://github.com/lampepfl/dotty/pull/19645) +- Fix HOAS pattern example and error message [#19655](https://github.com/lampepfl/dotty/pull/19655) +- Set the correct type when copying reflect Inlined trees [#19409](https://github.com/lampepfl/dotty/pull/19409) + +## Reporting + +- Don't explain erroneous bounds [#19338](https://github.com/lampepfl/dotty/pull/19338) +- Better error diagnostics for cyclic references [#19408](https://github.com/lampepfl/dotty/pull/19408) +- Properly identify empty bounds in error message [#19310](https://github.com/lampepfl/dotty/pull/19310) + +## Scala-JS + +- Fix #19528: Actually remove Dynamic from interfaces of native JS classes. [#19536](https://github.com/lampepfl/dotty/pull/19536) +- Consider static and non-static methods as non-double def [#19400](https://github.com/lampepfl/dotty/pull/19400) + +## Scaladoc + +- Scaladoc - add option for dynamic side menu [#19337](https://github.com/lampepfl/dotty/pull/19337) +- Scaladoc: Fix "case case Foo" in enum's cases [#19519](https://github.com/lampepfl/dotty/pull/19519) +- Fix(#19377): show inherited abstract members in dedicated section [#19552](https://github.com/lampepfl/dotty/pull/19552) +- Jsoup: 1.14.3 → 1.17.2 [#19564](https://github.com/lampepfl/dotty/pull/19564) +- Extend copyright into 2024 [#19367](https://github.com/lampepfl/dotty/pull/19367) + +## Tooling + +- Prioritize TASTy files over classfiles on classpath aggregation [#19431](https://github.com/lampepfl/dotty/pull/19431) + +## Transform + +- Fix purity check for val inside of object [#19598](https://github.com/lampepfl/dotty/pull/19598) +- Drop special treatment of function types in overloading resolution [#19654](https://github.com/lampepfl/dotty/pull/19654) +- Add checks for the consistency of the parents in TreeChecker [#18935](https://github.com/lampepfl/dotty/pull/18935) + +## Type Inference + +- More careful type variable instance improvements [#19659](https://github.com/lampepfl/dotty/pull/19659) + +## Typer + +- Reject wildcard types in using clauses [#19459](https://github.com/lampepfl/dotty/pull/19459) +- Don't leave underspecified SAM types in the code [#19461](https://github.com/lampepfl/dotty/pull/19461) +- Also compute base classes of wildcardTypes [#19465](https://github.com/lampepfl/dotty/pull/19465) +- Fix(#15784): ident rule for pat match was too strict [#19501](https://github.com/lampepfl/dotty/pull/19501) +- Heal occurrences of => T between ElimByName and Erasure [#19558](https://github.com/lampepfl/dotty/pull/19558) +- Fix(#i18645): overload ext method body in braces didn't compile [#19651](https://github.com/lampepfl/dotty/pull/19651) +- Fix #19202: Passing NotNullInfos to a mutable field of a Completer [#19463](https://github.com/lampepfl/dotty/pull/19463) +- Fix Java record problems (#19578) and (#19386) [#19583](https://github.com/lampepfl/dotty/pull/19583) +- Improve when deprecation warnings are emitted [#19621](https://github.com/lampepfl/dotty/pull/19621) +- Space: Replace showType & make Space Showable [#19370](https://github.com/lampepfl/dotty/pull/19370) + + +# Contributors + +Thank you to all the contributors who made this release possible 🎉 + +According to `git shortlog -sn --no-merges 3.4.0..3.4.1-RC1` these are: + +``` + 53 Martin Odersky + 53 Nicolas Stucki + 20 Dale Wijnand + 11 Szymon Rodziewicz + 11 i10416 + 7 noti0na1 + 6 Yilin Wei + 4 Hamza REMMAL + 4 Jędrzej Rochala + 3 Eugene Flesselle + 3 Paweł Marks + 3 Seth Tisue + 2 Florian3k + 2 Hamza Remmal + 2 Jan Chyb + 2 Katarzyna Marek + 2 Sébastien Doeraene + 2 Tomasz Godzik + 2 dependabot[bot] + 1 Bersier + 1 Fabián Heredia Montiel + 1 Jakub Ciesluk + 1 Jakub Cieśluk + 1 Kacper Korban + 1 Kenji Yoshida + 1 Mehdi Alaoui + 1 Nikita Gazarov + 1 Oron Port + 1 Pascal Weisenburger + 1 Philippus Baalman + 1 Quentin Bernet + 1 Som Snytt + 1 Wojciech Mazur + 1 Yichen Xu + 1 aherlihy + 1 rochala + +``` diff --git a/changelogs/3.4.1-RC2.md b/changelogs/3.4.1-RC2.md new file mode 100644 index 000000000000..7267d2339c35 --- /dev/null +++ b/changelogs/3.4.1-RC2.md @@ -0,0 +1,18 @@ +# Backported fixes + +- Adjust owner in Interactive.contextOfPath causing crash in ImplicitSearch [#19875](https://github.com/lampepfl/dotty/pull/19875) +- Add GADT symbols when typing typing-ahead lambda bodies[#19644](https://github.com/lampepfl/dotty/pull/19644) + +# Contributors + +Thank you to all the contributors who made this release possible 🎉 + +According to `git shortlog -sn --no-merges 3.4.1-RC1..3.4.1-RC2` these are: + +``` + 4 Hamza REMMAL + 2 Dale Wijnand + 2 Paweł Marks + 1 Jędrzej Rochala + +``` diff --git a/changelogs/3.4.1.md b/changelogs/3.4.1.md new file mode 100644 index 000000000000..920c78f61e8f --- /dev/null +++ b/changelogs/3.4.1.md @@ -0,0 +1,192 @@ +# Highlights of the release + +- Add support for `@deprecatedInheritance` [#19082](https://github.com/lampepfl/dotty/pull/19082) +- Avoid generating given definitions that loop [#19282](https://github.com/lampepfl/dotty/pull/19282) + +# Other changes and fixes + +## Coverage + +- Correctly prettify names in coverage info [#18542](https://github.com/lampepfl/dotty/pull/18542) + +## Desugaring + +- Make apply proxies work with overloaded ctors [#19464](https://github.com/lampepfl/dotty/pull/19464) +- Fix possible crash in Desugar [#19567](https://github.com/lampepfl/dotty/pull/19567) + +## Documentation + +- Update `private[this]` deprecation warning and documentation [#19393](https://github.com/lampepfl/dotty/pull/19393) + +## Erasure + +- Make eraseInfo work for classes with EmptyScopes [#19550](https://github.com/lampepfl/dotty/pull/19550) + +## Exports + +- Do not propagate `@tailrec` to exported methods [#19509](https://github.com/lampepfl/dotty/pull/19509) +- Fix retained flags in exports [#19636](https://github.com/lampepfl/dotty/pull/19636) + +## GADTs + +- Only cache base types when gadt state is empty [#19562](https://github.com/lampepfl/dotty/pull/19562) +- Add GADT symbols when typing typing-ahead lambda bodies[#19644](https://github.com/lampepfl/dotty/pull/19644) + +## Implicits + +- Run CheckStatic after UncacheGivenAliases [#19318](https://github.com/lampepfl/dotty/pull/19318) +- Add tests to verify that crash is fixed elsewhere. Fixes #19328 [#19329](https://github.com/lampepfl/dotty/pull/19329) +- Don't search for implicit conversions to NoType [#19563](https://github.com/lampepfl/dotty/pull/19563) +- Instantiate argument type vars before implicit search [#19096](https://github.com/lampepfl/dotty/pull/19096) +- Adjust owner in Interactive.contextOfPath causing crash in ImplicitSearch [#19875](https://github.com/lampepfl/dotty/pull/19875) + +## Java Interop + +- Classfile reader: handle JDK 9+ constant types in constant pool [#19533](https://github.com/lampepfl/dotty/pull/19533) + +## Linting + +- Make fatal warnings not fail compilation early & aggregate warns [#19245](https://github.com/lampepfl/dotty/pull/19245) + +## Macro Annotations + +- Check and enter missing symbols in MacroAnnotations only for definitions [#19579](https://github.com/lampepfl/dotty/pull/19579) + +## Match Types + +- Normalize MatchAlias in unrollTupleTypes [#19565](https://github.com/lampepfl/dotty/pull/19565) +- Fix #19445: Remove too-strict test in match type matching. [#19511](https://github.com/lampepfl/dotty/pull/19511) + +## Opaque Types + +- Fix problems with cycle checks [#19453](https://github.com/lampepfl/dotty/pull/19453) + +## Parser + +- Fix(#18265): crash on extension method without type nor RHS [#18743](https://github.com/lampepfl/dotty/pull/18743) +- Warn when @volatile is used on vals [#19462](https://github.com/lampepfl/dotty/pull/19462) +- Fix(#16459) xml parse regression [#19531](https://github.com/lampepfl/dotty/pull/19531) + +## Pattern Matching + +- Fix false unreachable due to opaqueness [#19368](https://github.com/lampepfl/dotty/pull/19368) +- Improve recursive decompose prefix fix [#19375](https://github.com/lampepfl/dotty/pull/19375) +- Allow constraining a parameter to Nothing [#19397](https://github.com/lampepfl/dotty/pull/19397) +- Add a test case, proving i15661 is fixed [#19432](https://github.com/lampepfl/dotty/pull/19432) + +## Presentation Compiler + +- Improvement: Support completions for implicit classes [#19314](https://github.com/lampepfl/dotty/pull/19314) +- Chore: Backport changes from Metals [#19410](https://github.com/lampepfl/dotty/pull/19410) +- Fix goto-def on exported forwarders [#19494](https://github.com/lampepfl/dotty/pull/19494) +- Backport pc changes from metals [#19617](https://github.com/lampepfl/dotty/pull/19617) +- Chore: Backport changes from Metals [#19592](https://github.com/lampepfl/dotty/pull/19592) +- Use comma counting for all signature help types [#19520](https://github.com/lampepfl/dotty/pull/19520) +- Make PC more resilient to crashes [#19488](https://github.com/lampepfl/dotty/pull/19488) +- Make order of renames and missing imports deterministic [#19468](https://github.com/lampepfl/dotty/pull/19468) +- Chore: backport changes from metals [#19452](https://github.com/lampepfl/dotty/pull/19452) +- Improve signature help by more stable position calculation + better named arg support [#19214](https://github.com/lampepfl/dotty/pull/19214) +- Instantiate Type Vars in completion labels of extension methods [#18914](https://github.com/lampepfl/dotty/pull/18914) + +## Quotes + +- Only evaluate transparent inline unapply once [#19380](https://github.com/lampepfl/dotty/pull/19380) +- Update `staging.Compiler.make` documentation [#19428](https://github.com/lampepfl/dotty/pull/19428) +- Error instead of StaleSymbol crash for certain cyclic macro dependencies [#19549](https://github.com/lampepfl/dotty/pull/19549) +- Refine handling of StaleSymbol type errors [#19605](https://github.com/lampepfl/dotty/pull/19605) +- Fix module symbol recovery from `NoClassDefFoundError` [#19645](https://github.com/lampepfl/dotty/pull/19645) +- Fix HOAS pattern example and error message [#19655](https://github.com/lampepfl/dotty/pull/19655) +- Set the correct type when copying reflect Inlined trees [#19409](https://github.com/lampepfl/dotty/pull/19409) + +## Reporting + +- Don't explain erroneous bounds [#19338](https://github.com/lampepfl/dotty/pull/19338) +- Better error diagnostics for cyclic references [#19408](https://github.com/lampepfl/dotty/pull/19408) +- Properly identify empty bounds in error message [#19310](https://github.com/lampepfl/dotty/pull/19310) + +## Scala-JS + +- Fix #19528: Actually remove Dynamic from interfaces of native JS classes. [#19536](https://github.com/lampepfl/dotty/pull/19536) +- Consider static and non-static methods as non-double def [#19400](https://github.com/lampepfl/dotty/pull/19400) + +## Scaladoc + +- Scaladoc - add option for dynamic side menu [#19337](https://github.com/lampepfl/dotty/pull/19337) +- Scaladoc: Fix "case case Foo" in enum's cases [#19519](https://github.com/lampepfl/dotty/pull/19519) +- Fix(#19377): show inherited abstract members in dedicated section [#19552](https://github.com/lampepfl/dotty/pull/19552) +- Jsoup: 1.14.3 → 1.17.2 [#19564](https://github.com/lampepfl/dotty/pull/19564) +- Extend copyright into 2024 [#19367](https://github.com/lampepfl/dotty/pull/19367) + +## Tooling + +- Prioritize TASTy files over classfiles on classpath aggregation [#19431](https://github.com/lampepfl/dotty/pull/19431) + +## Transform + +- Fix purity check for val inside of object [#19598](https://github.com/lampepfl/dotty/pull/19598) +- Drop special treatment of function types in overloading resolution [#19654](https://github.com/lampepfl/dotty/pull/19654) +- Add checks for the consistency of the parents in TreeChecker [#18935](https://github.com/lampepfl/dotty/pull/18935) + +## Type Inference + +- More careful type variable instance improvements [#19659](https://github.com/lampepfl/dotty/pull/19659) + +## Typer + +- Reject wildcard types in using clauses [#19459](https://github.com/lampepfl/dotty/pull/19459) +- Don't leave underspecified SAM types in the code [#19461](https://github.com/lampepfl/dotty/pull/19461) +- Also compute base classes of wildcardTypes [#19465](https://github.com/lampepfl/dotty/pull/19465) +- Fix(#15784): ident rule for pat match was too strict [#19501](https://github.com/lampepfl/dotty/pull/19501) +- Heal occurrences of => T between ElimByName and Erasure [#19558](https://github.com/lampepfl/dotty/pull/19558) +- Fix(#i18645): overload ext method body in braces didn't compile [#19651](https://github.com/lampepfl/dotty/pull/19651) +- Fix #19202: Passing NotNullInfos to a mutable field of a Completer [#19463](https://github.com/lampepfl/dotty/pull/19463) +- Fix Java record problems (#19578) and (#19386) [#19583](https://github.com/lampepfl/dotty/pull/19583) +- Improve when deprecation warnings are emitted [#19621](https://github.com/lampepfl/dotty/pull/19621) +- Space: Replace showType & make Space Showable [#19370](https://github.com/lampepfl/dotty/pull/19370) + + +# Contributors + +Thank you to all the contributors who made this release possible 🎉 + +According to `git shortlog -sn --no-merges 3.4.0..3.4.1` these are: + +``` + 53 Martin Odersky + 53 Nicolas Stucki + 22 Dale Wijnand + 11 Szymon Rodziewicz + 11 i10416 + 8 Hamza REMMAL + 7 Paweł Marks + 7 noti0na1 + 6 Yilin Wei + 5 Jędrzej Rochala + 3 Eugene Flesselle + 3 Seth Tisue + 2 Florian3k + 2 Hamza Remmal + 2 Jan Chyb + 2 Katarzyna Marek + 2 Sébastien Doeraene + 2 Tomasz Godzik + 2 dependabot[bot] + 1 Bersier + 1 Fabián Heredia Montiel + 1 Jakub Ciesluk + 1 Jakub Cieśluk + 1 Kacper Korban + 1 Kenji Yoshida + 1 Mehdi Alaoui + 1 Nikita Gazarov + 1 Oron Port + 1 Pascal Weisenburger + 1 Philippus Baalman + 1 Quentin Bernet + 1 Som Snytt + 1 Wojciech Mazur + 1 Yichen Xu + 1 aherlihy + 1 rochala + +``` diff --git a/community-build/community-projects/libretto b/community-build/community-projects/libretto index d229f3ccb9c4..64de079d5a7c 160000 --- a/community-build/community-projects/libretto +++ b/community-build/community-projects/libretto @@ -1 +1 @@ -Subproject commit d229f3ccb9c49aa3b0fef1b3f7425e986155cc97 +Subproject commit 64de079d5a7cf3efe3345421ac3e375a718f57f7 diff --git a/community-build/src/scala/dotty/communitybuild/projects.scala b/community-build/src/scala/dotty/communitybuild/projects.scala index 767667b491ce..ae030dc66336 100644 --- a/community-build/src/scala/dotty/communitybuild/projects.scala +++ b/community-build/src/scala/dotty/communitybuild/projects.scala @@ -140,7 +140,7 @@ final case class SbtCommunityProject( case Some(ivyHome) => List(s"-Dsbt.ivy.home=$ivyHome") case _ => Nil extraSbtArgs ++ sbtProps ++ List( - "-sbt-version", "1.9.3", + "-sbt-version", "1.9.7", "-Dsbt.supershell=false", s"-Ddotty.communitybuild.dir=$communitybuildDir", s"--addPluginSbtFile=$sbtPluginFilePath" diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala b/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala index 2ad58fea4cd1..385521e2785f 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala @@ -754,7 +754,7 @@ trait BCodeHelpers extends BCodeIdiomatic { case tp => report.warning( s"an unexpected type representation reached the compiler backend while compiling ${ctx.compilationUnit}: $tp. " + - "If possible, please file a bug on https://github.com/lampepfl/dotty/issues") + "If possible, please file a bug on https://github.com/scala/scala3/issues") tp match { case tp: ThisType if tp.cls == defn.ArrayClass => ObjectRef.asInstanceOf[ct.bTypes.ClassBType] // was introduced in 9b17332f11 to fix SI-999, but this code is not reached in its test, or any other test @@ -795,7 +795,7 @@ trait BCodeHelpers extends BCodeIdiomatic { report.error( em"""|compiler bug: created invalid generic signature for $sym in ${sym.denot.owner.showFullName} |signature: $sig - |if this is reproducible, please report bug at https://github.com/lampepfl/dotty/issues + |if this is reproducible, please report bug at https://github.com/scala/scala3/issues """, sym.sourcePos) throw ex } diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala b/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala index 0ab9ed85b6cf..394700c2898e 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala @@ -191,7 +191,7 @@ trait BCodeSkelBuilder extends BCodeHelpers { // Should we do this transformation earlier, say in Constructors? Or would that just cause // pain for scala-{js, native}? // - // @sjrd (https://github.com/lampepfl/dotty/pull/9181#discussion_r457458205): + // @sjrd (https://github.com/scala/scala3/pull/9181#discussion_r457458205): // moving that before the back-end would make things significantly more complicated for // Scala.js and Native. Both have a first-class concept of ModuleClass, and encode the // singleton pattern of MODULE$ in a completely different way. In the Scala.js IR, there @@ -202,7 +202,7 @@ trait BCodeSkelBuilder extends BCodeHelpers { // TODO: remove `!f.name.is(LazyBitMapName)` once we change lazy val encoding - // https://github.com/lampepfl/dotty/issues/7140 + // https://github.com/scala/scala3/issues/7140 // // Lazy val encoding assumes bitmap fields are non-static // diff --git a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index 37045bda17ec..8016c2bfc209 100644 --- a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -126,7 +126,7 @@ object DottyBackendInterface { * See also `genPlainClass` in `BCodeSkelBuilder.scala`. * * TODO: remove the special handing of `LazyBitMapName` once we swtich to - * the new lazy val encoding: https://github.com/lampepfl/dotty/issues/7140 + * the new lazy val encoding: https://github.com/scala/scala3/issues/7140 */ def isStaticModuleField(using Context): Boolean = sym.owner.isStaticModuleClass && sym.isField && !sym.name.is(LazyBitMapName) && !sym.name.is(LazyLocalName) diff --git a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala index 54af9f8dd088..5b0d37d28a9b 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala @@ -643,7 +643,7 @@ class JSCodeGen()(using genCtx: Context) { kind, None, superClass, - genClassInterfaces(sym, forJSClass = false), + genClassInterfaces(sym, forJSClass = true), None, jsNativeLoadSpec, Nil, @@ -793,6 +793,9 @@ class JSCodeGen()(using genCtx: Context) { name.name }.toSet + val staticNames = moduleClass.companionClass.info.allMembers + .collect { case d if d.name.isTermName && d.symbol.isScalaStatic => d.name }.toSet + val members = { moduleClass.info.membersBasedOnFlags(required = Flags.Method, excluded = Flags.ExcludedForwarder).map(_.symbol) @@ -815,6 +818,7 @@ class JSCodeGen()(using genCtx: Context) { || hasAccessBoundary || isOfJLObject || m.hasAnnotation(jsdefn.JSNativeAnnot) || isDefaultParamOfJSNativeDef // #4557 + || staticNames(m.name) } val forwarders = for { @@ -4769,7 +4773,7 @@ class JSCodeGen()(using genCtx: Context) { } private def isMethodStaticInIR(sym: Symbol): Boolean = - sym.is(JavaStatic) + sym.is(JavaStatic) || sym.isScalaStatic /** Generate a Class[_] value (e.g. coming from classOf[T]) */ private def genClassConstant(tpe: Type)(implicit pos: Position): js.Tree = diff --git a/compiler/src/dotty/tools/dotc/Compiler.scala b/compiler/src/dotty/tools/dotc/Compiler.scala index aaa14a052936..290df761d117 100644 --- a/compiler/src/dotty/tools/dotc/Compiler.scala +++ b/compiler/src/dotty/tools/dotc/Compiler.scala @@ -64,7 +64,6 @@ class Compiler { new CheckReentrant, // Internal use only: Check that compiled program has no data races involving global vars new ElimPackagePrefixes, // Eliminate references to package prefixes in Select nodes new CookComments, // Cook the comments: expand variables, doc, etc. - new CheckStatic, // Check restrictions that apply to @static members new CheckLoopingImplicits, // Check that implicit defs do not call themselves in an infinite loop new BetaReduce, // Reduce closure applications new InlineVals, // Check right hand-sides of an `inline val`s @@ -76,6 +75,7 @@ class Compiler { List(new ProtectedAccessors, // Add accessors for protected members new ExtensionMethods, // Expand methods of value classes with extension methods new UncacheGivenAliases, // Avoid caching RHS of simple parameterless given aliases + new CheckStatic, // Check restrictions that apply to @static members new ElimByName, // Map by-name parameters to functions new HoistSuperArgs, // Hoist complex arguments of supercalls to enclosing scope new ForwardDepChecks, // Check that there are no forward references to local vals diff --git a/compiler/src/dotty/tools/dotc/Driver.scala b/compiler/src/dotty/tools/dotc/Driver.scala index 4207baa57470..196752aceb29 100644 --- a/compiler/src/dotty/tools/dotc/Driver.scala +++ b/compiler/src/dotty/tools/dotc/Driver.scala @@ -54,8 +54,7 @@ class Driver { if (ctx.settings.XprintSuspension.value) report.echo(i"compiling suspended $suspendedUnits%, %") val run1 = compiler.newRun - for unit <- suspendedUnits do unit.suspended = false - run1.compileUnits(suspendedUnits) + run1.compileSuspendedUnits(suspendedUnits) finish(compiler, run1)(using MacroClassLoader.init(ctx.fresh)) protected def initCtx: Context = (new ContextBase).initialCtx @@ -127,7 +126,7 @@ class Driver { * The trade-off is that you can only pass a SimpleReporter to this method * and not a normal Reporter which is more powerful. * - * Usage example: [[https://github.com/lampepfl/dotty/tree/master/compiler/test/dotty/tools/dotc/InterfaceEntryPointTest.scala]] + * Usage example: [[https://github.com/scala/scala3/tree/master/compiler/test/dotty/tools/dotc/InterfaceEntryPointTest.scala]] * * @param args Arguments to pass to the compiler. * @param simple Used to log errors, warnings, and info messages. @@ -144,7 +143,7 @@ class Driver { /** Principal entry point to the compiler. * - * Usage example: [[https://github.com/lampepfl/dotty/tree/master/compiler/test/dotty/tools/dotc/EntryPointsTest.scala.disabled]] + * Usage example: [[https://github.com/scala/scala3/tree/master/compiler/test/dotty/tools/dotc/EntryPointsTest.scala.disabled]] * in method `runCompiler` * * @param args Arguments to pass to the compiler. @@ -183,7 +182,7 @@ class Driver { * the other overloads cannot be overridden, instead you * should override this one which they call internally. * - * Usage example: [[https://github.com/lampepfl/dotty/tree/master/compiler/test/dotty/tools/dotc/EntryPointsTest.scala.disabled]] + * Usage example: [[https://github.com/scala/scala3/tree/master/compiler/test/dotty/tools/dotc/EntryPointsTest.scala.disabled]] * in method `runCompilerWithContext` * * @param args Arguments to pass to the compiler. diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala index bec1c89d7216..4e0b7d09e95f 100644 --- a/compiler/src/dotty/tools/dotc/Run.scala +++ b/compiler/src/dotty/tools/dotc/Run.scala @@ -343,9 +343,12 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint runCtx.setProfiler(Profiler()) unfusedPhases.foreach(_.initContext(runCtx)) val fusedPhases = runCtx.base.allPhases + if ctx.settings.explainCyclic.value then + runCtx.setProperty(CyclicReference.Trace, new CyclicReference.Trace()) runCtx.withProgressCallback: cb => _progress = Progress(cb, this, fusedPhases.map(_.traversals).sum) runPhases(allPhases = fusedPhases)(using runCtx) + ctx.reporter.finalizeReporting() if (!ctx.reporter.hasErrors) Rewrites.writeBack() suppressions.runFinished(hasErrors = ctx.reporter.hasErrors) @@ -356,6 +359,17 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint compiling = false } + private var myCompilingSuspended: Boolean = false + + /** Is this run started via a compilingSuspended? */ + def isCompilingSuspended: Boolean = myCompilingSuspended + + /** Compile units `us` which were suspended in a previous run */ + def compileSuspendedUnits(us: List[CompilationUnit]): Unit = + myCompilingSuspended = true + for unit <- us do unit.suspended = false + compileUnits(us) + /** Enter top-level definitions of classes and objects contained in source file `file`. * The newly added symbols replace any previously entered symbols. * If `typeCheck = true`, also run typer on the compilation unit, and set diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 36f2d593de1c..9591bc5a93f0 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -1602,15 +1602,17 @@ object desugar { * skipping elements that are not convertible. */ def patternsToParams(elems: List[Tree])(using Context): List[ValDef] = - def toParam(elem: Tree, tpt: Tree): Tree = + def toParam(elem: Tree, tpt: Tree, span: Span): Tree = elem match - case Annotated(elem1, _) => toParam(elem1, tpt) - case Typed(elem1, tpt1) => toParam(elem1, tpt1) - case Ident(id: TermName) => ValDef(id, tpt, EmptyTree).withFlags(Param) + case Annotated(elem1, _) => toParam(elem1, tpt, span) + case Typed(elem1, tpt1) => toParam(elem1, tpt1, span) + case Ident(id: TermName) => ValDef(id, tpt, EmptyTree).withFlags(Param).withSpan(span) case _ => EmptyTree - elems.map(param => toParam(param, TypeTree()).withSpan(param.span)).collect { - case vd: ValDef => vd - } + elems + .map: param => + toParam(param, TypeTree(), param.span) + .collect: + case vd: ValDef => vd def makeContextualFunction(formals: List[Tree], paramNamesOrNil: List[TermName], body: Tree, erasedParams: List[Boolean])(using Context): Function = { val mods = Given diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index 5ded0e1262e4..28d3ef6daaef 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -578,8 +578,9 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => sym.owner.isPrimitiveValueClass || sym.owner == defn.StringClass || defn.pureMethods.contains(sym) + tree.tpe.isInstanceOf[ConstantType] && tree.symbol != NoSymbol && isKnownPureOp(tree.symbol) // A constant expression with pure arguments is pure. - || fn.symbol.isStableMember && !fn.symbol.is(Lazy) // constructors of no-inits classes are stable + || fn.symbol.isStableMember && fn.symbol.isConstructor // constructors of no-inits classes are stable /** The purity level of this reference. * @return diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 4ec41b95a90b..c64b636648ee 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -1501,7 +1501,7 @@ object Trees { * It ensures that the source is correct, and that the local context is used if * that's necessary for transforming the whole tree. * TODO: ensure transform is always called with the correct context as argument - * @see https://github.com/lampepfl/dotty/pull/13880#discussion_r836395977 + * @see https://github.com/scala/scala3/pull/13880#discussion_r836395977 */ def transformCtx(tree: Tree)(using Context): Context = val sourced = diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 44fa4e9b22fd..71b85d97a187 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -118,13 +118,13 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { * otherwise specified). */ def Closure(meth: TermSymbol, rhsFn: List[List[Tree]] => Tree, targs: List[Tree] = Nil, targetType: Type = NoType)(using Context): Block = { - val targetTpt = if (targetType.exists) TypeTree(targetType) else EmptyTree + val targetTpt = if (targetType.exists) TypeTree(targetType, inferred = true) else EmptyTree val call = if (targs.isEmpty) Ident(TermRef(NoPrefix, meth)) else TypeApply(Ident(TermRef(NoPrefix, meth)), targs) - Block( - DefDef(meth, rhsFn) :: Nil, - Closure(Nil, call, targetTpt)) + var mdef0 = DefDef(meth, rhsFn) + val mdef = cpy.DefDef(mdef0)(tpt = TypeTree(mdef0.tpt.tpe, inferred = true)) + Block(mdef :: Nil, Closure(Nil, call, targetTpt)) } /** A closure whose anonymous function has the given method type */ @@ -1142,6 +1142,11 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { buf.toList } + def collectSubTrees[A](f: PartialFunction[Tree, A])(using Context): List[A] = + val buf = mutable.ListBuffer[A]() + foreachSubTree(f.runWith(buf += _)(_)) + buf.toList + /** Set this tree as the `defTree` of its symbol and return this tree */ def setDefTree(using Context): ThisTree = { val sym = tree.symbol diff --git a/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala b/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala index a0d874007728..7c75ed833945 100644 --- a/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala +++ b/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala @@ -98,10 +98,14 @@ extension (tree: Tree) tree.putAttachment(Captures, refs) refs - /** The arguments of a @retains or @retainsByName annotation */ + /** The arguments of a @retains, @retainsCap or @retainsByName annotation */ def retainedElems(using Context): List[Tree] = tree match - case Apply(_, Typed(SeqLiteral(elems, _), _) :: Nil) => elems - case _ => Nil + case Apply(_, Typed(SeqLiteral(elems, _), _) :: Nil) => + elems + case _ => + if tree.symbol.maybeOwner == defn.RetainsCapAnnot + then ref(defn.captureRoot.termRef) :: Nil + else Nil extension (tp: Type) @@ -207,7 +211,7 @@ extension (tp: Type) def dropAllRetains(using Context): Type = // TODO we should drop retains from inferred types before unpickling val tm = new TypeMap: def apply(t: Type) = t match - case AnnotatedType(parent, annot) if annot.symbol == defn.RetainsAnnot => + case AnnotatedType(parent, annot) if annot.symbol.isRetains => apply(parent) case _ => mapOver(t) @@ -220,9 +224,31 @@ extension (tp: Type) * type of `x`. If `x` and `y` are different variables then `{x*}` and `{y*}` * are unrelated. */ - def reach(using Context): CaptureRef = - assert(tp.isTrackableRef) - AnnotatedType(tp, Annotation(defn.ReachCapabilityAnnot, util.Spans.NoSpan)) + def reach(using Context): CaptureRef = tp match + case tp: CaptureRef if tp.isTrackableRef => + if tp.isReach then tp else ReachCapability(tp) + + /** If `x` is a capture ref, its maybe capability `x?`, represented internally + * as `x @maybeCapability`. `x?` stands for a capability `x` that might or might + * not be part of a capture set. We have `{} <: {x?} <: {x}`. Maybe capabilities + * cannot be propagated between sets. If `a <: b` and `a` acquires `x?` then + * `x` is propagated to `b` as a conservative approximation. + * + * Maybe capabilities should only arise for capture sets that appear in invariant + * position in their surrounding type. They are similar to TypeBunds types, but + * restricted to capture sets. For instance, + * + * Array[C^{x?}] + * + * should be morally equivalent to + * + * Array[_ >: C^{} <: C^{x}] + * + * but it has fewer issues with type inference. + */ + def maybe(using Context): CaptureRef = tp match + case tp: CaptureRef if tp.isTrackableRef => + if tp.isMaybe then tp else MaybeCapability(tp) /** If `ref` is a trackable capture ref, and `tp` has only covariant occurrences of a * universal capture set, replace all these occurrences by `{ref*}`. This implements @@ -236,19 +262,19 @@ extension (tp: Type) * (2) all covariant occurrences of cap replaced by `x*`, provided there * are no occurrences in `T` at other variances. (1) is standard, whereas * (2) is new. - * + * * For (2), multiple-flipped covariant occurrences of cap won't be replaced. * In other words, * * - For xs: List[File^] ==> List[File^{xs*}], the cap is replaced; * - while f: [R] -> (op: File^ => R) -> R remains unchanged. - * + * * Without this restriction, the signature of functions like withFile: - * + * * (path: String) -> [R] -> (op: File^ => R) -> R * * could be refined to - * + * * (path: String) -> [R] -> (op: File^{withFile*} => R) -> R * * which is clearly unsound. @@ -315,8 +341,25 @@ extension (cls: ClassSymbol) // and err on the side of impure. && selfType.exists && selfType.captureSet.isAlwaysEmpty + def baseClassHasExplicitSelfType(using Context): Boolean = + cls.baseClasses.exists: bc => + bc.is(CaptureChecked) && bc.givenSelfType.exists + + def matchesExplicitRefsInBaseClass(refs: CaptureSet)(using Context): Boolean = + cls.baseClasses.tail.exists: bc => + val selfType = bc.givenSelfType + bc.is(CaptureChecked) && selfType.exists && selfType.captureSet.elems == refs.elems + extension (sym: Symbol) + /** This symbol is one of `retains` or `retainsCap` */ + def isRetains(using Context): Boolean = + sym == defn.RetainsAnnot || sym == defn.RetainsCapAnnot + + /** This symbol is one of `retains`, `retainsCap`, or`retainsByName` */ + def isRetainsLike(using Context): Boolean = + isRetains || sym == defn.RetainsByNameAnnot + /** A class is pure if: * - one its base types has an explicitly declared self type with an empty capture set * - or it is a value class @@ -410,12 +453,21 @@ object ReachCapabilityApply: case Apply(reach, arg :: Nil) if reach.symbol == defn.Caps_reachCapability => Some(arg) case _ => None +class AnnotatedCapability(annot: Context ?=> ClassSymbol): + def apply(tp: Type)(using Context) = + AnnotatedType(tp, Annotation(annot, util.Spans.NoSpan)) + def unapply(tree: AnnotatedType)(using Context): Option[SingletonCaptureRef] = tree match + case AnnotatedType(parent: SingletonCaptureRef, ann) if ann.symbol == annot => Some(parent) + case _ => None + /** An extractor for `ref @annotation.internal.reachCapability`, which is used to express * the reach capability `ref*` as a type. */ -object ReachCapability: - def unapply(tree: AnnotatedType)(using Context): Option[SingletonCaptureRef] = tree match - case AnnotatedType(parent: SingletonCaptureRef, ann) - if ann.symbol == defn.ReachCapabilityAnnot => Some(parent) - case _ => None +object ReachCapability extends AnnotatedCapability(defn.ReachCapabilityAnnot) + +/** An extractor for `ref @maybeCapability`, which is used to express + * the maybe capability `ref?` as a type. + */ +object MaybeCapability extends AnnotatedCapability(defn.MaybeCapabilityAnnot) + diff --git a/compiler/src/dotty/tools/dotc/cc/CaptureSet.scala b/compiler/src/dotty/tools/dotc/cc/CaptureSet.scala index fb086ca0399b..d1a5a07f6a0f 100644 --- a/compiler/src/dotty/tools/dotc/cc/CaptureSet.scala +++ b/compiler/src/dotty/tools/dotc/cc/CaptureSet.scala @@ -145,15 +145,16 @@ sealed abstract class CaptureSet extends Showable: /** x subsumes x * this subsumes this.f - * x subsumes y ==> x* subsumes y - * x subsumes y ==> x* subsumes y* + * x subsumes y ==> x* subsumes y, x subsumes y? + * x subsumes y ==> x* subsumes y*, x? subsumes y? */ extension (x: CaptureRef) private def subsumes(y: CaptureRef)(using Context): Boolean = (x eq y) || x.isRootCapability || y.match - case y: TermRef => !y.isReach && (y.prefix eq x) + case y: TermRef => y.prefix eq x + case MaybeCapability(y1) => x.stripMaybe.subsumes(y1) case _ => false || x.match case ReachCapability(x1) => x1.subsumes(y.stripReach) @@ -312,6 +313,8 @@ sealed abstract class CaptureSet extends Showable: def substParams(tl: BindingType, to: List[Type])(using Context) = map(Substituters.SubstParamsMap(tl, to)) + def maybe(using Context): CaptureSet = map(MaybeMap()) + /** Invoke handler if this set has (or later aquires) the root capability `cap` */ def disallowRootCapability(handler: () => Context ?=> Unit)(using Context): this.type = if isUniversal then handler() @@ -445,6 +448,8 @@ object CaptureSet: def isConst = isSolved def isAlwaysEmpty = false + def isMaybeSet = false // overridden in BiMapped + /** A handler to be invoked if the root reference `cap` is added to this set */ var rootAddedHandler: () => Context ?=> Unit = () => () @@ -490,9 +495,10 @@ object CaptureSet: if elem.isRootCapability then rootAddedHandler() newElemAddedHandler(elem) + val normElem = if isMaybeSet then elem else elem.stripMaybe // assert(id != 5 || elems.size != 3, this) val res = (CompareResult.OK /: deps): (r, dep) => - r.andAlso(dep.tryInclude(elem, this)) + r.andAlso(dep.tryInclude(normElem, this)) res.orElse: elems -= elem res.addToTrace(this) @@ -508,6 +514,8 @@ object CaptureSet: levelLimit.isContainedIn(elem.cls.levelOwner) case ReachCapability(elem1) => levelOK(elem1) + case MaybeCapability(elem1) => + levelOK(elem1) case _ => true @@ -701,24 +709,17 @@ object CaptureSet: if mapped.isConst then CompareResult.OK else if mapped.asVar.recordDepsState() then { addAsDependentTo(mapped); CompareResult.OK } else CompareResult.Fail(this :: Nil) - else if !isFixpoint then - // We did not yet observe the !isFixpoint condition in our tests, but it's a - // theoretical possibility. In that case, it would be inconsistent to both - // add `elem` to the set and back-propagate it. But if `{elem} <:< tm(elem)` - // and the variance of the set is positive, we can soundly add `tm(ref)` to - // the set while back-propagating `ref` as before. Otherwise there's nothing - // obvious left to do except fail (which is always sound). - if variance > 0 - && elem.singletonCaptureSet.subCaptures(mapped, frozen = true).isOK then - // widen to fixpoint. mapped is known to be a fixpoint since tm is idempotent. - // The widening is sound, but loses completeness. - addMapped - else - failNoFixpoint else if accountsFor(elem) then CompareResult.OK - else + else if variance > 0 then + // we can soundly add nothing to source and `x` to this set + addNewElem(elem) + else if isFixpoint then + // We can soundly add `x` to both this set and source since `f(x) = x` addNewElem(elem).andAlso(propagate) + else + // we are out of options; fail (which is always sound). + failNoFixpoint end tryInclude override def computeApprox(origin: CaptureSet)(using Context): CaptureSet = @@ -767,6 +768,7 @@ object CaptureSet: if source eq origin then supApprox.map(bimap.inverse) else source.upperApprox(this).map(bimap) ** supApprox + override def isMaybeSet: Boolean = bimap.isInstanceOf[MaybeMap] override def toString = s"BiMapped$id($source, elems = $elems)" end BiMapped @@ -847,8 +849,7 @@ object CaptureSet: upper.isAlwaysEmpty || upper.isConst && upper.elems.size == 1 && upper.elems.contains(r1) if variance > 0 || isExact then upper else if variance < 0 then CaptureSet.empty - else if ctx.mode.is(Mode.Printing) then upper - else assert(false, i"trying to add $upper from $r via ${tm.getClass} in a non-variant setting") + else upper.maybe /** Apply `f` to each element in `xs`, and join result sets with `++` */ def mapRefs(xs: Refs, f: CaptureRef => CaptureSet)(using Context): CaptureSet = @@ -987,6 +988,26 @@ object CaptureSet: /** The current VarState, as passed by the implicit context */ def varState(using state: VarState): VarState = state + /** Maps `x` to `x?` */ + private class MaybeMap(using Context) extends BiTypeMap: + + def apply(t: Type) = t match + case t: CaptureRef if t.isTrackableRef => t.maybe + case _ => mapOver(t) + + override def toString = "Maybe" + + lazy val inverse = new BiTypeMap: + + def apply(t: Type) = t match + case t: CaptureRef if t.isMaybe => t.stripMaybe + case t => mapOver(t) + + def inverse = MaybeMap.this + + override def toString = "Maybe.inverse" + end MaybeMap + /* Not needed: def ofClass(cinfo: ClassInfo, argTypes: List[Type])(using Context): CaptureSet = CaptureSet.empty diff --git a/compiler/src/dotty/tools/dotc/cc/CapturingType.scala b/compiler/src/dotty/tools/dotc/cc/CapturingType.scala index 2a5cb91b45d3..ee0cad4d4d03 100644 --- a/compiler/src/dotty/tools/dotc/cc/CapturingType.scala +++ b/compiler/src/dotty/tools/dotc/cc/CapturingType.scala @@ -58,8 +58,7 @@ object CapturingType: case AnnotatedType(parent, ann: CaptureAnnotation) if isCaptureCheckingOrSetup => Some((parent, ann.refs)) - case AnnotatedType(parent, ann) - if ann.symbol == defn.RetainsAnnot && isCaptureChecking => + case AnnotatedType(parent, ann) if ann.symbol.isRetains && isCaptureChecking => // There are some circumstances where we cannot map annotated types // with retains annotations to capturing types, so this second recognizer // path still has to exist. One example is when checking capture sets diff --git a/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala b/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala index d635096b2318..4564bed6db01 100644 --- a/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala +++ b/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala @@ -68,12 +68,6 @@ object CheckCaptures: */ final class SubstParamsMap(from: BindingType, to: List[Type])(using Context) extends ApproximatingTypeMap, IdempotentCaptRefMap: - /** This SubstParamsMap is exact if `to` only contains `CaptureRef`s. */ - private val isExactSubstitution: Boolean = to.forall(_.isTrackableRef) - - /** As long as this substitution is exact, there is no need to create `Range`s when mapping invariant positions. */ - override protected def needsRangeIfInvariant(refs: CaptureSet): Boolean = !isExactSubstitution - def apply(tp: Type): Type = tp match case tp: ParamRef => @@ -672,17 +666,13 @@ class CheckCaptures extends Recheck, SymTransformer: def checkInferredResult(tp: Type, tree: ValOrDefDef)(using Context): Type = val sym = tree.symbol - def isLocal = - sym.owner.ownersIterator.exists(_.isTerm) - || sym.accessBoundary(defn.RootClass).isContainedIn(sym.topLevelClass) - def canUseInferred = // If canUseInferred is false, all capturing types in the type of `sym` need to be given explicitly sym.is(Private) // private symbols can always have inferred types || sym.name.is(DefaultGetterName) // default getters are exempted since otherwise it would be // too annoying. This is a hole since a defualt getter's result type // might leak into a type variable. || // non-local symbols cannot have inferred types since external capture types are not inferred - isLocal // local symbols still need explicit types if + sym.isLocalToCompilationUnit // local symbols still need explicit types if && !sym.owner.is(Trait) // they are defined in a trait, since we do OverridingPairs checking before capture inference def addenda(expected: Type) = new Addenda: @@ -847,9 +837,13 @@ class CheckCaptures extends Recheck, SymTransformer: * where local capture roots are instantiated to root variables. */ override def checkConformsExpr(actual: Type, expected: Type, tree: Tree, addenda: Addenda)(using Context): Type = - val expected1 = alignDependentFunction(addOuterRefs(expected, actual), actual.stripCapturing) + var expected1 = alignDependentFunction(expected, actual.stripCapturing) val actualBoxed = adaptBoxed(actual, expected1, tree.srcPos) //println(i"check conforms $actualBoxed <<< $expected1") + + if actualBoxed eq actual then + // Only `addOuterRefs` when there is no box adaptation + expected1 = addOuterRefs(expected1, actual) if isCompatible(actualBoxed, expected1) then if debugSuccesses then tree match case Ident(_) => @@ -1178,7 +1172,7 @@ class CheckCaptures extends Recheck, SymTransformer: /** Check that self types of subclasses conform to self types of super classes. * (See comment below how this is achieved). The check assumes that classes * without an explicit self type have the universal capture set `{cap}` on the - * self type. If a class without explicit self type is not `effectivelyFinal` + * self type. If a class without explicit self type is not `effectivelySealed` * it is checked that the inferred self type is universal, in order to assure * that joint and separate compilation give the same result. */ @@ -1208,23 +1202,20 @@ class CheckCaptures extends Recheck, SymTransformer: checkSelfAgainstParents(root, root.baseClasses) val selfType = root.asClass.classInfo.selfType interpolator(startingVariance = -1).traverse(selfType) - if !root.isEffectivelySealed then - def matchesExplicitRefsInBaseClass(refs: CaptureSet, cls: ClassSymbol): Boolean = - cls.baseClasses.tail.exists { psym => - val selfType = psym.asClass.givenSelfType - selfType.exists && selfType.captureSet.elems == refs.elems - } - selfType match - case CapturingType(_, refs: CaptureSet.Var) - if !refs.elems.exists(_.isRootCapability) && !matchesExplicitRefsInBaseClass(refs, root) => - // Forbid inferred self types unless they are already implied by an explicit - // self type in a parent. - report.error( - em"""$root needs an explicitly declared self type since its - |inferred self type $selfType - |is not visible in other compilation units that define subclasses.""", - root.srcPos) - case _ => + selfType match + case CapturingType(_, refs: CaptureSet.Var) + if !root.isEffectivelySealed + && !refs.elems.exists(_.isRootCapability) + && !root.matchesExplicitRefsInBaseClass(refs) + => + // Forbid inferred self types unless they are already implied by an explicit + // self type in a parent. + report.error( + em"""$root needs an explicitly declared self type since its + |inferred self type $selfType + |is not visible in other compilation units that define subclasses.""", + root.srcPos) + case _ => parentTrees -= root capt.println(i"checked $root with $selfType") end checkSelfTypes diff --git a/compiler/src/dotty/tools/dotc/cc/RetainingType.scala b/compiler/src/dotty/tools/dotc/cc/RetainingType.scala index 7902b03445fb..efd0e96fd658 100644 --- a/compiler/src/dotty/tools/dotc/cc/RetainingType.scala +++ b/compiler/src/dotty/tools/dotc/cc/RetainingType.scala @@ -23,7 +23,7 @@ object RetainingType: def unapply(tp: AnnotatedType)(using Context): Option[(Type, List[Tree])] = val sym = tp.annot.symbol - if sym == defn.RetainsAnnot || sym == defn.RetainsByNameAnnot then + if sym.isRetainsLike then tp.annot match case _: CaptureAnnotation => assert(ctx.mode.is(Mode.IgnoreCaptures), s"bad retains $tp at ${ctx.phase}") diff --git a/compiler/src/dotty/tools/dotc/cc/Setup.scala b/compiler/src/dotty/tools/dotc/cc/Setup.scala index 74e67bda5fab..9ab41859f170 100644 --- a/compiler/src/dotty/tools/dotc/cc/Setup.scala +++ b/compiler/src/dotty/tools/dotc/cc/Setup.scala @@ -120,7 +120,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI: case tp @ CapturingType(parent, refs) => if tp.isBoxed then tp else tp.boxed case tp @ AnnotatedType(parent, ann) => - if ann.symbol == defn.RetainsAnnot + if ann.symbol.isRetains then CapturingType(parent, ann.tree.toCaptureSet, boxed = true) else tp.derivedAnnotatedType(box(parent), ann) case tp1 @ AppliedType(tycon, args) if defn.isNonRefinedFunction(tp1) => @@ -192,7 +192,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI: def apply(tp: Type) = val tp1 = tp match - case AnnotatedType(parent, annot) if annot.symbol == defn.RetainsAnnot => + case AnnotatedType(parent, annot) if annot.symbol.isRetains => // Drop explicit retains annotations apply(parent) case tp @ AppliedType(tycon, args) => @@ -283,7 +283,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI: t.derivedCapturingType(this(parent), refs) case t @ AnnotatedType(parent, ann) => val parent1 = this(parent) - if ann.symbol == defn.RetainsAnnot then + if ann.symbol.isRetains then for tpt <- tptToCheck do checkWellformedLater(parent1, ann.tree, tpt) CapturingType(parent1, ann.tree.toCaptureSet) @@ -416,7 +416,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI: case tree @ SeqLiteral(elems, tpt: TypeTree) => traverse(elems) - transformTT(tpt, boxed = true, exact = false) + tpt.rememberType(box(transformInferredType(tpt.tpe))) case _ => traverseChildren(tree) @@ -517,21 +517,34 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI: tree.symbol match case cls: ClassSymbol => val cinfo @ ClassInfo(prefix, _, ps, decls, selfInfo) = cls.classInfo - if ((selfInfo eq NoType) || cls.is(ModuleClass) && !cls.isStatic) - && !cls.isPureClass - then - // add capture set to self type of nested classes if no self type is given explicitly. - val newSelfType = CapturingType(cinfo.selfType, CaptureSet.Var(cls)) - val ps1 = inContext(ctx.withOwner(cls)): - ps.mapConserve(transformExplicitType(_)) - val newInfo = ClassInfo(prefix, cls, ps1, decls, newSelfType) + def innerModule = cls.is(ModuleClass) && !cls.isStatic + val selfInfo1 = + if (selfInfo ne NoType) && !innerModule then + // if selfInfo is explicitly given then use that one, except if + // self info applies to non-static modules, these still need to be inferred + selfInfo + else if cls.isPureClass then + // is cls is known to be pure, nothing needs to be added to self type + selfInfo + else if !cls.isEffectivelySealed && !cls.baseClassHasExplicitSelfType then + // assume {cap} for completely unconstrained self types of publicly extensible classes + CapturingType(cinfo.selfType, CaptureSet.universal) + else + // Infer the self type for the rest, which is all classes without explicit + // self types (to which we also add nested module classes), provided they are + // neither pure, nor are publicily extensible with an unconstrained self type. + CapturingType(cinfo.selfType, CaptureSet.Var(cls)) + val ps1 = inContext(ctx.withOwner(cls)): + ps.mapConserve(transformExplicitType(_)) + if (selfInfo1 ne selfInfo) || (ps1 ne ps) then + val newInfo = ClassInfo(prefix, cls, ps1, decls, selfInfo1) updateInfo(cls, newInfo) capt.println(i"update class info of $cls with parents $ps selfinfo $selfInfo to $newInfo") cls.thisType.asInstanceOf[ThisType].invalidateCaches() if cls.is(ModuleClass) then // if it's a module, the capture set of the module reference is the capture set of the self type val modul = cls.sourceModule - updateInfo(modul, CapturingType(modul.info, newSelfType.captureSet)) + updateInfo(modul, CapturingType(modul.info, selfInfo1.asInstanceOf[Type].captureSet)) modul.termRef.invalidateCaches() case _ => case _ => diff --git a/compiler/src/dotty/tools/dotc/classpath/AggregateClassPath.scala b/compiler/src/dotty/tools/dotc/classpath/AggregateClassPath.scala index 5fbe7212a674..4c5b632bf6ab 100644 --- a/compiler/src/dotty/tools/dotc/classpath/AggregateClassPath.scala +++ b/compiler/src/dotty/tools/dotc/classpath/AggregateClassPath.scala @@ -39,14 +39,14 @@ case class AggregateClassPath(aggregates: Seq[ClassPath]) extends ClassPath { def findEntry(isSource: Boolean): Option[ClassRepresentation] = aggregatesForPackage(PackageName(pkg)).iterator.map(_.findClass(className)).collectFirst { case Some(s: SourceFileEntry) if isSource => s - case Some(s: ClassFileEntry) if !isSource => s + case Some(s: BinaryFileEntry) if !isSource => s } val classEntry = findEntry(isSource = false) val sourceEntry = findEntry(isSource = true) (classEntry, sourceEntry) match { - case (Some(c: ClassFileEntry), Some(s: SourceFileEntry)) => Some(ClassAndSourceFilesEntry(c.file, s.file)) + case (Some(c: BinaryFileEntry), Some(s: SourceFileEntry)) => Some(BinaryAndSourceFilesEntry(c, s)) case (c @ Some(_), _) => c case (_, s) => s } @@ -63,7 +63,7 @@ case class AggregateClassPath(aggregates: Seq[ClassPath]) extends ClassPath { aggregatedPackages } - override private[dotty] def classes(inPackage: PackageName): Seq[ClassFileEntry] = + override private[dotty] def classes(inPackage: PackageName): Seq[BinaryFileEntry] = getDistinctEntries(_.classes(inPackage)) override private[dotty] def sources(inPackage: PackageName): Seq[SourceFileEntry] = @@ -102,10 +102,15 @@ case class AggregateClassPath(aggregates: Seq[ClassPath]) extends ClassPath { ClassPathEntries(distinctPackages, distinctClassesAndSources) } - /** - * Returns only one entry for each name. If there's both a source and a class entry, it - * creates an entry containing both of them. If there would be more than one class or source - * entries for the same class it always would use the first entry of each type found on a classpath. + /** Returns only one entry for each name. + * + * If there's both a source and a class entry, it + * creates an entry containing both of them. If there would be more than one class or source + * entries for the same class it always would use the first entry of each type found on a classpath. + * + * A TASTy file with no class file entry will be chosen over a class file entry. This can happen if we load + * the Scala 2 library as it has one JAR containing the class files and one JAR containing the TASTy files. + * As classpath orders are not guaranteed to be deterministic we might end up having the TASTy in a later classpath entry. */ private def mergeClassesAndSources(entries: scala.collection.Seq[ClassRepresentation]): Seq[ClassRepresentation] = { // based on the implementation from MergedClassPath @@ -119,11 +124,18 @@ case class AggregateClassPath(aggregates: Seq[ClassPath]) extends ClassPath { if (indices.contains(name)) { val index = indices(name) val existing = mergedEntries(index) - - if (existing.binary.isEmpty && entry.binary.isDefined) - mergedEntries(index) = ClassAndSourceFilesEntry(entry.binary.get, existing.source.get) - if (existing.source.isEmpty && entry.source.isDefined) - mergedEntries(index) = ClassAndSourceFilesEntry(existing.binary.get, entry.source.get) + (entry, existing) match + case (entry: SourceFileEntry, existing: BinaryFileEntry) => + mergedEntries(index) = BinaryAndSourceFilesEntry(existing, entry) + case (entry: BinaryFileEntry, existing: SourceFileEntry) => + mergedEntries(index) = BinaryAndSourceFilesEntry(entry, existing) + case (entry: StandaloneTastyFileEntry, _: ClassFileEntry) => + // Here we do not create a TastyWithClassFileEntry because the TASTy and the classfile + // come from different classpaths. These may not have the same TASTy UUID. + mergedEntries(index) = entry + case (entry: StandaloneTastyFileEntry, BinaryAndSourceFilesEntry(_: ClassFileEntry, sourceEntry)) => + mergedEntries(index) = BinaryAndSourceFilesEntry(entry, sourceEntry) + case _ => } else { indices(name) = count diff --git a/compiler/src/dotty/tools/dotc/classpath/ClassPath.scala b/compiler/src/dotty/tools/dotc/classpath/ClassPath.scala index 176b6acf9c6c..3210c6221a78 100644 --- a/compiler/src/dotty/tools/dotc/classpath/ClassPath.scala +++ b/compiler/src/dotty/tools/dotc/classpath/ClassPath.scala @@ -3,6 +3,7 @@ */ package dotty.tools.dotc.classpath +import dotty.tools.dotc.classpath.FileUtils.isTasty import dotty.tools.io.AbstractFile import dotty.tools.io.ClassRepresentation @@ -14,14 +15,6 @@ object ClassPathEntries { val empty = ClassPathEntries(Seq.empty, Seq.empty) } -trait ClassFileEntry extends ClassRepresentation { - def file: AbstractFile -} - -trait SourceFileEntry extends ClassRepresentation { - def file: AbstractFile -} - case class PackageName(dottedString: String) { val dirPathTrailingSlashJar: String = FileUtils.dirPathInJar(dottedString) + "/" @@ -48,28 +41,50 @@ trait PackageEntry { def name: String } -private[dotty] case class ClassFileEntryImpl(file: AbstractFile) extends ClassFileEntry { +/** A TASTy file or classfile */ +sealed trait BinaryFileEntry extends ClassRepresentation { + def file: AbstractFile final def fileName: String = file.name - def name: String = FileUtils.stripClassExtension(file.name) // class name + final def name: String = FileUtils.stripClassExtension(file.name) // class name + final def source: Option[AbstractFile] = None +} +object BinaryFileEntry { + def apply(file: AbstractFile): BinaryFileEntry = + if file.isTasty then + if file.resolveSiblingWithExtension("class") != null then TastyWithClassFileEntry(file) + else StandaloneTastyFileEntry(file) + else + ClassFileEntry(file) +} + +/** A classfile or .sig that does not have an associated TASTy file */ +private[dotty] final case class ClassFileEntry(file: AbstractFile) extends BinaryFileEntry { def binary: Option[AbstractFile] = Some(file) - def source: Option[AbstractFile] = None } -private[dotty] case class SourceFileEntryImpl(file: AbstractFile) extends SourceFileEntry { +/** A TASTy file that has an associated class file */ +private[dotty] final case class TastyWithClassFileEntry(file: AbstractFile) extends BinaryFileEntry { + def binary: Option[AbstractFile] = Some(file) +} + +/** A TASTy file that does not have an associated class file */ +private[dotty] final case class StandaloneTastyFileEntry(file: AbstractFile) extends BinaryFileEntry { + def binary: Option[AbstractFile] = Some(file) +} + +private[dotty] final case class SourceFileEntry(file: AbstractFile) extends ClassRepresentation { final def fileName: String = file.name def name: String = FileUtils.stripSourceExtension(file.name) - def binary: Option[AbstractFile] = None def source: Option[AbstractFile] = Some(file) } -private[dotty] case class ClassAndSourceFilesEntry(classFile: AbstractFile, srcFile: AbstractFile) extends ClassRepresentation { - final def fileName: String = classFile.name - def name: String = FileUtils.stripClassExtension(classFile.name) - - def binary: Option[AbstractFile] = Some(classFile) - def source: Option[AbstractFile] = Some(srcFile) +private[dotty] final case class BinaryAndSourceFilesEntry(binaryEntry: BinaryFileEntry, sourceEntry: SourceFileEntry) extends ClassRepresentation { + final def fileName: String = binaryEntry.fileName + def name: String = binaryEntry.name + def binary: Option[AbstractFile] = binaryEntry.binary + def source: Option[AbstractFile] = sourceEntry.source } private[dotty] case class PackageEntryImpl(name: String) extends PackageEntry @@ -81,5 +96,5 @@ private[dotty] trait NoSourcePaths { private[dotty] trait NoClassPaths { def findClassFile(className: String): Option[AbstractFile] = None - private[dotty] def classes(inPackage: PackageName): Seq[ClassFileEntry] = Seq.empty + private[dotty] def classes(inPackage: PackageName): Seq[BinaryFileEntry] = Seq.empty } diff --git a/compiler/src/dotty/tools/dotc/classpath/DirectoryClassPath.scala b/compiler/src/dotty/tools/dotc/classpath/DirectoryClassPath.scala index 26ed2734890e..c5b267bc774d 100644 --- a/compiler/src/dotty/tools/dotc/classpath/DirectoryClassPath.scala +++ b/compiler/src/dotty/tools/dotc/classpath/DirectoryClassPath.scala @@ -183,12 +183,12 @@ final class JrtClassPath(fs: java.nio.file.FileSystem) extends ClassPath with No override private[dotty] def packages(inPackage: PackageName): Seq[PackageEntry] = packageToModuleBases.keysIterator.filter(pack => packageContains(inPackage.dottedString, pack)).map(PackageEntryImpl(_)).toVector - private[dotty] def classes(inPackage: PackageName): Seq[ClassFileEntry] = + private[dotty] def classes(inPackage: PackageName): Seq[BinaryFileEntry] = if (inPackage.isRoot) Nil else packageToModuleBases.getOrElse(inPackage.dottedString, Nil).flatMap(x => Files.list(x.resolve(inPackage.dirPathTrailingSlash)).iterator().asScala.filter(_.getFileName.toString.endsWith(".class"))).map(x => - ClassFileEntryImpl(x.toPlainFile)).toVector + ClassFileEntry(x.toPlainFile)).toVector override private[dotty] def list(inPackage: PackageName): ClassPathEntries = if (inPackage.isRoot) ClassPathEntries(packages(inPackage), Nil) @@ -246,12 +246,12 @@ final class CtSymClassPath(ctSym: java.nio.file.Path, release: Int) extends Clas override private[dotty] def packages(inPackage: PackageName): Seq[PackageEntry] = { packageIndex.keysIterator.filter(pack => packageContains(inPackage.dottedString, pack)).map(PackageEntryImpl(_)).toVector } - private[dotty] def classes(inPackage: PackageName): Seq[ClassFileEntry] = { + private[dotty] def classes(inPackage: PackageName): Seq[BinaryFileEntry] = { if (inPackage.isRoot) Nil else { val sigFiles = packageIndex.getOrElse(inPackage.dottedString, Nil).iterator.flatMap(p => Files.list(p).iterator.asScala.filter(_.getFileName.toString.endsWith(".sig"))) - sigFiles.map(f => ClassFileEntryImpl(f.toPlainFile)).toVector + sigFiles.map(f => ClassFileEntry(f.toPlainFile)).toVector } } @@ -273,8 +273,9 @@ final class CtSymClassPath(ctSym: java.nio.file.Path, release: Int) extends Clas } } -case class DirectoryClassPath(dir: JFile) extends JFileDirectoryLookup[ClassFileEntryImpl] with NoSourcePaths { - override def findClass(className: String): Option[ClassRepresentation] = findClassFile(className) map ClassFileEntryImpl.apply +case class DirectoryClassPath(dir: JFile) extends JFileDirectoryLookup[BinaryFileEntry] with NoSourcePaths { + override def findClass(className: String): Option[ClassRepresentation] = + findClassFile(className).map(BinaryFileEntry(_)) def findClassFile(className: String): Option[AbstractFile] = { val relativePath = FileUtils.dirPath(className) @@ -282,24 +283,25 @@ case class DirectoryClassPath(dir: JFile) extends JFileDirectoryLookup[ClassFile if tastyFile.exists then Some(tastyFile.toPath.toPlainFile) else val classFile = new JFile(dir, relativePath + ".class") - if classFile.exists then Some(classFile.toPath.toPlainFile) + if classFile.exists then Some(classFile.toPath.toPlainFile) else None } - protected def createFileEntry(file: AbstractFile): ClassFileEntryImpl = ClassFileEntryImpl(file) + protected def createFileEntry(file: AbstractFile): BinaryFileEntry = BinaryFileEntry(file) + protected def isMatchingFile(f: JFile): Boolean = f.isTasty || (f.isClass && f.classToTasty.isEmpty) - private[dotty] def classes(inPackage: PackageName): Seq[ClassFileEntry] = files(inPackage) + private[dotty] def classes(inPackage: PackageName): Seq[BinaryFileEntry] = files(inPackage) } -case class DirectorySourcePath(dir: JFile) extends JFileDirectoryLookup[SourceFileEntryImpl] with NoClassPaths { +case class DirectorySourcePath(dir: JFile) extends JFileDirectoryLookup[SourceFileEntry] with NoClassPaths { def asSourcePathString: String = asClassPathString - protected def createFileEntry(file: AbstractFile): SourceFileEntryImpl = SourceFileEntryImpl(file) + protected def createFileEntry(file: AbstractFile): SourceFileEntry = SourceFileEntry(file) protected def isMatchingFile(f: JFile): Boolean = endsScalaOrJava(f.getName) - override def findClass(className: String): Option[ClassRepresentation] = findSourceFile(className) map SourceFileEntryImpl.apply + override def findClass(className: String): Option[ClassRepresentation] = findSourceFile(className).map(SourceFileEntry(_)) private def findSourceFile(className: String): Option[AbstractFile] = { val relativePath = FileUtils.dirPath(className) diff --git a/compiler/src/dotty/tools/dotc/classpath/VirtualDirectoryClassPath.scala b/compiler/src/dotty/tools/dotc/classpath/VirtualDirectoryClassPath.scala index f520cd97767e..93583c85fff7 100644 --- a/compiler/src/dotty/tools/dotc/classpath/VirtualDirectoryClassPath.scala +++ b/compiler/src/dotty/tools/dotc/classpath/VirtualDirectoryClassPath.scala @@ -7,7 +7,7 @@ import dotty.tools.io.{AbstractFile, VirtualDirectory} import FileUtils.* import java.net.{URI, URL} -case class VirtualDirectoryClassPath(dir: VirtualDirectory) extends ClassPath with DirectoryLookup[ClassFileEntryImpl] with NoSourcePaths { +case class VirtualDirectoryClassPath(dir: VirtualDirectory) extends ClassPath with DirectoryLookup[BinaryFileEntry] with NoSourcePaths { type F = AbstractFile // From AbstractFileClassLoader @@ -38,7 +38,8 @@ case class VirtualDirectoryClassPath(dir: VirtualDirectory) extends ClassPath wi def asURLs: Seq[URL] = Seq(new URI(dir.name).toURL) def asClassPathStrings: Seq[String] = Seq(dir.path) - override def findClass(className: String): Option[ClassRepresentation] = findClassFile(className) map ClassFileEntryImpl.apply + override def findClass(className: String): Option[ClassRepresentation] = + findClassFile(className).map(BinaryFileEntry(_)) def findClassFile(className: String): Option[AbstractFile] = { val pathSeq = FileUtils.dirPath(className).split(java.io.File.separator) @@ -49,9 +50,10 @@ case class VirtualDirectoryClassPath(dir: VirtualDirectory) extends ClassPath wi .orElse(Option(lookupPath(parentDir)(pathSeq.last + ".class" :: Nil, directory = false))) } - private[dotty] def classes(inPackage: PackageName): Seq[ClassFileEntry] = files(inPackage) + private[dotty] def classes(inPackage: PackageName): Seq[BinaryFileEntry] = files(inPackage) + + protected def createFileEntry(file: AbstractFile): BinaryFileEntry = BinaryFileEntry(file) - protected def createFileEntry(file: AbstractFile): ClassFileEntryImpl = ClassFileEntryImpl(file) protected def isMatchingFile(f: AbstractFile): Boolean = f.isTasty || (f.isClass && f.classToTasty.isEmpty) } diff --git a/compiler/src/dotty/tools/dotc/classpath/ZipAndJarFileLookupFactory.scala b/compiler/src/dotty/tools/dotc/classpath/ZipAndJarFileLookupFactory.scala index 0ca996db4812..dac156c5f647 100644 --- a/compiler/src/dotty/tools/dotc/classpath/ZipAndJarFileLookupFactory.scala +++ b/compiler/src/dotty/tools/dotc/classpath/ZipAndJarFileLookupFactory.scala @@ -41,22 +41,23 @@ sealed trait ZipAndJarFileLookupFactory { */ object ZipAndJarClassPathFactory extends ZipAndJarFileLookupFactory { private case class ZipArchiveClassPath(zipFile: File, override val release: Option[String]) - extends ZipArchiveFileLookup[ClassFileEntryImpl] + extends ZipArchiveFileLookup[BinaryFileEntry] with NoSourcePaths { override def findClassFile(className: String): Option[AbstractFile] = findClass(className).map(_.file) // This method is performance sensitive as it is used by SBT's ExtractDependencies phase. - override def findClass(className: String): Option[ClassFileEntryImpl] = { + override def findClass(className: String): Option[BinaryFileEntry] = { val (pkg, simpleClassName) = PackageNameUtils.separatePkgAndClassNames(className) val binaries = files(PackageName(pkg), simpleClassName + ".tasty", simpleClassName + ".class") binaries.find(_.file.isTasty).orElse(binaries.find(_.file.isClass)) } - override private[dotty] def classes(inPackage: PackageName): Seq[ClassFileEntry] = files(inPackage) + override private[dotty] def classes(inPackage: PackageName): Seq[BinaryFileEntry] = files(inPackage) + + override protected def createFileEntry(file: FileZipArchive#Entry): BinaryFileEntry = BinaryFileEntry(file) - override protected def createFileEntry(file: FileZipArchive#Entry): ClassFileEntryImpl = ClassFileEntryImpl(file) override protected def isRequiredFileType(file: AbstractFile): Boolean = file.isTasty || (file.isClass && file.classToTasty.isEmpty) } @@ -128,10 +129,10 @@ object ZipAndJarClassPathFactory extends ZipAndJarFileLookupFactory { subpackages.map(packageFile => PackageEntryImpl(inPackage.entryName(packageFile.name))) } - override private[dotty] def classes(inPackage: PackageName): Seq[ClassFileEntry] = cachedPackages.get(inPackage.dottedString) match { + override private[dotty] def classes(inPackage: PackageName): Seq[BinaryFileEntry] = cachedPackages.get(inPackage.dottedString) match { case None => Seq.empty case Some(PackageFileInfo(pkg, _)) => - (for (file <- pkg if file.isClass) yield ClassFileEntryImpl(file)).toSeq + (for (file <- pkg if file.isClass) yield ClassFileEntry(file)).toSeq } override private[dotty] def hasPackage(pkg: PackageName) = cachedPackages.contains(pkg.dottedString) @@ -162,7 +163,7 @@ object ZipAndJarClassPathFactory extends ZipAndJarFileLookupFactory { */ object ZipAndJarSourcePathFactory extends ZipAndJarFileLookupFactory { private case class ZipArchiveSourcePath(zipFile: File) - extends ZipArchiveFileLookup[SourceFileEntryImpl] + extends ZipArchiveFileLookup[SourceFileEntry] with NoClassPaths { def release: Option[String] = None @@ -171,7 +172,7 @@ object ZipAndJarSourcePathFactory extends ZipAndJarFileLookupFactory { override private[dotty] def sources(inPackage: PackageName): Seq[SourceFileEntry] = files(inPackage) - override protected def createFileEntry(file: FileZipArchive#Entry): SourceFileEntryImpl = SourceFileEntryImpl(file) + override protected def createFileEntry(file: FileZipArchive#Entry): SourceFileEntry = SourceFileEntry(file) override protected def isRequiredFileType(file: AbstractFile): Boolean = file.isScalaOrJavaSource } diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index d1b91f77f933..85e6ebef751f 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -120,6 +120,7 @@ trait CommonScalaSettings: // -explain-types setting is necessary for cross compilation, since it is mentioned in sbt-tpolecat, for instance // it is otherwise subsumed by -explain, and should be dropped as soon as we can. val explainTypes: Setting[Boolean] = BooleanSetting("-explain-types", "Explain type errors in more detail (deprecated, use -explain instead).", aliases = List("--explain-types", "-explaintypes")) + val explainCyclic: Setting[Boolean] = BooleanSetting("-explain-cyclic", "Explain cyclic reference errors in more detail.", aliases = List("--explain-cyclic")) val unchecked: Setting[Boolean] = BooleanSetting("-unchecked", "Enable additional warnings where generated code depends on assumptions.", initialValue = true, aliases = List("--unchecked")) val language: Setting[List[String]] = MultiStringSetting("-language", "feature", "Enable one or more language features.", aliases = List("--language")) val experimental: Setting[Boolean] = BooleanSetting("-experimental", "Annotate all top-level definitions with @experimental. This enables the use of experimental features anywhere in the project.") @@ -351,6 +352,7 @@ private sealed trait YSettings: val YdebugTypeError: Setting[Boolean] = BooleanSetting("-Ydebug-type-error", "Print the stack trace when a TypeError is caught", false) val YdebugError: Setting[Boolean] = BooleanSetting("-Ydebug-error", "Print the stack trace when any error is caught.", false) val YdebugUnpickling: Setting[Boolean] = BooleanSetting("-Ydebug-unpickling", "Print the stack trace when an error occurs when reading Tasty.", false) + val YdebugCyclic: Setting[Boolean] = BooleanSetting("-Ydebug-cyclic", "Print the stack trace when a cyclic reference error occurs.", false) val YtermConflict: Setting[String] = ChoiceSetting("-Yresolve-term-conflict", "strategy", "Resolve term conflicts", List("package", "object", "error"), "error") val Ylog: Setting[List[String]] = PhasesSetting("-Ylog", "Log operations during") val YlogClasspath: Setting[Boolean] = BooleanSetting("-Ylog-classpath", "Output information about what classpath is being applied.") diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala index 6be6ec94c1c3..da94226b34af 100644 --- a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala +++ b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala @@ -858,7 +858,8 @@ trait ConstraintHandling { addParamBound(bound) case _ => val pbound = avoidLambdaParams(bound) - kindCompatible(param, pbound) && addBoundTransitively(param, pbound, !fromBelow) + (pbound.isNothingType || kindCompatible(param, pbound)) + && addBoundTransitively(param, pbound, !fromBelow) finally canWidenAbstract = saved addConstraintInvocations -= 1 diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index ee288a08b53f..c5f04d18b7fb 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -95,7 +95,7 @@ object Contexts { inline def atPhaseNoEarlier[T](limit: Phase)(inline op: Context ?=> T)(using Context): T = op(using if !limit.exists || limit <= ctx.phase then ctx else ctx.withPhase(limit)) - inline def inMode[T](mode: Mode)(inline op: Context ?=> T)(using ctx: Context): T = + inline private def inMode[T](mode: Mode)(inline op: Context ?=> T)(using ctx: Context): T = op(using if mode != ctx.mode then ctx.fresh.setMode(mode) else ctx) inline def withMode[T](mode: Mode)(inline op: Context ?=> T)(using ctx: Context): T = diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index e08672c693b9..3cde29ee3d79 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -535,6 +535,10 @@ class Definitions { List(AnyType), EmptyScope) @tu lazy val SingletonType: TypeRef = SingletonClass.typeRef + @tu lazy val MaybeCapabilityAnnot: ClassSymbol = + completeClass(enterCompleteClassSymbol( + ScalaPackageClass, tpnme.maybeCapability, Final, List(StaticAnnotationClass.typeRef))) + @tu lazy val CollectionSeqType: TypeRef = requiredClassRef("scala.collection.Seq") @tu lazy val SeqType: TypeRef = requiredClassRef("scala.collection.immutable.Seq") @tu lazy val SeqModule: Symbol = requiredModule("scala.collection.immutable.Seq") @@ -1010,11 +1014,11 @@ class Definitions { @tu lazy val ProvisionalSuperClassAnnot: ClassSymbol = requiredClass("scala.annotation.internal.ProvisionalSuperClass") @tu lazy val DeprecatedAnnot: ClassSymbol = requiredClass("scala.deprecated") @tu lazy val DeprecatedOverridingAnnot: ClassSymbol = requiredClass("scala.deprecatedOverriding") + @tu lazy val DeprecatedInheritanceAnnot: ClassSymbol = requiredClass("scala.deprecatedInheritance") @tu lazy val ImplicitAmbiguousAnnot: ClassSymbol = requiredClass("scala.annotation.implicitAmbiguous") @tu lazy val ImplicitNotFoundAnnot: ClassSymbol = requiredClass("scala.annotation.implicitNotFound") @tu lazy val InlineParamAnnot: ClassSymbol = requiredClass("scala.annotation.internal.InlineParam") @tu lazy val ErasedParamAnnot: ClassSymbol = requiredClass("scala.annotation.internal.ErasedParam") - @tu lazy val InvariantBetweenAnnot: ClassSymbol = requiredClass("scala.annotation.internal.InvariantBetween") @tu lazy val MainAnnot: ClassSymbol = requiredClass("scala.main") @tu lazy val MappedAlternativeAnnot: ClassSymbol = requiredClass("scala.annotation.internal.MappedAlternative") @tu lazy val MigrationAnnot: ClassSymbol = requiredClass("scala.annotation.migration") @@ -1026,7 +1030,7 @@ class Definitions { @tu lazy val SourceFileAnnot: ClassSymbol = requiredClass("scala.annotation.internal.SourceFile") @tu lazy val ScalaSignatureAnnot: ClassSymbol = requiredClass("scala.reflect.ScalaSignature") @tu lazy val ScalaLongSignatureAnnot: ClassSymbol = requiredClass("scala.reflect.ScalaLongSignature") - @tu lazy val ScalaStrictFPAnnot: ClassSymbol = requiredClass("scala.annotation.strictfp") + // @tu lazy val ScalaStrictFPAnnot: ClassSymbol = requiredClass("scala.annotation.strictfp") @tu lazy val ScalaStaticAnnot: ClassSymbol = requiredClass("scala.annotation.static") @tu lazy val SerialVersionUIDAnnot: ClassSymbol = requiredClass("scala.SerialVersionUID") @tu lazy val TailrecAnnot: ClassSymbol = requiredClass("scala.annotation.tailrec") @@ -1054,10 +1058,10 @@ class Definitions { @tu lazy val FunctionalInterfaceAnnot: ClassSymbol = requiredClass("java.lang.FunctionalInterface") @tu lazy val TargetNameAnnot: ClassSymbol = requiredClass("scala.annotation.targetName") @tu lazy val VarargsAnnot: ClassSymbol = requiredClass("scala.annotation.varargs") - @tu lazy val SinceAnnot: ClassSymbol = requiredClass("scala.annotation.since") @tu lazy val ReachCapabilityAnnot = requiredClass("scala.annotation.internal.reachCapability") @tu lazy val RequiresCapabilityAnnot: ClassSymbol = requiredClass("scala.annotation.internal.requiresCapability") @tu lazy val RetainsAnnot: ClassSymbol = requiredClass("scala.annotation.retains") + @tu lazy val RetainsCapAnnot: ClassSymbol = requiredClass("scala.annotation.retainsCap") @tu lazy val RetainsByNameAnnot: ClassSymbol = requiredClass("scala.annotation.retainsByName") @tu lazy val PublicInBinaryAnnot: ClassSymbol = requiredClass("scala.annotation.publicInBinary") @@ -1172,19 +1176,18 @@ class Definitions { } } - object RefinedFunctionOf { + object RefinedFunctionOf: + /** Matches a refined `PolyFunction`/`FunctionN[...]`/`ContextFunctionN[...]`. * Extracts the method type type and apply info. */ - def unapply(tpe: RefinedType)(using Context): Option[MethodOrPoly] = { + def unapply(tpe: RefinedType)(using Context): Option[MethodOrPoly] = tpe.refinedInfo match case mt: MethodOrPoly - if tpe.refinedName == nme.apply - && (tpe.parent.derivesFrom(defn.PolyFunctionClass) || isFunctionNType(tpe.parent)) => - Some(mt) + if tpe.refinedName == nme.apply && isFunctionType(tpe.parent) => Some(mt) case _ => None - } - } + + end RefinedFunctionOf object PolyFunctionOf { @@ -2009,7 +2012,7 @@ class Definitions { @tu lazy val ccExperimental: Set[Symbol] = Set( CapsModule, CapsModule.moduleClass, PureClass, CapabilityAnnot, RequiresCapabilityAnnot, - RetainsAnnot, RetainsByNameAnnot) + RetainsAnnot, RetainsCapAnnot, RetainsByNameAnnot) // ----- primitive value class machinery ------------------------------------------ @@ -2138,7 +2141,8 @@ class Definitions { AnyValClass, NullClass, NothingClass, - SingletonClass) + SingletonClass, + MaybeCapabilityAnnot) @tu lazy val syntheticCoreClasses: List[Symbol] = syntheticScalaClasses ++ List( EmptyPackageVal, diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index 3608f16e3478..bd92fa814a6e 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -22,6 +22,7 @@ import config.Config import config.Printers.overload import util.common.* import typer.ProtoTypes.NoViewsAllowed +import reporting.Message import collection.mutable.ListBuffer import scala.compiletime.uninitialized @@ -954,7 +955,9 @@ object Denotations { } def staleSymbolError(using Context): Nothing = - throw new StaleSymbol(staleSymbolMsg) + if symbol.isPackageObject && ctx.run != null && ctx.run.nn.isCompilingSuspended + then throw StaleSymbolTypeError(symbol) + else throw StaleSymbolException(staleSymbolMsg) def staleSymbolMsg(using Context): String = { def ownerMsg = this match { @@ -1362,9 +1365,19 @@ object Denotations { else NoSymbol + trait StaleSymbol extends Exception + /** An exception for accessing symbols that are no longer valid in current run */ - class StaleSymbol(msg: => String) extends Exception { + class StaleSymbolException(msg: => String) extends Exception, StaleSymbol { util.Stats.record("stale symbol") override def getMessage(): String = msg } + + /** An exception that is at the same type a StaleSymbol and a TypeError. + * Sine it is a TypeError it can be reported as a nroaml error instead of crashing + * the compiler. + */ + class StaleSymbolTypeError(symbol: Symbol)(using Context) extends TypeError, StaleSymbol: + def toMessage(using Context) = + em"Cyclic macro dependency; macro refers to a toplevel symbol in ${symbol.source} from which the macro is called" } diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index 8c1b715e3e30..be43cbc8dfcf 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -242,7 +242,7 @@ object Flags { val (AccessorOrSealed @ _, Accessor @ _, Sealed @ _) = newFlags(11, "", "sealed") /** A mutable var, an open class */ - val (MutableOrOpen @ __, Mutable @ _, Open @ _) = newFlags(12, "mutable", "open") + val (MutableOrOpen @ _, Mutable @ _, Open @ _) = newFlags(12, "mutable", "open") /** Symbol is local to current class (i.e. private[this] or protected[this] * pre: Private or Protected are also set @@ -363,7 +363,7 @@ object Flags { val (Enum @ _, EnumVal @ _, _) = newFlags(40, "enum") /** An export forwarder */ - val (Exported @ _, _, _) = newFlags(41, "exported") + val (Exported @ _, ExportedTerm @ _, ExportedType @ _) = newFlags(41, "exported") /** Labeled with `erased` modifier (erased value or class) */ val (Erased @ _, _, _) = newFlags(42, "erased") @@ -532,8 +532,15 @@ object Flags { /** Flags that can apply to a module class */ val RetainedModuleClassFlags: FlagSet = RetainedModuleValAndClassFlags | Enum - /** Flags retained in export forwarders */ - val RetainedExportFlags = Given | Implicit | Inline | Transparent + /** Flags retained in term export forwarders */ + val RetainedExportTermFlags = Infix | Given | Implicit | Inline | Transparent | Erased | HasDefaultParams | NoDefaultParams | ExtensionMethod + + val MandatoryExportTermFlags = Exported | Method | Final + + /** Flags retained in type export forwarders */ + val RetainedExportTypeFlags = Infix + + val MandatoryExportTypeFlags = Exported | Final /** Flags that apply only to classes */ val ClassOnlyFlags = Sealed | Open | Abstract.toTypeFlags diff --git a/compiler/src/dotty/tools/dotc/core/Periods.scala b/compiler/src/dotty/tools/dotc/core/Periods.scala index 019c5932b3c9..60226eb59fe0 100644 --- a/compiler/src/dotty/tools/dotc/core/Periods.scala +++ b/compiler/src/dotty/tools/dotc/core/Periods.scala @@ -1,6 +1,10 @@ -package dotty.tools.dotc.core +package dotty.tools +package dotc +package core import Contexts.* +import printing.* +import Texts.* import Phases.unfusedPhases object Periods { @@ -35,7 +39,7 @@ object Periods { * * // Dmitry: sign == 0 isn't actually always true, in some cases phaseId == -1 is used for shifts, that easily creates code < 0 */ - class Period(val code: Int) extends AnyVal { + class Period(val code: Int) extends AnyVal with Showable { /** The run identifier of this period. */ def runId: RunId = code >>> (PhaseWidth * 2) @@ -97,7 +101,25 @@ object Periods { this.firstPhaseId min that.firstPhaseId, this.lastPhaseId max that.lastPhaseId) - override def toString: String = s"Period($firstPhaseId..$lastPhaseId, run = $runId)" + def toText(p: Printer): Text = + inContext(p.printerContext): + this match + case Nowhere => "Nowhere" + case InitialPeriod => "InitialPeriod" + case InvalidPeriod => "InvalidPeriod" + case Period(NoRunId, 0, PhaseMask) => s"Period(NoRunId.all)" + case Period(runId, 0, PhaseMask) => s"Period($runId.all)" + case Period(runId, p1, pn) if p1 == pn => s"Period($runId.$p1(${ctx.base.phases(p1)}))" + case Period(runId, p1, pn) => s"Period($runId.$p1(${ctx.base.phases(p1)})-$pn(${ctx.base.phases(pn)}))" + + override def toString: String = this match + case Nowhere => "Nowhere" + case InitialPeriod => "InitialPeriod" + case InvalidPeriod => "InvalidPeriod" + case Period(NoRunId, 0, PhaseMask) => s"Period(NoRunId.all)" + case Period(runId, 0, PhaseMask) => s"Period($runId.all)" + case Period(runId, p1, pn) if p1 == pn => s"Period($runId.$p1)" + case Period(runId, p1, pn) => s"Period($runId.$p1-$pn)" def ==(that: Period): Boolean = this.code == that.code def !=(that: Period): Boolean = this.code != that.code @@ -116,6 +138,17 @@ object Periods { /** The interval consisting of all periods of given run id */ def allInRun(rid: RunId): Period = apply(rid, 0, PhaseMask) + + def unapply(p: Period): Extractor = new Extractor(p.code) + + final class Extractor(private val code: Int) extends AnyVal { + private def p = new Period(code) + def isEmpty: false = false + def get: this.type = this + def _1 = p.runId + def _2 = p.firstPhaseId + def _3 = p.lastPhaseId + } } inline val NowhereCode = 0 diff --git a/compiler/src/dotty/tools/dotc/core/Scopes.scala b/compiler/src/dotty/tools/dotc/core/Scopes.scala index 7df5a7fa3c09..d6387ea1fe46 100644 --- a/compiler/src/dotty/tools/dotc/core/Scopes.scala +++ b/compiler/src/dotty/tools/dotc/core/Scopes.scala @@ -159,19 +159,28 @@ object Scopes { } /** The scope that keeps only those symbols from this scope that match the - * given predicates. If all symbols match, returns the scope itself, otherwise - * a copy with the matching symbols. + * given predicates, renamed with the given rename function. + * If renaming is not needed for a symbol, the rename function should return `null`. + * If all symbols match and none are renamed, returns the scope itself, otherwise + * a copy with the matching and renamed symbols. */ - final def filteredScope(p: Symbol => Boolean)(using Context): Scope = { + final def filteredScope( + keep: Symbol => Boolean, + rename: Symbol => Name | Null = _ => null)(using Context): Scope = var result: MutableScope | Null = null - for (sym <- iterator) - if (!p(sym)) { - if (result == null) result = cloneScope + for sym <- iterator do + def drop() = + if result == null then result = cloneScope result.nn.unlink(sym) - } + if keep(sym) then + val newName = rename(sym) + if newName != null then + drop() + result.nn.enter(newName, sym) + else + drop() // TODO: improve flow typing to handle this case - if (result == null) this else result.uncheckedNN - } + if result == null then this else result.uncheckedNN def implicitDecls(using Context): List[TermRef] = Nil diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index 253a45ffd7a8..a2e78add1338 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -537,6 +537,7 @@ object StdNames { val ManifestFactory: N = "ManifestFactory" val manifestToTypeTag: N = "manifestToTypeTag" val map: N = "map" + val maybeCapability: N = "maybeCapability" val materializeClassTag: N = "materializeClassTag" val materializeWeakTypeTag: N = "materializeWeakTypeTag" val materializeTypeTag: N = "materializeTypeTag" @@ -583,6 +584,7 @@ object StdNames { val releaseFence : N = "releaseFence" val retains: N = "retains" val retainsByName: N = "retainsByName" + val retainsCap: N = "retainsCap" val rootMirror : N = "rootMirror" val run: N = "run" val runOrElse: N = "runOrElse" diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index b1e85f2b4f90..13eb5ce8b5ba 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -167,12 +167,17 @@ object SymDenotations { println(i"${" " * indent}completed $name in $owner") } } - else { - if (myFlags.is(Touched)) - throw CyclicReference(this)(using ctx.withOwner(symbol)) - myFlags |= Touched - atPhase(validFor.firstPhaseId)(completer.complete(this)) - } + else + val traceCycles = CyclicReference.isTraced + try + if traceCycles then + CyclicReference.pushTrace("compute the signature of ", symbol, "") + if myFlags.is(Touched) then + throw CyclicReference(this)(using ctx.withOwner(symbol)) + myFlags |= Touched + atPhase(validFor.firstPhaseId)(completer.complete(this)) + finally + if traceCycles then CyclicReference.popTrace() protected[dotc] def info_=(tp: Type): Unit = { /* // DEBUG @@ -1197,7 +1202,14 @@ object SymDenotations { * is defined in Scala 3 and is neither abstract nor open. */ final def isEffectivelySealed(using Context): Boolean = - isOneOf(FinalOrSealed) || isClass && !isOneOf(EffectivelyOpenFlags) + isOneOf(FinalOrSealed) + || isClass && (!isOneOf(EffectivelyOpenFlags) + || isLocalToCompilationUnit) + + final def isLocalToCompilationUnit(using Context): Boolean = + is(Private) + || owner.ownersIterator.exists(_.isTerm) + || accessBoundary(defn.RootClass).isContainedIn(symbol.topLevelClass) final def isTransparentClass(using Context): Boolean = is(TransparentType) @@ -2180,7 +2192,7 @@ object SymDenotations { Stats.record("basetype cache entries") if (!baseTp.exists) Stats.record("basetype cache NoTypes") } - if (!tp.isProvisional && !CapturingType.isUncachable(tp)) + if !(tp.isProvisional || CapturingType.isUncachable(tp) || ctx.gadt.isNarrowing) then btrCache(tp) = baseTp else btrCache.remove(tp) // Remove any potential sentinel value @@ -2971,7 +2983,10 @@ object SymDenotations { def apply(clsd: ClassDenotation)(implicit onBehalf: BaseData, ctx: Context) : (List[ClassSymbol], BaseClassSet) = { assert(isValid) + val traceCycles = CyclicReference.isTraced try + if traceCycles then + CyclicReference.pushTrace("compute the base classes of ", clsd.symbol, "") if (cache != null) cache.uncheckedNN else { if (locked) throw CyclicReference(clsd) @@ -2984,7 +2999,9 @@ object SymDenotations { else onBehalf.signalProvisional() computed } - finally addDependent(onBehalf) + finally + if traceCycles then CyclicReference.popTrace() + addDependent(onBehalf) } def sameGroup(p1: Phase, p2: Phase) = p1.sameParentsStartId == p2.sameParentsStartId diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index ddddaf9b07fb..32a2da8b46b6 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -19,9 +19,7 @@ import DenotTransformers.* import StdNames.* import NameOps.* import NameKinds.LazyImplicitName -import ast.tpd -import tpd.{Tree, TreeProvider, TreeOps} -import ast.TreeTypeMap +import ast.*, tpd.* import Constants.Constant import Variances.Variance import reporting.Message @@ -134,7 +132,7 @@ object Symbols extends SymUtils { final def lastKnownDenotation: SymDenotation = lastDenot - private[core] def defRunId: RunId = + private[dotc] def defRunId: RunId = lastDenot.validFor.runId private inline def associatedFileMatches(inline filter: AbstractFile => Boolean)(using Context): Boolean = @@ -325,13 +323,26 @@ object Symbols extends SymUtils { /** A symbol related to `sym` that is defined in source code. * - * @see enclosingSourceSymbols + * @see [[interactive.Interactive.enclosingSourceSymbols]] */ @annotation.tailrec final def sourceSymbol(using Context): Symbol = if (!denot.exists) this else if (denot.is(ModuleVal)) this.moduleClass.sourceSymbol // The module val always has a zero-extent position + else if denot.is(ExportedType) then + denot.info.dropAlias.finalResultType.typeConstructor match + case tp: NamedType => tp.symbol.sourceSymbol + case _ => this + else if denot.is(ExportedTerm) then + val root = denot.maybeOwner match + case cls: ClassSymbol => cls.rootTreeContaining(name.toString) + case _ => EmptyTree + val targets = root.collectSubTrees: + case tree: DefDef if tree.symbol == denot.symbol => methPart(tree.rhs).tpe + targets.match + case (tp: NamedType) :: _ => tp.symbol.sourceSymbol + case _ => this else if (denot.is(Synthetic)) { val linked = denot.linkedClass if (linked.exists && !linked.is(Synthetic)) diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 38f975a8dac8..b04978357508 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -2318,40 +2318,35 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling else if !tp2.exists || (tp2 eq WildcardType) then tp1 else if tp1.isAny && !tp2.isLambdaSub || tp1.isAnyKind || isBottom(tp2) then tp2 else if tp2.isAny && !tp1.isLambdaSub || tp2.isAnyKind || isBottom(tp1) then tp1 - else tp2 match - case tp2: LazyRef => - glb(tp1, tp2.ref) - case _ => - tp1 match - case tp1: LazyRef => - glb(tp1.ref, tp2) - case _ => - val tp1a = dropIfSuper(tp1, tp2) - if tp1a ne tp1 then glb(tp1a, tp2) - else - val tp2a = dropIfSuper(tp2, tp1) - if tp2a ne tp2 then glb(tp1, tp2a) - else tp2 match // normalize to disjunctive normal form if possible. - case tp2 @ OrType(tp21, tp22) => - lub(tp1 & tp21, tp1 & tp22, isSoft = tp2.isSoft) - case _ => - tp1 match - case tp1 @ OrType(tp11, tp12) => - lub(tp11 & tp2, tp12 & tp2, isSoft = tp1.isSoft) - case tp1: ConstantType => - tp2 match - case tp2: ConstantType => - // Make use of the fact that the intersection of two constant types - // types which are not subtypes of each other is known to be empty. - // Note: The same does not apply to singleton types in general. - // E.g. we could have a pattern match against `x.type & y.type` - // which might succeed if `x` and `y` happen to be the same ref - // at run time. It would not work to replace that with `Nothing`. - // However, maybe we can still apply the replacement to - // types which are not explicitly written. - NothingType - case _ => andType(tp1, tp2) + else + def mergedGlb(tp1: Type, tp2: Type): Type = + val tp1a = dropIfSuper(tp1, tp2) + if tp1a ne tp1 then glb(tp1a, tp2) + else + val tp2a = dropIfSuper(tp2, tp1) + if tp2a ne tp2 then glb(tp1, tp2a) + else tp2 match // normalize to disjunctive normal form if possible. + case tp2 @ OrType(tp21, tp22) => + lub(tp1 & tp21, tp1 & tp22, isSoft = tp2.isSoft) + case _ => + tp1 match + case tp1 @ OrType(tp11, tp12) => + lub(tp11 & tp2, tp12 & tp2, isSoft = tp1.isSoft) + case tp1: ConstantType => + tp2 match + case tp2: ConstantType => + // Make use of the fact that the intersection of two constant types + // types which are not subtypes of each other is known to be empty. + // Note: The same does not apply to singleton types in general. + // E.g. we could have a pattern match against `x.type & y.type` + // which might succeed if `x` and `y` happen to be the same ref + // at run time. It would not work to replace that with `Nothing`. + // However, maybe we can still apply the replacement to + // types which are not explicitly written. + NothingType case _ => andType(tp1, tp2) + case _ => andType(tp1, tp2) + mergedGlb(dropExpr(tp1.stripLazyRef), dropExpr(tp2.stripLazyRef)) } def widenInUnions(using Context): Boolean = @@ -2390,7 +2385,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling if ((tp1 ne tp1w) || (tp2 ne tp2w)) lub(tp1w, tp2w, canConstrain = canConstrain, isSoft = isSoft) else orType(tp1w, tp2w, isSoft = isSoft) // no need to check subtypes again } - mergedLub(tp1.stripLazyRef, tp2.stripLazyRef) + mergedLub(dropExpr(tp1.stripLazyRef), dropExpr(tp2.stripLazyRef)) } /** Try to produce joint arguments for a lub `A[T_1, ..., T_n] | A[T_1', ..., T_n']` using @@ -2508,6 +2503,19 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling NoType } + /** There's a window of vulnerability between ElimByName and Erasure where some + * ExprTypes `=> T` that appear as parameters of function types are not yet converted + * to by-name functions `() ?=> T`. These would cause an assertion violation when + * used as operands of glb or lub. We fix this on the fly here. As explained in + * ElimByName, we can't fix it beforehand by mapping all occurrences of `=> T` to + * `() ?=> T` since that could lead to cycles. + */ + private def dropExpr(tp: Type): Type = tp match + case ExprType(rt) if (Phases.elimByNamePhase <= ctx.phase) && !ctx.erasedTypes => + defn.ByNameFunction(rt) + case _ => + tp + private def andTypeGen(tp1: Type, tp2: Type, op: (Type, Type) => Type, original: (Type, Type) => Type = _ & _, isErased: Boolean = ctx.erasedTypes): Type = trace(s"andTypeGen(${tp1.show}, ${tp2.show})", subtyping, show = true) { val t1 = distributeAnd(tp1, tp2) @@ -3436,7 +3444,8 @@ class TrackingTypeComparer(initctx: Context) extends TypeComparer(initctx) { case MatchTypeCasePattern.BaseTypeTest(classType, argPatterns, needsConcreteScrut) => val cls = classType.classSymbol.asClass scrut.baseType(cls) match - case base @ AppliedType(baseTycon, baseArgs) if baseTycon =:= classType => + case base @ AppliedType(baseTycon, baseArgs) => + // #19445 Don't check the prefix of baseTycon here; it is handled by `scrut <:< instantiatedPat`. val innerScrutIsWidenedAbstract = scrutIsWidenedAbstract || (needsConcreteScrut && !isConcrete(scrut)) // no point in checking concreteness if it does not need to be concrete diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala index 48559787c6a1..0474aff4087a 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala @@ -725,14 +725,14 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst tr1 :: trs1.filterNot(_.isAnyRef) case nil => nil } - var erasedDecls = decls.filteredScope(sym => !sym.isType || sym.isClass).openForMutations - for dcl <- erasedDecls.iterator do - if dcl.lastKnownDenotation.unforcedAnnotation(defn.TargetNameAnnot).isDefined - && dcl.targetName != dcl.name - then - if erasedDecls eq decls then erasedDecls = erasedDecls.cloneScope - erasedDecls.unlink(dcl) - erasedDecls.enter(dcl.targetName, dcl) + val erasedDecls = decls.filteredScope( + keep = sym => !sym.isType || sym.isClass, + rename = sym => + if sym.lastKnownDenotation.unforcedAnnotation(defn.TargetNameAnnot).isDefined + && sym.targetName != sym.name + then sym.targetName + else null + ) val selfType1 = if cls.is(Module) then cls.sourceModule.termRef else NoType tp.derivedClassInfo(NoPrefix, erasedParents, erasedDecls, selfType1) // can't replace selftype by NoType because this would lose the sourceModule link @@ -814,7 +814,8 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst eraseResult(tp1.resultType) match case rt: MethodType => rt case rt => MethodType(Nil, Nil, rt) - case tp1 => this(tp1) + case tp1 => + this(tp1) private def eraseDerivedValueClass(tp: Type)(using Context): Type = { val cls = tp.classSymbol.asClass diff --git a/compiler/src/dotty/tools/dotc/core/TypeErrors.scala b/compiler/src/dotty/tools/dotc/core/TypeErrors.scala index 76be98d9bd65..240bc4eebd84 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErrors.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErrors.scala @@ -12,7 +12,9 @@ import Denotations.* import Decorators.* import reporting.* import ast.untpd +import util.Property import config.Printers.{cyclicErrors, noPrinter} +import collection.mutable import scala.annotation.constructorOnly @@ -27,6 +29,7 @@ abstract class TypeError(using creationContext: Context) extends Exception(""): || ctx.settings.YdebugTypeError.value || ctx.settings.YdebugError.value || ctx.settings.YdebugUnpickling.value + || ctx.settings.YdebugCyclic.value override def fillInStackTrace(): Throwable = if computeStackTrace then super.fillInStackTrace().nn @@ -72,8 +75,7 @@ extends TypeError: def explanation: String = s"$op $details" private def recursions: List[RecursionOverflow] = { - import scala.collection.mutable.ListBuffer - val result = ListBuffer.empty[RecursionOverflow] + val result = mutable.ListBuffer.empty[RecursionOverflow] @annotation.tailrec def loop(throwable: Throwable): List[RecursionOverflow] = throwable match { case ro: RecursionOverflow => result += ro @@ -135,7 +137,10 @@ end handleRecursive * so it requires knowing denot already. * @param denot */ -class CyclicReference(val denot: SymDenotation)(using Context) extends TypeError: +class CyclicReference( + val denot: SymDenotation, + val optTrace: Option[Array[CyclicReference.TraceElement]])(using Context) +extends TypeError: var inImplicitSearch: Boolean = false val cycleSym = denot.symbol @@ -161,11 +166,11 @@ class CyclicReference(val denot: SymDenotation)(using Context) extends TypeError cx.tree match { case tree: untpd.ValOrDefDef if !tree.tpt.typeOpt.exists => if (inImplicitSearch) - TermMemberNeedsResultTypeForImplicitSearch(cycleSym) + TermMemberNeedsResultTypeForImplicitSearch(this) else if (isMethod) - OverloadedOrRecursiveMethodNeedsResultType(cycleSym) + OverloadedOrRecursiveMethodNeedsResultType(this) else if (isVal) - RecursiveValueNeedsResultType(cycleSym) + RecursiveValueNeedsResultType(this) else errorMsg(cx.outer) case _ => @@ -174,22 +179,38 @@ class CyclicReference(val denot: SymDenotation)(using Context) extends TypeError // Give up and give generic errors. else if (cycleSym.isOneOf(GivenOrImplicitVal, butNot = Method) && cycleSym.owner.isTerm) - CyclicReferenceInvolvingImplicit(cycleSym) + CyclicReferenceInvolvingImplicit(this) else - CyclicReferenceInvolving(denot) + CyclicReferenceInvolving(this) errorMsg(ctx) end toMessage object CyclicReference: + def apply(denot: SymDenotation)(using Context): CyclicReference = - val ex = new CyclicReference(denot) + val ex = new CyclicReference(denot, ctx.property(Trace).map(_.toArray)) if ex.computeStackTrace then cyclicErrors.println(s"Cyclic reference involving $denot") val sts = ex.getStackTrace.asInstanceOf[Array[StackTraceElement]] for (elem <- sts take 200) cyclicErrors.println(elem.toString) ex + + type TraceElement = (/*prefix:*/ String, Symbol, /*suffix:*/ String) + type Trace = mutable.ArrayBuffer[TraceElement] + val Trace = Property.Key[Trace] + + def isTraced(using Context) = + ctx.property(CyclicReference.Trace).isDefined + + def pushTrace(info: TraceElement)(using Context): Unit = + for buf <- ctx.property(CyclicReference.Trace) do + buf += info + + def popTrace()(using Context): Unit = + for buf <- ctx.property(CyclicReference.Trace) do + buf.dropRightInPlace(1) end CyclicReference class UnpicklingError(denot: Denotation, where: String, cause: Throwable)(using Context) extends TypeError: diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 2005aa702782..587c52688456 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -540,18 +540,6 @@ object TypeOps: val sym = tp.symbol forbidden.contains(sym) - /** We need to split the set into upper and lower approximations - * only if it contains a local element. The idea here is that at the - * time we perform an `avoid` all local elements are already accounted for - * and no further elements will be added afterwards. So we can just keep - * the set as it is. See comment by @linyxus on #16261. - */ - override def needsRangeIfInvariant(refs: CaptureSet): Boolean = - refs.elems.exists { - case ref: TermRef => toAvoid(ref) - case _ => false - } - override def apply(tp: Type): Type = tp match case tp: TypeVar if mapCtx.typerState.constraint.contains(tp) => val lo = TypeComparer.instanceType( diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index fba5f3f56648..b151dcdf8270 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -38,7 +38,7 @@ import config.Printers.{core, typr, matchTypes} import reporting.{trace, Message} import java.lang.ref.WeakReference import compiletime.uninitialized -import cc.{CapturingType, CaptureSet, derivedCapturingType, isBoxedCapturing, RetainingType, isCaptureChecking} +import cc.{CapturingType, CaptureSet, derivedCapturingType, isBoxedCapturing, isCaptureChecking, isRetains, isRetainsLike} import CaptureSet.{CompareResult, IdempotentCaptRefMap, IdentityCaptRefMap} import scala.annotation.internal.sharable @@ -197,7 +197,7 @@ object Types extends TypeUtils { */ def isRef(sym: Symbol, skipRefined: Boolean = true)(using Context): Boolean = this match { case this1: TypeRef => - this1.info match { // see comment in Namer#typeDefSig + this1.info match { // see comment in Namer#TypeDefCompleter#typeSig case TypeAlias(tp) => tp.isRef(sym, skipRefined) case _ => this1.symbol eq sym } @@ -657,6 +657,8 @@ object Types extends TypeUtils { tp.superType.baseClasses case tp: ClassInfo => tp.cls.classDenot.baseClasses + case tp: WildcardType => + tp.effectiveBounds.hi.baseClasses case _ => Nil catch case ex: Throwable => handleRecursive("base classes of", this.show, ex) @@ -843,7 +845,9 @@ object Types extends TypeUtils { safeIntersection = ctx.base.pendingMemberSearches.contains(name)) joint match case joint: SingleDenotation - if isRefinedMethod && rinfo <:< joint.info => + if isRefinedMethod + && (rinfo <:< joint.info + || name == nme.apply && defn.isFunctionType(tp.parent)) => // use `rinfo` to keep the right parameter names for named args. See i8516.scala. joint.derivedSingleDenotation(joint.symbol, rinfo, pre, isRefinedMethod) case _ => @@ -2196,7 +2200,11 @@ object Types extends TypeUtils { /** Is this a reach reference of the form `x*`? */ def isReach(using Context): Boolean = false // overridden in AnnotatedType + /** Is this a maybe reference of the form `x?`? */ + def isMaybe(using Context): Boolean = false // overridden in AnnotatedType + def stripReach(using Context): CaptureRef = this // overridden in AnnotatedType + def stripMaybe(using Context): CaptureRef = this // overridden in AnnotatedType /** Is this reference the generic root capability `cap` ? */ def isRootCapability(using Context): Boolean = false @@ -4023,7 +4031,7 @@ object Types extends TypeUtils { mapOver(tp) case AnnotatedType(parent, ann) if ann.refersToParamOf(thisLambdaType) => val parent1 = mapOver(parent) - if ann.symbol == defn.RetainsAnnot || ann.symbol == defn.RetainsByNameAnnot then + if ann.symbol.isRetainsLike then range( AnnotatedType(parent1, CaptureSet.empty.toRegularAnnotation(ann.symbol)), AnnotatedType(parent1, CaptureSet.universal.toRegularAnnotation(ann.symbol))) @@ -5035,7 +5043,7 @@ object Types extends TypeUtils { record("MatchType.reduce computed") if (myReduced != null) record("MatchType.reduce cache miss") myReduced = - trace(i"reduce match type $this $hashCode", matchTypes, show = true)(inMode(Mode.Type) { + trace(i"reduce match type $this $hashCode", matchTypes, show = true)(withMode(Mode.Type) { def matchCases(cmp: TrackingTypeComparer): Type = val saved = ctx.typerState.snapshot() try cmp.matchCases(scrutinee.normalized, cases.map(MatchTypeCaseSpec.analyze(_))) @@ -5313,10 +5321,10 @@ object Types extends TypeUtils { else if (clsd.is(Module)) givenSelf else if (ctx.erasedTypes) appliedRef else givenSelf.dealiasKeepAnnots match - case givenSelf1 @ AnnotatedType(tp, ann) if ann.symbol == defn.RetainsAnnot => - givenSelf1.derivedAnnotatedType(tp & appliedRef, ann) + case givenSelf1 @ AnnotatedType(tp, ann) if ann.symbol.isRetains => + givenSelf1.derivedAnnotatedType(AndType.make(tp, appliedRef), ann) case _ => - AndType(givenSelf, appliedRef) + AndType.make(givenSelf, appliedRef) } selfTypeCache.nn } @@ -5616,14 +5624,21 @@ object Types extends TypeUtils { } override def isTrackableRef(using Context) = - isReach && parent.isTrackableRef + (isReach || isMaybe) && parent.isTrackableRef /** Is this a reach reference of the form `x*`? */ override def isReach(using Context): Boolean = annot.symbol == defn.ReachCapabilityAnnot - override def stripReach(using Context): SingletonCaptureRef = - (if isReach then parent else this).asInstanceOf[SingletonCaptureRef] + /** Is this a reach reference of the form `x*`? */ + override def isMaybe(using Context): Boolean = + annot.symbol == defn.MaybeCapabilityAnnot + + override def stripReach(using Context): CaptureRef = + if isReach then parent.asInstanceOf[CaptureRef] else this + + override def stripMaybe(using Context): CaptureRef = + if isMaybe then parent.asInstanceOf[CaptureRef] else this override def normalizedRef(using Context): CaptureRef = if isReach then AnnotatedType(stripReach.normalizedRef, annot) else this @@ -6473,15 +6488,6 @@ object Types extends TypeUtils { tp.derivedLambdaType(tp.paramNames, formals, restpe) } - /** Overridden in TypeOps.avoid and in CheckCaptures.substParamsMap */ - protected def needsRangeIfInvariant(refs: CaptureSet): Boolean = true - - override def mapCapturingType(tp: Type, parent: Type, refs: CaptureSet, v: Int): Type = - if v == 0 && needsRangeIfInvariant(refs) then - range(mapCapturingType(tp, parent, refs, -1), mapCapturingType(tp, parent, refs, 1)) - else - super.mapCapturingType(tp, parent, refs, v) - protected def reapply(tp: Type): Type = apply(tp) } diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileConstants.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileConstants.scala index 6ad71c5fd1ce..7a2232891a83 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileConstants.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileConstants.scala @@ -73,7 +73,10 @@ object ClassfileConstants { inline val CONSTANT_METHODHANDLE = 15 inline val CONSTANT_METHODTYPE = 16 + inline val CONSTANT_DYNAMIC = 17 inline val CONSTANT_INVOKEDYNAMIC = 18 + inline val CONSTANT_MODULE = 19 + inline val CONSTANT_PACKAGE = 20 // tags describing the type of a literal in attribute values inline val BYTE_TAG = 'B' diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index 93ebcfeee62a..894d430fe54b 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -106,13 +106,14 @@ object ClassfileParser { (in.nextByte.toInt: @switch) match { case CONSTANT_UTF8 | CONSTANT_UNICODE => in.skip(in.nextChar) - case CONSTANT_CLASS | CONSTANT_STRING | CONSTANT_METHODTYPE => + case CONSTANT_CLASS | CONSTANT_STRING | CONSTANT_METHODTYPE + | CONSTANT_MODULE | CONSTANT_PACKAGE => in.skip(2) case CONSTANT_METHODHANDLE => in.skip(3) case CONSTANT_FIELDREF | CONSTANT_METHODREF | CONSTANT_INTFMETHODREF | CONSTANT_NAMEANDTYPE | CONSTANT_INTEGER | CONSTANT_FLOAT - | CONSTANT_INVOKEDYNAMIC => + | CONSTANT_INVOKEDYNAMIC | CONSTANT_DYNAMIC => in.skip(4) case CONSTANT_LONG | CONSTANT_DOUBLE => in.skip(8) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index b7a25cb75613..b95e4df663a1 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -141,20 +141,25 @@ class TreeUnpickler(reader: TastyReader, val mode = ctx.mode val source = ctx.source def complete(denot: SymDenotation)(using Context): Unit = - def fail(ex: Throwable) = - def where = - val f = denot.symbol.associatedFile - if f == null then "" else s" in $f" - throw UnpicklingError(denot, where, ex) + def where = + val f = denot.symbol.associatedFile + if f == null then "" else s" in $f" + def fail(ex: Throwable) = throw UnpicklingError(denot, where, ex) treeAtAddr(currentAddr) = + val traceCycles = CyclicReference.isTraced try + if traceCycles then + CyclicReference.pushTrace("read the definition of ", denot.symbol, where) atPhaseBeforeTransforms { new TreeReader(reader).readIndexedDef()( using ctx.withOwner(owner).withModeBits(mode).withSource(source)) } catch + case ex: CyclicReference => throw ex case ex: AssertionError => fail(ex) case ex: Exception => fail(ex) + finally + if traceCycles then CyclicReference.popTrace() } class TreeReader(val reader: TastyReader) { diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index f876c87e8920..806f39ee0425 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -151,7 +151,6 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas assert(moduleRoot.isTerm) checkVersion(using ictx) - checkScala2Stdlib(using ictx) private val loadingMirror = defn(using ictx) // was: mirrorThatLoaded(classRoot) @@ -238,9 +237,6 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas " in " + source) } - private def checkScala2Stdlib(using Context): Unit = - assert(!ctx.settings.YcompileScala2Library.value, "No Scala 2 libraries should be unpickled under -Ycompile-scala2-library") - /** The `decls` scope associated with given symbol */ protected def symScope(sym: Symbol): Scope = symScopes.getOrElseUpdate(sym, newScope(0)) diff --git a/compiler/src/dotty/tools/dotc/coverage/Location.scala b/compiler/src/dotty/tools/dotc/coverage/Location.scala index 88893709b8bd..de1a3db710a3 100644 --- a/compiler/src/dotty/tools/dotc/coverage/Location.scala +++ b/compiler/src/dotty/tools/dotc/coverage/Location.scala @@ -31,9 +31,9 @@ object Location: val ownerDenot = ctx.owner.denot val enclosingClass = ownerDenot.enclosingClass - val packageName = ownerDenot.enclosingPackageClass.fullName.toSimpleName.toString - val className = enclosingClass.name.toSimpleName.toString - val methodName = ownerDenot.enclosingMethod.name.toSimpleName.toString + val packageName = ownerDenot.enclosingPackageClass.fullName.toSimpleName.show + val className = enclosingClass.name.toSimpleName.show + val methodName = ownerDenot.enclosingMethod.name.toSimpleName.show val classType: String = if enclosingClass.is(Trait) then "Trait" diff --git a/compiler/src/dotty/tools/dotc/inlines/Inlines.scala b/compiler/src/dotty/tools/dotc/inlines/Inlines.scala index 4860913bdc63..230092898051 100644 --- a/compiler/src/dotty/tools/dotc/inlines/Inlines.scala +++ b/compiler/src/dotty/tools/dotc/inlines/Inlines.scala @@ -172,10 +172,10 @@ object Inlines: /** Try to inline a pattern with an inline unapply method. Fail with error if the maximal * inline depth is exceeded. * - * @param unapp The tree of the pattern to inline + * @param fun The function of an Unapply node * @return An `Unapply` with a `fun` containing the inlined call to the unapply */ - def inlinedUnapply(unapp: tpd.UnApply)(using Context): Tree = + def inlinedUnapplyFun(fun: tpd.Tree)(using Context): Tree = // We cannot inline the unapply directly, since the pattern matcher relies on unapply applications // as signposts what to do. On the other hand, we can do the inlining only in typer, not afterwards. // So the trick is to create a "wrapper" unapply in an anonymous class that has the inlined unapply @@ -189,7 +189,6 @@ object Inlines: // transforms the patterns into terms, the `inlinePatterns` phase removes this anonymous class by β-reducing // the call to the `unapply`. - val fun = unapp.fun val sym = fun.symbol val newUnapply = AnonClass(ctx.owner, List(defn.ObjectType), sym.coord) { cls => @@ -199,7 +198,7 @@ object Inlines: val unapplyInfo = fun.tpe.widen val unapplySym = newSymbol(cls, sym.name.toTermName, Synthetic | Method, unapplyInfo, coord = sym.coord).entered - val unapply = DefDef(unapplySym.asTerm, argss => fun.appliedToArgss(argss).withSpan(unapp.span)) + val unapply = DefDef(unapplySym.asTerm, argss => fun.appliedToArgss(argss).withSpan(fun.span)) if sym.is(Transparent) then // Inline the body and refine the type of the unapply method @@ -214,9 +213,8 @@ object Inlines: List(unapply) } - val newFun = newUnapply.select(sym.name).withSpan(unapp.span) - cpy.UnApply(unapp)(fun = newFun) - end inlinedUnapply + newUnapply.select(sym.name).withSpan(fun.span) + end inlinedUnapplyFun /** For a retained inline method, another method that keeps track of * the body that is kept at runtime. For instance, an inline method @@ -443,6 +441,9 @@ object Inlines: unrollTupleTypes(tail).map(head :: _) case tpe: TermRef if tpe.symbol == defn.EmptyTupleModule => Some(Nil) + case tpRef: TypeRef => tpRef.info match + case MatchAlias(alias) => unrollTupleTypes(alias.tryNormalize) + case _ => None case _ => None diff --git a/compiler/src/dotty/tools/dotc/interactive/Completion.scala b/compiler/src/dotty/tools/dotc/interactive/Completion.scala index 6e91254c2d72..5237f19d19ae 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Completion.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Completion.scala @@ -1,6 +1,7 @@ package dotty.tools.dotc.interactive import dotty.tools.dotc.ast.untpd +import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.ast.NavigateAST import dotty.tools.dotc.config.Printers.interactiv import dotty.tools.dotc.core.Contexts.* @@ -19,6 +20,8 @@ import dotty.tools.dotc.core.TypeError import dotty.tools.dotc.core.Phases import dotty.tools.dotc.core.Types.{AppliedType, ExprType, MethodOrPoly, NameFilter, NoType, RefinedType, TermRef, Type, TypeProxy} import dotty.tools.dotc.parsing.Tokens +import dotty.tools.dotc.typer.Implicits.SearchSuccess +import dotty.tools.dotc.typer.Inferencing import dotty.tools.dotc.util.Chars import dotty.tools.dotc.util.SourcePosition @@ -28,6 +31,7 @@ import dotty.tools.dotc.core.ContextOps.localContext import dotty.tools.dotc.core.Names import dotty.tools.dotc.core.Types import dotty.tools.dotc.core.Symbols +import dotty.tools.dotc.core.Constants /** * One of the results of a completion query. @@ -42,15 +46,35 @@ case class Completion(label: String, description: String, symbols: List[Symbol]) object Completion: - import dotty.tools.dotc.ast.tpd.* - /** Get possible completions from tree at `pos` * * @return offset and list of symbols for possible completions */ def completions(pos: SourcePosition)(using Context): (Int, List[Completion]) = - val path: List[Tree] = Interactive.pathTo(ctx.compilationUnit.tpdTree, pos.span) - computeCompletions(pos, path)(using Interactive.contextOfPath(path).withPhase(Phases.typerPhase)) + val tpdPath = Interactive.pathTo(ctx.compilationUnit.tpdTree, pos.span) + val completionContext = Interactive.contextOfPath(tpdPath).withPhase(Phases.typerPhase) + inContext(completionContext): + val untpdPath = Interactive.resolveTypedOrUntypedPath(tpdPath, pos) + val mode = completionMode(untpdPath, pos) + val rawPrefix = completionPrefix(untpdPath, pos) + val completions = rawCompletions(pos, mode, rawPrefix, tpdPath, untpdPath) + + postProcessCompletions(untpdPath, completions, rawPrefix) + + /** Get possible completions from tree at `pos` + * This method requires manually computing the mode, prefix and paths. + * + * @return completion map of name to list of denotations + */ + def rawCompletions( + pos: SourcePosition, + mode: Mode, + rawPrefix: String, + tpdPath: List[tpd.Tree], + untpdPath: List[untpd.Tree] + )(using Context): CompletionMap = + val adjustedPath = typeCheckExtensionConstructPath(untpdPath, tpdPath, pos) + computeCompletions(pos, mode, rawPrefix, adjustedPath) /** * Inspect `path` to determine what kinds of symbols should be considered. @@ -63,20 +87,32 @@ object Completion: * Otherwise, provide no completion suggestion. */ def completionMode(path: List[untpd.Tree], pos: SourcePosition): Mode = - path match - case untpd.Ident(_) :: untpd.Import(_, _) :: _ => Mode.ImportOrExport - case untpd.Ident(_) :: (_: untpd.ImportSelector) :: _ => Mode.ImportOrExport - case (ref: untpd.RefTree) :: _ => - if (ref.name.isTermName) Mode.Term - else if (ref.name.isTypeName) Mode.Type - else Mode.None - case (sel: untpd.ImportSelector) :: _ => - if sel.imported.span.contains(pos.span) then Mode.ImportOrExport - else Mode.None // Can't help completing the renaming + val completionSymbolKind: Mode = + path match + case untpd.Ident(_) :: untpd.Import(_, _) :: _ => Mode.ImportOrExport + case untpd.Ident(_) :: (_: untpd.ImportSelector) :: _ => Mode.ImportOrExport + case untpd.Literal(Constants.Constant(_: String)) :: _ => Mode.Term // literal completions + case (ref: untpd.RefTree) :: _ => + if (ref.name.isTermName) Mode.Term + else if (ref.name.isTypeName) Mode.Type + else Mode.None + + case (sel: untpd.ImportSelector) :: _ => + if sel.imported.span.contains(pos.span) then Mode.ImportOrExport + else Mode.None // Can't help completing the renaming + + case (_: untpd.ImportOrExport) :: _ => Mode.ImportOrExport + case _ => Mode.None + + val completionKind: Mode = + path match + case Nil | (_: untpd.PackageDef) :: _ => Mode.None + case untpd.Ident(_) :: (_: untpd.ImportSelector) :: _ => Mode.Member + case (_: untpd.Select) :: _ => Mode.Member + case _ => Mode.Scope - case (_: untpd.ImportOrExport) :: _ => Mode.ImportOrExport - case _ => Mode.None + completionSymbolKind | completionKind /** When dealing with in varios palces we check to see if they are * due to incomplete backticks. If so, we ensure we get the full prefix @@ -99,12 +135,18 @@ object Completion: * returned prefix should be considered. */ def completionPrefix(path: List[untpd.Tree], pos: SourcePosition)(using Context): String = + def fallback: Int = + var i = pos.point - 1 + while i >= 0 && Chars.isIdentifierPart(pos.source.content()(i)) do i -= 1 + i + 1 + path match case (sel: untpd.ImportSelector) :: _ => completionPrefix(sel.imported :: Nil, pos) case untpd.Ident(_) :: (sel: untpd.ImportSelector) :: _ if !sel.isGiven => - completionPrefix(sel.imported :: Nil, pos) + if sel.isWildcard then pos.source.content()(pos.point - 1).toString + else completionPrefix(sel.imported :: Nil, pos) case (tree: untpd.ImportOrExport) :: _ => tree.selectors.find(_.span.contains(pos.span)).map: selector => @@ -119,34 +161,19 @@ object Completion: case (ident: untpd.Ident) :: _ if ident.name == nme.ERROR => checkBacktickPrefix(ident.source.content(), ident.span.start, ident.span.end) - case (ref: untpd.RefTree) :: _ => - if (ref.name == nme.ERROR) "" - else ref.name.toString.take(pos.span.point - ref.span.point) + case (tree: untpd.RefTree) :: _ if tree.name != nme.ERROR => + tree.name.toString.take(pos.span.point - tree.span.point) + + case _ => pos.source.content.slice(fallback, pos.point).mkString - case _ => "" end completionPrefix /** Inspect `path` to determine the offset where the completion result should be inserted. */ def completionOffset(untpdPath: List[untpd.Tree]): Int = - untpdPath match { + untpdPath match case (ref: untpd.RefTree) :: _ => ref.span.point case _ => 0 - } - - /** Some information about the trees is lost after Typer such as Extension method construct - * is expanded into methods. In order to support completions in those cases - * we have to rely on untyped trees and only when types are necessary use typed trees. - */ - def resolveTypedOrUntypedPath(tpdPath: List[Tree], pos: SourcePosition)(using Context): List[untpd.Tree] = - lazy val untpdPath: List[untpd.Tree] = NavigateAST - .pathTo(pos.span, List(ctx.compilationUnit.untpdTree), true).collect: - case untpdTree: untpd.Tree => untpdTree - - tpdPath match - case (_: Bind) :: _ => tpdPath - case (_: untpd.TypTree) :: _ => tpdPath - case _ => untpdPath /** Handle case when cursor position is inside extension method construct. * The extension method construct is then desugared into methods, and consturct parameters @@ -159,8 +186,8 @@ object Completion: * @return Typed path to the parameter of the extension construct if found or tpdPath */ private def typeCheckExtensionConstructPath( - untpdPath: List[untpd.Tree], tpdPath: List[Tree], pos: SourcePosition - )(using Context): List[Tree] = + untpdPath: List[untpd.Tree], tpdPath: List[tpd.Tree], pos: SourcePosition + )(using Context): List[tpd.Tree] = untpdPath.collectFirst: case untpd.ExtMethods(paramss, _) => val enclosingParam = paramss.flatten.find(_.span.contains(pos.span)) @@ -170,38 +197,41 @@ object Completion: Interactive.pathTo(typedEnclosingParam, pos.span) .flatten.getOrElse(tpdPath) - private def computeCompletions(pos: SourcePosition, tpdPath: List[Tree])(using Context): (Int, List[Completion]) = - val path0 = resolveTypedOrUntypedPath(tpdPath, pos) - val mode = completionMode(path0, pos) - val rawPrefix = completionPrefix(path0, pos) - + private def computeCompletions( + pos: SourcePosition, mode: Mode, rawPrefix: String, adjustedPath: List[tpd.Tree] + )(using Context): CompletionMap = val hasBackTick = rawPrefix.headOption.contains('`') val prefix = if hasBackTick then rawPrefix.drop(1) else rawPrefix - val completer = new Completer(mode, prefix, pos) - val adjustedPath = typeCheckExtensionConstructPath(path0, tpdPath, pos) - val completions = adjustedPath match - // Ignore synthetic select from `This` because in code it was `Ident` - // See example in dotty.tools.languageserver.CompletionTest.syntheticThis - case Select(qual @ This(_), _) :: _ if qual.span.isSynthetic => completer.scopeCompletions - case Select(qual, _) :: _ if qual.tpe.hasSimpleKind => completer.selectionCompletions(qual) - case Select(qual, _) :: _ => Map.empty - case (tree: ImportOrExport) :: _ => completer.directMemberCompletions(tree.expr) - case (_: untpd.ImportSelector) :: Import(expr, _) :: _ => completer.directMemberCompletions(expr) - case _ => completer.scopeCompletions - + val result = adjustedPath match + // Ignore synthetic select from `This` because in code it was `Ident` + // See example in dotty.tools.languageserver.CompletionTest.syntheticThis + case tpd.Select(qual @ tpd.This(_), _) :: _ if qual.span.isSynthetic => completer.scopeCompletions + case tpd.Select(qual, _) :: _ if qual.typeOpt.hasSimpleKind => completer.selectionCompletions(qual) + case tpd.Select(qual, _) :: _ => Map.empty + case (tree: tpd.ImportOrExport) :: _ => completer.directMemberCompletions(tree.expr) + case (_: untpd.ImportSelector) :: tpd.Import(expr, _) :: _ => completer.directMemberCompletions(expr) + case _ => completer.scopeCompletions + + interactiv.println(i"""completion info with pos = $pos, + | prefix = ${completer.prefix}, + | term = ${completer.mode.is(Mode.Term)}, + | type = ${completer.mode.is(Mode.Type)}, + | scope = ${completer.mode.is(Mode.Scope)}, + | member = ${completer.mode.is(Mode.Member)}""") + + result + + def postProcessCompletions(path: List[untpd.Tree], completions: CompletionMap, rawPrefix: String)(using Context): (Int, List[Completion]) = val describedCompletions = describeCompletions(completions) + val hasBackTick = rawPrefix.headOption.contains('`') val backtickedCompletions = describedCompletions.map(completion => backtickCompletions(completion, hasBackTick)) - val offset = completionOffset(path0) + interactiv.println(i"""completion resutls = $backtickedCompletions%, %""") - interactiv.println(i"""completion with pos = $pos, - | prefix = ${completer.prefix}, - | term = ${completer.mode.is(Mode.Term)}, - | type = ${completer.mode.is(Mode.Type)} - | results = $backtickedCompletions%, %""") + val offset = completionOffset(path) (offset, backtickedCompletions) def backtickCompletions(completion: Completion, hasBackTick: Boolean) = @@ -249,6 +279,16 @@ object Completion: if denot.isType then denot.symbol.showFullName else denot.info.widenTermRefExpr.show + given ScopeOrdering(using Context): Ordering[Seq[SingleDenotation]] with + val order = + List(defn.ScalaPredefModuleClass, defn.ScalaPackageClass, defn.JavaLangPackageClass) + + override def compare(x: Seq[SingleDenotation], y: Seq[SingleDenotation]): Int = + val owner0 = x.headOption.map(_.symbol.effectiveOwner).getOrElse(NoSymbol) + val owner1 = y.headOption.map(_.symbol.effectiveOwner).getOrElse(NoSymbol) + + order.indexOf(owner0) - order.indexOf(owner1) + /** Computes code completions depending on the context in which completion is requested * @param mode Should complete names of terms, types or both * @param prefix The prefix that all suggested completions should start with @@ -265,13 +305,22 @@ object Completion: * This mimics the logic for deciding what is ambiguous used by the compiler. * In general in case of a name clash symbols introduced in more deeply nested scopes * have higher priority and shadow previous definitions with the same name although: - * - imports with the same level of nesting cause an ambiguity + * - imports with the same level of nesting cause an ambiguity if they are in the same name space * - members and local definitions with the same level of nesting are allowed for overloading * - an import is ignored if there is a local definition or a member introduced in the same scope * (even if the import follows it syntactically) * - a more deeply nested import shadowing a member or a local definition causes an ambiguity */ def scopeCompletions(using context: Context): CompletionMap = + + /** Temporary data structure representing denotations with the same name introduced in a given scope + * as a member of a type, by a local definition or by an import clause + */ + case class ScopedDenotations private (denots: Seq[SingleDenotation], ctx: Context) + object ScopedDenotations: + def apply(denots: Seq[SingleDenotation], ctx: Context, includeFn: SingleDenotation => Boolean): ScopedDenotations = + ScopedDenotations(denots.filter(includeFn), ctx) + val mappings = collection.mutable.Map.empty[Name, List[ScopedDenotations]].withDefaultValue(List.empty) def addMapping(name: Name, denots: ScopedDenotations) = mappings(name) = mappings(name) :+ denots @@ -279,18 +328,18 @@ object Completion: ctx.outersIterator.foreach { case ctx @ given Context => if ctx.isImportContext then importedCompletions.foreach { (name, denots) => - addMapping(name, ScopedDenotations(denots, ctx)) + addMapping(name, ScopedDenotations(denots, ctx, include(_, name))) } else if ctx.owner.isClass then accessibleMembers(ctx.owner.thisType) .groupByName.foreach { (name, denots) => - addMapping(name, ScopedDenotations(denots, ctx)) + addMapping(name, ScopedDenotations(denots, ctx, include(_, name))) } else if ctx.scope ne EmptyScope then ctx.scope.toList.filter(symbol => include(symbol, symbol.name)) .flatMap(_.alternatives) .groupByName.foreach { (name, denots) => - addMapping(name, ScopedDenotations(denots, ctx)) + addMapping(name, ScopedDenotations(denots, ctx, include(_, name))) } } @@ -303,26 +352,22 @@ object Completion: def isSingleImport = denotss.length < 2 // import a.C // locally { import b.C } - def isImportedInDifferentScope = first.ctx.scope ne denotss(1).ctx.scope + def isImportedInDifferentScope = first.ctx.scope ne denotss(1).ctx.scope // import a.C // import a.C - def isSameSymbolImportedDouble = denotss.forall(_.denots == first.denots) - - def isScalaPackage(scopedDenots: ScopedDenotations) = - scopedDenots.denots.exists(_.info.typeSymbol.owner == defn.ScalaPackageClass) - - def isJavaLangPackage(scopedDenots: ScopedDenotations) = - scopedDenots.denots.exists(_.info.typeSymbol.owner == defn.JavaLangPackageClass) - - // For example - // import java.lang.annotation - // is shadowed by - // import scala.annotation - def isJavaLangAndScala = - try - denotss.forall(denots => isScalaPackage(denots) || isJavaLangPackage(denots)) - catch - case NonFatal(_) => false + def isSameSymbolImportedDouble = denotss.forall(_.denots == first.denots) + + // https://scala-lang.org/files/archive/spec/3.4/02-identifiers-names-and-scopes.html + // import java.lang.* + // { + // import scala.* + // { + // import Predef.* + // { /* source */ } + // } + // } + def notConflictingWithDefaults = // is imported symbol + denotss.filterNot(_.denots.exists(denot => Interactive.isImportedByDefault(denot.symbol))).size <= 1 denotss.find(!_.ctx.isImportContext) match { // most deeply nested member or local definition if not shadowed by an import @@ -331,13 +376,9 @@ object Completion: case None if isSingleImport || isImportedInDifferentScope || isSameSymbolImportedDouble => resultMappings += name -> first.denots - case None if isJavaLangAndScala => - denotss.foreach{ - denots => - if isScalaPackage(denots) then - resultMappings += name -> denots.denots - } - + case None if notConflictingWithDefaults => + val ordered = denotss.map(_.denots).sorted + resultMappings += name -> ordered.head case _ => } } @@ -347,8 +388,8 @@ object Completion: /** Widen only those types which are applied or are exactly nothing */ - def widenQualifier(qual: Tree)(using Context): Tree = - qual.tpe.widenDealias match + def widenQualifier(qual: tpd.Tree)(using Context): tpd.Tree = + qual.typeOpt.widenDealias match case widenedType if widenedType.isExactlyNothing => qual.withType(widenedType) case appliedType: AppliedType => qual.withType(appliedType) case _ => qual @@ -357,7 +398,7 @@ object Completion: * Direct members take priority over members from extensions * and so do members from extensions over members from implicit conversions */ - def selectionCompletions(qual: Tree)(using Context): CompletionMap = + def selectionCompletions(qual: tpd.Tree)(using Context): CompletionMap = val adjustedQual = widenQualifier(qual) implicitConversionMemberCompletions(adjustedQual) ++ @@ -367,11 +408,11 @@ object Completion: /** Completions for members of `qual`'s type. * These include inherited definitions but not members added by extensions or implicit conversions */ - def directMemberCompletions(qual: Tree)(using Context): CompletionMap = - if qual.tpe.isExactlyNothing then + def directMemberCompletions(qual: tpd.Tree)(using Context): CompletionMap = + if qual.typeOpt.isExactlyNothing then Map.empty else - accessibleMembers(qual.tpe).groupByName + accessibleMembers(qual.typeOpt).groupByName /** Completions introduced by imports directly in this context. * Completions from outer contexts are not included. @@ -414,17 +455,28 @@ object Completion: end importedCompletions /** Completions from implicit conversions including old style extensions using implicit classes */ - private def implicitConversionMemberCompletions(qual: Tree)(using Context): CompletionMap = - if qual.tpe.isExactlyNothing || qual.tpe.isNullType then + private def implicitConversionMemberCompletions(qual: tpd.Tree)(using Context): CompletionMap = + + def tryToInstantiateTypeVars(conversionTarget: SearchSuccess): Type = + try + val typingCtx = ctx.fresh + inContext(typingCtx): + val methodRefTree = tpd.ref(conversionTarget.ref, needLoad = false) + val convertedTree = ctx.typer.typedAheadExpr(untpd.Apply(untpd.TypedSplice(methodRefTree), untpd.TypedSplice(qual) :: Nil)) + Inferencing.fullyDefinedType(convertedTree.tpe, "", pos) + catch + case error => conversionTarget.tree.tpe // fallback to not fully defined type + + if qual.typeOpt.isExactlyNothing || qual.typeOpt.isNullType then Map.empty else implicitConversionTargets(qual)(using ctx.fresh.setExploreTyperState()) - .flatMap(accessibleMembers) + .flatMap { conversionTarget => accessibleMembers(tryToInstantiateTypeVars(conversionTarget)) } .toSeq .groupByName /** Completions from extension methods */ - private def extensionCompletions(qual: Tree)(using Context): CompletionMap = + private def extensionCompletions(qual: tpd.Tree)(using Context): CompletionMap = def asDefLikeType(tpe: Type): Type = tpe match case _: MethodOrPoly => tpe case _ => ExprType(tpe) @@ -432,7 +484,7 @@ object Completion: def tryApplyingReceiverToExtension(termRef: TermRef): Option[SingleDenotation] = ctx.typer.tryApplyingExtensionMethod(termRef, qual) .map { tree => - val tpe = asDefLikeType(tree.tpe.dealias) + val tpe = asDefLikeType(tree.typeOpt.dealias) termRef.denot.asSingleDenotation.mapInfo(_ => tpe) } @@ -453,16 +505,16 @@ object Completion: // 1. The extension method is visible under a simple name, by being defined or inherited or imported in a scope enclosing the reference. val termCompleter = new Completer(Mode.Term, prefix, pos) - val extMethodsInScope = termCompleter.scopeCompletions.toList.flatMap { - case (name, denots) => denots.collect { case d: SymDenotation if d.isTerm => (d.termRef, name.asTermName) } - } + val extMethodsInScope = termCompleter.scopeCompletions.toList.flatMap: + case (name, denots) => denots.collect: + case d: SymDenotation if d.isTerm && d.termRef.symbol.is(Extension) => (d.termRef, name.asTermName) // 2. The extension method is a member of some given instance that is visible at the point of the reference. val givensInScope = ctx.implicits.eligible(defn.AnyType).map(_.implicitRef.underlyingRef) val extMethodsFromGivensInScope = extractMemberExtensionMethods(givensInScope) // 3. The reference is of the form r.m and the extension method is defined in the implicit scope of the type of r. - val implicitScopeCompanions = ctx.run.nn.implicitScope(qual.tpe).companionRefs.showAsList + val implicitScopeCompanions = ctx.run.nn.implicitScope(qual.typeOpt).companionRefs.showAsList val extMethodsFromImplicitScope = extractMemberExtensionMethods(implicitScopeCompanions) // 4. The reference is of the form r.m and the extension method is defined in some given instance in the implicit scope of the type of r. @@ -472,7 +524,7 @@ object Completion: val availableExtMethods = extMethodsFromGivensInImplicitScope ++ extMethodsFromImplicitScope ++ extMethodsFromGivensInScope ++ extMethodsInScope val extMethodsWithAppliedReceiver = availableExtMethods.flatMap { case (termRef, termName) => - if termRef.symbol.is(ExtensionMethod) && !qual.tpe.isBottomType then + if termRef.symbol.is(ExtensionMethod) && !qual.typeOpt.isBottomType then tryApplyingReceiverToExtension(termRef) .map(denot => termName -> denot) else None @@ -551,21 +603,20 @@ object Completion: * @param qual The argument to which the implicit conversion should be applied. * @return The set of types after `qual` implicit conversion. */ - private def implicitConversionTargets(qual: Tree)(using Context): Set[Type] = { + private def implicitConversionTargets(qual: tpd.Tree)(using Context): Set[SearchSuccess] = { val typer = ctx.typer val conversions = new typer.ImplicitSearch(defn.AnyType, qual, pos.span).allImplicits - val targets = conversions.map(_.tree.tpe) + conversions.map(_.tree.typeOpt) - interactiv.println(i"implicit conversion targets considered: ${targets.toList}%, %") - targets + interactiv.println(i"implicit conversion targets considered: ${conversions.toList}%, %") + conversions } /** Filter for names that should appear when looking for completions. */ - private object completionsFilter extends NameFilter { + private object completionsFilter extends NameFilter: def apply(pre: Type, name: Name)(using Context): Boolean = !name.isConstructorName && name.toTermName.info.kind == SimpleNameKind def isStable = true - } extension (denotations: Seq[SingleDenotation]) def groupByName(using Context): CompletionMap = denotations.groupBy(_.name) @@ -576,11 +627,6 @@ object Completion: private type CompletionMap = Map[Name, Seq[SingleDenotation]] - /** Temporary data structure representing denotations with the same name introduced in a given scope - * as a member of a type, by a local definition or by an import clause - */ - private case class ScopedDenotations(denots: Seq[SingleDenotation], ctx: Context) - /** * The completion mode: defines what kinds of symbols should be included in the completion * results. @@ -602,3 +648,7 @@ object Completion: /** Both term and type symbols are allowed */ val ImportOrExport: Mode = new Mode(4) | Term | Type + val Scope: Mode = new Mode(8) + + val Member: Mode = new Mode(16) + diff --git a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala index 3f3e5e25f66e..16079125a434 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala @@ -250,7 +250,7 @@ object Interactive { * Note that if the given `pos` points out places for incomplete parses, * this method returns `errorTermTree` (`Literal(Consotant(null)`). * - * @see https://github.com/lampepfl/dotty/issues/15294 + * @see https://github.com/scala/scala3/issues/15294 */ def pathTo(trees: List[SourceTree], pos: SourcePosition)(using Context): List[Tree] = pathTo(trees.map(_.tree), pos.span) @@ -282,12 +282,10 @@ object Interactive { case nested :: encl :: rest => val outer = contextOfPath(encl :: rest) try encl match { - case tree @ PackageDef(pkg, stats) => - assert(tree.symbol.exists) + case tree @ PackageDef(pkg, stats) if tree.symbol.exists => if (nested `eq` pkg) outer else contextOfStat(stats, nested, pkg.symbol.moduleClass, outer.packageContext(tree, tree.symbol)) - case tree: DefDef => - assert(tree.symbol.exists) + case tree: DefDef if tree.symbol.exists => val localCtx = outer.localContext(tree, tree.symbol).setNewScope for params <- tree.paramss; param <- params do localCtx.enter(param.symbol) // Note: this overapproximates visibility a bit, since value parameters are only visible @@ -299,14 +297,14 @@ object Interactive { else outer case tree @ Block(stats, expr) => - val localCtx = outer.fresh.setNewScope + val localCtx = outer.localContext(tree, outer.owner).setNewScope stats.foreach { case stat: MemberDef => localCtx.enter(stat.symbol) case _ => } - contextOfStat(stats, nested, ctx.owner, localCtx) + contextOfStat(stats, nested, localCtx.owner, localCtx) case tree @ CaseDef(pat, _, _) => - val localCtx = outer.fresh.setNewScope + val localCtx = outer.localContext(tree, outer.owner).setNewScope pat.foreachSubTree { case bind: Bind => localCtx.enter(bind.symbol) case _ => @@ -422,6 +420,21 @@ object Interactive { false } + + /** Some information about the trees is lost after Typer such as Extension method construct + * is expanded into methods. In order to support completions in those cases + * we have to rely on untyped trees and only when types are necessary use typed trees. + */ + def resolveTypedOrUntypedPath(tpdPath: List[Tree], pos: SourcePosition)(using Context): List[untpd.Tree] = + lazy val untpdPath: List[untpd.Tree] = NavigateAST + .pathTo(pos.span, List(ctx.compilationUnit.untpdTree), true).collect: + case untpdTree: untpd.Tree => untpdTree + + tpdPath match + case (_: Bind) :: _ => tpdPath + case (_: untpd.TypTree) :: _ => tpdPath + case _ => untpdPath + /** * Is this tree using a renaming introduced by an import statement or an alias for `this`? * @@ -438,6 +451,20 @@ object Interactive { def sameName(n0: Name, n1: Name): Boolean = n0.stripModuleClassSuffix.toTermName eq n1.stripModuleClassSuffix.toTermName + /** https://scala-lang.org/files/archive/spec/3.4/02-identifiers-names-and-scopes.html + * import java.lang.* + * { + * import scala.* + * { + * import Predef.* + * { /* source */ } + * } + * } + */ + def isImportedByDefault(sym: Symbol)(using Context): Boolean = + val owner = sym.effectiveOwner + owner == defn.ScalaPredefModuleClass || owner == defn.ScalaPackageClass || owner == defn.JavaLangPackageClass + private[interactive] def safely[T](op: => List[T]): List[T] = try op catch { case ex: TypeError => Nil } } diff --git a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala index b00cd1036018..8f42c62cb3b0 100644 --- a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala +++ b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala @@ -47,14 +47,10 @@ class InteractiveDriver(val settings: List[String]) extends Driver { private val compiler: Compiler = new InteractiveCompiler - private val myOpenedFiles = new mutable.LinkedHashMap[URI, SourceFile] { - override def default(key: URI) = NoSource - } + private val myOpenedFiles = new mutable.LinkedHashMap[URI, SourceFile].withDefaultValue(NoSource) def openedFiles: Map[URI, SourceFile] = myOpenedFiles - private val myOpenedTrees = new mutable.LinkedHashMap[URI, List[SourceTree]] { - override def default(key: URI) = Nil - } + private val myOpenedTrees = new mutable.LinkedHashMap[URI, List[SourceTree]].withDefaultValue(Nil) def openedTrees: Map[URI, List[SourceTree]] = myOpenedTrees private val myCompilationUnits = new mutable.LinkedHashMap[URI, CompilationUnit] @@ -281,7 +277,7 @@ class InteractiveDriver(val settings: List[String]) extends Driver { if (t.symbol.exists && t.hasType) { if (!t.symbol.isCompleted) t.symbol.info = UnspecifiedErrorType t.symbol.annotations.foreach { annot => - /* In some cases annotations are are used on themself (possibly larger cycles). + /* In some cases annotations are used on themself (possibly larger cycles). * This is the case with the java.lang.annotation.Target annotation, would end * in an infinite loop while cleaning. The `seen` is added to ensure that those * trees are not cleand twice. diff --git a/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala b/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala index 5480d4a43043..b950d71eb045 100644 --- a/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala +++ b/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala @@ -33,7 +33,7 @@ case class SourceTree(tree: tpd.Import | tpd.NameTree, source: SourceFile) { } val position = { // FIXME: This is incorrect in some cases, like with backquoted identifiers, - // see https://github.com/lampepfl/dotty/pull/1634#issuecomment-257079436 + // see https://github.com/scala/scala3/pull/1634#issuecomment-257079436 val (start, end) = if (!treeSpan.isSynthetic) (treeSpan.point, treeSpan.point + nameLength) @@ -42,7 +42,12 @@ case class SourceTree(tree: tpd.Import | tpd.NameTree, source: SourceFile) { (treeSpan.end - nameLength, treeSpan.end) Span(start, end, start) } - source.atSpan(position) + // Don't widen the span, only narrow. + // E.g. The star in a wildcard export is 1 character, + // and that is the span of the type alias that results from it + // but the name may very well be larger, which we don't want. + val span1 = if treeSpan.contains(position) then position else treeSpan + source.atSpan(span1) } case _ => NoSourcePosition diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala index f7ef86ee5cde..e98ff6c9d66d 100644 --- a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala @@ -854,13 +854,13 @@ object JavaParsers { val accessors = (for (name, (tpt, annots)) <- fieldsByName yield - DefDef(name, Nil, tpt, unimplementedExpr) + DefDef(name, List(Nil), tpt, unimplementedExpr) .withMods(Modifiers(Flags.JavaDefined | Flags.Method | Flags.Synthetic)) ).toList // generate the canonical constructor val canonicalConstructor = - DefDef(nme.CONSTRUCTOR, joinParams(tparams, List(header)), TypeTree(), EmptyTree) + DefDef(nme.CONSTRUCTOR, joinParams(Nil, List(header)), TypeTree(), EmptyTree) .withMods(Modifiers(Flags.JavaDefined | Flags.Synthetic, mods.privateWithin)) // return the trees @@ -872,7 +872,7 @@ object JavaParsers { tparams = tparams, needsDummyConstr = true ) - ).withMods(mods) + ).withMods(mods.withFlags(Flags.JavaDefined | Flags.Final)) } addCompanionObject(statics, recordTypeDef) end recordDecl diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 47b7ffbbc840..6892dfdd94ca 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -906,6 +906,7 @@ object Parsers { var braces = 0 while (true) { val token = lookahead.token + if (query != LARROW && token == XMLSTART) return false if (braces == 0) { if (token == query) return true if (stopScanTokens.contains(token) || lookahead.isNestedEnd) return false @@ -927,6 +928,7 @@ object Parsers { lookahead.nextToken() while (parens != 0 && lookahead.token != EOF) { val token = lookahead.token + if (token == XMLSTART) return true if (token == LPAREN) parens += 1 else if (token == RPAREN) parens -= 1 lookahead.nextToken() @@ -1763,12 +1765,11 @@ object Parsers { RefinedTypeTree(rejectWildcardType(t), refinement(indentOK = true)) }) else if Feature.ccEnabled && in.isIdent(nme.UPARROW) && isCaptureUpArrow then - val upArrowStart = in.offset - in.nextToken() - def cs = - if in.token == LBRACE then captureSet() - else atSpan(upArrowStart)(captureRoot) :: Nil - makeRetaining(t, cs, tpnme.retains) + atSpan(t.span.start): + in.nextToken() + if in.token == LBRACE + then makeRetaining(t, captureSet(), tpnme.retains) + else makeRetaining(t, Nil, tpnme.retainsCap) else t } @@ -2651,6 +2652,8 @@ object Parsers { parents match { case parent :: Nil if !in.isNestedStart => reposition(if (parent.isType) ensureApplied(wrapNew(parent)) else parent) + case tkn if in.token == INDENT => + New(templateBodyOpt(emptyConstructor, parents, Nil)) case _ => New(reposition(templateBodyOpt(emptyConstructor, parents, Nil))) } @@ -3151,7 +3154,8 @@ object Parsers { } if mods1.is(Local) then report.errorOrMigrationWarning( - em"""The [this] qualifier will be deprecated in the future; it should be dropped. + em"""Ignoring [this] qualifier. + |This syntax will be deprecated in the future; it should be dropped. |See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html${rewriteNotice(`3.4-migration`)}""", in.sourcePos(), MigrationVersion.RemoveThisQualifier) @@ -3313,7 +3317,7 @@ object Parsers { /** ContextTypes ::= FunArgType {‘,’ FunArgType} */ def contextTypes(paramOwner: ParamOwner, numLeadParams: Int, impliedMods: Modifiers): List[ValDef] = - val tps = commaSeparated(funArgType) + val tps = commaSeparated(() => paramTypeOf(toplevelTyp)) var counter = numLeadParams def nextIdx = { counter += 1; counter } val paramFlags = if paramOwner.isClass then LocalParamAccessor else Param diff --git a/compiler/src/dotty/tools/dotc/printing/Formatting.scala b/compiler/src/dotty/tools/dotc/printing/Formatting.scala index 02f470324e8a..ac13f0161c70 100644 --- a/compiler/src/dotty/tools/dotc/printing/Formatting.scala +++ b/compiler/src/dotty/tools/dotc/printing/Formatting.scala @@ -24,6 +24,17 @@ object Formatting { object Shown: given [A: Show]: Conversion[A, Shown] = Show[A].show(_) + extension (s: Shown) + def runCtxShow(using Context): Shown = s match + case cs: CtxShow => cs.run + case _ => s + + def toStr(x: Shown)(using Context): String = x match + case seq: Seq[?] => seq.map(toStr).mkString("[", ", ", "]") + case res => res.tryToShow + + import Shown.runCtxShow + sealed abstract class Show[-T]: /** Show a value T by returning a "shown" result. */ def show(x: T): Shown @@ -31,10 +42,9 @@ object Formatting { trait CtxShow: def run(using Context): Shown - extension (s: Shown) - def ctxShow(using Context): Shown = s match - case cs: CtxShow => cs.run - case _ => s + private inline def CtxShow(inline x: Context ?=> Shown) = new CtxShow { def run(using Context) = x(using ctx) } + private def toStr[A: Show](x: A)(using Context): String = Shown.toStr(toShown(x)) + private def toShown[A: Show](x: A)(using Context): Shown = Show[A].show(x).runCtxShow /** The base implementation, passing the argument to StringFormatter which will try to `.show` it. */ object ShowAny extends Show[Any]: @@ -54,16 +64,26 @@ object Formatting { object Show extends ShowImplicits1: inline def apply[A](using inline z: Show[A]): Show[A] = z + given [X: Show]: Show[Option[X]] with + def show(x: Option[X]) = + CtxShow(x.map(toStr)) + end given + given [X: Show]: Show[Seq[X]] with - def show(x: Seq[X]) = new CtxShow: - def run(using Context) = x.map(show1) + def show(x: Seq[X]) = CtxShow(x.map(toStr)) + + given [K: Show, V: Show]: Show[Map[K, V]] with + def show(x: Map[K, V]) = + CtxShow(x.map((k, v) => s"${toStr(k)} => ${toStr(v)}")) + end given given [H: Show, T <: Tuple: Show]: Show[H *: T] with - def show(x: H *: T) = new CtxShow: - def run(using Context) = show1(x.head) *: Show[T].show(x.tail).ctxShow.asInstanceOf[Tuple] + def show(x: H *: T) = + CtxShow(toStr(x.head) *: toShown(x.tail).asInstanceOf[Tuple]) + end given given [X: Show]: Show[X | Null] with - def show(x: X | Null) = if x == null then "null" else Show[X].show(x.nn) + def show(x: X | Null) = if x == null then "null" else CtxShow(toStr(x.nn)) given Show[FlagSet] with def show(x: FlagSet) = x.flagsString @@ -79,7 +99,13 @@ object Formatting { case ast.TreeInfo.Impure => "PurityLevel.Impure" case ast.TreeInfo.PurePath => "PurityLevel.PurePath" case ast.TreeInfo.IdempotentPath => "PurityLevel.IdempotentPath" - case _ => s"PurityLevel(${x.x})" + case _ => s"PurityLevel(${x.x.toBinaryString})" + + given Show[Atoms] with + def show(x: Atoms) = x match + case Atoms.Unknown => "Unknown" + case Atoms.Range(lo, hi) => CtxShow(s"Range(${toStr(lo.toList)}, ${toStr(hi.toList)})") + end given given Show[Showable] = ShowAny given Show[Shown] = ShowAny @@ -101,11 +127,6 @@ object Formatting { given Show[util.Spans.Span] = ShowAny given Show[tasty.TreeUnpickler#OwnerTree] = ShowAny given Show[typer.ForceDegree.Value] = ShowAny - - private def show1[A: Show](x: A)(using Context) = show2(Show[A].show(x).ctxShow) - private def show2(x: Shown)(using Context): String = x match - case seq: Seq[?] => seq.map(show2).mkString("[", ", ", "]") - case res => res.tryToShow end Show end ShownDef export ShownDef.{ Show, Shown } @@ -122,7 +143,7 @@ object Formatting { class StringFormatter(protected val sc: StringContext) { protected def showArg(arg: Any)(using Context): String = arg.tryToShow - private def treatArg(arg: Shown, suffix: String)(using Context): (String, String) = arg.ctxShow match { + private def treatArg(arg: Shown, suffix: String)(using Context): (String, String) = arg.runCtxShow match { case arg: Seq[?] if suffix.indexOf('%') == 0 && suffix.indexOf('%', 1) != -1 => val end = suffix.indexOf('%', 1) val sep = StringContext.processEscapes(suffix.substring(1, end)) diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 83e6a3b204c3..8fc0c568e125 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -15,7 +15,7 @@ import util.SourcePosition import scala.util.control.NonFatal import scala.annotation.switch import config.{Config, Feature} -import cc.{CapturingType, RetainingType, CaptureSet, ReachCapability, isBoxed, levelOwner, retainedElems} +import cc.{CapturingType, RetainingType, CaptureSet, ReachCapability, MaybeCapability, isBoxed, levelOwner, retainedElems} class PlainPrinter(_ctx: Context) extends Printer { @@ -404,6 +404,7 @@ class PlainPrinter(_ctx: Context) extends Printer { case tp: TermRef if tp.symbol == defn.captureRoot => Str("cap") case tp: SingletonType => toTextRef(tp) case ReachCapability(tp1) => toTextRef(tp1) ~ "*" + case MaybeCapability(tp1) => toTextRef(tp1) ~ "?" case _ => toText(tp) protected def isOmittablePrefix(sym: Symbol): Boolean = diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index de9e21aa4146..5d8b448e409c 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -27,7 +27,7 @@ import config.{Config, Feature} import dotty.tools.dotc.util.SourcePosition import dotty.tools.dotc.ast.untpd.{MemberDef, Modifiers, PackageDef, RefTree, Template, TypeDef, ValOrDefDef} -import cc.{CaptureSet, CapturingType, toCaptureSet, IllegalCaptureRef} +import cc.{CaptureSet, CapturingType, toCaptureSet, IllegalCaptureRef, isRetains} import dotty.tools.dotc.parsing.JavaParsers class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { @@ -643,7 +643,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { def toTextRetainsAnnot = try changePrec(GlobalPrec)(toText(arg) ~ "^" ~ toTextCaptureSet(captureSet)) catch case ex: IllegalCaptureRef => toTextAnnot - if annot.symbol.maybeOwner == defn.RetainsAnnot + if annot.symbol.maybeOwner.isRetains && Feature.ccEnabled && !printDebug && Phases.checkCapturesPhase.exists // might be missing on -Ytest-pickler then toTextRetainsAnnot @@ -764,7 +764,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { val spliceTypeText = (keywordStr("[") ~ toTextGlobal(tree.typeOpt) ~ keywordStr("]")).provided(printDebug && tree.typeOpt.exists) keywordStr("$") ~ spliceTypeText ~ { if args.isEmpty then keywordStr("{") ~ inPattern(toText(pattern)) ~ keywordStr("}") - else toText(pattern.symbol.name) ~ "(" ~ toTextGlobal(args, ", ") ~ ")" + else toText(pattern) ~ "(" ~ toTextGlobal(args, ", ") ~ ")" } case Hole(isTerm, idx, args, content) => val (prefix, postfix) = if isTerm then ("{{{", "}}}") else ("[[[", "]]]") diff --git a/compiler/src/dotty/tools/dotc/quoted/Interpreter.scala b/compiler/src/dotty/tools/dotc/quoted/Interpreter.scala index c124e12077fe..17e23ebcf014 100644 --- a/compiler/src/dotty/tools/dotc/quoted/Interpreter.scala +++ b/compiler/src/dotty/tools/dotc/quoted/Interpreter.scala @@ -353,11 +353,16 @@ object Interpreter: if !ctx.compilationUnit.isSuspendable then None else targetException match case _: NoClassDefFoundError | _: ClassNotFoundException => - val className = targetException.getMessage - if className eq null then None + val message = targetException.getMessage + if message eq null then None else - val sym = staticRef(className.toTypeName).symbol - if (sym.isDefinedInCurrentRun) Some(sym) else None + val className = message.replace('/', '.') + val sym = + if className.endsWith(str.MODULE_SUFFIX) then staticRef(className.toTermName).symbol.moduleClass + else staticRef(className.toTypeName).symbol + // If the symbol does not a a position we assume that it came from the current run and it has an error + if sym.isDefinedInCurrentRun || (sym.exists && !sym.srcPos.span.exists) then Some(sym) + else None case _ => None } } diff --git a/compiler/src/dotty/tools/dotc/report.scala b/compiler/src/dotty/tools/dotc/report.scala index 8e39afdd6e7d..a63b6569fefe 100644 --- a/compiler/src/dotty/tools/dotc/report.scala +++ b/compiler/src/dotty/tools/dotc/report.scala @@ -154,7 +154,7 @@ object report: | | An unhandled exception was thrown in the compiler. | Please file a crash report here: - | https://github.com/lampepfl/dotty/issues/new/choose + | https://github.com/scala/scala3/issues/new/choose | For non-enriched exceptions, compile with -Yno-enrich-error-messages. | |$info1 diff --git a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala index f5e7f9d44f56..6011587a7100 100644 --- a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala +++ b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala @@ -206,6 +206,7 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe case PureUnitExpressionID // errorNumber: 190 case MatchTypeLegacyPatternID // errorNumber: 191 case UnstableInlineAccessorID // errorNumber: 192 + case VolatileOnValID // errorNumber: 193 def errorNumber = ordinal - 1 diff --git a/compiler/src/dotty/tools/dotc/reporting/Message.scala b/compiler/src/dotty/tools/dotc/reporting/Message.scala index 484789a7fe45..1ac5c6ecf407 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Message.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Message.scala @@ -57,8 +57,7 @@ object Message: def openLambda(tp: LambdaType): Unit = openedLambdas += tp - val seen = new collection.mutable.HashMap[SeenKey, List[Recorded]]: - override def default(key: SeenKey) = Nil + val seen = new collection.mutable.HashMap[SeenKey, List[Recorded]].withDefaultValue(Nil) var nonSensical = false @@ -77,8 +76,7 @@ object Message: * and following recordings get consecutive superscripts starting with 2. * @return The possibly superscripted version of `str`. */ - def record(str: String, isType: Boolean, entry: Recorded)(using Context): String = - if !recordOK then return str + def record(str: String, isType: Boolean, entry: Recorded)(using Context): String = if !recordOK then str else //println(s"recording $str, $isType, $entry") /** If `e1` is an alias of another class of the same name, return the other @@ -147,7 +145,7 @@ object Message: } def addendum(cat: String, info: Type): String = info match { - case bounds @ TypeBounds(lo, hi) if bounds ne TypeBounds.empty => + case bounds @ TypeBounds(lo, hi) if !(bounds =:= TypeBounds.empty) && !bounds.isErroneous => if (lo eq hi) i" which is an alias of $lo" else i" with $cat ${boundsStr(bounds)}" case _ => @@ -177,9 +175,8 @@ object Message: def needsExplanation(entry: Recorded) = entry match { case param: TypeParamRef => ctx.typerState.constraint.contains(param) case param: ParamRef => false - case skolem: SkolemType => true - case sym: Symbol => - ctx.gadt.contains(sym) && ctx.gadt.fullBounds(sym) != TypeBounds.empty + case skolem: SkolemType => true + case sym: Symbol => ctx.gadt.contains(sym) && ctx.gadt.fullBounds(sym) != TypeBounds.empty } val toExplain: List[(String, Recorded)] = seen.toList.flatMap { kvs => @@ -192,7 +189,7 @@ object Message: (tickedString, alt) } } - res // help the inferrencer out + res // help the inferencer out }.sortBy(_._1) def columnar(parts: List[(String, String)]): List[String] = { @@ -271,11 +268,11 @@ end Message * * Messages modify the rendendering of interpolated strings in several ways: * - * 1. The size of the printed code is limited with a MessafeLimiter. If the message + * 1. The size of the printed code is limited with a MessageLimiter. If the message * would get too large or too deeply nested, a `...` is printed instead. - * 2. References to module classes are prefixed with `object ` for better recogniability. + * 2. References to module classes are prefixed with `object` for better recognizability. * 3. A where clause is sometimes added which contains the following additional explanations: - * - Rerences are disambiguated: If a message contains occurrences of the same identifier + * - References are disambiguated: If a message contains occurrences of the same identifier * representing different symbols, the duplicates are printed with superscripts * and the where-clause explains where each symbol is located. * - Uninstantiated variables are explained in the where-clause with additional diff --git a/compiler/src/dotty/tools/dotc/reporting/Reporter.scala b/compiler/src/dotty/tools/dotc/reporting/Reporter.scala index ca4114a82cdc..22500cbbaa48 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Reporter.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Reporter.scala @@ -172,19 +172,14 @@ abstract class Reporter extends interfaces.ReporterResult { end issueUnconfigured def issueIfNotSuppressed(dia: Diagnostic)(using Context): Unit = - def toErrorIfFatal(dia: Diagnostic) = dia match - case w: Warning if ctx.settings.silentWarnings.value => dia - case w: ConditionalWarning if w.isSummarizedConditional => dia - case w: Warning if ctx.settings.XfatalWarnings.value => w.toError - case _ => dia def go() = import Action.* dia match case w: Warning => WConf.parsed.action(dia) match case Error => issueUnconfigured(w.toError) - case Warning => issueUnconfigured(toErrorIfFatal(w)) - case Verbose => issueUnconfigured(toErrorIfFatal(w.setVerbose())) + case Warning => issueUnconfigured(w) + case Verbose => issueUnconfigured(w.setVerbose()) case Info => issueUnconfigured(w.toInfo) case Silent => case _ => issueUnconfigured(dia) @@ -214,6 +209,10 @@ abstract class Reporter extends interfaces.ReporterResult { def incomplete(dia: Diagnostic)(using Context): Unit = incompleteHandler(dia, ctx) + def finalizeReporting()(using Context) = + if (hasWarnings && ctx.settings.XfatalWarnings.value) + report(new Error("No warnings can be incurred under -Werror (or -Xfatal-warnings)", NoSourcePosition)) + /** Summary of warnings and errors */ def summary: String = { val b = new mutable.ListBuffer[String] diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index 4c7cf003cbc9..c230e3b4d6d7 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -84,6 +84,23 @@ abstract class PatternMatchMsg(errorId: ErrorMessageID)(using Context) extends M abstract class CyclicMsg(errorId: ErrorMessageID)(using Context) extends Message(errorId): def kind = MessageKind.Cyclic + val ex: CyclicReference + protected def cycleSym = ex.denot.symbol + + protected def debugInfo = + if ctx.settings.YdebugCyclic.value then + "\n\nStacktrace:" ++ ex.getStackTrace().nn.mkString("\n ", "\n ", "") + else "\n\n Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace." + + protected def context: String = ex.optTrace match + case Some(trace) => + s"\n\nThe error occurred while trying to ${ + trace.map((prefix, sym, suffix) => i"$prefix$sym$suffix").mkString("\n which required to ") + }$debugInfo" + case None => + "\n\n Run with -explain-cyclic for more details." +end CyclicMsg + abstract class ReferenceMsg(errorId: ErrorMessageID)(using Context) extends Message(errorId): def kind = MessageKind.Reference @@ -1249,9 +1266,9 @@ class UnreducibleApplication(tycon: Type)(using Context) extends TypeMsg(Unreduc |Such applications are equivalent to existential types, which are not |supported in Scala 3.""" -class OverloadedOrRecursiveMethodNeedsResultType(cycleSym: Symbol)(using Context) +class OverloadedOrRecursiveMethodNeedsResultType(val ex: CyclicReference)(using Context) extends CyclicMsg(OverloadedOrRecursiveMethodNeedsResultTypeID) { - def msg(using Context) = i"""Overloaded or recursive $cycleSym needs return type""" + def msg(using Context) = i"""Overloaded or recursive $cycleSym needs return type$context""" def explain(using Context) = i"""Case 1: $cycleSym is overloaded |If there are multiple methods named $cycleSym and at least one definition of @@ -1263,29 +1280,29 @@ extends CyclicMsg(OverloadedOrRecursiveMethodNeedsResultTypeID) { |""" } -class RecursiveValueNeedsResultType(cycleSym: Symbol)(using Context) +class RecursiveValueNeedsResultType(val ex: CyclicReference)(using Context) extends CyclicMsg(RecursiveValueNeedsResultTypeID) { - def msg(using Context) = i"""Recursive $cycleSym needs type""" + def msg(using Context) = i"""Recursive $cycleSym needs type$context""" def explain(using Context) = i"""The definition of $cycleSym is recursive and you need to specify its type. |""" } -class CyclicReferenceInvolving(denot: SymDenotation)(using Context) +class CyclicReferenceInvolving(val ex: CyclicReference)(using Context) extends CyclicMsg(CyclicReferenceInvolvingID) { def msg(using Context) = - val where = if denot.exists then s" involving $denot" else "" - i"Cyclic reference$where" + val where = if ex.denot.exists then s" involving ${ex.denot}" else "" + i"Cyclic reference$where$context" def explain(using Context) = - i"""|$denot is declared as part of a cycle which makes it impossible for the - |compiler to decide upon ${denot.name}'s type. - |To avoid this error, try giving ${denot.name} an explicit type. + i"""|${ex.denot} is declared as part of a cycle which makes it impossible for the + |compiler to decide upon ${ex.denot.name}'s type. + |To avoid this error, try giving ${ex.denot.name} an explicit type. |""" } -class CyclicReferenceInvolvingImplicit(cycleSym: Symbol)(using Context) +class CyclicReferenceInvolvingImplicit(val ex: CyclicReference)(using Context) extends CyclicMsg(CyclicReferenceInvolvingImplicitID) { - def msg(using Context) = i"""Cyclic reference involving implicit $cycleSym""" + def msg(using Context) = i"""Cyclic reference involving implicit $cycleSym$context""" def explain(using Context) = i"""|$cycleSym is declared as part of a cycle which makes it impossible for the |compiler to decide upon ${cycleSym.name}'s type. @@ -2340,9 +2357,9 @@ class TypeTestAlwaysDiverges(scrutTp: Type, testTp: Type)(using Context) extends } // Relative of CyclicReferenceInvolvingImplicit and RecursiveValueNeedsResultType -class TermMemberNeedsResultTypeForImplicitSearch(cycleSym: Symbol)(using Context) +class TermMemberNeedsResultTypeForImplicitSearch(val ex: CyclicReference)(using Context) extends CyclicMsg(TermMemberNeedsNeedsResultTypeForImplicitSearchID) { - def msg(using Context) = i"""$cycleSym needs result type because its right-hand side attempts implicit search""" + def msg(using Context) = i"""$cycleSym needs result type because its right-hand side attempts implicit search$context""" def explain(using Context) = i"""|The right hand-side of $cycleSym's definition requires an implicit search at the highlighted position. |To avoid this error, give `$cycleSym` an explicit type. @@ -2415,9 +2432,14 @@ class UnqualifiedCallToAnyRefMethod(stat: untpd.Tree, method: Symbol)(using Cont def kind = MessageKind.PotentialIssue def msg(using Context) = i"Suspicious top-level unqualified call to ${hl(method.name.toString)}" def explain(using Context) = + val getClassExtraHint = + if method.name == nme.getClass_ && ctx.settings.classpath.value.contains("scala3-staging") then + i"""\n\n + |This class should not be used to get the classloader for `scala.quoted.staging.Compile.make`.""" + else "" i"""Top-level unqualified calls to ${hl("AnyRef")} or ${hl("Any")} methods such as ${hl(method.name.toString)} are |resolved to calls on ${hl("Predef")} or on imported methods. This might not be what - |you intended.""" + |you intended.$getClassExtraHint""" } class SynchronizedCallOnBoxedClass(stat: tpd.Tree)(using Context) @@ -2553,13 +2575,13 @@ class UnknownNamedEnclosingClassOrObject(name: TypeName)(using Context) """ } -class IllegalCyclicTypeReference(sym: Symbol, where: String, lastChecked: Type)(using Context) +class IllegalCyclicTypeReference(val ex: CyclicReference, sym: Symbol, where: String, lastChecked: Type)(using Context) extends CyclicMsg(IllegalCyclicTypeReferenceID) { def msg(using Context) = val lastCheckedStr = try lastChecked.show catch case ex: CyclicReference => "..." - i"illegal cyclic type reference: ${where} ${hl(lastCheckedStr)} of $sym refers back to the type itself" + i"illegal cyclic type reference: ${where} ${hl(lastCheckedStr)} of $sym refers back to the type itself$context" def explain(using Context) = "" } @@ -3128,3 +3150,8 @@ class UnstableInlineAccessor(accessed: Symbol, accessorTree: tpd.Tree)(using Con if accessor.owner.name.isPackageObjectName then accessor.owner.owner.name.stripModuleClassSuffix else accessor.owner.name.stripModuleClassSuffix } + +class VolatileOnVal()(using Context) +extends SyntaxMsg(VolatileOnValID): + protected def msg(using Context): String = "values cannot be volatile" + protected def explain(using Context): String = "" diff --git a/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala b/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala index 2586ad8604c3..305f61dfa177 100644 --- a/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala +++ b/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala @@ -15,7 +15,7 @@ import dotty.tools.dotc.reporting.CodeAction /** Handles rewriting of Scala2 files to Dotty */ object Rewrites { - private class PatchedFiles extends mutable.HashMap[SourceFile, Patches] + private type PatchedFiles = mutable.HashMap[SourceFile, Patches] private case class Patch(span: Span, replacement: String) { def delta = replacement.length - (span.end - span.start) diff --git a/compiler/src/dotty/tools/dotc/semanticdb/SemanticSymbolBuilder.scala b/compiler/src/dotty/tools/dotc/semanticdb/SemanticSymbolBuilder.scala index 6376fb86d6c5..50ea6ec48510 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/SemanticSymbolBuilder.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/SemanticSymbolBuilder.scala @@ -20,8 +20,7 @@ class SemanticSymbolBuilder: private val locals = mutable.HashMap[Symbol, Int]() /** The local symbol(s) starting at given offset */ - private val symsAtOffset = new mutable.HashMap[Int, Set[Symbol]](): - override def default(key: Int) = Set[Symbol]() + private val symsAtOffset = new mutable.HashMap[Int, Set[Symbol]]().withDefault(_ => Set[Symbol]()) def symbolName(sym: Symbol)(using Context): String = diff --git a/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala b/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala index 26c94407f35b..6c74f302b65d 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala @@ -30,6 +30,9 @@ class CheckStatic extends MiniPhase { override def description: String = CheckStatic.description + override def runsAfter: Set[String] = Set(UncacheGivenAliases.name) + // UncachedGivenAliases eliminates static lazy vals, which are flagged as errors here + override def transformTemplate(tree: tpd.Template)(using Context): tpd.Tree = { val defns = tree.body.collect{case t: ValOrDefDef => t} var hadNonStaticField = false diff --git a/compiler/src/dotty/tools/dotc/transform/CountOuterAccesses.scala b/compiler/src/dotty/tools/dotc/transform/CountOuterAccesses.scala index b5c02347d5d2..e55c3d953ac2 100644 --- a/compiler/src/dotty/tools/dotc/transform/CountOuterAccesses.scala +++ b/compiler/src/dotty/tools/dotc/transform/CountOuterAccesses.scala @@ -43,9 +43,7 @@ class CountOuterAccesses extends MiniPhase: // LambdaLift can create outer paths. These need to be known in this phase. /** The number of times an outer accessor that might be dropped is accessed */ - val outerAccessCount = new mutable.HashMap[Symbol, Int] { - override def default(s: Symbol): Int = 0 - } + val outerAccessCount = new mutable.HashMap[Symbol, Int].withDefaultValue(0) private def markAccessed(tree: RefTree)(using Context): Tree = val sym = tree.symbol diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index 8582420d64ee..9fdffb0ed537 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -2,6 +2,7 @@ package dotty.tools package dotc package transform +import ast.Trees import core.Phases.* import core.DenotTransformers.* import core.Denotations.* @@ -1044,7 +1045,21 @@ object Erasure { override def typedClassDef(cdef: untpd.TypeDef, cls: ClassSymbol)(using Context): Tree = if cls.is(Flags.Erased) then erasedDef(cls) - else super.typedClassDef(cdef, cls) + else + val typedTree@TypeDef(name, impl @ Template(constr, _, self, _)) = super.typedClassDef(cdef, cls): @unchecked + // In the case where a trait extends a class, we need to strip any non trait class from the signature + // and accept the first one (see tests/run/mixins.scala) + val newTraits = impl.parents.tail.filterConserve: tree => + def isTraitConstructor = tree match + case Trees.Block(_, expr) => // Specific management for trait constructors (see tests/pos/i9213.scala) + expr.symbol.isConstructor && expr.symbol.owner.is(Flags.Trait) + case _ => tree.symbol.isConstructor && tree.symbol.owner.is(Flags.Trait) + tree.symbol.is(Flags.Trait) || isTraitConstructor + + val newParents = + if impl.parents.tail eq newTraits then impl.parents + else impl.parents.head :: newTraits + cpy.TypeDef(typedTree)(rhs = cpy.Template(impl)(parents = newParents)) override def typedAnnotated(tree: untpd.Annotated, pt: Type)(using Context): Tree = typed(tree.arg, pt) diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala index fa2492a261d5..9a6a04621074 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala @@ -25,8 +25,8 @@ import ValueClasses.* * This is necessary since private methods are not allowed to have the same name * as inherited public ones. * - * See discussion in https://github.com/lampepfl/dotty/pull/784 - * and https://github.com/lampepfl/dotty/issues/783 + * See discussion in https://github.com/scala/scala3/pull/784 + * and https://github.com/scala/scala3/issues/783 */ class ExpandPrivate extends MiniPhase with IdentityDenotTransformer { thisPhase => import ast.tpd.* diff --git a/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala b/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala index 2723f726f064..3ff72d61d41f 100644 --- a/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala +++ b/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala @@ -98,10 +98,10 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer: start = pos.start, end = pos.end, // +1 to account for the line number starting at 1 - // the internal line number is 0-base https://github.com/lampepfl/dotty/blob/18ada516a85532524a39a962b2ddecb243c65376/compiler/src/dotty/tools/dotc/util/SourceFile.scala#L173-L176 + // the internal line number is 0-base https://github.com/scala/scala3/blob/18ada516a85532524a39a962b2ddecb243c65376/compiler/src/dotty/tools/dotc/util/SourceFile.scala#L173-L176 line = pos.line + 1, desc = sourceFile.content.slice(pos.start, pos.end).mkString, - symbolName = tree.symbol.name.toSimpleName.toString, + symbolName = tree.symbol.name.toSimpleName.show, treeName = tree.getClass.getSimpleName.nn, branch ) diff --git a/compiler/src/dotty/tools/dotc/transform/MacroAnnotations.scala b/compiler/src/dotty/tools/dotc/transform/MacroAnnotations.scala index dbc1639f4b55..939497caf31c 100644 --- a/compiler/src/dotty/tools/dotc/transform/MacroAnnotations.scala +++ b/compiler/src/dotty/tools/dotc/transform/MacroAnnotations.scala @@ -141,7 +141,7 @@ class MacroAnnotations(phase: IdentityDenotTransformer): def traverse(tree: tpd.Tree)(using Context): Unit = tree match case tdef @ TypeDef(_, template: Template) => val isSymbolInDecls = tdef.symbol.asClass.info.decls.toList.toSet - for tree <- template.body do + for tree <- template.body if tree.isDef do if tree.symbol.owner != tdef.symbol then report.error(em"Macro added a definition with the wrong owner - ${tree.symbol.owner} - ${tdef.symbol} in ${tree.source}", tree.srcPos) else if !isSymbolInDecls(tree.symbol) then diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index 7b196692a9c9..bed29a122399 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -512,9 +512,7 @@ object PatternMatcher { } private class RefCounter extends PlanTransform { - val count = new mutable.HashMap[Symbol, Int] { - override def default(key: Symbol) = 0 - } + val count = new mutable.HashMap[Symbol, Int].withDefaultValue(0) } /** Reference counts for all labels */ diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index d847d14603a2..17298a45e01e 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -547,8 +547,24 @@ object TreeChecker { i"owner chain = ${tree.symbol.ownersIterator.toList}%, %, ctxOwners = ${ctx.outersIterator.map(_.owner).toList}%, %") } + private def checkParents(tree: untpd.TypeDef)(using Context): Unit = { + val TypeDef(_, impl: Template) = tree: @unchecked + assert(ctx.owner.isClass) + val sym = ctx.owner.asClass + if !sym.isPrimitiveValueClass then + val symbolParents = sym.classInfo.parents.map(_.dealias.typeSymbol) + val treeParents = impl.parents.map(_.tpe.dealias.typeSymbol) + assert(symbolParents == treeParents, + i"""Parents of class symbol differs from the parents in the tree for $sym + | + |Parents in symbol: $symbolParents + |Parents in tree: $treeParents + |""".stripMargin) + } + override def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(using Context): Tree = { assert(sym.info.isInstanceOf[ClassInfo | TypeBounds], i"wrong type, expect a template or type bounds for ${sym.fullName}, but found: ${sym.info}") + if sym.isClass then checkParents(tdef) super.typedTypeDef(tdef, sym) } @@ -561,6 +577,8 @@ object TreeChecker { checkOwner(impl) checkOwner(impl.constr) + checkParents(cdef) + def isNonMagicalMember(x: Symbol) = !x.isValueClassConvertMethod && !x.name.is(DocArtifactName) && @@ -812,7 +830,7 @@ object TreeChecker { else err.getStackTrace.nn.mkString(" ", " \n", "") report.error( - s"""Malformed tree was found while expanding macro with -Xcheck-macros. + em"""Malformed tree was found while expanding macro with -Xcheck-macros. |The tree does not conform to the compiler's tree invariants. | |Macro was: diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 0df81f756925..012f2affffc1 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -3,23 +3,13 @@ package dotc package transform package patmat -import core.* -import Types.* -import Contexts.* -import Flags.* -import ast.* -import Decorators.{ show => _, * } -import Symbols.* -import StdNames.* -import NameOps.* -import Constants.* -import typer.* -import Applications.* -import Inferencing.* -import ProtoTypes.* +import core.*, Constants.*, Contexts.*, Decorators.*, Flags.*, Names.*, NameOps.*, StdNames.*, Symbols.*, Types.* +import ast.*, tpd.* +import config.Printers.* +import printing.{ Printer, * }, Texts.* import reporting.* -import config.Printers.{exhaustivity => debug} -import util.{SrcPos, NoSourcePosition} +import typer.*, Applications.*, Inferencing.*, ProtoTypes.* +import util.* import scala.annotation.internal.sharable import scala.collection.mutable @@ -56,7 +46,7 @@ import SpaceEngine.* */ /** space definition */ -sealed trait Space: +sealed trait Space extends Showable: @sharable private val isSubspaceCache = mutable.HashMap.empty[Space, Boolean] @@ -67,9 +57,7 @@ sealed trait Space: if (a ne a2) || (b ne b2) then a2.isSubspace(b2) else if a == Empty then true else if b == Empty then false - else trace(s"isSubspace(${show(this)}, ${show(b)})", debug) { - isSubspaceCache.getOrElseUpdate(b, computeIsSubspace(a, b)) - } + else isSubspaceCache.getOrElseUpdate(b, computeIsSubspace(a, b)) @sharable private var mySimplified: Space | Null = null @@ -80,6 +68,13 @@ sealed trait Space: mySimplified = simplified simplified else simplified + + def toText(p: Printer): Text = inContext(p.printerContext)(this match { + case Empty => s"Empty" + case sp: Typ => s"Typ(${display(sp)})" + case sp: Prod => s"Prod(${display(sp)})" + case sp: Or => s"Or(${display(sp)})" + }) end Space /** Empty space */ @@ -114,15 +109,13 @@ case class Prod(tp: Type, unappTp: TermRef, params: List[Space]) extends Space case class Or(spaces: Seq[Space]) extends Space object SpaceEngine { - import tpd.* - def simplify(space: Space)(using Context): Space = space.simplify def isSubspace(a: Space, b: Space)(using Context): Boolean = a.isSubspace(b) def canDecompose(typ: Typ)(using Context): Boolean = typ.canDecompose def decompose(typ: Typ)(using Context): List[Typ] = typ.decompose /** Simplify space such that a space equal to `Empty` becomes `Empty` */ - def computeSimplify(space: Space)(using Context): Space = trace(s"simplify ${show(space)} --> ", debug, show)(space match { + def computeSimplify(space: Space)(using Context): Space = trace(i"simplify($space)")(space match { case Prod(tp, fun, spaces) => val sps = spaces.mapconserve(simplify) if sps.contains(Empty) then Empty @@ -173,7 +166,7 @@ object SpaceEngine { } /** Is `a` a subspace of `b`? Equivalent to `simplify(simplify(a) - simplify(b)) == Empty`, but faster */ - def computeIsSubspace(a: Space, b: Space)(using Context): Boolean = { + def computeIsSubspace(a: Space, b: Space)(using Context): Boolean = trace(i"isSubspace($a, $b)") { val a2 = simplify(a) val b2 = simplify(b) if (a ne a2) || (b ne b2) then isSubspace(a2, b2) @@ -202,7 +195,7 @@ object SpaceEngine { } /** Intersection of two spaces */ - def intersect(a: Space, b: Space)(using Context): Space = trace(s"${show(a)} & ${show(b)}", debug, show) { + def intersect(a: Space, b: Space)(using Context): Space = trace(i"intersect($a & $b)") { (a, b) match { case (Empty, _) | (_, Empty) => Empty case (_, Or(ss)) => Or(ss.map(intersect(a, _)).filter(_ ne Empty)) @@ -211,11 +204,11 @@ object SpaceEngine { if isSubType(tp1, tp2) then a else if isSubType(tp2, tp1) then b else intersectUnrelatedAtomicTypes(tp1, tp2)(a) - case (a @ Typ(tp1, _), Prod(tp2, fun, ss)) => + case (a @ Typ(tp1, _), b @ Prod(tp2, fun, ss)) => if isSubType(tp2, tp1) then b else if isSubType(tp1, tp2) then a // problematic corner case: inheriting a case class else intersectUnrelatedAtomicTypes(tp1, tp2)(b) - case (Prod(tp1, fun, ss), b @ Typ(tp2, _)) => + case (a @ Prod(tp1, fun, ss), b @ Typ(tp2, _)) => if isSubType(tp1, tp2) then a else if isSubType(tp2, tp1) then a // problematic corner case: inheriting a case class else intersectUnrelatedAtomicTypes(tp1, tp2)(a) @@ -227,7 +220,7 @@ object SpaceEngine { } /** The space of a not covered by b */ - def minus(a: Space, b: Space)(using Context): Space = trace(s"${show(a)} - ${show(b)}", debug, show) { + def minus(a: Space, b: Space)(using Context): Space = trace(i"minus($a - $b)") { (a, b) match { case (Empty, _) => Empty case (_, Empty) => a @@ -291,8 +284,8 @@ object SpaceEngine { /** Is the unapply or unapplySeq irrefutable? * @param unapp The unapply function tree */ - def isIrrefutable(unapp: tpd.Tree, argLen: Int)(using Context): Boolean = { - tpd.funPart(unapp).tpe match + def isIrrefutable(unapp: Tree, argLen: Int)(using Context): Boolean = { + funPart(unapp).tpe match case funRef: TermRef => isIrrefutable(funRef, argLen) case _: ErrorType => false } @@ -301,7 +294,7 @@ object SpaceEngine { * @param body The body of the quoted pattern * @param bodyPt The scrutinee body type */ - def isIrrefutableQuotePattern(pat: tpd.QuotePattern, pt: Type)(using Context): Boolean = { + def isIrrefutableQuotePattern(pat: QuotePattern, pt: Type)(using Context): Boolean = { if pat.body.isType then pat.bindings.isEmpty && pt =:= pat.tpe else pat.body match case _: SplicePattern | Typed(_: SplicePattern, _) => pat.bindings.isEmpty && pt <:< pat.tpe @@ -313,24 +306,24 @@ object SpaceEngine { * The types should be atomic (non-decomposable) and unrelated (neither * should be a subtype of the other). */ - def intersectUnrelatedAtomicTypes(tp1: Type, tp2: Type)(sp: Space)(using Context): Space = trace(i"atomic intersection: ${AndType(tp1, tp2)}", debug, show) { + def intersectUnrelatedAtomicTypes(tp1: Type, tp2: Type)(sp: Typ | Prod)(using Context): Space = trace(i"intersectUnrelatedAtomicTypes($tp1, $tp2)(${sp.className})") { // Precondition: !isSubType(tp1, tp2) && !isSubType(tp2, tp1). + def intersection = sp match + case sp: Prod => sp.copy(AndType(tp1, tp2)) + case sp: Typ => sp.copy(AndType(tp1, tp2)) if !ctx.mode.is(Mode.SafeNulls) && (tp1.isNullType || tp2.isNullType) then // Since projections of types don't include null, intersection with null is empty. Empty - else - val intersection = sp match - case sp: Prod => sp.copy(AndType(tp1, tp2)) - case _ => Typ(AndType(tp1, tp2), decomposed = false) + else if tp1.classSymbol.isNumericValueClass && tp2.classSymbol.isNumericValueClass then // unrelated numeric value classes can equal each other, so let's not consider type space intersection empty - if tp1.classSymbol.isNumericValueClass && tp2.classSymbol.isNumericValueClass then intersection - else if isPrimToBox(tp1, tp2) || isPrimToBox(tp2, tp1) then intersection - else if TypeComparer.provablyDisjoint(tp1, tp2) then Empty - else intersection + intersection + else if isPrimToBox(tp1, tp2) || isPrimToBox(tp2, tp1) then intersection + else if TypeComparer.provablyDisjoint(tp1, tp2) then Empty + else intersection } /** Return the space that represents the pattern `pat` */ - def project(pat: Tree)(using Context): Space = trace(i"project($pat ${pat.className} ${pat.tpe})", debug, show)(pat match { + def project(pat: Tree)(using Context): Space = trace(i"project($pat ${pat.className} ${pat.tpe})")(pat match { case Literal(c) => if (c.value.isInstanceOf[Symbol]) Typ(c.value.asInstanceOf[Symbol].termRef, decomposed = false) @@ -447,7 +440,10 @@ object SpaceEngine { * This is needed to avoid spurious unreachable warnings. See tests/patmat/i6197.scala. */ private def erase(tp: Type, inArray: Boolean = false, isValue: Boolean = false, isTyped: Boolean = false)(using Context): Type = - trace(i"erase($tp${if inArray then " inArray" else ""}${if isValue then " isValue" else ""}${if isTyped then " isTyped" else ""})", debug)(tp match { + val inArr = if inArray then " inArray" else "" + val isVal = if isValue then " isValue" else "" + val isTyp = if isTyped then " isTyped" else "" + trace(i"erase($tp ${tp.className}$inArr$isVal$isTyp)")(tp match { case tp @ AppliedType(tycon, args) if tycon.typeSymbol.isPatternBound => WildcardType @@ -496,7 +492,7 @@ object SpaceEngine { tp.isPrimitiveValueType && (defn.boxedType(tp).classSymbol eq pt.classSymbol) /** Is `tp1` a subtype of `tp2`? */ - def isSubType(tp1: Type, tp2: Type)(using Context): Boolean = trace(i"$tp1 <:< $tp2", debug, show = true) { + def isSubType(tp1: Type, tp2: Type)(using Context): Boolean = trace(i"$tp1 <:< $tp2") { if tp1 == ConstantType(Constant(null)) && !ctx.mode.is(Mode.SafeNulls) then tp2 == ConstantType(Constant(null)) else if tp1.isTupleXXLExtract(tp2) then true // See isTupleXXLExtract, fixes TupleXXL parameter type @@ -520,11 +516,9 @@ object SpaceEngine { /** Return term parameter types of the extractor `unapp`. * Parameter types of the case class type `tp`. Adapted from `unapplyPlan` in patternMatcher */ - def signature(unapp: TermRef, scrutineeTp: Type, argLen: Int)(using Context): List[Type] = { + def signature(unapp: TermRef, scrutineeTp: Type, argLen: Int)(using Context): List[Type] = trace(i"signature($unapp, $scrutineeTp, $argLen)") { val unappSym = unapp.symbol - // println("scrutineeTp = " + scrutineeTp.show) - val mt: MethodType = unapp.widen match { case mt: MethodType => mt case pt: PolyType => @@ -583,8 +577,6 @@ object SpaceEngine { } } - debug.println(s"signature of ${unappSym.showFullName} ----> ${sig.map(_.show).mkString(", ")}") - sig.map(_.annotatedToRepeated) } @@ -602,7 +594,7 @@ object SpaceEngine { } /** Decompose a type into subspaces -- assume the type can be decomposed */ - def decompose(tp: Type)(using Context): List[Type] = trace(i"decompose($tp)", debug) { + def decompose(tp: Type)(using Context): List[Type] = trace(i"decompose($tp)") { def rec(tp: Type, mixins: List[Type]): List[Type] = tp.dealias match case AndType(tp1, tp2) => var tpB = tp2 @@ -619,7 +611,7 @@ object SpaceEngine { case OrType(tp1, tp2) => List(tp1, tp2) case tp if tp.isRef(defn.BooleanClass) => List(ConstantType(Constant(true)), ConstantType(Constant(false))) case tp if tp.isRef(defn.UnitClass) => ConstantType(Constant(())) :: Nil - case tp @ NamedType(Parts(parts), _) => parts.map(tp.derivedSelect) + case tp @ NamedType(Parts(parts), _) => if parts.exists(_ eq tp) then ListOfNoType else parts.map(tp.derivedSelect) case _: SingletonType => ListOfNoType case tp if tp.classSymbol.isAllOf(JavaEnum) => tp.classSymbol.children.map(_.termRef) // the class of a java enum value is the enum class, so this must follow SingletonType to not loop infinitely @@ -640,13 +632,11 @@ object SpaceEngine { else if (child.is(Private) || child.is(Sealed)) && child.isOneOf(AbstractOrTrait) then getChildren(child) else List(child) } - val children = getChildren(tp.classSymbol) - debug.println(i"candidates for $tp : $children") + val children = trace(i"getChildren($tp)")(getChildren(tp.classSymbol)) val parts = children.map { sym => val sym1 = if (sym.is(ModuleClass)) sym.sourceModule else sym - val refined = TypeOps.refineUsingParent(tp, sym1, mixins) - debug.println(i"$sym1 refined to $refined") + val refined = trace(i"refineUsingParent($tp, $sym1, $mixins)")(TypeOps.refineUsingParent(tp, sym1, mixins)) def inhabited(tp: Type): Boolean = tp.dealias match case AndType(tp1, tp2) => !TypeComparer.provablyDisjoint(tp1, tp2) @@ -658,7 +648,6 @@ object SpaceEngine { if inhabited(refined) then refined else NoType }.filter(_.exists) - debug.println(i"$tp decomposes to $parts") parts case _ => ListOfNoType @@ -668,17 +657,15 @@ object SpaceEngine { } extension (tp: Type) - /** A type is decomposable to children if it has a simple kind, it's sealed, - * abstract (or a trait) - so its not a sealed concrete class that can be instantiated on its own, - * has no anonymous children, which we wouldn't be able to name as counter-examples, - * but does have children. - * - * A sealed trait with no subclasses is considered not decomposable and thus is treated as an opaque type. - * A sealed trait with subclasses that then get removed after `refineUsingParent`, decomposes to the empty list. - * So that's why we consider whether a type has children. */ def isDecomposableToChildren(using Context): Boolean = - val cls = tp.classSymbol - tp.hasSimpleKind && cls.is(Sealed) && cls.isOneOf(AbstractOrTrait) && !cls.hasAnonymousChild && cls.children.nonEmpty + val sym = tp.typeSymbol // e.g. Foo[List[Int]] = type Foo (i19275) + val cls = tp.classSymbol // e.g. Foo[List[Int]] = class List + tp.hasSimpleKind // can't decompose higher-kinded types + && cls.is(Sealed) + && cls.isOneOf(AbstractOrTrait) // ignore sealed non-abstract classes + && !cls.hasAnonymousChild // can't name anonymous classes as counter-examples + && cls.children.nonEmpty // can't decompose without children + && !sym.isOpaqueAlias // can't instantiate subclasses to conform to an opaque type (i19275) val ListOfNoType = List(NoType) val ListOfTypNoType = ListOfNoType.map(Typ(_, decomposed = true)) @@ -693,49 +680,13 @@ object SpaceEngine { * * E.g. C.this.B --> B if current owner is C * C.this.x.T --> x.T if current owner is C - * X[T] --> X * C --> C if current owner is C !!! - * */ - def showType(tp: Type, showTypeArgs: Boolean = false)(using Context): String = { + private class LocalPrinter(_ctx: Context) extends RefinedPrinter(_ctx): val enclosingCls = ctx.owner.enclosingClass - - def isOmittable(sym: Symbol) = - sym.isEffectiveRoot || sym.isAnonymousClass || sym.name.isReplWrapperName || - ctx.definitions.unqualifiedOwnerTypes.exists(_.symbol == sym) || - sym.showFullName.startsWith("scala.") || - sym == enclosingCls || sym == enclosingCls.sourceModule - - def refinePrefix(tp: Type): String = tp match { - case NoPrefix => "" - case tp: NamedType if isOmittable(tp.symbol) => "" - case tp: ThisType => refinePrefix(tp.tref) - case tp: RefinedType => refinePrefix(tp.parent) - case tp: NamedType => tp.name.show.stripSuffix("$") - case tp: TypeVar => refinePrefix(tp.instanceOpt) - case _ => tp.show - } - - def refine(tp: Type): String = tp.stripped match { - case tp: RefinedType => refine(tp.parent) - case tp: AppliedType => - refine(tp.typeConstructor) + ( - if (showTypeArgs) tp.argInfos.map(refine).mkString("[", ",", "]") - else "" - ) - case tp: ThisType => refine(tp.tref) - case tp: NamedType => - val pre = refinePrefix(tp.prefix) - if (tp.name == tpnme.higherKinds) pre - else if (pre.isEmpty) tp.name.show.stripSuffix("$") - else pre + "." + tp.name.show.stripSuffix("$") - case tp: OrType => refine(tp.tp1) + " | " + refine(tp.tp2) - case _: TypeBounds => "_" - case _ => tp.show.stripSuffix("$") - } - - refine(tp) - } + override def isOmittablePrefix(sym: Symbol) = + super.isOmittablePrefix(sym) + || sym == enclosingCls || sym == enclosingCls.sourceModule /** Whether the counterexample is satisfiable. The space is flattened and non-empty. */ def satisfiable(sp: Space)(using Context): Boolean = { @@ -769,10 +720,8 @@ object SpaceEngine { checkConstraint(genConstraint(sp))(using ctx.fresh.setNewTyperState()) } - def showSpaces(ss: Seq[Space])(using Context): Seq[String] = ss.map(show) - - /** Display spaces */ - def show(s: Space)(using Context): String = { + /** Display spaces. Used for printing uncovered spaces in the in-exhaustive error message. */ + def display(s: Space)(using Context): String = inContext(ctx.fresh.setPrinterFn(LocalPrinter(_))) { def params(tp: Type): List[Type] = tp.classSymbol.primaryConstructor.info.firstParamTypes /** does the companion object of the given symbol have custom unapply */ @@ -789,39 +738,38 @@ object SpaceEngine { if (flattenList && tp <:< defn.NilType) "" else tp.symbol.showName case Typ(tp, decomposed) => - - val sym = tp.classSymbol - - if (ctx.definitions.isTupleNType(tp)) + val cls = tp.classSymbol + if ctx.definitions.isTupleNType(tp) then params(tp).map(_ => "_").mkString("(", ", ", ")") - else if (defn.ListType.isRef(sym)) - if (flattenList) "_*" else "_: List" - else if (defn.ConsType.isRef(sym)) - if (flattenList) "_, _*" else "List(_, _*)" - else if (tp.classSymbol.is(Sealed) && tp.classSymbol.hasAnonymousChild) - "_: " + showType(tp) + " (anonymous)" - else if (tp.classSymbol.is(CaseClass) && !hasCustomUnapply(tp.classSymbol)) - // use constructor syntax for case class - showType(tp) + params(tp).map(_ => "_").mkString("(", ", ", ")") - else if (decomposed) "_: " + showType(tp, showTypeArgs = true) - else "_" + else if defn.ListType.isRef(cls) then + if flattenList then "_*" else "_: List" + else if (defn.ConsType.isRef(cls)) + if flattenList then "_, _*" else "List(_, _*)" + else if cls.hasAnonymousChild then + s"_: ${tp.typeConstructor.show} (anonymous)" + else if cls.is(CaseClass) && !hasCustomUnapply(cls) then + // use constructor syntax for case class + tp.typeConstructor.show + params(tp).map(_ => "_").mkString("(", ", ", ")") + else if !decomposed then "_" + else "_: " + tp.show case Prod(tp, fun, params) => - if (ctx.definitions.isTupleNType(tp)) + if ctx.definitions.isTupleNType(tp) then "(" + params.map(doShow(_)).mkString(", ") + ")" - else if (tp.isRef(defn.ConsType.symbol)) - if (flattenList) params.map(doShow(_, flattenList)).filter(_.nonEmpty).mkString(", ") - else params.map(doShow(_, flattenList = true)).filter(!_.isEmpty).mkString("List(", ", ", ")") - else { - val sym = fun.symbol - val isUnapplySeq = sym.name.eq(nme.unapplySeq) + else if tp.isRef(defn.ConsType.symbol) then + val body = params.map(doShow(_, flattenList = true)).filter(_.nonEmpty).mkString(", ") + if flattenList then body else s"List($body)" + else + val isUnapplySeq = fun.symbol.name eq nme.unapplySeq val paramsStr = params.map(doShow(_, flattenList = isUnapplySeq)).mkString("(", ", ", ")") - showType(fun.prefix) + paramsStr - } + val prefix = fun.prefix match + case pre: TermRef => pre.symbol.typeRef + case pre => pre + prefix.typeConstructor.show + paramsStr case Or(ss) => ss.map(doShow(_, flattenList)).mkString(" | ") } - doShow(s, flattenList = false) + doShow(s) } private def exhaustivityCheckable(sel: Tree)(using Context): Boolean = { @@ -845,13 +793,11 @@ object SpaceEngine { else true // recursive case class: return true and other members can still fail the check } - val res = !sel.tpe.hasAnnotation(defn.UncheckedAnnot) && { + !sel.tpe.hasAnnotation(defn.UncheckedAnnot) + && { ctx.settings.YcheckAllPatmat.value || isCheckable(sel.tpe) } - - debug.println(s"exhaustivity checkable: ${sel.show} = $res") - res } /** Whether counter-examples should be further checked? True for GADTs. */ @@ -866,7 +812,7 @@ object SpaceEngine { /** Return the underlying type of non-module, non-constant, non-enum case singleton types. * Also widen ExprType to its result type, and rewrap any annotation wrappers. * For example, with `val opt = None`, widen `opt.type` to `None.type`. */ - def toUnderlying(tp: Type)(using Context): Type = trace(i"toUnderlying($tp)", show = true)(tp match { + def toUnderlying(tp: Type)(using Context): Type = trace(i"toUnderlying($tp)")(tp match { case _: ConstantType => tp case tp: TermRef if tp.symbol.is(Module) => tp case tp: TermRef if tp.symbol.isAllOf(EnumCase) => tp @@ -876,27 +822,25 @@ object SpaceEngine { case _ => tp }) - def checkExhaustivity(m: Match)(using Context): Unit = trace(i"checkExhaustivity($m)", debug) { + def checkExhaustivity(m: Match)(using Context): Unit = trace(i"checkExhaustivity($m)") { val selTyp = toUnderlying(m.selector.tpe).dealias - debug.println(i"selTyp = $selTyp") + val targetSpace = trace(i"targetSpace($selTyp)")(project(selTyp)) val patternSpace = Or(m.cases.foldLeft(List.empty[Space]) { (acc, x) => - val space = if (x.guard.isEmpty) project(x.pat) else Empty - debug.println(s"${x.pat.show} ====> ${show(space)}") + val space = if x.guard.isEmpty then trace(i"project(${x.pat})")(project(x.pat)) else Empty space :: acc }) val checkGADTSAT = shouldCheckExamples(selTyp) val uncovered = - flatten(simplify(minus(project(selTyp), patternSpace))).filter({ s => + flatten(simplify(minus(targetSpace, patternSpace))).filter({ s => s != Empty && (!checkGADTSAT || satisfiable(s)) }) - if uncovered.nonEmpty then val deduped = dedup(uncovered) - report.warning(PatternMatchExhaustivity(showSpaces(deduped), m), m.selector) + report.warning(PatternMatchExhaustivity(deduped.map(display), m), m.selector) } private def reachabilityCheckable(sel: Tree)(using Context): Boolean = @@ -909,17 +853,16 @@ object SpaceEngine { && !sel.tpe.widen.isRef(defn.QuotedExprClass) && !sel.tpe.widen.isRef(defn.QuotedTypeClass) - def checkReachability(m: Match)(using Context): Unit = trace(i"checkReachability($m)", debug) { + def checkReachability(m: Match)(using Context): Unit = trace(i"checkReachability($m)") { val cases = m.cases.toIndexedSeq val selTyp = toUnderlying(m.selector.tpe).dealias - debug.println(i"selTyp = $selTyp") val isNullable = selTyp.classSymbol.isNullableClass - val targetSpace = if isNullable + val targetSpace = trace(i"targetSpace($selTyp)")(if isNullable then project(OrType(selTyp, ConstantType(Constant(null)), soft = false)) else project(selTyp) - debug.println(s"targetSpace: ${show(targetSpace)}") + ) var i = 0 val len = cases.length @@ -929,16 +872,11 @@ object SpaceEngine { while (i < len) { val CaseDef(pat, guard, _) = cases(i) - debug.println(i"case pattern: $pat") - - val curr = project(pat) - debug.println(i"reachable? ${show(curr)}") + val curr = trace(i"project($pat)")(project(pat)) - val prev = simplify(Or(prevs)) - debug.println(s"prev: ${show(prev)}") + val covered = trace("covered")(simplify(intersect(curr, targetSpace))) - val covered = simplify(intersect(curr, targetSpace)) - debug.println(s"covered: ${show(covered)}") + val prev = trace("prev")(simplify(Or(prevs))) if prev == Empty && covered == Empty then // defer until a case is reachable deferred ::= pat diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 004b21ce4fb5..8a1db87a4f92 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -34,6 +34,7 @@ import Denotations.SingleDenotation import annotation.threadUnsafe import scala.util.control.NonFatal +import dotty.tools.dotc.inlines.Inlines object Applications { import tpd.* @@ -1408,6 +1409,50 @@ trait Applications extends Compatibility { } } + /** Inlines the unapply function before the dummy argument + * + * A call `P.unapply[...](using l1, ..)(`dummy`)(using t1, ..)` becomes + * ``` + * { + * class $anon { + * def unapply(s: S)(using t1: T1, ..): R = + * ... // inlined code for: P.unapply[...](using l1, ..)(s)(using t1, ..) + * } + * new $anon + * }.unapply(`dummy`)(using t1, ..) + * ``` + */ + def inlinedUnapplyFnAndApp(dummyArg: Tree, unapplyAppCall: Tree): (Tree, Tree) = + def rec(unapp: Tree): (Tree, Tree) = + unapp match + case DynamicUnapply(_) => + report.error(em"Structural unapply is not supported", unapplyFn.srcPos) + (unapplyFn, unapplyAppCall) + case Apply(fn, `dummyArg` :: Nil) => + val inlinedUnapplyFn = Inlines.inlinedUnapplyFun(fn) + (inlinedUnapplyFn, inlinedUnapplyFn.appliedToArgs(`dummyArg` :: Nil)) + case Apply(fn, args) => + val (fn1, app) = rec(fn) + (fn1, tpd.cpy.Apply(unapp)(app, args)) + + if unapplyAppCall.symbol.isAllOf(Transparent | Inline) then rec(unapplyAppCall) + else (unapplyFn, unapplyAppCall) + end inlinedUnapplyFnAndApp + + def unapplyImplicits(dummyArg: Tree, unapp: Tree): List[Tree] = + val res = List.newBuilder[Tree] + def loop(unapp: Tree): Unit = unapp match + case Apply(Apply(unapply, `dummyArg` :: Nil), args2) => assert(args2.nonEmpty); res ++= args2 + case Apply(unapply, `dummyArg` :: Nil) => + case Inlined(u, _, _) => loop(u) + case DynamicUnapply(_) => report.error(em"Structural unapply is not supported", unapplyFn.srcPos) + case Apply(fn, args) => assert(args.nonEmpty); loop(fn); res ++= args + case _ => ().assertingErrorsReported + + loop(unapp) + res.result() + end unapplyImplicits + /** Add a `Bind` node for each `bound` symbol in a type application `unapp` */ def addBinders(unapp: Tree, bound: List[Symbol]) = unapp match { case TypeApply(fn, args) => @@ -1446,20 +1491,10 @@ trait Applications extends Compatibility { unapplyArgType val dummyArg = dummyTreeOfType(ownType) - val unapplyApp = typedExpr(untpd.TypedSplice(Apply(unapplyFn, dummyArg :: Nil))) - def unapplyImplicits(unapp: Tree): List[Tree] = { - val res = List.newBuilder[Tree] - def loop(unapp: Tree): Unit = unapp match { - case Apply(Apply(unapply, `dummyArg` :: Nil), args2) => assert(args2.nonEmpty); res ++= args2 - case Apply(unapply, `dummyArg` :: Nil) => - case Inlined(u, _, _) => loop(u) - case DynamicUnapply(_) => report.error(em"Structural unapply is not supported", unapplyFn.srcPos) - case Apply(fn, args) => assert(args.nonEmpty); loop(fn); res ++= args - case _ => ().assertingErrorsReported - } - loop(unapp) - res.result() - } + val (newUnapplyFn, unapplyApp) = + val unapplyAppCall = withMode(Mode.NoInline): + typedExpr(untpd.TypedSplice(Apply(unapplyFn, dummyArg :: Nil))) + inlinedUnapplyFnAndApp(dummyArg, unapplyAppCall) var argTypes = unapplyArgs(unapplyApp.tpe, unapplyFn, args, tree.srcPos) for (argType <- argTypes) assert(!isBounds(argType), unapplyApp.tpe.show) @@ -1475,7 +1510,7 @@ trait Applications extends Compatibility { List.fill(argTypes.length - args.length)(WildcardType) } val unapplyPatterns = bunchedArgs.lazyZip(argTypes) map (typed(_, _)) - val result = assignType(cpy.UnApply(tree)(unapplyFn, unapplyImplicits(unapplyApp), unapplyPatterns), ownType) + val result = assignType(cpy.UnApply(tree)(newUnapplyFn, unapplyImplicits(dummyArg, unapplyApp), unapplyPatterns), ownType) unapp.println(s"unapply patterns = $unapplyPatterns") if (ownType.stripped eq selType.stripped) || ownType.isError then result else tryWithTypeTest(Typed(result, TypeTree(ownType)), selType) @@ -2088,34 +2123,27 @@ trait Applications extends Compatibility { else resolveMapped(alts1, _.widen.appliedTo(targs1.tpes), pt1) case pt => - val compat0 = pt.dealias match - case defn.FunctionNOf(args, resType, _) => - narrowByTypes(alts, args, resType) - case _ => - Nil - if (compat0.isEmpty) then - val compat = alts.filterConserve(normalizedCompatible(_, pt, keepConstraint = false)) - if (compat.isEmpty) - /* - * the case should not be moved to the enclosing match - * since SAM type must be considered only if there are no candidates - * For example, the second f should be chosen for the following code: - * def f(x: String): Unit = ??? - * def f: java.io.OutputStream = ??? - * new java.io.ObjectOutputStream(f) - */ - pt match { - case SAMType(mtp, _) => - narrowByTypes(alts, mtp.paramInfos, mtp.resultType) - case _ => - // pick any alternatives that are not methods since these might be convertible - // to the expected type, or be used as extension method arguments. - val convertible = alts.filterNot(alt => - normalize(alt, IgnoredProto(pt)).widenSingleton.isInstanceOf[MethodType]) - if convertible.length == 1 then convertible else compat - } - else compat - else compat0 + val compat = alts.filterConserve(normalizedCompatible(_, pt, keepConstraint = false)) + if compat.isEmpty then + pt match + case SAMType(mtp, _) => + // If we have a SAM type as expected type, treat it as if the expression was eta-expanded + // Note 1: No need to do that for function types, the previous normalizedCompatible test already + // handles those. + // Note 2: This case should not be moved to the enclosing match + // since fSAM types must be considered only if there are no candidates. + // For example, the second f should be chosen for the following code: + // def f(x: String): Unit = ??? + // def f: java.io.OutputStream = ??? + // new java.io.ObjectOutputStream(f) + narrowByTypes(alts, mtp.paramInfos, mtp.resultType) + case _ => + // pick any alternatives that are not methods since these might be convertible + // to the expected type, or be used as extension method arguments. + val convertible = alts.filterNot(alt => + normalize(alt, IgnoredProto(pt)).widenSingleton.isInstanceOf[MethodType]) + if convertible.length == 1 then convertible else compat + else compat } /** The type of alternative `alt` after instantiating its first parameter diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 81375fe73549..5fc63f4575e3 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -38,7 +38,7 @@ import config.Feature.sourceVersion import config.SourceVersion.* import config.MigrationVersion import printing.Formatting.hlAsKeyword -import cc.isCaptureChecking +import cc.{isCaptureChecking, isRetainsLike} import collection.mutable import reporting.* @@ -332,8 +332,14 @@ object Checking { || sym.owner.isContainedIn(prefix.cls) // sym reachable through member references ) case prefix: NamedType => - (!sym.is(Private) && prefix.derivesFrom(sym.owner)) || - (!prefix.symbol.moduleClass.isStaticOwner && isInteresting(prefix.prefix)) + !sym.is(Private) && prefix.derivesFrom(sym.owner) + || { + val pcls = prefix.symbol.moduleClass + if pcls.isStaticOwner then + pcls.span.exists && pcls.defRunId == ctx.runId // cheaper approximation to isDefinedInCurrentRun + else + isInteresting(prefix.prefix) + } case SuperType(thistp, _) => isInteresting(thistp) case AndType(tp1, tp2) => isInteresting(tp1) || isInteresting(tp2) case OrType(tp1, tp2) => isInteresting(tp1) && isInteresting(tp2) @@ -342,15 +348,27 @@ object Checking { case _ => false } - if (isInteresting(pre)) { - val pre1 = this(pre, false, false) - if (locked.contains(tp) || tp.symbol.infoOrCompleter.isInstanceOf[NoCompleter]) - throw CyclicReference(tp.symbol) - locked += tp - try if (!tp.symbol.isClass) checkInfo(tp.info) - finally locked -= tp - tp.withPrefix(pre1) - } + if isInteresting(pre) then + val traceCycles = CyclicReference.isTraced + try + if traceCycles then + CyclicReference.pushTrace("explore ", tp.symbol, " for cyclic references") + val pre1 = this(pre, false, false) + if locked.contains(tp) + || tp.symbol.infoOrCompleter.isInstanceOf[NoCompleter] + then + throw CyclicReference(tp.symbol) + locked += tp + try + if tp.symbol.isOpaqueAlias then + checkInfo(TypeAlias(tp.translucentSuperType)) + else if !tp.symbol.isClass then + checkInfo(tp.info) + finally + locked -= tp + tp.withPrefix(pre1) + finally + if traceCycles then CyclicReference.popTrace() else tp } catch { @@ -387,11 +405,15 @@ object Checking { */ def checkNonCyclic(sym: Symbol, info: Type, reportErrors: Boolean)(using Context): Type = { val checker = withMode(Mode.CheckCyclic)(new CheckNonCyclicMap(sym, reportErrors)) - try checker.checkInfo(info) + try + val toCheck = info match + case info: RealTypeBounds if sym.isOpaqueAlias => TypeAlias(sym.opaqueAlias) + case _ => info + checker.checkInfo(toCheck) catch { case ex: CyclicReference => if (reportErrors) - errorType(IllegalCyclicTypeReference(sym, checker.where, checker.lastChecked), sym.srcPos) + errorType(IllegalCyclicTypeReference(ex, sym, checker.where, checker.lastChecked), sym.srcPos) else info } } @@ -683,8 +705,7 @@ object Checking { declaredParents = tp.declaredParents.map(p => transformedParent(apply(p))) ) - case tp @ AnnotatedType(underlying, annot) - if annot.symbol == defn.RetainsAnnot || annot.symbol == defn.RetainsByNameAnnot => + case tp @ AnnotatedType(underlying, annot) if annot.symbol.isRetainsLike => val underlying1 = this(underlying) val saved = inCaptureSet inCaptureSet = true @@ -1158,9 +1179,7 @@ trait Checking { /** Check that class does not declare same symbol twice */ def checkNoDoubleDeclaration(cls: Symbol)(using Context): Unit = { - val seen = new mutable.HashMap[Name, List[Symbol]] { - override def default(key: Name) = Nil - } + val seen = new mutable.HashMap[Name, List[Symbol]].withDefaultValue(Nil) typr.println(i"check no double declarations $cls") def checkDecl(decl: Symbol): Unit = { @@ -1169,7 +1188,8 @@ trait Checking { def javaFieldMethodPair = decl.is(JavaDefined) && other.is(JavaDefined) && decl.is(Method) != other.is(Method) - if (decl.matches(other) && !javaFieldMethodPair) { + def staticNonStaticPair = decl.isScalaStatic != other.isScalaStatic + if (decl.matches(other) && !javaFieldMethodPair && !staticNonStaticPair) { def doubleDefError(decl: Symbol, other: Symbol): Unit = if (!decl.info.isErroneous && !other.info.isErroneous) report.error(DoubleDefinition(decl, other, cls), decl.srcPos) diff --git a/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala b/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala index 91303b00618c..c22d03ca77d7 100644 --- a/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala @@ -32,10 +32,16 @@ class CrossVersionChecks extends MiniPhase: checkMigration(sym, pos, xMigrationValue) end checkUndesiredProperties - /** If @deprecated is present, and the point of reference is not enclosed - * in either a deprecated member or a scala bridge method, issue a warning. - */ - private def checkDeprecated(sym: Symbol, pos: SrcPos)(using Context): Unit = + /**Skip warnings for synthetic members of case classes during declaration and + * scan the chain of outer declaring scopes from the current context + * a deprecation warning will be skipped if one the following holds + * for a given declaring scope: + * - the symbol associated with the scope is also deprecated. + * - if and only if `sym` is an enum case, the scope is either + * a module that declares `sym`, or the companion class of the + * module that declares `sym`. + */ + def skipWarning(sym: Symbol)(using Context): Boolean = /** is the owner an enum or its companion and also the owner of sym */ def isEnumOwner(owner: Symbol)(using Context) = @@ -46,26 +52,22 @@ class CrossVersionChecks extends MiniPhase: def isDeprecatedOrEnum(owner: Symbol)(using Context) = // pre: sym is an enumcase - owner.isDeprecated - || isEnumOwner(owner) - - /**Skip warnings for synthetic members of case classes during declaration and - * scan the chain of outer declaring scopes from the current context - * a deprecation warning will be skipped if one the following holds - * for a given declaring scope: - * - the symbol associated with the scope is also deprecated. - * - if and only if `sym` is an enum case, the scope is either - * a module that declares `sym`, or the companion class of the - * module that declares `sym`. - */ - def skipWarning(using Context): Boolean = - (ctx.owner.is(Synthetic) && sym.is(CaseClass)) - || ctx.owner.ownersIterator.exists(if sym.isEnumCase then isDeprecatedOrEnum else _.isDeprecated) + owner.isDeprecated || isEnumOwner(owner) + + (ctx.owner.is(Synthetic) && sym.is(CaseClass)) + || ctx.owner.ownersIterator.exists(if sym.isEnumCase then isDeprecatedOrEnum else _.isDeprecated) + end skipWarning + + + /** If @deprecated is present, and the point of reference is not enclosed + * in either a deprecated member or a scala bridge method, issue a warning. + */ + private def checkDeprecated(sym: Symbol, pos: SrcPos)(using Context): Unit = // Also check for deprecation of the companion class for synthetic methods val toCheck = sym :: (if sym.isAllOf(SyntheticMethod) then sym.owner.companionClass :: Nil else Nil) for sym <- toCheck; annot <- sym.getAnnotation(defn.DeprecatedAnnot) do - if !skipWarning then + if !skipWarning(sym) then val msg = annot.argumentConstant(0).map(": " + _.stringValue).getOrElse("") val since = annot.argumentConstant(1).map(" since " + _.stringValue).getOrElse("") report.deprecationWarning(em"${sym.showLocated} is deprecated${since}${msg}", pos) @@ -107,6 +109,18 @@ class CrossVersionChecks extends MiniPhase: } } + /** ??? */ + def checkDeprecatedInheritance(parents: List[Tree])(using Context): Unit = { + for parent <- parents + psym = parent.tpe.classSymbol + annot <- psym.getAnnotation(defn.DeprecatedInheritanceAnnot) + if !skipWarning(psym) + do + val msg = annot.argumentConstantString(0).map(msg => s": $msg").getOrElse("") + val since = annot.argumentConstantString(1).map(version => s" (since: $version)").getOrElse("") + report.deprecationWarning(em"inheritance from $psym is deprecated$since$msg", parent.srcPos) + } + override def transformValDef(tree: ValDef)(using Context): ValDef = checkDeprecatedOvers(tree) checkExperimentalAnnots(tree.symbol) @@ -122,6 +136,10 @@ class CrossVersionChecks extends MiniPhase: checkExperimentalAnnots(tree.symbol) tree + override def transformTemplate(tree: tpd.Template)(using Context): tpd.Tree = + checkDeprecatedInheritance(tree.parents) + tree + override def transformIdent(tree: Ident)(using Context): Ident = { checkUndesiredProperties(tree.symbol, tree.srcPos) tree @@ -141,10 +159,12 @@ class CrossVersionChecks extends MiniPhase: val tpe = tree.tpe tpe.foreachPart { case TypeRef(_, sym: Symbol) => - checkDeprecated(sym, tree.srcPos) + if tree.span.isSourceDerived then + checkDeprecated(sym, tree.srcPos) checkExperimentalRef(sym, tree.srcPos) case TermRef(_, sym: Symbol) => - checkDeprecated(sym, tree.srcPos) + if tree.span.isSourceDerived then + checkDeprecated(sym, tree.srcPos) checkExperimentalRef(sym, tree.srcPos) case _ => } diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 389669beff01..c3bf2dd822c9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -1074,7 +1074,7 @@ trait Implicits: if (argument.isEmpty) i"missing implicit parameter of type $pt after typer at phase ${ctx.phase.phaseName}" else i"type error: ${argument.tpe} does not conform to $pt${err.whyNoMatchStr(argument.tpe, pt)}") - val usableForInference = !pt.unusableForInference + val usableForInference = pt.exists && !pt.unusableForInference && (argument.isEmpty || !argument.tpe.unusableForInference) val result0 = if usableForInference then diff --git a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala index 7e35b8be8caa..ed37a869d612 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala @@ -205,7 +205,7 @@ object Inferencing { private def instantiate(tvar: TypeVar, fromBelow: Boolean): Boolean = if fromBelow && force.canImprove(tvar) then val inst = tvar.typeToInstantiateWith(fromBelow = true) - if apply(true, inst) then + if isFullyDefined(inst, ForceDegree.none) then // need to recursively check before improving, since improving adds type vars // which should not be instantiated at this point val better = improve(tvar)(inst) @@ -383,8 +383,9 @@ object Inferencing { def isSkolemFree(tp: Type)(using Context): Boolean = !tp.existsPart(_.isInstanceOf[SkolemType]) - /** The list of uninstantiated type variables bound by some prefix of type `T` which - * occur in at least one formal parameter type of a prefix application. + /** The list of uninstantiated type variables bound by some prefix of type `T` or + * by arguments of an application prefix, which occur at least once as a formal type parameter + * of an application either from a prefix or an argument of an application node. * Considered prefixes are: * - The function `f` of an application node `f(e1, .., en)` * - The function `f` of a type application node `f[T1, ..., Tn]` @@ -392,8 +393,10 @@ object Inferencing { * - The result expression `e` of a block `{s1; .. sn; e}`. */ def tvarsInParams(tree: Tree, locked: TypeVars)(using Context): List[TypeVar] = { - @tailrec def boundVars(tree: Tree, acc: List[TypeVar]): List[TypeVar] = tree match { - case Apply(fn, _) => boundVars(fn, acc) + def boundVars(tree: Tree, acc: List[TypeVar]): List[TypeVar] = tree match { + case Apply(fn, args) => + val argTpVars = args.flatMap(boundVars(_, Nil)) + boundVars(fn, acc ++ argTpVars) case TypeApply(fn, targs) => val tvars = targs.filter(_.isInstanceOf[InferredTypeTree]).tpes.collect { case tvar: TypeVar @@ -406,16 +409,18 @@ object Inferencing { case Block(_, expr) => boundVars(expr, acc) case _ => acc } - @tailrec def occurring(tree: Tree, toTest: List[TypeVar], acc: List[TypeVar]): List[TypeVar] = + def occurring(tree: Tree, toTest: List[TypeVar], acc: List[TypeVar]): List[TypeVar] = if (toTest.isEmpty) acc else tree match { - case Apply(fn, _) => + case Apply(fn, args) => + val argsOcc = args.flatMap(occurring(_, toTest, Nil)) + val argsNocc = toTest.filterNot(argsOcc.contains) fn.tpe.widen match { case mtp: MethodType => - val (occ, nocc) = toTest.partition(tvar => mtp.paramInfos.exists(tvar.occursIn)) - occurring(fn, nocc, occ ::: acc) + val (occ, nocc) = argsNocc.partition(tvar => mtp.paramInfos.exists(tvar.occursIn)) + occurring(fn, nocc, occ ::: argsOcc ::: acc) case _ => - occurring(fn, toTest, acc) + occurring(fn, argsNocc, argsOcc ::: acc) } case TypeApply(fn, targs) => occurring(fn, toTest, acc) case Select(pre, _) => occurring(pre, toTest, acc) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index f8ced1c6599a..3af87d311d9d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -22,6 +22,7 @@ import parsing.JavaParsers.JavaParser import parsing.Parsers.Parser import Annotations.* import Inferencing.* +import Nullables.* import transform.ValueClasses.* import TypeErasure.erasure import reporting.* @@ -784,12 +785,19 @@ class Namer { typer: Typer => protected def localContext(owner: Symbol): FreshContext = ctx.fresh.setOwner(owner).setTree(original) + /** Stores the latest NotNullInfos (updated by `setNotNullInfos`) */ + private var myNotNullInfos: List[NotNullInfo] | Null = null + /** The context with which this completer was created */ - given creationContext: Context = ictx + given creationContext[Dummy_so_its_a_def]: Context = + if myNotNullInfos == null then ictx else ictx.withNotNullInfos(myNotNullInfos.nn) // make sure testing contexts are not captured by completers assert(!ictx.reporter.isInstanceOf[ExploringReporter]) + def setNotNullInfos(infos: List[NotNullInfo]): Unit = + myNotNullInfos = infos + protected def typeSig(sym: Symbol): Type = original match case original: ValDef => if (sym.is(Module)) moduleValSig(sym) @@ -871,6 +879,10 @@ class Namer { typer: Typer => * with a user-defined method in the same scope with a matching type. */ private def invalidateIfClashingSynthetic(denot: SymDenotation): Unit = + + def isJavaRecord(owner: Symbol) = + owner.is(JavaDefined) && owner.derivesFrom(defn.JavaRecordClass) + def isCaseClassOrCompanion(owner: Symbol) = owner.isClass && { if (owner.is(Module)) owner.linkedClass.is(CaseClass) @@ -894,9 +906,9 @@ class Namer { typer: Typer => && (definesMember || inheritsConcreteMember) ) || - // remove synthetic constructor of a java Record if it clashes with a non-synthetic constructor - (denot.isConstructor - && denot.owner.is(JavaDefined) && denot.owner.derivesFrom(defn.JavaRecordClass) + // remove synthetic constructor or method of a java Record if it clashes with a non-synthetic constructor + (isJavaRecord(denot.owner) + && denot.is(Method) && denot.owner.unforcedDecls.lookupAll(denot.name).exists(c => c != denot.symbol && c.info.matches(denot.info)) ) ) @@ -1191,7 +1203,7 @@ class Namer { typer: Typer => target = target.etaExpand(target.typeParams) newSymbol( cls, forwarderName, - Exported | Final, + MandatoryExportTypeFlags | (sym.flags & RetainedExportTypeFlags), TypeAlias(target), coord = span) // Note: This will always create unparameterzied aliases. So even if the original type is @@ -1237,16 +1249,19 @@ class Namer { typer: Typer => then addPathMethodParams(pathMethod.info, mbr.info.widenExpr) else mbr.info.ensureMethodic (EmptyFlags, mbrInfo) - var flagMask = RetainedExportFlags - if sym.isTerm then flagMask |= HasDefaultParams | NoDefaultParams - var mbrFlags = Exported | Method | Final | maybeStable | sym.flags & flagMask - if sym.is(ExtensionMethod) || pathMethod.exists then - mbrFlags |= ExtensionMethod + var mbrFlags = MandatoryExportTermFlags | maybeStable | (sym.flags & RetainedExportTermFlags) + if pathMethod.exists then mbrFlags |= ExtensionMethod val forwarderName = checkNoConflict(alias, isPrivate = false, span) newSymbol(cls, forwarderName, mbrFlags, mbrInfo, coord = span) forwarder.info = avoidPrivateLeaks(forwarder) - forwarder.addAnnotations(sym.annotations.filterConserve(_.symbol != defn.BodyAnnot)) + forwarder.addAnnotations(sym.annotations.filterConserve { annot => + annot.symbol != defn.BodyAnnot + && annot.symbol != defn.TailrecAnnot + && annot.symbol != defn.MainAnnot + && !annot.symbol.derivesFrom(defn.MacroAnnotationClass) + && !annot.symbol.derivesFrom(defn.MainAnnotationClass) + }) if forwarder.isType then buf += tpd.TypeDef(forwarder.asType).withSpan(span) @@ -1719,8 +1734,9 @@ class Namer { typer: Typer => val tpe = (paramss: @unchecked) match case TypeSymbols(tparams) :: TermSymbols(vparams) :: Nil => tpFun(tparams, vparams) case TermSymbols(vparams) :: Nil => tpFun(Nil, vparams) + val rhsCtx = prepareRhsCtx(ctx.fresh, paramss) if (isFullyDefined(tpe, ForceDegree.none)) tpe - else typedAheadExpr(mdef.rhs, tpe).tpe + else typedAheadExpr(mdef.rhs, tpe)(using rhsCtx).tpe case TypedSplice(tpt: TypeTree) if !isFullyDefined(tpt.tpe, ForceDegree.none) => mdef match { @@ -1918,14 +1934,7 @@ class Namer { typer: Typer => var rhsCtx = ctx.fresh.addMode(Mode.InferringReturnType) if sym.isInlineMethod then rhsCtx = rhsCtx.addMode(Mode.InlineableBody) if sym.is(ExtensionMethod) then rhsCtx = rhsCtx.addMode(Mode.InExtensionMethod) - val typeParams = paramss.collect { case TypeSymbols(tparams) => tparams }.flatten - if (typeParams.nonEmpty) { - // we'll be typing an expression from a polymorphic definition's body, - // so we must allow constraining its type parameters - // compare with typedDefDef, see tests/pos/gadt-inference.scala - rhsCtx.setFreshGADTBounds - rhsCtx.gadtState.addToConstraint(typeParams) - } + rhsCtx = prepareRhsCtx(rhsCtx, paramss) def typedAheadRhs(pt: Type) = PrepareInlineable.dropInlineIfError(sym, @@ -1970,4 +1979,15 @@ class Namer { typer: Typer => lhsType orElse WildcardType } end inferredResultType + + /** Prepare a GADT-aware context used to type the RHS of a ValOrDefDef. */ + def prepareRhsCtx(rhsCtx: FreshContext, paramss: List[List[Symbol]])(using Context): FreshContext = + val typeParams = paramss.collect { case TypeSymbols(tparams) => tparams }.flatten + if typeParams.nonEmpty then + // we'll be typing an expression from a polymorphic definition's body, + // so we must allow constraining its type parameters + // compare with typedDefDef, see tests/pos/gadt-inference.scala + rhsCtx.setFreshGADTBounds + rhsCtx.gadtState.addToConstraint(typeParams) + rhsCtx } diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index 6b72f3a8b56e..53ae7438d381 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -126,7 +126,7 @@ object ProtoTypes { constrainResult(mt, pt) } } else { - // Best-effort to fix https://github.com/lampepfl/dotty/issues/9685 in the 3.3.x series + // Best-effort to fix https://github.com/scala/scala3/issues/9685 in the 3.3.x series // while preserving source compatibility as much as possible val methodMatchedType = constrainResult(mt, wildApprox(pt)) meth.is(Transparent) || methodMatchedType diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index fb692446f1df..f0914a9f6664 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -1001,6 +1001,10 @@ object RefChecks { report.error(em"private $sym cannot override ${other.showLocated}", sym.srcPos) end checkNoPrivateOverrides + def checkVolatile(sym: Symbol)(using Context): Unit = + if sym.isVolatile && !sym.is(Mutable) then + report.warning(VolatileOnVal(), sym.srcPos) + /** Check that unary method definition do not receive parameters. * They can only receive inferred parameters such as type parameters and implicit parameters. */ @@ -1183,6 +1187,7 @@ class RefChecks extends MiniPhase { thisPhase => if tree.symbol.exists then checkNoPrivateOverrides(tree) val sym = tree.symbol + checkVolatile(sym) if (sym.exists && sym.owner.isTerm) { tree.rhs match { case Ident(nme.WILDCARD) => report.error(UnboundPlaceholderParameter(), sym.srcPos) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index fe2a6f92eb97..f1db302e958c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -48,7 +48,7 @@ import staging.StagingLevel import reporting.* import Nullables.* import NullOpsDecorator.* -import cc.CheckCaptures +import cc.{CheckCaptures, isRetainsLike} import config.Config import config.MigrationVersion @@ -944,7 +944,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer * (x: T) to (x @ (w: T)). This is either `_` or `_*`. */ def cases(ifPat: => Tree, ifExpr: => Tree, wildName: TermName) = tree.expr match { - case id: untpd.Ident if (ctx.mode is Mode.Pattern) && untpd.isVarPattern(id) => + case id: untpd.Ident if (ctx.mode is Mode.Pattern) => if (id.name == nme.WILDCARD || id.name == nme.WILDCARD_STAR) ifPat else { import untpd.* @@ -1738,8 +1738,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer // Replace the underspecified expected type by one based on the closure method type defn.PartialFunctionOf(mt.firstParamTypes.head, mt.resultType) else - report.error(em"result type of lambda is an underspecified SAM type $samParent", tree.srcPos) - samParent + errorType(em"result type of lambda is an underspecified SAM type $samParent", tree.srcPos) TypeTree(targetTpe) case _ => if (mt.isParamDependent) @@ -1938,7 +1937,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer if (bounds != null) sym.info = bounds } b - case t: UnApply if t.symbol.is(Inline) => Inlines.inlinedUnapply(t) + case t: UnApply if t.symbol.is(Inline) => + assert(!t.symbol.is(Transparent)) + cpy.UnApply(t)(fun = Inlines.inlinedUnapplyFun(t.fun)) // TODO inline these in the inlining phase (see #19382) case t => t } } @@ -2547,10 +2548,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer def canBeInvalidated(sym: Symbol): Boolean = sym.is(Synthetic) && (desugar.isRetractableCaseClassMethodName(sym.name) || - (sym.isConstructor && sym.owner.derivesFrom(defn.JavaRecordClass))) + (sym.owner.is(JavaDefined) && sym.owner.derivesFrom(defn.JavaRecordClass) && sym.is(Method))) if !sym.info.exists then - // it's a discarded method (synthetic case class method or synthetic java record constructor), drop it + // it's a discarded method (synthetic case class method or synthetic java record constructor or overriden member), drop it assert(canBeInvalidated(sym)) sym.owner.info.decls.openForMutations.unlink(sym) return EmptyTree @@ -2939,9 +2940,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer val arg1 = typed(tree.arg, pt) if (ctx.mode is Mode.Type) { val cls = annot1.symbol.maybeOwner - if Feature.ccEnabled - && (cls == defn.RetainsAnnot || cls == defn.RetainsByNameAnnot) - then + if Feature.ccEnabled && cls.isRetainsLike then CheckCaptures.checkWellformed(arg1, annot1) if arg1.isType then assignType(cpy.Annotated(tree)(arg1, annot1), arg1, annot1) @@ -3362,12 +3361,11 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer mdef.getAttachment(SymOfTree) match { case Some(sym) => sym.infoOrCompleter match { case completer: Namer#Completer => - if (completer.creationContext.notNullInfos ne ctx.notNullInfos) + if completer.creationContext.notNullInfos ne ctx.notNullInfos then // The RHS of a val def should know about not null facts established // in preceding statements (unless the DefTree is completed ahead of time, // then it is impossible). - sym.info = Completer(completer.original)( - completer.creationContext.withNotNullInfos(ctx.notNullInfos)) + completer.setNotNullInfos(ctx.notNullInfos) true case _ => // If it has been completed, then it must be because there is a forward reference @@ -4300,8 +4298,12 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer case _ => } - /** Convert constructor proxy reference to a new expression */ - def newExpr = + /** If `tree` is a constructor proxy reference, convert it to a `new` expression, + * otherwise return EmptyTree. + */ + def newExpr(tree: Tree): Tree = + val ctorResultType = applyProxyResultType(tree) + if !ctorResultType.exists then return EmptyTree val qual = qualifier(tree) val tpt = qual match case Ident(name) => @@ -4312,7 +4314,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer cpy.Ident(qual)(qual.symbol.name.sourceModuleName.toTypeName) case _ => errorTree(tree, em"cannot convert from $tree to an instance creation expression") - val tycon = tree.tpe.widen.finalResultType.underlyingClassRef(refinementOK = false) + val tycon = ctorResultType.underlyingClassRef(refinementOK = false) typed( untpd.Select( untpd.New(untpd.TypedSplice(tpt.withType(tycon))), @@ -4320,9 +4322,19 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer pt) .showing(i"convert creator $tree -> $result", typr) - def isApplyProxy(tree: Tree) = tree match - case Select(_, nme.apply) => tree.symbol.isAllOf(ApplyProxyFlags) - case _ => false + /** If `tree` is a constructor proxy reference, return the type it constructs, + * otherwise return NoType. + */ + def applyProxyResultType(tree: Tree): Type = tree match + case Select(_, nme.apply) => + // can't use tree.symbol and tree.tpe.widen.finalResultType, because when overloaded + // tree.symbol is NoSymbol (via MultiDenotation.symbol) and tree.tpe won't widen. + tree.denot.altsWith(_.isAllOf(ApplyProxyFlags)) match + case denot :: _ => + // any of the constructors will do, in order to get the result type, so using the first one + denot.info.widen.finalResultType + case _ => NoType + case _ => NoType tree match { case _: MemberDef | _: PackageDef | _: Import | _: WithoutTypeOrPos[?] | _: Closure => tree @@ -4336,7 +4348,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer if needsTupledDual(ref, pt) && Feature.autoTuplingEnabled => adapt(tree, pt.tupledDual, locked) case _ => - adaptOverloaded(ref) + newExpr(tree).orElse(adaptOverloaded(ref)) } case poly: PolyType if !(ctx.mode is Mode.Type) && dummyTreeOfType.unapply(tree).isEmpty => @@ -4345,22 +4357,21 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer // Test case was but i18695.scala, but it got fixed by a different tweak in #18719. // We leave test for this condition in as a defensive measure in case // it arises somewhere else. - if isApplyProxy(tree) then newExpr - else if pt.isInstanceOf[PolyProto] then tree - else - var typeArgs = tree match - case Select(qual, nme.CONSTRUCTOR) => qual.tpe.widenDealias.argTypesLo.map(TypeTree(_)) - case _ => Nil - if typeArgs.isEmpty then typeArgs = constrained(poly, tree)._2.map(_.wrapInTypeTree(tree)) - convertNewGenericArray(readapt(tree.appliedToTypeTrees(typeArgs))) + newExpr(tree).orElse: + if pt.isInstanceOf[PolyProto] then tree + else + var typeArgs = tree match + case Select(qual, nme.CONSTRUCTOR) => qual.tpe.widenDealias.argTypesLo.map(TypeTree(_)) + case _ => Nil + if typeArgs.isEmpty then typeArgs = constrained(poly, tree)._2.map(_.wrapInTypeTree(tree)) + convertNewGenericArray(readapt(tree.appliedToTypeTrees(typeArgs))) case wtp => val isStructuralCall = wtp.isValueType && isStructuralTermSelectOrApply(tree) if (isStructuralCall) readaptSimplified(handleStructural(tree)) else pt match { case pt: FunProto => - if isApplyProxy(tree) then newExpr - else adaptToArgs(wtp, pt) + newExpr(tree).orElse(adaptToArgs(wtp, pt)) case pt: PolyProto if !wtp.isImplicitMethod => tryInsertApplyOrImplicit(tree, pt, locked)(tree) // error will be reported in typedTypeApply case _ => diff --git a/compiler/src/dotty/tools/dotc/util/Signatures.scala b/compiler/src/dotty/tools/dotc/util/Signatures.scala index ce05cfb40294..9131f4f761a2 100644 --- a/compiler/src/dotty/tools/dotc/util/Signatures.scala +++ b/compiler/src/dotty/tools/dotc/util/Signatures.scala @@ -1,13 +1,18 @@ package dotty.tools.dotc package util +import dotty.tools.dotc.ast.NavigateAST +import dotty.tools.dotc.ast.Positioned +import dotty.tools.dotc.ast.untpd +import dotty.tools.dotc.core.NameOps.* +import dotty.tools.dotc.core.StdNames.nme +import dotty.tools.dotc.core.Symbols.defn + import ast.Trees.* import ast.tpd -import core.Constants.Constant import core.Contexts.* import core.Denotations.{SingleDenotation, Denotation} import core.Flags -import core.NameOps.isUnapplyName import core.Names.* import core.NameKinds import core.Types.* @@ -31,54 +36,56 @@ object Signatures { */ case class Signature( name: String, - tparams: List[String], paramss: List[List[Param]], returnType: Option[String], doc: Option[String] = None, denot: Option[SingleDenotation] = None ) + sealed trait Param: + def show: String + val doc: Option[String] = None + /** * Represent a method's parameter. * - * @param name The name of the parameter - * @param tpe The type of the parameter - * @param doc The documentation of this parameter - * @param isImplicit Is this parameter implicit? + * @param name The name of the parameter + * @param tpe The type of the parameter + * @param doc The documentation of this parameter + * @param isImplicit Is this parameter implicit? + * @param isReordered Is the parameter reordered in its parameter list? */ - case class Param(name: String, tpe: String, doc: Option[String] = None, isImplicit: Boolean = false) { - def show: String = if name.nonEmpty then s"$name: $tpe" else tpe - } + case class MethodParam( + name: String, + tpe: String, + override val doc: Option[String] = None, + isImplicit: Boolean = false, + isReordered: Boolean = false + ) extends Param: + def show: String = if name.nonEmpty && !isReordered then s"$name: $tpe" + else if name.nonEmpty then s"[$name: $tpe]" + else tpe /** - * Extract (current parameter index, function index, functions) method call for given position. - * - * @param path The path to the function application - * @param pos The position of the cursor + * Represent a type parameter. * - * @return A triple containing the index of the parameter being edited, the index of functeon - * being called, the list of overloads of this function). + * @param tpe The type of the parameter + * @param doc The documentation of this parameter */ - def signatureHelp(path: List[tpd.Tree], pos: Span)(using Context): (Int, Int, List[Signature]) = - computeSignatureHelp(path, pos) + case class TypeParam(tpe: String, override val doc: Option[String] = None) extends Param: + def show = tpe /** - * Extract (current parameter index, function index, functions) out of a method call. + * Extract (current parameter index, function index, functions) method call for given position. * * @param path The path to the function application - * @param span The position of the cursor + * @param pos The position of the cursor * - * @return A triple containing the index of the parameter being edited, the index of the function + * @return A triple containing the index of the parameter being edited, the index of function * being called, the list of overloads of this function). */ - @deprecated( - """This method is deprecated in favor of `signatureHelp`. - Returned denotation cannot be distinguished if its unapply or apply context""", - "3.1.3" - ) - def callInfo(path: List[tpd.Tree], span: Span)(using Context): (Int, Int, List[SingleDenotation]) = - val (paramN, funN, signatures) = computeSignatureHelp(path, span) - (paramN, funN, signatures.flatMap(_.denot)) + def signatureHelp(path: List[tpd.Tree], pos: Span)(using Context): (Int, Int, List[Signature]) = + computeSignatureHelp(path, pos) /** * Computes call info (current parameter index, function index, functions) for a method call. @@ -91,10 +98,10 @@ object Signatures { */ def computeSignatureHelp(path: List[tpd.Tree], span: Span)(using Context): (Int, Int, List[Signature]) = findEnclosingApply(path, span) match - case Apply(fun, params) => applyCallInfo(span, params, fun) + case Apply(fun, params) => applyCallInfo(span, params, fun, false) case UnApply(fun, _, patterns) => unapplyCallInfo(span, fun, patterns) - case appliedTypeTree @ AppliedTypeTree(_, types) => appliedTypeTreeCallInfo(appliedTypeTree, types) - case tp @ TypeApply(fun, types) => applyCallInfo(span, types, fun, true) + case appliedTypeTree @ AppliedTypeTree(_, types) => appliedTypeTreeCallInfo(span, appliedTypeTree, types) + case tp @ TypeApply(fun, types) => applyCallInfo(span, types, fun, isTypeApply = true) case _ => (0, 0, Nil) @@ -136,7 +143,6 @@ object Signatures { val enclosingTree = enclosingFunction.getOrElse(expr) findEnclosingApply(Interactive.pathTo(enclosingTree, span), span) - case direct :: enclosing :: _ if isClosingSymbol(direct.source(span.end -1)) => enclosing case direct :: _ => direct @@ -149,17 +155,31 @@ object Signatures { * @param fun Function tree which is being applied */ private def appliedTypeTreeCallInfo( + span: Span, fun: tpd.Tree, types: List[tpd.Tree] )(using Context): (Int, Int, List[Signature]) = val typeName = fun.symbol.name.show - val typeParams = fun.symbol.typeRef.typeParams.map(_.paramName.show) + val typeParams = fun.symbol.typeRef.typeParams.map(_.paramName.show).map(TypeParam.apply(_)) val denot = fun.denot.asSingleDenotation - val activeParameter = (types.length - 1) max 0 + val activeParameter = findCurrentParamIndex(types, span, typeParams.length - 1) - val signature = Signature(typeName, typeParams, Nil, Some(typeName) , None, Some(denot)) + val signature = Signature(typeName, List(typeParams), Some(typeName) , None, Some(denot)) (activeParameter, 0, List(signature)) + private def findOutermostCurriedApply(untpdPath: List[untpd.Tree]): Option[untpd.GenericApply] = + val trimmedPath = untpdPath.dropWhile(!_.isInstanceOf[untpd.GenericApply]) + val maybeCurriedTrees = (trimmedPath zip trimmedPath.drop(1)).takeWhile: + case (currentTree: untpd.GenericApply, nextTree: untpd.GenericApply) => + nextTree.fun == currentTree + case _ => false + .map(_._2) + + maybeCurriedTrees.lastOption.orElse: + trimmedPath.headOption + .collect: + case genericApply: untpd.GenericApply => genericApply + /** * Extracts call information for a function application and type application. * @@ -183,9 +203,10 @@ object Signatures { case Select(qual, _) => qual case _ => tree + val paramssListIndex = findParamssIndex(fun) val (alternativeIndex, alternatives) = fun.tpe match case err: ErrorType => - val (alternativeIndex, alternatives) = alternativesFromError(err, params) match + val (alternativeIndex, alternatives) = alternativesFromError(err, params, paramssListIndex) match // if we have no alternatives from error, we have to fallback to function denotation // Check `partialyFailedCurriedFunctions` test for example case (_, Nil) => @@ -204,21 +225,74 @@ object Signatures { (alternativeIndex, alternatives) if alternativeIndex < alternatives.length then - val curriedArguments = countParams(fun, alternatives(alternativeIndex)) - // We have to shift all arguments by number of type parameters to properly show activeParameter index - val typeParamsShift = if !isTypeApply then fun.symbol.denot.paramSymss.flatten.filter(_.isType).length else 0 - val paramIndex = params.indexWhere(_.span.contains(span)) match - case -1 => (params.length - 1 max 0) + curriedArguments + typeParamsShift - case n => n + curriedArguments + typeParamsShift + val alternativeSymbol = alternatives(alternativeIndex).symbol + val safeParamssListIndex = paramssListIndex min (alternativeSymbol.paramSymss.length - 1) + val previousArgs = alternativeSymbol.paramSymss.take(safeParamssListIndex).foldLeft(0)(_ + _.length) + + val untpdPath: List[untpd.Tree] = NavigateAST + .untypedPath(fun, false).collect { case untpdTree: untpd.Tree => untpdTree } + + val untpdArgs = untpdPath match + case (Ident(_) | Select(_, _)) :: New(_) :: Select(_, name) :: untpd.Apply(untpdFun, args) :: _ + if name.isConstructorName => args + case _ :: untpd.Apply(_, args) :: _ => args + case _ :: untpd.TypeApply(_, args) :: _ => args + case _ => Nil + + val currentParamsIndex = + findCurrentParamIndex(untpdArgs, span, alternativeSymbol.paramSymss(safeParamssListIndex).length - 1) val pre = treeQualifier(fun) val alternativesWithTypes = alternatives.map(_.asSeenFrom(pre.tpe.widenTermRefExpr)) - val alternativeSignatures = alternativesWithTypes.flatMap(toApplySignature) + val alternativeSignatures = alternativesWithTypes + .flatMap(toApplySignature(_, findOutermostCurriedApply(untpdPath), safeParamssListIndex)) - (paramIndex, alternativeIndex, alternativeSignatures) + val finalParamIndex = currentParamsIndex + previousArgs + (finalParamIndex, alternativeIndex, alternativeSignatures) else (0, 0, Nil) + /** Finds current parameter index + * @param args List of currently applied arguments + * @param span The position of the cursor + * @param maxIndex The maximum index of the parameter in the current apply list + * + * @return Index of the current parameter + */ + private def findCurrentParamIndex(args: List[Positioned], span: Span, maxIndex: Int)(using Context): Int = + (args.indexWhere(_.span.contains(span)) match + case -1 if args.isEmpty => 0 + case -1 => + commaIndex(args, span) match + // comma is before CURSOR, so we are in parameter b example: test("a", CURSOR) + case Some(index) if index <= span.end => args.takeWhile(_.span.end < span.start).length + // comma is after CURSOR, so we are in parameter a example: test("a" CURSOR,) + case Some(index) => args.takeWhile(_.span.start < span.end).length - 1 + // we are either in first or last parameter + case None => + if args.head.span.start >= span.end then 0 + else args.length - 1 max 0 + + case n => n + ) min maxIndex + + /** Parser ignores chars between arguments, we have to manually find the index of comma + * @param untpdArgs List of applied untyped arguments + * @param span The position of the cursor + * + * @return None if we are in first or last parameter, comma index otherwise + */ + private def commaIndex(untpdArgs: List[Positioned], span: Span)(using Context): Option[Int] = + val previousArgIndex = untpdArgs.lastIndexWhere(_.span.end < span.end) + for + previousArg <- untpdArgs.lift(previousArgIndex) + nextArg = untpdArgs.lift(previousArgIndex + 1) + text = ctx.source.content.slice(previousArg.span.end - 1, nextArg.map(_.span.start).getOrElse(span.end)) + commaIndex = text.indexOf(',') + if commaIndex != -1 + yield + commaIndex + previousArg.span.end + /** * Extracts call informatioin for function in unapply context. * @@ -235,13 +309,12 @@ object Signatures { patterns: List[tpd.Tree] )(using Context): (Int, Int, List[Signature]) = val resultType = unapplyMethodResult(fun) - val isUnapplySeq = fun.denot.name == core.Names.termName("unapplySeq") val denot = fun.denot.mapInfo(_ => resultType) val paramTypes = extractParamTypess(resultType, denot, patterns.size).flatten.map(stripAllAnnots) val paramNames = extractParamNamess(resultType, denot).flatten - val activeParameter = unapplyParameterIndex(patterns, span, paramTypes.length) + val activeParameter = findCurrentParamIndex(patterns, span, paramTypes.length - 1) val unapplySignature = toUnapplySignature(denot.asSingleDenotation, paramNames, paramTypes).toList (activeParameter, 0, unapplySignature) @@ -303,27 +376,22 @@ object Signatures { case other => other.stripAnnots /** - * Get index of currently edited parameter in unapply context. - * - * @param patterns Currently applied patterns for unapply method - * @param span The position of the cursor - * @param maximumParams Number of parameters taken by unapply method - * @return Index of currently edited parameter - */ - private def unapplyParameterIndex(patterns: List[tpd.Tree], span: Span, maximumParams: Int)(using Context): Int = - val patternPosition = patterns.indexWhere(_.span.contains(span)) - (patternPosition, patterns.length) match - case (-1, 0) => 0 // there are no patterns yet so it must be first one - case (-1, pos) => -1 // there are patterns, we must be outside range so we set no active parameter - case _ => (maximumParams - 1) min patternPosition max 0 // handle unapplySeq to always highlight Seq[A] on elements - - /** - * Checks if tree is valid for signatureHelp. Skipped trees are either tuple type or function type + * Checks if tree is valid for signatureHelp. Skipped trees are either tuple or function applies * * @param tree tree to validate */ private def isValid(tree: tpd.Tree)(using Context): Boolean = - !ctx.definitions.isTupleNType(tree.tpe) && !ctx.definitions.isFunctionNType(tree.tpe) + val isTupleApply = + tree.symbol.name == nme.apply + && tree.symbol.exists + && ctx.definitions.isTupleClass(tree.symbol.owner.companionClass) + + val isFunctionNApply = + tree.symbol.name == nme.apply + && tree.symbol.exists + && ctx.definitions.isFunctionSymbol(tree.symbol.owner) + + !isTupleApply && !isFunctionNApply /** * Get unapply method result type omiting unknown types and another method calls. @@ -397,85 +465,136 @@ object Signatures { * * @return Signature if denot is a function, None otherwise */ - private def toApplySignature(denot: SingleDenotation)(using Context): Option[Signature] = { + private def toApplySignature( + denot: SingleDenotation, + untpdFun: Option[untpd.GenericApply], + paramssIndex: Int + )(using Context): Option[Signature] = { val symbol = denot.symbol val docComment = ParsedComment.docOf(symbol) def isDummyImplicit(res: MethodType): Boolean = res.resultType.isParameterless && res.isImplicitMethod && - res.paramInfos.forall(info => - info.classSymbol.derivesFrom(ctx.definitions.DummyImplicitClass)) - - def toParamss(tp: Type)(using Context): List[List[Param]] = - val rest = tp.resultType match - case res: MethodType => if isDummyImplicit(res) then Nil else toParamss(res) - case _ => Nil - - val currentParams = (tp.paramNamess, tp.paramInfoss) match - case (params :: _, infos :: _) => params zip infos - case _ => Nil - - val params = currentParams.map { (name, info) => - Signatures.Param( - name.show, - info.widenTermRefExpr.show, - docComment.flatMap(_.paramDoc(name)), - isImplicit = tp.isImplicitMethod - ) - } - - (params :: rest) + ( + res.paramNames.forall(name => + name.startsWith(NameKinds.ContextBoundParamName.separator) || + name.startsWith(NameKinds.ContextFunctionParamName.separator)) || + res.paramInfos.forall(info => + info.classSymbol.derivesFrom(ctx.definitions.DummyImplicitClass)) + ) + + def toApplyList(tree: untpd.GenericApply): List[untpd.GenericApply] = + tree match + case untpd.GenericApply(fun: untpd.GenericApply, args) => toApplyList(fun) :+ tree + case _ => List(tree) + + def toMethodTypeList(tpe: Type): List[Type] = + tpe.resultType match + case res: MethodOrPoly => toMethodTypeList(res) :+ tpe + case res => List(tpe) def isSyntheticEvidence(name: String) = if !name.startsWith(NameKinds.ContextBoundParamName.separator) then false else symbol.paramSymss.flatten.find(_.name.show == name).exists(_.flags.is(Flags.Implicit)) - denot.info.stripPoly match - case tpe: (MethodType | AppliedType | TypeRef | TypeParamRef) => - val paramss = toParamss(tpe).map(_.filterNot(param => isSyntheticEvidence(param.name))) - val evidenceParams = (tpe.paramNamess.flatten zip tpe.paramInfoss.flatten).flatMap { - case (name, AppliedType(tpe, (ref: TypeParamRef) :: _)) if isSyntheticEvidence(name.show) => - Some(ref.paramName -> tpe) - case _ => None - } - - val typeParams = denot.info match - case poly: PolyType => - val tparams = poly.paramNames.zip(poly.paramInfos) - tparams.map { (name, info) => - evidenceParams.find((evidenceName: TypeName, _: Type) => name == evidenceName).flatMap { - case (_, tparam) => tparam.show.split('.').lastOption - } match { - case Some(evidenceTypeName) => s"${name.show}: ${evidenceTypeName}" - case None => name.show + info.show - } - } + def toTypeParam(tpe: PolyType): List[Param] = + val evidenceParams = (tpe.paramNamess.flatten zip tpe.paramInfoss.flatten).flatMap: + case (name, AppliedType(tpe, (ref: TypeParamRef) :: _)) if isSyntheticEvidence(name.show) => + Some(ref.paramName -> tpe) + case _ => None + + val tparams = tpe.paramNames.zip(tpe.paramInfos) + tparams.map: (name, info) => + evidenceParams.find((evidenceName: TypeName, _: Type) => name == evidenceName).flatMap: + case (_, tparam) => tparam.show.split('.').lastOption + match + case Some(evidenceTypeName) => TypeParam(s"${name.show}: ${evidenceTypeName}") + case None => TypeParam(name.show + info.show) + + def toParamss(tp: Type, fun: Option[untpd.GenericApply])(using Context): List[List[Param]] = + val paramSymss = symbol.paramSymss + + def reduceToParamss(applies: List[untpd.Tree], types: List[Type], paramList: Int = 0): List[List[Param]] = + applies -> types match + case ((_: untpd.TypeApply) :: restTrees, (poly: PolyType) :: restTypes) => + toTypeParam(poly) :: reduceToParamss(restTrees, restTypes, paramList + 1) + case (restTrees, (poly: PolyType) :: restTypes) => + toTypeParam(poly) :: reduceToParamss(restTrees, restTypes, paramList + 1) + case ((apply: untpd.GenericApply) :: other, tpe :: otherType) => + toParams(tpe, Some(apply), paramList) :: reduceToParamss(other, otherType, paramList + 1) + case (other, (tpe @ MethodTpe(names, _, _)) :: otherType) if !isDummyImplicit(tpe) => + toParams(tpe, None, paramList) :: reduceToParamss(other, otherType, paramList + 1) case _ => Nil - val (name, returnType) = - if (symbol.isConstructor) then - (symbol.owner.name.show, None) - else - (denot.name.show, Some(tpe.finalResultType.widenTermRefExpr.show)) - Some(Signatures.Signature(name, typeParams, paramss, returnType, docComment.map(_.mainDoc), Some(denot))) - case other => None - } - @deprecated("Deprecated in favour of `signatureHelp` which now returns Signature along SingleDenotation", "3.1.3") - def toSignature(denot: SingleDenotation)(using Context): Option[Signature] = { - if denot.name.isUnapplyName then - val resultType = denot.info.stripPoly.finalResultType match - case methodType: MethodType => methodType.resultType.widen - case other => other + def toParams(tp: Type, apply: Option[untpd.GenericApply], paramList: Int)(using Context): List[Param] = + val currentParams = (paramSymss.lift(paramList), tp.paramInfoss.headOption) match + case (Some(params), Some(infos)) => params zip infos + case _ => Nil - // We can't get already applied patterns so we won't be able to get proper signature in case when - // it can be both name-based or single match extractor. See test `nameBasedTest` - val paramTypes = extractParamTypess(resultType, denot, 0).flatten.map(stripAllAnnots) - val paramNames = extractParamNamess(resultType, denot).flatten + val params = currentParams.map: (symbol, info) => + // TODO after we migrate ShortenedTypePrinter into the compiler, it should rely on its api + val name = if symbol.isAllOf(Flags.Given | Flags.Param) && symbol.name.startsWith("x$") then nme.EMPTY else symbol.name.asTermName - toUnapplySignature(denot.asSingleDenotation, paramNames, paramTypes) - else - toApplySignature(denot) + Signatures.MethodParam( + name.show, + info.widenTermRefExpr.show, + docComment.flatMap(_.paramDoc(name)), + isImplicit = tp.isImplicitMethod, + ) + + val finalParams = apply.map: apply => + apply.args match + case Nil => params + case n if n.length > params.length => params + case _ => + // map argument order with their corresponding order so + // def foo(a: Int, b: Int, c: Int, d: Int) + // foo(b = 0, a = 0, d = 0, c = 0) order is List(1, 0, 3, 2) + // and if there are missing arguments, they are set to -1 so for the same method: + // foo(b= 0, d = 0, ) order is List(1, 3, -1, -1) + val argsWithOriginalIndices = apply.args.map: + case untpd.NamedArg(name, _) => + params.indexWhere(_.name == name.toString) + case param => -1 + .padTo(params.length, -1) + + var remainingParams = params.zipWithIndex.filter: (param, index) => + !argsWithOriginalIndices.contains(index) + .map(_._1) + + val result = argsWithOriginalIndices.map: + case -1 => + val h = remainingParams.head + remainingParams = remainingParams.tail + h + case n => params(n) + + val isReordered = params != result + val (ordered, reordered) = params.zip(result).span: (definitionMember, reorderedMember) => + definitionMember == reorderedMember + + ordered.map(_._2) ++ reordered.map(_._2.copy(isReordered = isReordered)) + + + finalParams.getOrElse(params) + end toParams + + val applies = untpdFun.map(toApplyList).getOrElse(Nil) + val types = toMethodTypeList(tp).reverse + + reduceToParamss(applies, types) + + val paramss = toParamss(denot.info, untpdFun) + val (name, returnType) = + if (symbol.isConstructor) then + (symbol.owner.name.show, None) + else + denot.symbol.defTree match + // if there is an error in denotation type, we will fallback to source tree + case defn: tpd.DefDef if denot.info.isErroneous => (denot.name.show, Some(defn.tpt.show)) + case _ => (denot.name.show, Some(denot.info.finalResultType.widenTermRefExpr.show)) + Some(Signatures.Signature(name, paramss, returnType, docComment.map(_.mainDoc), Some(denot))) } /** @@ -493,34 +612,31 @@ object Signatures { */ private def toUnapplySignature(denot: SingleDenotation, paramNames: List[Name], paramTypes: List[Type])(using Context): Option[Signature] = val params = if paramNames.length == paramTypes.length then - (paramNames zip paramTypes).map((name, info) => Param(name.show, info.show)) + (paramNames zip paramTypes).map((name, info) => MethodParam(name.show, info.show)) else - paramTypes.map(info => Param("", info.show)) + // even if we only show types of arguments, they are still method params + paramTypes.map(info => MethodParam("", info.show)) - if params.nonEmpty then - Some(Signature("", Nil, List(params), None, None, Some(denot))) - else - None + if params.nonEmpty then Some(Signature("", List(params), None, None, Some(denot))) + else None /** - * The number of parameters before `tree` application. It is necessary to properly show - * parameter number for erroneous applications before current one. - * - * This handles currying, so for an application such as `foo(1, 2)(3)`, the result of - * `countParams` should be 3. It also takes into considerations unapplied arguments so for `foo(1)(3)` - * we will still get 3, as first application `foo(1)` takes 2 parameters with currently only 1 applied. + * The number of params lists before `tree` application. + * It handles currying, so for an application such as `foo(1, 2)(3)`, the result of + * `findParamssIndex` should be 1. * * @param tree The tree to inspect. - * @param denot Denotation of function we are trying to apply * @param alreadyCurried Number of subsequent Apply trees before current tree * - * @return The number of parameters that are passed. + * @return The index of paramss we are currently in. */ - private def countParams(tree: tpd.Tree, denot: SingleDenotation, alreadyCurried: Int = 0)(using Context): Int = + private def findParamssIndex(tree: tpd.Tree, alreadyCurried: Int = 0)(using Context): Int = tree match - case Apply(fun, params) => - countParams(fun, denot, alreadyCurried + 1) + denot.symbol.paramSymss(alreadyCurried).length - case _ => 0 + case GenericApply(fun, params) + if params.nonEmpty && params.forall(_.isInstanceOf[untpd.SearchFailureIdent]) => + findParamssIndex(fun, alreadyCurried) + case GenericApply(fun, params) => findParamssIndex(fun, alreadyCurried + 1) + case _ => alreadyCurried /** * Inspect `err` to determine, if it is an error related to application of an overloaded @@ -530,35 +646,32 @@ object Signatures { * given the parameters `params`: The alternative that has the most formal parameters * matching the given arguments is chosen. * - * @param err The error message to inspect. - * @param params The parameters that were given at the call site. + * @param err The error message to inspect. + * @param params The parameters that were given at the call site. + * @param alreadyCurried Index of paramss we are currently in. * * @return A pair composed of the index of the best alternative (0 if no alternatives * were found), and the list of alternatives. */ - private def alternativesFromError(err: ErrorType, params: List[tpd.Tree])(using Context): (Int, List[SingleDenotation]) = { + private def alternativesFromError(err: ErrorType, params: List[tpd.Tree], paramssIndex: Int)(using Context): (Int, List[SingleDenotation]) = { val alternatives = err.msg match case msg: AmbiguousOverload => msg.alternatives case msg: NoMatchingOverload => msg.alternatives case _ => Nil - // If the user writes `foo(bar, )`, the typer will insert a synthetic - // `null` parameter: `foo(bar, null)`. This may influence what's the "best" - // alternative, so we discard it. - val userParams = params match - case xs :+ (nul @ Literal(Constant(null))) if nul.span.isZeroExtent => xs - case _ => params - val userParamsTypes = userParams.map(_.tpe) + val userParamsTypes = params.map(_.tpe) // Assign a score to each alternative (how many parameters are correct so far), and // use that to determine what is the current active signature. val alternativesScores = alternatives.map { alt => + val alreadyCurriedBonus = if (alt.symbol.paramSymss.length > paramssIndex) 1 else 0 alt.info.stripPoly match - case tpe: MethodType => + case tpe: MethodType => alreadyCurriedBonus + userParamsTypes.zip(tpe.paramInfos).takeWhile{ case (t0, t1) => t0 <:< t1 }.size case _ => 0 } + val bestAlternative = if (alternativesScores.isEmpty) 0 else alternativesScores.zipWithIndex.maxBy(_._1)._2 diff --git a/compiler/src/dotty/tools/dotc/util/Stats.scala b/compiler/src/dotty/tools/dotc/util/Stats.scala index 750a799a9f0a..2f4e3bd9cb4f 100644 --- a/compiler/src/dotty/tools/dotc/util/Stats.scala +++ b/compiler/src/dotty/tools/dotc/util/Stats.scala @@ -19,9 +19,7 @@ import collection.mutable @volatile private var stack: List[String] = Nil - val hits: mutable.HashMap[String, Int] = new mutable.HashMap[String, Int] { - override def default(key: String): Int = 0 - } + val hits: mutable.Map[String, Int] = new mutable.HashMap[String, Int].withDefaultValue(0) inline def record(inline fn: String, inline n: Int = 1, inline skip: Boolean = timerOnly): Unit = if (enabled && !skip) doRecord(fn, n) diff --git a/compiler/src/dotty/tools/io/AbstractFile.scala b/compiler/src/dotty/tools/io/AbstractFile.scala index a7dcb7d396e8..243dc2953d2e 100644 --- a/compiler/src/dotty/tools/io/AbstractFile.scala +++ b/compiler/src/dotty/tools/io/AbstractFile.scala @@ -258,6 +258,9 @@ abstract class AbstractFile extends Iterable[AbstractFile] { final def resolveSibling(name: String): AbstractFile | Null = container.lookupName(name, directory = false) + final def resolveSiblingWithExtension(extension: String): AbstractFile | Null = + resolveSibling(name.stripSuffix(this.extension) + extension) + private def fileOrSubdirectoryNamed(name: String, isDir: Boolean): AbstractFile = lookupName(name, isDir) match { case null => diff --git a/compiler/src/dotty/tools/io/ClassPath.scala b/compiler/src/dotty/tools/io/ClassPath.scala index 8df4015a53c2..5344e2cf7e35 100644 --- a/compiler/src/dotty/tools/io/ClassPath.scala +++ b/compiler/src/dotty/tools/io/ClassPath.scala @@ -26,7 +26,7 @@ trait ClassPath { final def hasPackage(pkg: String): Boolean = hasPackage(PackageName(pkg)) final def packages(inPackage: String): Seq[PackageEntry] = packages(PackageName(inPackage)) - final def classes(inPackage: String): Seq[ClassFileEntry] = classes(PackageName(inPackage)) + final def classes(inPackage: String): Seq[BinaryFileEntry] = classes(PackageName(inPackage)) final def sources(inPackage: String): Seq[SourceFileEntry] = sources(PackageName(inPackage)) final def list(inPackage: String): ClassPathEntries = list(PackageName(inPackage)) @@ -43,7 +43,7 @@ trait ClassPath { private[dotty] def hasPackage(pkg: PackageName): Boolean private[dotty] def packages(inPackage: PackageName): Seq[PackageEntry] - private[dotty] def classes(inPackage: PackageName): Seq[ClassFileEntry] + private[dotty] def classes(inPackage: PackageName): Seq[BinaryFileEntry] private[dotty] def sources(inPackage: PackageName): Seq[SourceFileEntry] /** diff --git a/compiler/src/dotty/tools/io/ZipArchive.scala b/compiler/src/dotty/tools/io/ZipArchive.scala index 3a4d32614c82..9af935690ffc 100644 --- a/compiler/src/dotty/tools/io/ZipArchive.scala +++ b/compiler/src/dotty/tools/io/ZipArchive.scala @@ -160,7 +160,7 @@ final class FileZipArchive(jpath: JPath, release: Option[String]) extends ZipArc override def sizeOption: Option[Int] = Some(zipEntry.getSize.toInt) } - @volatile lazy val (root, allDirs): (DirEntry, collection.Map[String, DirEntry]) = { + lazy val (root, allDirs): (DirEntry, collection.Map[String, DirEntry]) = { val root = new DirEntry("/", null) val dirs = mutable.HashMap[String, DirEntry]("/" -> root) val zipFile = openZipFile() diff --git a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala index 51f133c972b4..04d8d7bc51a0 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala @@ -1030,7 +1030,11 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler def apply(call: Option[Tree], bindings: List[Definition], expansion: Term): Inlined = withDefaultPos(tpd.Inlined(call.getOrElse(tpd.EmptyTree), bindings.map { case b: tpd.MemberDef => b }, xCheckMacroValidExpr(expansion))) def copy(original: Tree)(call: Option[Tree], bindings: List[Definition], expansion: Term): Inlined = - tpd.Inlined(call.getOrElse(tpd.EmptyTree), bindings.asInstanceOf[List[tpd.MemberDef]], xCheckMacroValidExpr(expansion)).withSpan(original.span).withType(original.tpe) + original match + case original: Inlined => + tpd.cpy.Inlined(original)(call.getOrElse(tpd.EmptyTree), bindings.asInstanceOf[List[tpd.MemberDef]], xCheckMacroValidExpr(expansion)) + case original => + throw new IllegalArgumentException(i"Expected argument `original` to be an `Inlined` but was: ${original.show}") def unapply(x: Inlined): (Option[Tree /* Term | TypeTree */], List[Definition], Term) = (optional(x.call), x.bindings, x.body) end Inlined diff --git a/compiler/test-resources/repl/rewrite-messages b/compiler/test-resources/repl/rewrite-messages index a63a72195019..d7bcbe5d3a90 100644 --- a/compiler/test-resources/repl/rewrite-messages +++ b/compiler/test-resources/repl/rewrite-messages @@ -1,17 +1,20 @@ //> using options -source:future-migration -deprecation -Werror scala> import scala.util._ --- Error: ---------------------------------------------------------------------- +-- Migration Warning: ---------------------------------------------------------- 1 | import scala.util._ | ^ | `_` is no longer supported for a wildcard import; use `*` instead - +No warnings can be incurred under -Werror (or -Xfatal-warnings) +1 warning found +1 error found scala> extension (x: Int) def foo(y: Int) = x + y def foo(x: Int)(y: Int): Int - scala> 2 foo 4 --- Error: ---------------------------------------------------------------------- +-- Migration Warning: ---------------------------------------------------------- 1 | 2 foo 4 | ^^^ |Alphanumeric method foo is not declared infix; it should not be used as infix operator. |Instead, use method syntax .foo(...) or backticked identifier `foo`. -1 error found +No warnings can be incurred under -Werror (or -Xfatal-warnings) +1 warning found +1 error found \ No newline at end of file diff --git a/compiler/test/dotty/Properties.scala b/compiler/test/dotty/Properties.scala index 4bb3628722ad..e085b0de4875 100644 --- a/compiler/test/dotty/Properties.scala +++ b/compiler/test/dotty/Properties.scala @@ -87,6 +87,9 @@ object Properties { /** If we are using the scala-library TASTy jar */ def usingScalaLibraryTasty: Boolean = scalaLibraryTasty.isDefined + /** If we are using the scala-library TASTy jar */ + + def usingScalaLibraryCCTasty: Boolean = scalaLibraryTasty.exists(_.contains("scala2-library-cc-tasty")) /** scala-asm jar */ def scalaAsm: String = sys.props("dotty.tests.classes.scalaAsm") diff --git a/compiler/test/dotty/tools/backend/jvm/ClassfileParserTest.scala b/compiler/test/dotty/tools/backend/jvm/ClassfileParserTest.scala new file mode 100644 index 000000000000..9263103f1712 --- /dev/null +++ b/compiler/test/dotty/tools/backend/jvm/ClassfileParserTest.scala @@ -0,0 +1,57 @@ +package dotty.tools.backend.jvm + +// painful to do Java reflection stuff without this +import scala.language.unsafeNulls + +import org.junit.Assert.assertEquals +import org.junit.Test + +import java.lang.reflect.Member + +class ClassfileParserTest { + @Test + def noConstantPoolLag(): Unit = { + def constNames(ms: List[Member]) = ms.collect { + case f if f.getName.startsWith("CONSTANT_") => f.getName + }.sorted + + val toDotc = Map( + "CONSTANT_INTERFACE_METHODREF" -> "CONSTANT_INTFMETHODREF", + "CONSTANT_INVOKE_DYNAMIC" -> "CONSTANT_INVOKEDYNAMIC", + "CONSTANT_METHOD_HANDLE" -> "CONSTANT_METHODHANDLE", + "CONSTANT_METHOD_TYPE" -> "CONSTANT_METHODTYPE", + "CONSTANT_NAME_AND_TYPE" -> "CONSTANT_NAMEANDTYPE", + ).withDefault(x => x) + + val asmConsts = constNames(Class.forName("scala.tools.asm.Symbol").getDeclaredFields.toList) + .map(_.stripSuffix("_TAG")) + .map(toDotc) + .::("CONSTANT_UNICODE") + .sorted + // in the Scala 2 version of this test, we also use Java reflection to get the constant + // names out of ClassfileConstants. in Dotty, the constants are `inline val`s, invisible + // to Java reflection, so we hardcode them here + assertEquals(asmConsts, List( + // do not add to this list without also making the corresponding change + // in ClassfileConstants! that would defeat the purpose of the test + "CONSTANT_CLASS", + "CONSTANT_DOUBLE", + "CONSTANT_DYNAMIC", + "CONSTANT_FIELDREF", + "CONSTANT_FLOAT", + "CONSTANT_INTEGER", + "CONSTANT_INTFMETHODREF", + "CONSTANT_INVOKEDYNAMIC", + "CONSTANT_LONG", + "CONSTANT_METHODHANDLE", + "CONSTANT_METHODREF", + "CONSTANT_METHODTYPE", + "CONSTANT_MODULE", + "CONSTANT_NAMEANDTYPE", + "CONSTANT_PACKAGE", + "CONSTANT_STRING", + "CONSTANT_UNICODE", + "CONSTANT_UTF8", + )) + } +} diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 120b7373f7cc..64c2bd3b8807 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -45,9 +45,9 @@ class CompilationTests { compileFilesInDir("tests/pos", defaultOptions.and("-Ysafe-init", "-Ylegacy-lazy-vals", "-Ycheck-constraint-deps"), FileFilter.include(TestSources.posLazyValsAllowlist)), compileDir("tests/pos-special/java-param-names", defaultOptions.withJavacOnlyOptions("-parameters")), ) ::: ( - // FIXME: This fails due to a bug involving self types and capture checking - if Properties.usingScalaLibraryTasty then Nil - else List(compileDir("tests/pos-special/stdlib", allowDeepSubtypes)) + // TODO create a folder for capture checking tests with the stdlib, or use tests/pos-custom-args/captures under this mode? + if Properties.usingScalaLibraryCCTasty then List(compileDir("tests/pos-special/stdlib", allowDeepSubtypes)) + else Nil ) if scala.util.Properties.isJavaAtLeast("16") then @@ -215,9 +215,8 @@ class CompilationTests { // initialization tests @Test def checkInitGlobal: Unit = { implicit val testGroup: TestGroup = TestGroup("checkInitGlobal") - val options = defaultOptions.and("-Ysafe-init-global", "-Xfatal-warnings") - compileFilesInDir("tests/init-global/neg", options, FileFilter.exclude(TestSources.negInitGlobalScala2LibraryTastyBlacklisted)).checkExpectedErrors() - compileFilesInDir("tests/init-global/pos", options, FileFilter.exclude(TestSources.posInitGlobalScala2LibraryTastyBlacklisted)).checkCompile() + compileFilesInDir("tests/init-global/warn", defaultOptions.and("-Ysafe-init-global"), FileFilter.exclude(TestSources.negInitGlobalScala2LibraryTastyBlacklisted)).checkWarnings() + compileFilesInDir("tests/init-global/pos", defaultOptions.and("-Ysafe-init-global", "-Xfatal-warnings"), FileFilter.exclude(TestSources.posInitGlobalScala2LibraryTastyBlacklisted)).checkCompile() } // initialization tests @@ -225,6 +224,7 @@ class CompilationTests { implicit val testGroup: TestGroup = TestGroup("checkInit") val options = defaultOptions.and("-Ysafe-init", "-Xfatal-warnings") compileFilesInDir("tests/init/neg", options).checkExpectedErrors() + compileFilesInDir("tests/init/warn", defaultOptions.and("-Ysafe-init")).checkWarnings() compileFilesInDir("tests/init/pos", options).checkCompile() compileFilesInDir("tests/init/crash", options.without("-Xfatal-warnings")).checkCompile() // The regression test for i12128 has some atypical classpath requirements. diff --git a/compiler/test/dotty/tools/dotc/transform/patmat/SpaceEngineTest.scala b/compiler/test/dotty/tools/dotc/transform/patmat/SpaceEngineTest.scala index c13ef0532348..d7b2fd6a5173 100644 --- a/compiler/test/dotty/tools/dotc/transform/patmat/SpaceEngineTest.scala +++ b/compiler/test/dotty/tools/dotc/transform/patmat/SpaceEngineTest.scala @@ -27,12 +27,12 @@ class SpaceEngineTest: val a = Prod(tp, unappTp, params) val b = Empty - val res1 = isSubspace(a, b) + val res1 = a.isSubspace(b) - val a2 = simplify(a) - val b2 = simplify(b) + val a2 = a.simplify + val b2 = b.simplify val rem1 = minus(a2, b2) - val rem2 = simplify(rem1) + val rem2 = rem1.simplify val res2 = rem2 == Empty assertEquals( @@ -46,19 +46,12 @@ class SpaceEngineTest: |simplify(rem1) == Empty |rem2 == Empty | - |a = ${show(a)} - |b = ${show(b)} - |a2 = ${show(a2)} - |b2 = ${show(b2)} - |rem1 = ${show(rem1)} - |rem2 = ${show(rem2)} - | - |a = ${a.toString} - |b = ${b.toString} - |a2 = ${a2.toString} - |b2 = ${b2.toString} - |rem1 = ${rem1.toString} - |rem2 = ${rem2.toString} + |a = $a + |b = $b + |a2 = $a2 + |b2 = $b2 + |rem1 = $rem1 + |rem2 = $rem2 | |""".stripMargin, res1, res2) } diff --git a/compiler/test/dotty/tools/io/PathTest.scala b/compiler/test/dotty/tools/io/PathTest.scala index 731d29cee8e6..a3755e0ea7dc 100644 --- a/compiler/test/dotty/tools/io/PathTest.scala +++ b/compiler/test/dotty/tools/io/PathTest.scala @@ -3,7 +3,7 @@ package dotty.tools.io import org.junit.Test class PathTest { - // Ref https://github.com/lampepfl/dotty/issues/11644#issuecomment-792457275 + // Ref https://github.com/scala/scala3/issues/11644#issuecomment-792457275 @Test def parent(): Unit = { testParent(Path(""), Directory("..")) testParent(Path("."), Directory("..")) diff --git a/compiler/test/dotty/tools/vulpix/FileDiff.scala b/compiler/test/dotty/tools/vulpix/FileDiff.scala index 5e882be6425a..80fb2bf43534 100644 --- a/compiler/test/dotty/tools/vulpix/FileDiff.scala +++ b/compiler/test/dotty/tools/vulpix/FileDiff.scala @@ -12,10 +12,13 @@ import java.nio.charset.StandardCharsets object FileDiff { + def diffCommand(expectFile: String, actualFile: String): String = + s"git diff --no-index -- $expectFile $actualFile" + def diffMessage(expectFile: String, actualFile: String): String = s"""Test output dumped in: $actualFile - | See diff of the checkfile (`brew install icdiff` for colored diff) - | > diff $expectFile $actualFile + | See diff of the checkfile (`--color=always` for colored diff) + | > ${FileDiff.diffCommand(expectFile, actualFile)} | Replace checkfile with current output | > mv $actualFile $expectFile """.stripMargin diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala index e93a0435987b..59d5d3d542fd 100644 --- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala +++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala @@ -290,15 +290,25 @@ trait ParallelTesting extends RunnerOrchestration { self => /** This callback is executed once the compilation of this test source finished */ private final def onComplete(testSource: TestSource, reportersOrCrash: Try[Seq[TestReporter]], logger: LoggedRunnable): Unit = - reportersOrCrash match { - case TryFailure(exn) => onFailure(testSource, Nil, logger, Some(s"Fatal compiler crash when compiling: ${testSource.title}:\n${exn.getMessage}${exn.getStackTrace.map("\n\tat " + _).mkString}")) - case TrySuccess(reporters) if !reporters.exists(_.skipped) => - maybeFailureMessage(testSource, reporters) match { - case Some(msg) => onFailure(testSource, reporters, logger, Option(msg).filter(_.nonEmpty)) - case None => onSuccess(testSource, reporters, logger) + try + reportersOrCrash match + case TryFailure(exn) => onFailure(testSource, Nil, logger, Some(s"Fatal compiler crash when compiling: ${testSource.title}:\n${exn.getMessage}${exn.getStackTrace.map("\n\tat " + _).mkString}")) + case TrySuccess(reporters) if !reporters.exists(_.skipped) => + maybeFailureMessage(testSource, reporters) match { + case Some(msg) => onFailure(testSource, reporters, logger, Option(msg).filter(_.nonEmpty)) + case None => onSuccess(testSource, reporters, logger) + } + case _ => + catch case ex: Throwable => + echo(s"Exception thrown onComplete (probably by a reporter) in $testSource: ${ex.getClass}") + Try(ex.printStackTrace()) + .recover{ _ => + val trace = ex.getStackTrace.map(_.toString) // compute this first in case getStackTrace throws an exception + echo(s"${ex.getClass.getName} message could not be printed due to an exception while computing the message.") + if trace.nonEmpty then trace.foreach(echo) else echo(s"${ex.getClass.getName} stack trace is empty.") } - case _ => - } + .getOrElse(echo(s"${ex.getClass.getName} stack trace could not be printed due to an exception while printing the stack trace.")) + failTestSource(testSource) /** * Based on the reporters obtained after the compilation, determines if this test has failed. @@ -776,7 +786,7 @@ trait ParallelTesting extends RunnerOrchestration { self => end maybeFailureMessage def getWarnMapAndExpectedCount(files: Seq[JFile]): (HashMap[String, Integer], Int) = - val comment = raw"//( *)warn".r + val comment = raw"//( *)(nopos-)?warn".r val map = new HashMap[String, Integer]() var count = 0 def bump(key: String): Unit = @@ -787,8 +797,11 @@ trait ParallelTesting extends RunnerOrchestration { self => files.filter(isSourceFile).foreach { file => Using(Source.fromFile(file, StandardCharsets.UTF_8.name)) { source => source.getLines.zipWithIndex.foreach { case (line, lineNbr) => - comment.findAllMatchIn(line).foreach { _ => - bump(s"${file.getPath}:${lineNbr+1}") + comment.findAllMatchIn(line).foreach { m => + m.group(2) match + case "nopos-" => + bump("nopos") + case _ => bump(s"${file.getPath}:${lineNbr+1}") } } }.get @@ -809,7 +822,7 @@ trait ParallelTesting extends RunnerOrchestration { self => val key = s"${relativize(srcpos.source.file.toString())}:${srcpos.line + 1}" if !seenAt(key) then unexpected += key else - unpositioned += relativize(srcpos.source.file.toString()) + if(!seenAt("nopos")) unpositioned += relativize(srcpos.source.file.toString()) reporterWarnings.foreach(sawDiagnostic) diff --git a/dist/bin/scalac b/dist/bin/scalac index 4b888641e786..d9bd21ca425b 100644 --- a/dist/bin/scalac +++ b/dist/bin/scalac @@ -40,7 +40,7 @@ while [[ $# -gt 0 ]]; do # pass all remaining arguments to scala, e.g. to avoid interpreting them here as -D or -J while [[ $# -gt 0 ]]; do addScala "$1" && shift ; done ;; - # Optimize for short-running applications, see https://github.com/lampepfl/dotty/issues/222 + # Optimize for short-running applications, see https://github.com/scala/scala3/issues/222 -Oshort) addScala "-Oshort" && \ addJava "-XX:+TieredCompilation" && addJava "-XX:TieredStopAtLevel=1" && shift ;; diff --git a/dist/bin/scalac.bat b/dist/bin/scalac.bat index 454158c85666..cb1a76471f70 100644 --- a/dist/bin/scalac.bat +++ b/dist/bin/scalac.bat @@ -55,7 +55,7 @@ if defined _CONSUME_REMAINING ( set _SCALA_ARGS=!_SCALA_ARGS! "%__ARG%" shift ) else if "%__ARG%"=="-Oshort" ( - @rem optimize for short-running applications, see https://github.com/lampepfl/dotty/issues/222 + @rem optimize for short-running applications, see https://github.com/scala/scala3/issues/222 set _JAVA_ARGS=!_JAVA_ARGS! "-XX:+TieredCompilation" "-XX:TieredStopAtLevel=1" set _SCALA_ARGS=!_SCALA_ARGS! -Oshort shift diff --git a/docs/_blog/_posts/2016-02-17-scaling-dot-soundness.md b/docs/_blog/_posts/2016-02-17-scaling-dot-soundness.md index 7619545b844e..bc9c558e3011 100644 --- a/docs/_blog/_posts/2016-02-17-scaling-dot-soundness.md +++ b/docs/_blog/_posts/2016-02-17-scaling-dot-soundness.md @@ -69,9 +69,9 @@ categories: is not associated with a runtime value. We can in fact construct soundness issues in all of these cases. Look -at the discussion for issues [#50](https://github.com/lampepfl/dotty/issues/50) -and [#1050](https://github.com/lampepfl/dotty/issues/1050) in the -[Dotty](https://github.com/lampepfl/dotty/issues/1050) repository +at the discussion for issues [#50](https://github.com/scala/scala3/issues/50) +and [#1050](https://github.com/scala/scala3/issues/1050) in the +[Dotty](https://github.com/scala/scala3/issues/1050) repository on GitHub. All issues work fundamentally in the same way: Construct a type `S` which has a type member `T` with bad bounds, say: @@ -98,7 +98,7 @@ course. The promise is usually broken at run-time by failing with a ## Plugging the Loopholes To get back to soundness we need to plug the loopholes. Some of the -necessary measures are taken in pull request [#1051](https://github.com/lampepfl/dotty/issues/1051). +necessary measures are taken in pull request [#1051](https://github.com/scala/scala3/issues/1051). That pull request - tightens the rules for overrides of lazy values: lazy values diff --git a/docs/_blog/_posts/2016-05-05-multiversal-equality.md b/docs/_blog/_posts/2016-05-05-multiversal-equality.md index 236225eec318..d9a48a9f4424 100644 --- a/docs/_blog/_posts/2016-05-05-multiversal-equality.md +++ b/docs/_blog/_posts/2016-05-05-multiversal-equality.md @@ -6,7 +6,7 @@ authorImg: images/martin.jpg date: 2016-05-05 --- -I have been working recently on making equality tests using `==` and `!=` safer in Scala. This has led to a [Language Enhancement Proposal](https://github.com/lampepfl/dotty/issues/1247) which I summarize in this blog. +I have been working recently on making equality tests using `==` and `!=` safer in Scala. This has led to a [Language Enhancement Proposal](https://github.com/scala/scala3/issues/1247) which I summarize in this blog. ## Why Change Equality? @@ -77,7 +77,7 @@ Given a set of `Eq` instances, the idea is that the Scala compiler will check ev So this means we still keep universal equality as it is in Scala now - we don't have a choice here anyway, because of backwards compatibility. But we render it safe by checking that for each comparison the corresponding `Eq` instance exists. -What about types for which no `Eq` instance exists? To maintain backwards compatibility, we allow comparisons of such types as well, by means of a fall-back `eqAny` instance. But we do not allow comparisons between types that have an `Eq` instance and types that have none. Details are explained in the [proposal](https://github.com/lampepfl/dotty/issues/1247). +What about types for which no `Eq` instance exists? To maintain backwards compatibility, we allow comparisons of such types as well, by means of a fall-back `eqAny` instance. But we do not allow comparisons between types that have an `Eq` instance and types that have none. Details are explained in the [proposal](https://github.com/scala/scala3/issues/1247). ## Properties diff --git a/docs/_blog/_posts/2016-12-05-implicit-function-types.md b/docs/_blog/_posts/2016-12-05-implicit-function-types.md index ba28159c0fa3..0d9eae53d37f 100644 --- a/docs/_blog/_posts/2016-12-05-implicit-function-types.md +++ b/docs/_blog/_posts/2016-12-05-implicit-function-types.md @@ -6,7 +6,7 @@ authorImg: images/martin.jpg date: 2016-12-05 --- -I just made the [first pull request](https://github.com/lampepfl/dotty/pull/1775) to add _implicit function types_ to +I just made the [first pull request](https://github.com/scala/scala3/pull/1775) to add _implicit function types_ to Scala. I am pretty excited about it, because - citing the explanation of the pull request - "_This is the first step to bring contextual abstraction to Scala_". What do I mean by this? @@ -181,7 +181,7 @@ implicit Transaction => Int ``` Just like the normal function type syntax `A => B`, desugars to `scala.Function1[A, B]` the implicit function type syntax `implicit A => B` desugars to `scala.ImplicitFunction1[A, B]`. -The same holds at other function arities. With Dotty's [pull request #1758](https://github.com/lampepfl/dotty/pull/1758) +The same holds at other function arities. With Dotty's [pull request #1758](https://github.com/scala/scala3/pull/1758) merged there is no longer an upper limit of 22 for such functions. The type `ImplicitFunction1` can be thought of being defined as follows: diff --git a/docs/_blog/_posts/2017-05-31-first-dotty-milestone-release.md b/docs/_blog/_posts/2017-05-31-first-dotty-milestone-release.md index 9bfd22b2e3db..3063e658537d 100644 --- a/docs/_blog/_posts/2017-05-31-first-dotty-milestone-release.md +++ b/docs/_blog/_posts/2017-05-31-first-dotty-milestone-release.md @@ -46,7 +46,7 @@ using Dotty with sbt, see the Releases are available for download on the _Releases_ section of the Dotty repository: -https://github.com/lampepfl/dotty/releases +https://github.com/scala/scala3/releases We also provide a [homebrew](https://brew.sh/) package that can be installed by running @@ -92,9 +92,9 @@ See here for the full [version number explanation](https://dotty.epfl.ch/docs/us Over the coming weeks and months, we plan to work on the following topics: - - [Integrate Local optimizations developed in Dotty linker](https://github.com/lampepfl/dotty/pull/2513); - - [Add Language-level support for HMaps and HLists](https://github.com/lampepfl/dotty/pull/2199); - - [Port global optimizations from Dotty linker](https://github.com/lampepfl/dotty/pull/1840). + - [Integrate Local optimizations developed in Dotty linker](https://github.com/scala/scala3/pull/2513); + - [Add Language-level support for HMaps and HLists](https://github.com/scala/scala3/pull/2199); + - [Port global optimizations from Dotty linker](https://github.com/scala/scala3/pull/1840). If you want to get your hands dirty with any of this, now is a good moment to get involved! Join the team of contributors, including diff --git a/docs/_blog/_posts/2017-07-12-second-dotty-milestone-release.md b/docs/_blog/_posts/2017-07-12-second-dotty-milestone-release.md index 9172b5ad67ec..ff314eed13f2 100644 --- a/docs/_blog/_posts/2017-07-12-second-dotty-milestone-release.md +++ b/docs/_blog/_posts/2017-07-12-second-dotty-milestone-release.md @@ -34,52 +34,52 @@ The [previous technology preview](/_blog/_posts/2017-05-31-first-dotty-milestone This technology preview is geared towards improving stability and reliability. It includes: - - [Local optimizations upstreamed from the Dotty Linker](https://github.com/lampepfl/dotty/pull/2513), [2647](https://github.com/lampepfl/dotty/pull/2647) by ([@OlivierBlanvillain](https://github.com/OlivierBlanvillain)). See more details below. - - [Optimizing Pattern Matcher](https://github.com/lampepfl/dotty/pull/2829) by ([@odersky](https://github.com/odersky)) - - [Idempotency checks](https://github.com/lampepfl/dotty/pull/2756) are the first step to reproducible builds - - [Faster Base class sets](https://github.com/lampepfl/dotty/pull/2676) by ([@odersky](https://github.com/odersky)) and ([@darkdimius](https://twitter.com/darkdimius)) + - [Local optimizations upstreamed from the Dotty Linker](https://github.com/scala/scala3/pull/2513), [2647](https://github.com/scala/scala3/pull/2647) by ([@OlivierBlanvillain](https://github.com/OlivierBlanvillain)). See more details below. + - [Optimizing Pattern Matcher](https://github.com/scala/scala3/pull/2829) by ([@odersky](https://github.com/odersky)) + - [Idempotency checks](https://github.com/scala/scala3/pull/2756) are the first step to reproducible builds + - [Faster Base class sets](https://github.com/scala/scala3/pull/2676) by ([@odersky](https://github.com/odersky)) and ([@darkdimius](https://twitter.com/darkdimius)) - Numerous fixes to IDE and Dotty Language Server covering: - - [Windows support for VS Code plugin](https://github.com/lampepfl/dotty/pull/2776) - - [Fix hover-on-type for implicitly converted expressions](https://github.com/lampepfl/dotty/pull/2836) - - [Fixes to find all references in external projects](https://github.com/lampepfl/dotty/pull/2810), [2773](https://github.com/lampepfl/dotty/pull/2773/files) - - [Fix conflict with dragos-vscode-scala](https://github.com/lampepfl/dotty/pull/2777) - - [Fix ide crash on non-parsable file](https://github.com/lampepfl/dotty/pull/2752) - - [Fix hover functionality for enum classes](https://github.com/lampepfl/dotty/pull/2722) - - [Report errors on Dotty Language Server initialization](https://github.com/lampepfl/dotty/pull/2708) - - [Fixes to sbt setting up Dotty IDE](https://github.com/lampepfl/dotty/pull/2690) - - General stability improvements [2838](https://github.com/lampepfl/dotty/pull/2838), [2787](https://github.com/lampepfl/dotty/pull/2787), [2692](https://github.com/lampepfl/dotty/pull/2692) + - [Windows support for VS Code plugin](https://github.com/scala/scala3/pull/2776) + - [Fix hover-on-type for implicitly converted expressions](https://github.com/scala/scala3/pull/2836) + - [Fixes to find all references in external projects](https://github.com/scala/scala3/pull/2810), [2773](https://github.com/scala/scala3/pull/2773/files) + - [Fix conflict with dragos-vscode-scala](https://github.com/scala/scala3/pull/2777) + - [Fix ide crash on non-parsable file](https://github.com/scala/scala3/pull/2752) + - [Fix hover functionality for enum classes](https://github.com/scala/scala3/pull/2722) + - [Report errors on Dotty Language Server initialization](https://github.com/scala/scala3/pull/2708) + - [Fixes to sbt setting up Dotty IDE](https://github.com/scala/scala3/pull/2690) + - General stability improvements [2838](https://github.com/scala/scala3/pull/2838), [2787](https://github.com/scala/scala3/pull/2787), [2692](https://github.com/scala/scala3/pull/2692) - Scalac compatibility improvements: - - [Support Scala 2.12 traits](https://github.com/lampepfl/dotty/pull/2685) - - [Fixes to handling of Scala 2 classfiles](https://github.com/lampepfl/dotty/pull/2834/files) - - [Scalac parser crashes on Dotty.jar](https://github.com/lampepfl/dotty/pull/2719) + - [Support Scala 2.12 traits](https://github.com/scala/scala3/pull/2685) + - [Fixes to handling of Scala 2 classfiles](https://github.com/scala/scala3/pull/2834/files) + - [Scalac parser crashes on Dotty.jar](https://github.com/scala/scala3/pull/2719) - Java compatibility improvements: - - [Fixes to handing of Java generic signatures](https://github.com/lampepfl/dotty/pull/2831) - - [java.lang.System.out is final but that's a lie](https://github.com/lampepfl/dotty/pull/2781) + - [Fixes to handing of Java generic signatures](https://github.com/scala/scala3/pull/2831) + - [java.lang.System.out is final but that's a lie](https://github.com/scala/scala3/pull/2781) - Improved error messages: - - [Nicer error message for "implicit function type needs non-empty parameter list"](https://github.com/lampepfl/dotty/pull/2821) - - [Nicer error message for nonsensical modifier combination](https://github.com/lampepfl/dotty/pull/2807/files), [2747](https://github.com/lampepfl/dotty/pull/2747) - - [Nicer error message for supercall inside @inline method](https://github.com/lampepfl/dotty/pull/2740) - - [Check that case classes don't inherit case classes](https://github.com/lampepfl/dotty/pull/2790) - - [Check that named parameters don't conflict with positional ones](https://github.com/lampepfl/dotty/pull/2785) + - [Nicer error message for "implicit function type needs non-empty parameter list"](https://github.com/scala/scala3/pull/2821) + - [Nicer error message for nonsensical modifier combination](https://github.com/scala/scala3/pull/2807/files), [2747](https://github.com/scala/scala3/pull/2747) + - [Nicer error message for supercall inside @inline method](https://github.com/scala/scala3/pull/2740) + - [Check that case classes don't inherit case classes](https://github.com/scala/scala3/pull/2790) + - [Check that named parameters don't conflict with positional ones](https://github.com/scala/scala3/pull/2785) - Improved command line handling: - - [Support params in a file like @file.txt](https://github.com/lampepfl/dotty/pull/2765) + - [Support params in a file like @file.txt](https://github.com/scala/scala3/pull/2765) - Type system stability: - - [Handle wildcard types in unions and intersections](https://github.com/lampepfl/dotty/pull/2742) + - [Handle wildcard types in unions and intersections](https://github.com/scala/scala3/pull/2742) - Fixes to implicit search: - - [Fix shadowing of higher order implicits](https://github.com/lampepfl/dotty/pull/2739) + - [Fix shadowing of higher order implicits](https://github.com/scala/scala3/pull/2739) ### Better generated code: @@ -313,7 +313,7 @@ using Dotty with sbt, see the Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) We also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -338,10 +338,10 @@ You can try it out there without installing anything. Over the coming weeks and months, we plan to work on the following topics: - - [Add support for using Dotty generated classes with Scala 2.12](https://github.com/lampepfl/dotty/pull/2827) - - [Add Language-level support for HMaps and HLists](https://github.com/lampepfl/dotty/pull/2199); + - [Add support for using Dotty generated classes with Scala 2.12](https://github.com/scala/scala3/pull/2827) + - [Add Language-level support for HMaps and HLists](https://github.com/scala/scala3/pull/2199); - Upstream more optimizations from Dotty Linker - - [Add support for existing in the same classpath with Scala 2.12](https://github.com/lampepfl/dotty/pull/2827) + - [Add support for existing in the same classpath with Scala 2.12](https://github.com/scala/scala3/pull/2827) If you want to get your hands dirty with any of this, now is a good moment to get involved! Join the team of contributors, including diff --git a/docs/_blog/_posts/2017-09-07-third-dotty-milestone-release.md b/docs/_blog/_posts/2017-09-07-third-dotty-milestone-release.md index 236591139105..01fec156ecde 100644 --- a/docs/_blog/_posts/2017-09-07-third-dotty-milestone-release.md +++ b/docs/_blog/_posts/2017-09-07-third-dotty-milestone-release.md @@ -33,12 +33,12 @@ stability and reliability: This technology preview further improves stability and reliability. Some highlighted PRs are: - IDE bug fixes: - [#2986](https://github.com/lampepfl/dotty/pull/2986), - [#2932](https://github.com/lampepfl/dotty/pull/2932), - [#2885](https://github.com/lampepfl/dotty/pull/2885), - [#2876](https://github.com/lampepfl/dotty/pull/2876), - [#2870](https://github.com/lampepfl/dotty/pull/2870), - [#2872](https://github.com/lampepfl/dotty/pull/2872) by [@odersky] and [@smarter]. + [#2986](https://github.com/scala/scala3/pull/2986), + [#2932](https://github.com/scala/scala3/pull/2932), + [#2885](https://github.com/scala/scala3/pull/2885), + [#2876](https://github.com/scala/scala3/pull/2876), + [#2870](https://github.com/scala/scala3/pull/2870), + [#2872](https://github.com/scala/scala3/pull/2872) by [@odersky] and [@smarter]. ## How can you try it out? @@ -65,7 +65,7 @@ using Dotty with sbt, see the ### Standalone installation Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) We also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -87,16 +87,16 @@ You can try it out there without installing anything. ## What are the next steps? Over the coming weeks and months, we plan to work on the following topics: - - [Add support for using Dotty generated classes with Scala 2.12](https://github.com/lampepfl/dotty/pull/2827) - - [Add Language-level support for HMaps and HLists](https://github.com/lampepfl/dotty/pull/2199); + - [Add support for using Dotty generated classes with Scala 2.12](https://github.com/scala/scala3/pull/2827) + - [Add Language-level support for HMaps and HLists](https://github.com/scala/scala3/pull/2199); - Upstream more optimizations from Dotty Linker - - [Add support for existing in the same classpath with Scala 2.12](https://github.com/lampepfl/dotty/pull/2827) - - [Add native Dotty REPL](https://github.com/lampepfl/dotty/pull/2991) + - [Add support for existing in the same classpath with Scala 2.12](https://github.com/scala/scala3/pull/2827) + - [Add native Dotty REPL](https://github.com/scala/scala3/pull/2991) ## Questions / Reporting Bugs If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing Thank you to all the contributors who made this release possible! @@ -122,7 +122,7 @@ According to `git shortlog -sn --no-merges 0.2.0-RC1..0.3.0-RC2` these are: If you want to get your hands dirty with any of this, now is a good moment to get involved! You can have a look at our [Getting Started page](https://dotty.epfl.ch/docs/contributing/getting-started.html), our [Awesome Error Messages](http://scala-lang.org/blog/2016/10/14/dotty-errors.html) or some of -the simple [Dotty issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +the simple [Dotty issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry-points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2017-10-16-fourth-dotty-milestone-release.md b/docs/_blog/_posts/2017-10-16-fourth-dotty-milestone-release.md index 7f98c4835ee6..1edf198380c8 100644 --- a/docs/_blog/_posts/2017-10-16-fourth-dotty-milestone-release.md +++ b/docs/_blog/_posts/2017-10-16-fourth-dotty-milestone-release.md @@ -25,14 +25,14 @@ stability and reliability. ## What’s new in the 0.4.0-RC1 technology preview? -### Rewritten REPL [#2991](https://github.com/lampepfl/dotty/pull/2991) +### Rewritten REPL [#2991](https://github.com/scala/scala3/pull/2991) The original Dotty REPL was a proof of concept hacked together from -[an ancient version of the scalac REPL](https://github.com/lampepfl/dotty/pull/1082#issuecomment-183905504). +[an ancient version of the scalac REPL](https://github.com/scala/scala3/pull/1082#issuecomment-183905504). It worked by creating Scala source files from the user input using string concatenation, this made it easy to adapt it for Dotty since it did not rely on the internals of scalac, but it was also fragile and hard to reason about. -The [new REPL](https://github.com/lampepfl/dotty/pull/2991) instead works by +The [new REPL](https://github.com/scala/scala3/pull/2991) instead works by manipulating ASTs (Abstract Syntax Trees), this is more robust and will make it easier to develop new features: we have already implemented auto-completion support (by reusing the APIs we had created for @@ -42,7 +42,7 @@ Note that the user interface of the REPL has not changed: like in the old REPL we use code adapted from the [Ammonite REPL](http://ammonite.io/#Ammonite-REPL) to provide syntax highlighting, multi-line editing, history, etc. -### Scala 2.12 support [#2827](https://github.com/lampepfl/dotty/pull/2827) +### Scala 2.12 support [#2827](https://github.com/scala/scala3/pull/2827) Since our first release, it has been possible to use Scala 2 libraries in a Dotty project as explained in the [dotty-example-project](https://github.com/smarter/dotty-example-project#getting-your-project-to-compile-with-dotty). @@ -82,7 +82,7 @@ the IDE sections of the [getting-started page](https://docs.scala-lang.org/scala ### Standalone installation Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) We also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -99,7 +99,7 @@ brew upgrade dotty ## Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing Thank you to all the contributors who made this release possible! @@ -131,7 +131,7 @@ According to `git shortlog -sn --no-merges 0.3.0-RC2..0.4.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! You can have a look at our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), the [Awesome Error Messages](http://scala-lang.org/blog/2016/10/14/dotty-errors.html) project or some of -the simple [Dotty issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +the simple [Dotty issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry-points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2017-12-01-fifth-dotty-milestone-release.md b/docs/_blog/_posts/2017-12-01-fifth-dotty-milestone-release.md index 60d1062b7eac..dfc97e64f496 100644 --- a/docs/_blog/_posts/2017-12-01-fifth-dotty-milestone-release.md +++ b/docs/_blog/_posts/2017-12-01-fifth-dotty-milestone-release.md @@ -25,7 +25,7 @@ support for Scala 2.12 and came with a brand new REPL. ## What’s new in the 0.5.0-RC1 technology preview? -### Reworked implicit search [#3421](https://github.com/lampepfl/dotty/pull/3421) +### Reworked implicit search [#3421](https://github.com/scala/scala3/pull/3421) The treatment of ambiguity errors has changed. If an ambiguity is encountered in some recursive step of an implicit search, the ambiguity is propagated to the caller. Example: Say you have the following definitions: @@ -56,7 +56,7 @@ techniques no longer work. But there is now a new special type `scala.implicits. implements negation directly. For any query type `Q`: `Not[Q]` succeeds if and only if the implicit search for `Q` fails. -### Dependent function types [#3464](https://github.com/lampepfl/dotty/pull/3464) +### Dependent function types [#3464](https://github.com/scala/scala3/pull/3464) A dependent function type describes functions where the result type may depend on the function's parameter values. Example: @@ -108,7 +108,7 @@ are currently two backends using the TASTY frontend: This is the first step toward linking and whole word optimisations, recompiling code to a different backends... -### Generic java signatures [#3234](https://github.com/lampepfl/dotty/pull/3234) +### Generic java signatures [#3234](https://github.com/scala/scala3/pull/3234) Dotty now emits generic signatures for classes and methods. Those signatures are used by compilers, debuggers and to support runtime reflection. For example: @@ -144,7 +144,7 @@ the IDE sections of the [getting-started page](https://docs.scala-lang.org/scala ### Standalone installation Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) We also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -161,7 +161,7 @@ brew upgrade dotty ## Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing Thank you to all the contributors who made this release possible! @@ -198,7 +198,7 @@ According to `git shortlog -sn --no-merges 0.4.0-RC1..0.5.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! You can have a look at our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), the [Awesome Error Messages](http://scala-lang.org/blog/2016/10/14/dotty-errors.html) project or some of -the simple [Dotty issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +the simple [Dotty issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry-points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2018-03-05-seventh-dotty-milestone-release.md b/docs/_blog/_posts/2018-03-05-seventh-dotty-milestone-release.md index a72e04409ea0..a70d71bc17b8 100644 --- a/docs/_blog/_posts/2018-03-05-seventh-dotty-milestone-release.md +++ b/docs/_blog/_posts/2018-03-05-seventh-dotty-milestone-release.md @@ -19,12 +19,12 @@ You can learn more about Dotty on our [website](http://dotty.epfl.ch). This is our seventh scheduled release according to our [6-week release schedule](https://dotty.epfl.ch/docs/usage/version-numbers.html). -The [previous technology preview](https://github.com/lampepfl/dotty/releases/tag/0.6.0-RC1) focussed +The [previous technology preview](https://github.com/scala/scala3/releases/tag/0.6.0-RC1) focussed on bug fixes and stability work. ## What’s new in the 0.7.0-RC1 technology preview? -### Enum Simplification [#4003](https://github.com/lampepfl/dotty/pull/4003) +### Enum Simplification [#4003](https://github.com/scala/scala3/pull/4003) The previously introduced syntax and rules for enum were arguably too complex. We can considerably simplify them by taking away one capability: that cases can have bodies which can define members. Arguably, if we choose an ADT decomposition of a problem, it's good style to write all methods using @@ -75,7 +75,7 @@ and how to use them to model [Algebraic Data Types](https://dotty.epfl.ch/docs/r visit the respective sections in our documentation. -### Erased terms [#3342](https://github.com/lampepfl/dotty/pull/3342) +### Erased terms [#3342](https://github.com/scala/scala3/pull/3342) The `erased` modifier can be used on parameters, `val` and `def` to enforce that no reference to those terms is ever used. As they are never used, they can safely be removed during compilation. @@ -103,10 +103,10 @@ For more information, visit the [Erased Terms](https://dotty.epfl.ch/docs/refere section of our documentation. **Note**: Erased terms replace _phantom types_: they have similar semantics, but with the added -advantage that any type can be an erased parameter. See [#3410](https://github.com/lampepfl/dotty/pull/3410). +advantage that any type can be an erased parameter. See [#3410](https://github.com/scala/scala3/pull/3410). -### Improved IDE support [#3960](https://github.com/lampepfl/dotty/pull/3960) +### Improved IDE support [#3960](https://github.com/scala/scala3/pull/3960) The Dotty language server now supports context sensitive IDE completions. Completions now include local and imported definitions. Members completions take possible implicit conversions into account. @@ -183,7 +183,7 @@ compile-time. For example, writing `(eval(a), eval(a))` instead of `(eval(a), eval(b))` in the example above should be an error, but it was not caught by Scala 2 or previous versions of Dotty, whereas we now get a type mismatch error as expected. More work remains to be done to fix the remaining [GADT-related -issues](https://github.com/lampepfl/dotty/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+gadt), +issues](https://github.com/scala/scala3/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+gadt), but so far no show-stopper has been found. ## Trying out Dotty @@ -210,7 +210,7 @@ the IDE sections of the [getting-started page](https://docs.scala-lang.org/scala ### Standalone installation Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) We also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -227,7 +227,7 @@ brew upgrade dotty ## Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing Thank you to all the contributors who made this release possible! @@ -255,7 +255,7 @@ According to `git shortlog -sn --no-merges 0.6.0..0.7.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry-points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2018-04-27-eighth-dotty-milestone-release.md b/docs/_blog/_posts/2018-04-27-eighth-dotty-milestone-release.md index 72c0747e659d..d2194594edcc 100644 --- a/docs/_blog/_posts/2018-04-27-eighth-dotty-milestone-release.md +++ b/docs/_blog/_posts/2018-04-27-eighth-dotty-milestone-release.md @@ -24,12 +24,12 @@ You can learn more about Dotty on our [website](https://dotty.epfl.ch). This is our eighth scheduled release according to our [6-week release schedule](https://dotty.epfl.ch/docs/usage/version-numbers.html). -The [previous technology preview](https://github.com/lampepfl/dotty/releases/tag/0.7.0-RC1) simplified +The [previous technology preview](https://github.com/scala/scala3/releases/tag/0.7.0-RC1) simplified enums, introduced erased terms, improved IDE support and improved pattern matching for GADT. ## What’s new in the 0.8.0-RC1 technology preview? -### sbt 1 support [#3872](https://github.com/lampepfl/dotty/pull/3872) +### sbt 1 support [#3872](https://github.com/scala/scala3/pull/3872) Starting with Dotty 0.8.0, we will only support versions of sbt >= 1.1.4. Migrating to sbt 1 lets us use the new improved incremental compiler for Scala called [Zinc](https://github.com/sbt/zinc), and enables integration with tools such as [Bloop](https://scalacenter.github.io/bloop/). @@ -43,7 +43,7 @@ If you are already using Dotty with sbt 0.13, follow these simple steps to upgra ``` - replace usages of `.withDottyCompat()` by `.withDottyCompat(scalaVersion.value)` -### Unchecked warnings [#4045](https://github.com/lampepfl/dotty/pull/4045) +### Unchecked warnings [#4045](https://github.com/scala/scala3/pull/4045) Dotty now emits `unchecked` warnings like `scalac` whenever a type test is performed but cannot be fully checked at runtime because of type erasure. For example: @@ -64,7 +64,7 @@ def foo[T](x: T) = x match { } ``` -### Kind Polymorphism [#4108](https://github.com/lampepfl/dotty/pull/4108) +### Kind Polymorphism [#4108](https://github.com/scala/scala3/pull/4108) Normally type parameters in Scala are partitioned into kinds. First-level types are types of values. Higher-kinded types are type constructors such as `List` or `Map`. The kind of a type is indicated by the top type of which it is a subtype. Normal types are subtypes of `Any`, covariant single @@ -94,7 +94,7 @@ f[[X] =>> String] (i.e. `-Ykind-polymorphism`). For more information, visit the [Kind Polymorphism](https://dotty.epfl.ch/docs/reference/other-new-features/kind-polymorphism.html) section of our documentation. -### Improved support for SAM type [#4152](https://github.com/lampepfl/dotty/pull/4152) +### Improved support for SAM type [#4152](https://github.com/scala/scala3/pull/4152) This release includes fixes to [SAM types](https://www.scala-lang.org/news/2.12.0/#lambda-syntax-for-sam-types) that greatly improve interoperability with Java 8 lambdas. One can now easily write Scala code that uses Java streams: @@ -139,7 +139,7 @@ the IDE sections of the [getting-started page](https://docs.scala-lang.org/scala ### Standalone installation Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) We also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -156,7 +156,7 @@ brew upgrade dotty ## Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing Thank you to all the contributors who made this release possible! @@ -187,7 +187,7 @@ According to `git shortlog -sn --no-merges 0.7.0..0.8.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry-points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2018-07-06-ninth-dotty-milestone-release.md b/docs/_blog/_posts/2018-07-06-ninth-dotty-milestone-release.md index 914eca4d73d3..73066551300b 100644 --- a/docs/_blog/_posts/2018-07-06-ninth-dotty-milestone-release.md +++ b/docs/_blog/_posts/2018-07-06-ninth-dotty-milestone-release.md @@ -24,23 +24,23 @@ You can learn more about Dotty on our [website](https://dotty.epfl.ch). This is our ninth scheduled release according to our [6-week release schedule](https://dotty.epfl.ch/docs/usage/version-numbers.html). -The [previous technology preview](https://github.com/lampepfl/dotty/releases/tag/0.8.0-RC1) added +The [previous technology preview](https://github.com/scala/scala3/releases/tag/0.8.0-RC1) added support for sbt 1, introduced improved unchecked warnings and improved SAM type support. ## What’s new in the 0.9.0-RC1 technology preview? -### Improved REPL [#4680](https://github.com/lampepfl/dotty/pull/4680) +### Improved REPL [#4680](https://github.com/scala/scala3/pull/4680) The REPL now uses [JLine 3](https://github.com/jline/jline3) under the hood which improves on many aspects such as, auto-completions and multi-line editing. The REPL now also works on Windows! -### Documentation support in the IDE [#4461](https://github.com/lampepfl/dotty/pull/4461), [#4648](https://github.com/lampepfl/dotty/pull/4648) +### Documentation support in the IDE [#4461](https://github.com/scala/scala3/pull/4461), [#4648](https://github.com/scala/scala3/pull/4648) The Dotty IDE will now display documentation while hovering over symbols that were previously compiled by the Dotty compiler. In the future, we plan to let users query the documentation in the REPL as well. -### Drop requirement that implicit functions must be non-empty [#4549](https://github.com/lampepfl/dotty/pull/4549) +### Drop requirement that implicit functions must be non-empty [#4549](https://github.com/scala/scala3/pull/4549) We remove the arbitrary restriction that parameters of implicit functions must by non-empty. We can now write: ```scala @@ -63,7 +63,7 @@ timed { Both definitions above are equivalent. -### Emit feature warnings for implicit conversions [#4229](https://github.com/lampepfl/dotty/pull/4229) +### Emit feature warnings for implicit conversions [#4229](https://github.com/scala/scala3/pull/4229) Implicit conversions are easily the most misused feature in Scala. We now emit feature warnings when encountering an implicit conversion definition, just like Scala 2 does. @@ -76,7 +76,7 @@ unless the conversion is: (we might extend this to more conversions). -### Optimise s and raw interpolators [#3961](https://github.com/lampepfl/dotty/pull/3961) +### Optimise s and raw interpolators [#3961](https://github.com/scala/scala3/pull/3961) `s` and `raw` string interpolators were known to be slower than their not type-safe counterparts: ```scala s"Hello $name!" @@ -89,7 +89,7 @@ The compiler will now desugar the former into the latter. Special thanks to compiler! -### Support for compiler plugins [#3438](https://github.com/lampepfl/dotty/pull/3438) +### Support for compiler plugins [#3438](https://github.com/scala/scala3/pull/3438) Dotty now supports Compiler plugins. Compiler plugins let you customize the compiler pipeline without having to modify the compiler source code. A major difference compared to Scala 2 is that Dotty plugins must run after the type checker. Being able to influence normal type checking @@ -123,7 +123,7 @@ the IDE sections of the [getting-started page](https://docs.scala-lang.org/scala ### Standalone installation Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) We also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -144,7 +144,7 @@ installing anything. Note however that Scastie only supports Dotty 0.7.0-RC1. ## Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing Thank you to all the contributors who made this release possible! @@ -180,7 +180,7 @@ According to `git shortlog -sn --no-merges 0.8.0..0.9.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry-points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2018-10-10-10th-dotty-milestone-release.md b/docs/_blog/_posts/2018-10-10-10th-dotty-milestone-release.md index b583d1bd0f49..0a5ebd067391 100644 --- a/docs/_blog/_posts/2018-10-10-10th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2018-10-10-10th-dotty-milestone-release.md @@ -99,7 +99,7 @@ or the enclosing class did not change at call site. E.g. This restriction has now been removed. We also improve upon `scalac` which is not able to optimise methods that change the type of `this` on a polymorphic recursive call. -[Examples](https://github.com/lampepfl/dotty/blob/7a45a4a386d33180e5b7b21aa74271a77cce4707/tests/neg-tailcall/tailrec.scala#L43-L44) +[Examples](https://github.com/scala/scala3/blob/7a45a4a386d33180e5b7b21aa74271a77cce4707/tests/neg-tailcall/tailrec.scala#L43-L44) can be found in our test suite. ### Experimental support for generic Tuples @@ -125,7 +125,7 @@ val t2: (Int, String, Long, Int, String, Long) = (1,2,3,1,2,3) ### And much more! -Please read our [release notes](https://github.com/lampepfl/dotty/releases/tag/0.10.0-RC1) +Please read our [release notes](https://github.com/scala/scala3/releases/tag/0.10.0-RC1) for more details! ## Breaking changes @@ -160,7 +160,7 @@ the IDE sections of the [getting-started page](https://docs.scala-lang.org/scala Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) For macOS users, we also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -179,7 +179,7 @@ brew upgrade dotty If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -222,7 +222,7 @@ According to `git shortlog -sn --no-merges 0.9.0..0.10.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2018-11-30-11th-dotty-milestone-release.md b/docs/_blog/_posts/2018-11-30-11th-dotty-milestone-release.md index 344900e2e164..268d86db00c6 100644 --- a/docs/_blog/_posts/2018-11-30-11th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2018-11-30-11th-dotty-milestone-release.md @@ -115,7 +115,7 @@ information from the Scaladoc comment, then format it before we display it in th ### And much more! -Please read our [release notes](https://github.com/lampepfl/dotty/releases/tag/0.11.0-RC1) +Please read our [release notes](https://github.com/scala/scala3/releases/tag/0.11.0-RC1) for more details! ## Trying out Dotty @@ -146,7 +146,7 @@ the IDE sections of the [getting-started page](https://docs.scala-lang.org/scala Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) For macOS users, we also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -165,7 +165,7 @@ brew upgrade dotty If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -201,7 +201,7 @@ According to `git shortlog -sn --no-merges 0.10.0..0.11.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-01-21-12th-dotty-milestone-release.md b/docs/_blog/_posts/2019-01-21-12th-dotty-milestone-release.md index f9fc25375d86..d56a03b4e345 100644 --- a/docs/_blog/_posts/2019-01-21-12th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-01-21-12th-dotty-milestone-release.md @@ -106,7 +106,7 @@ This kind of reasoning is necessary for many advanced GADT usages! ### And much more! -Please read our [release notes](https://github.com/lampepfl/dotty/releases/tag/0.12.0-RC1) +Please read our [release notes](https://github.com/scala/scala3/releases/tag/0.12.0-RC1) for more details! ## Trying out Dotty @@ -137,7 +137,7 @@ the IDE sections of the [getting-started page](https://docs.scala-lang.org/scala Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) For macOS users, we also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -156,7 +156,7 @@ brew upgrade dotty If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -195,7 +195,7 @@ According to `git shortlog -sn --no-merges 0.11.0-RC1..0.12.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-03-05-13th-dotty-milestone-release.md b/docs/_blog/_posts/2019-03-05-13th-dotty-milestone-release.md index f1838847d81e..8ebb70ea59e5 100644 --- a/docs/_blog/_posts/2019-03-05-13th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-03-05-13th-dotty-milestone-release.md @@ -50,11 +50,11 @@ smoothly, but the *Parallelism and Concurrency* course given in the Spring semester teaches Spark, which means we needed to support it in Dotty! Luckily, this turned out to be mostly straightforward: we adopted the [object -serialization scheme](https://github.com/lampepfl/dotty/pull/5775) and [lambda -serialization scheme](https://github.com/lampepfl/dotty/pull/5837) pioneered by +serialization scheme](https://github.com/scala/scala3/pull/5775) and [lambda +serialization scheme](https://github.com/scala/scala3/pull/5837) pioneered by Scala 2, and that was enough to make our Spark assignments run correctly! This doesn't mean that our support is perfect however, so don't hesitate to [open an -issue](http://github.com/lampepfl/dotty/issues) if something is amiss. +issue](http://github.com/scala/scala3/issues) if something is amiss. ## Introducing top level definitions @@ -74,7 +74,7 @@ def b = a._2 You can read about [dropping package objects](https://dotty.epfl.ch/docs/reference/dropped-features/package-objects.html) at the documentation linked or at the relevant PR -[#5754](https://github.com/lampepfl/dotty/pull/5754). +[#5754](https://github.com/scala/scala3/pull/5754). ## All things impl... implied @@ -211,7 +211,7 @@ object B { **You can read more about** [implied imports](https://dotty.epfl.ch/docs/reference/contextual/import-delegate.html) from the docs or the relevant PR -[#5868](https://github.com/lampepfl/dotty/pull/5868). +[#5868](https://github.com/scala/scala3/pull/5868). As we mentioned above, *context queries* are functions with (only) inferable parameters. Here is an example of such a function: @@ -227,9 +227,9 @@ merely an alignment of IFTs into the new scheme. **You can read more about** the alternative to implicits through the *Contextual Abstractions* section of our documentation or for a deep dive from the relevant PR chain that originated from -[#5458](https://github.com/lampepfl/dotty/pull/5458). The syntax changes for new +[#5458](https://github.com/scala/scala3/pull/5458). The syntax changes for new implicits are summarized in -[#5825](https://github.com/lampepfl/dotty/pull/5825). +[#5825](https://github.com/scala/scala3/pull/5825). This release offers the support for _type class derivation_ as a language feature. Type class derivation is a way to generate instances of certain type @@ -279,8 +279,8 @@ def derived[T] given Generic[T] = ... **You can read more about** [Type class Derivation](https://dotty.epfl.ch/docs/reference/contextual/derivation.html) or have a deep dive at the relevant PRs: -[#5540](https://github.com/lampepfl/dotty/pull/5540) and -[#5839](https://github.com/lampepfl/dotty/pull/5839). +[#5540](https://github.com/scala/scala3/pull/5540) and +[#5839](https://github.com/scala/scala3/pull/5839). _Multiversal equality_ is now supported through the `Eql` marker trait (renamed from `Eq` to differentiate it from Cats' `Eq`). For example, in order to be able @@ -292,7 +292,7 @@ implied for Eql[Int, String] = Eql.derived ``` **You can read more about** how we based multiversal equality on type class derivation through -the relevant PR [#5843](https://github.com/lampepfl/dotty/pull/5843). +the relevant PR [#5843](https://github.com/scala/scala3/pull/5843). _Implicit conversions_ are now defined by implied instances of the `scala.Conversion` class. For example: @@ -311,7 +311,7 @@ important with the documentation of each feature, please consult the ## Implicit resolution rule changes -PR [#5887](https://github.com/lampepfl/dotty/pull/5887) applies the following +PR [#5887](https://github.com/scala/scala3/pull/5887) applies the following changes to implicit resolution: 1. nested implicits always take precedence over outer ones @@ -324,12 +324,12 @@ changes to implicit resolution: data model for semantic information such as symbols and types about programs in Scala and other languages. SemanticDB decouples production and consumption of semantic information, establishing documented means for communication between -tools. With PR [#5761](https://github.com/lampepfl/dotty/pull/5761) we add the +tools. With PR [#5761](https://github.com/scala/scala3/pull/5761) we add the first prototype for the generation of SemanticDB information from TASTy. ## And much more! -Please read our [release notes](https://github.com/lampepfl/dotty/releases/tag/0.13.0-RC1) +Please read our [release notes](https://github.com/scala/scala3/releases/tag/0.13.0-RC1) for more details! # Trying out Dotty @@ -360,7 +360,7 @@ the IDE sections of the [getting-started page](https://docs.scala-lang.org/scala Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) For macOS users, we also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -379,7 +379,7 @@ brew upgrade dotty If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -417,7 +417,7 @@ According to `git shortlog -sn --no-merges 0.12.0-RC1..0.13.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-04-15-14th-dotty-milestone-release.md b/docs/_blog/_posts/2019-04-15-14th-dotty-milestone-release.md index 6724ae11cef1..1ac1c3ae9fbb 100644 --- a/docs/_blog/_posts/2019-04-15-14th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-04-15-14th-dotty-milestone-release.md @@ -72,7 +72,7 @@ For more information, please read more in the [documentation](https://dotty.epfl ## An immutable array type -A new type, `scala.IArray[T]`, is added, which is an immutable version of the `Array` type. Its implementation deserves a special attention, as it uses the new Dotty features in an elegant way (the below is an abstract from the corresponding [commit](https://github.com/lampepfl/dotty/commit/af2a0e66eb4b1204eac5dcb1d979486b92ef93d7#diff-156dc405d9f228bbc0fe406dfba63f65): +A new type, `scala.IArray[T]`, is added, which is an immutable version of the `Array` type. Its implementation deserves a special attention, as it uses the new Dotty features in an elegant way (the below is an abstract from the corresponding [commit](https://github.com/scala/scala3/commit/af2a0e66eb4b1204eac5dcb1d979486b92ef93d7#diff-156dc405d9f228bbc0fe406dfba63f65): ```scala opaque type IArray[T] = Array[T] @@ -131,7 +131,7 @@ Some of the other changes include: If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -171,7 +171,7 @@ According to `git shortlog -sn --no-merges 0.13.0-RC1..0.14.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-05-23-15th-dotty-milestone-release.md b/docs/_blog/_posts/2019-05-23-15th-dotty-milestone-release.md index 68337d78ca8c..1ffb07377da4 100644 --- a/docs/_blog/_posts/2019-05-23-15th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-05-23-15th-dotty-milestone-release.md @@ -6,7 +6,7 @@ authorImg: images/anatolii.png date: 2019-05-23 --- -Hi! We are very excited to announce the 15th release of Dotty. The most exciting thing in this release is the full bootstrap for Dotty introduced by PR [#5923](https://github.com/lampepfl/dotty/pull/5923)🎉😍. This means that we now always compile Dotty with Dotty itself, hence we can use use all the new features in the compiler code base. +Hi! We are very excited to announce the 15th release of Dotty. The most exciting thing in this release is the full bootstrap for Dotty introduced by PR [#5923](https://github.com/scala/scala3/pull/5923)🎉😍. This means that we now always compile Dotty with Dotty itself, hence we can use use all the new features in the compiler code base. With this release comes a bunch of new features and improvements, such as the ability to enforce whether an operator is intended to be used in an infix position, the type safe pattern bindings and more. @@ -36,7 +36,7 @@ This is our 15th scheduled release according to our ## Full Bootstrap Bootstrapping Dotty is a big milestone for us and in compiler construction in general. Firstly, we feel more confident that our compiler works as is (even without reusing the new features). Secondly, in the immediate future, we will be able to reuse many of the features that dotty proposes within dotty itself. For example, we have no fewer than 2641 occurrences of the text string (implicit ctx: Context) in the compiler that we can scrap with [Contextual Function types](https://www.scala-lang.org/blog/2016/12/07/implicit-function-types.html). Big milestones have high risk/high gain and we must be attentive. That is the reason that we will wait a bit until we start using new features. Consequently, at the moment we cross-compile the build with 2.12 on the CI so that we don't accidentally start using Dotty features in case we need to revise the bootstrap process (we'll start using Dotty features eventually, but let's wait until we're confident that this setup works well enough). -Check the following for more information [#5923 (comment)](https://github.com/lampepfl/dotty/pull/5923#issuecomment-485421148) and please let us know if you have any incremental compilation issues or anything else! +Check the following for more information [#5923 (comment)](https://github.com/scala/scala3/pull/5923#issuecomment-485421148) and please let us know if you have any incremental compilation issues or anything else! ## Operator Rules This change addresses the problem of the regulation of whether an operator is supposed to be used in an infix position. The motivation is for the library authors to be able to enforce whether a method or a type is supposed to be used in an infix position by the users. This ability will help to make code bases more consistent in the way the calls to methods are performed. @@ -150,7 +150,7 @@ For the migration purposes, the above change will only take effect in Scala 3.1. For more information, see the [documentation](https://dotty.epfl.ch/docs/reference/changed-features/pattern-bindings.html). ## Further improvements to Generalised Algebraic Data Types (GADTs) support -In this release, we've further improved our support for GADTs. Most notably, we now support variant GADTs, thus fixing [#2985](https://github.com/lampepfl/dotty/issues/2985): +In this release, we've further improved our support for GADTs. Most notably, we now support variant GADTs, thus fixing [#2985](https://github.com/scala/scala3/issues/2985): ```scala enum Expr[+T] { @@ -164,20 +164,20 @@ def eval[T](e: Expr[T]): T = e match { } ``` -We've also plugged a few soundness problems (e.g. [#5667](https://github.com/lampepfl/dotty/issues/5667)) caused by inferring too much when matching on abstract, union and intersection types. For more information, see PR [#5736](https://github.com/lampepfl/dotty/pull/5736). +We've also plugged a few soundness problems (e.g. [#5667](https://github.com/scala/scala3/issues/5667)) caused by inferring too much when matching on abstract, union and intersection types. For more information, see PR [#5736](https://github.com/scala/scala3/pull/5736). ## Other changes Some of the other notable changes include the following: - Singletons are now allowed in union types. E.g. the following is allowed: `object foo; type X = Int | foo.type`. -- A bunch of improvements was made for the type inference system – see, e.g., PRs [#6454](https://github.com/lampepfl/dotty/pull/6454) and [#6467](https://github.com/lampepfl/dotty/pull/6467). -- Improvements to the Scala 2 code support which, in particular, improves Cats support – see PRs [#6494](https://github.com/lampepfl/dotty/pull/6494) and [#6498](https://github.com/lampepfl/dotty/pull/6498). +- A bunch of improvements was made for the type inference system – see, e.g., PRs [#6454](https://github.com/scala/scala3/pull/6454) and [#6467](https://github.com/scala/scala3/pull/6467). +- Improvements to the Scala 2 code support which, in particular, improves Cats support – see PRs [#6494](https://github.com/scala/scala3/pull/6494) and [#6498](https://github.com/scala/scala3/pull/6498). # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -205,7 +205,7 @@ According to `git shortlog -sn --no-merges 0.14.0-RC1..0.15.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-06-11-16th-dotty-milestone-release.md b/docs/_blog/_posts/2019-06-11-16th-dotty-milestone-release.md index 41194df26625..91f63a5610b7 100644 --- a/docs/_blog/_posts/2019-06-11-16th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-06-11-16th-dotty-milestone-release.md @@ -49,7 +49,7 @@ represented by `=>>`. As a result a function from types to types is written as `[X] =>> F[X]`. For those who are interested in the discussions, -[#6558](https://github.com/lampepfl/dotty/pull/6558) introduced the new syntax. +[#6558](https://github.com/scala/scala3/pull/6558) introduced the new syntax. ## Syntax Change: Wildcard Arguments in Types @@ -92,7 +92,7 @@ delegate ListOrd[T] for Ord[List[T]] given (ord: Ord[T]) { ``` For more information, the documentation has been updated as part of the relevant -PR [#6649](https://github.com/lampepfl/dotty/pull/6649) +PR [#6649](https://github.com/scala/scala3/pull/6649) ## Polymorphic function types @@ -127,7 +127,7 @@ With PFTs we can now achieve what we want: ``` For those who are interested in the discussions and more test cases, -[#4672](https://github.com/lampepfl/dotty/pull/4672/) introduced PFTs. +[#4672](https://github.com/scala/scala3/pull/4672/) introduced PFTs. ## `lazy val`s are now thread-safe by default @@ -156,9 +156,9 @@ enum B(val gravity: Double) extends java.lang.Enum[B] { } ``` -For more information please check the [test case](https://github.com/lampepfl/dotty/tree/main/tests/run/enum-java) and -also the relevant PRs [#6602](https://github.com/lampepfl/dotty/pull/6602) and -[#6629](https://github.com/lampepfl/dotty/pull/6629). +For more information please check the [test case](https://github.com/scala/scala3/tree/main/tests/run/enum-java) and +also the relevant PRs [#6602](https://github.com/scala/scala3/pull/6602) and +[#6629](https://github.com/scala/scala3/pull/6629). In the test, the enums are defined in the `MainScala.scala` file and used from a Java source, `Test.java`. @@ -212,13 +212,13 @@ Advantages of new scheme: - Complete decoupling between derives clauses and mirror generation. For the technical details of these changes please consule the corresponding PR -[#6531](https://github.com/lampepfl/dotty/pull/6531). +[#6531](https://github.com/scala/scala3/pull/6531). # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -245,7 +245,7 @@ According to `git shortlog -sn --no-merges 0.15.0-RC1..0.16.0-RC3` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-07-25-17th-dotty-milestone-release.md b/docs/_blog/_posts/2019-07-25-17th-dotty-milestone-release.md index eea99263def9..62e0a550598d 100644 --- a/docs/_blog/_posts/2019-07-25-17th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-07-25-17th-dotty-milestone-release.md @@ -31,7 +31,7 @@ This is our 17th scheduled release according to our # What’s new in the 0.17.0-RC1 technology preview? ## New implicit scoping rules -We aim to make the implicit scoping rules clean and intuitive. In this release, the scoping rules were refactored to facilitate this goal. As specified in the [code documentation](https://github.com/lampepfl/dotty/pull/6832/files#diff-584b631c45ba6f2d4bc5d803074b8f12R474): +We aim to make the implicit scoping rules clean and intuitive. In this release, the scoping rules were refactored to facilitate this goal. As specified in the [code documentation](https://github.com/scala/scala3/pull/6832/files#diff-584b631c45ba6f2d4bc5d803074b8f12R474): The implicit scope of a type `tp` is the smallest set S of object references (i.e. TermRefs with Module symbol) such that: @@ -48,14 +48,14 @@ with Module symbol) such that: - If `tp` is some other type, its implicit scope is the union of the implicit scopes of its parts (parts defined as in the spec). -You can learn more from PR [#6832](https://github.com/lampepfl/dotty/pull/6832). +You can learn more from PR [#6832](https://github.com/scala/scala3/pull/6832). ## Metaprogramming We are making steady progress developing metaprogramming features. The highlights for this release are: -- Tasty Reflection's `Reflection` object moved inside `QuoteContext` object. This means that if previously to do Tasty Reflection you had to implicitly depend on `Reflection`, now you need to depend on `QuoteContext`. To know more, see [#6723](https://github.com/lampepfl/dotty/pull/6723). -- Progress made on quoted patterns – see [#6504](https://github.com/lampepfl/dotty/pull/6504). -- `code` string interpolator allows to obtain the code a user passes to a macro as a String. See [#6661](https://github.com/lampepfl/dotty/pull/6661). To enable this feature, do the following import: `import scala.compiletime._`. +- Tasty Reflection's `Reflection` object moved inside `QuoteContext` object. This means that if previously to do Tasty Reflection you had to implicitly depend on `Reflection`, now you need to depend on `QuoteContext`. To know more, see [#6723](https://github.com/scala/scala3/pull/6723). +- Progress made on quoted patterns – see [#6504](https://github.com/scala/scala3/pull/6504). +- `code` string interpolator allows to obtain the code a user passes to a macro as a String. See [#6661](https://github.com/scala/scala3/pull/6661). To enable this feature, do the following import: `import scala.compiletime._`. ## 2.12 build removed from the CI tests 2.12 build is removed from the test suite. The 2.12 build compiled and tested the Dotty compiler with the Scala 2.12 compiler. This means that, even though Dotty is bootstrapped (i.e. capable of compiling itself), we were not able to use any of the new Dotty features in the Dotty codebase since these features would not compile with Scala 2.12. The decision to abstain from using the new features was made to give us the time to see if something goes wrong with the bootstrap and the ability to revert to Scala 2.12 if it becomes necessary. @@ -74,7 +74,7 @@ There were some organizational and infrastructural changes worth mentioning. If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -113,7 +113,7 @@ According to `git shortlog -sn --no-merges 0.16.0-RC3..0.17.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-08-30-18th-dotty-milestone-release.md b/docs/_blog/_posts/2019-08-30-18th-dotty-milestone-release.md index 420b9103d3b7..8c06b2058230 100644 --- a/docs/_blog/_posts/2019-08-30-18th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-08-30-18th-dotty-milestone-release.md @@ -168,7 +168,7 @@ val iterator = Iterator.from(10, -1) } ``` -For more information, see PR [#6994](https://github.com/lampepfl/dotty/pull/6994). +For more information, see PR [#6994](https://github.com/scala/scala3/pull/6994). ## Brace-less syntax for control expressions This is an effort to clean-up the control expressions. Scala 2 has two ways of writing `if` statements – with and without parentheses. Parentheses can be dropped in Scala 2 `if`s inside `match` or `for` statements. We'd like to have a single style of writing all of the control expressions, and the cleaner the better. @@ -202,7 +202,7 @@ This release, hence, brings the ability to write all of the control expressions Moreover, the compiler can automatically rewrite your sources from the old syntax to the new syntax and vice versa. To rewrite the sources to the new syntax, run the compiler with the `-rewrite -new-syntax` flags, and to rewrite to the old syntax, use `-rewrite -old-syntax`. So far, both syntaxes are supported. -For more information and the precise rules, see PR [#7024](https://github.com/lampepfl/dotty/pull/7024). +For more information and the precise rules, see PR [#7024](https://github.com/scala/scala3/pull/7024). ## Significant indentation syntax Significant indentations syntax is here! A logical continuation of the brace-less syntax for control expressions described above, meant as an exploration into a better way to write Scala, it allows writing Scala programs without braces. For example: @@ -232,7 +232,7 @@ given as scala.util.FromString[Day]: So far, it is a purely experimental effort. This means there is no final decision yet on whether or not it will be included in Scala 3. However, we treat this feature seriously enough to give it an extended period of trial and see if it is viable as the new look and feel for Scala. -For more details and the discussion, see PRs [#7083](https://github.com/lampepfl/dotty/pull/7083) and [#7114](https://github.com/lampepfl/dotty/pull/7114). +For more details and the discussion, see PRs [#7083](https://github.com/scala/scala3/pull/7083) and [#7114](https://github.com/scala/scala3/pull/7114). ## Generic Number Literals It is now possible to seamlessly integrate with different number formats: that is, to write a number and get it automatically converted to your class of choice. E.g.: @@ -256,13 +256,13 @@ For precise rules, semantics and a larger example of `BigFloat`, see [the docume ## Metaprogramming Progress We are making steady progress with the language metaprogramming features. The metaprogramming spotlights of this release are as follows: -- `toExprOfTuple` method which allows converting a `Seq[Expr[Any]]` to `Expr[Tuple]`. The types of the expressions will be preserved in the tuple. See [#7037](https://github.com/lampepfl/dotty/pull/7037) and [#7076](https://github.com/lampepfl/dotty/pull/7076) for the details. -- `toExprOfTuple` method that converts a tuple of expressions to an expression of tuple – see [#7047](https://github.com/lampepfl/dotty/pull/7047). -- `toExprOfSeq` which converts an `Seq[Expr[A]]` to `Expr[Seq[A]]` – see [#6935](https://github.com/lampepfl/dotty/pull/6935). -- More `Liftable` instances – for Tuples of arity greater than 22, `BigInt` and `BigDecimal` – see [#6947](https://github.com/lampepfl/dotty/pull/6947) and [#6944](https://github.com/lampepfl/dotty/pull/6944). -- Leverage implicit lambdas to simplify `Liftable.toExpr` method – see [#6924](https://github.com/lampepfl/dotty/pull/6924) to learn how it is done. -- Runtime staging `run` moved to `scala.quoted.staging` in [#7077](https://github.com/lampepfl/dotty/pull/7077). -- Runtime staging factored out to a separate library in [#7080](https://github.com/lampepfl/dotty/pull/7080). +- `toExprOfTuple` method which allows converting a `Seq[Expr[Any]]` to `Expr[Tuple]`. The types of the expressions will be preserved in the tuple. See [#7037](https://github.com/scala/scala3/pull/7037) and [#7076](https://github.com/scala/scala3/pull/7076) for the details. +- `toExprOfTuple` method that converts a tuple of expressions to an expression of tuple – see [#7047](https://github.com/scala/scala3/pull/7047). +- `toExprOfSeq` which converts an `Seq[Expr[A]]` to `Expr[Seq[A]]` – see [#6935](https://github.com/scala/scala3/pull/6935). +- More `Liftable` instances – for Tuples of arity greater than 22, `BigInt` and `BigDecimal` – see [#6947](https://github.com/scala/scala3/pull/6947) and [#6944](https://github.com/scala/scala3/pull/6944). +- Leverage implicit lambdas to simplify `Liftable.toExpr` method – see [#6924](https://github.com/scala/scala3/pull/6924) to learn how it is done. +- Runtime staging `run` moved to `scala.quoted.staging` in [#7077](https://github.com/scala/scala3/pull/7077). +- Runtime staging factored out to a separate library in [#7080](https://github.com/scala/scala3/pull/7080). ## Type Class Derivation Type class derivation has received a major rework and an [updated documentation](https://dotty.epfl.ch/docs/reference/contextual/derivation.html). We have dropped the usage of the `Shape` type to describe the shape of a type. Instead, all the relevant information is now encoded in the `Mirror` type and its subtypes as tuples. @@ -270,15 +270,15 @@ Type class derivation has received a major rework and an [updated documentation] For more information, see the [documentation](https://dotty.epfl.ch/docs/reference/contextual/derivation.html). ## Other -- This release also features the new version of the SBT Dotty Plugin – 0.3.4. It contains some bug fixes – see [#7120](https://github.com/lampepfl/dotty/pull/7120) for details. -- Scala Days 2019 talks related to Dotty are now [mentioned](https://dotty.epfl.ch/docs/resources/talks.html) at our website – this allows to systematize the knowledge about the next generation of Scala in one place – see [#6984](https://github.com/lampepfl/dotty/pull/6984). -- ScalaJS needs your help! We would like to have robust support for ScalaJS in Dotty, which unfortunately is not the case so far. If you are interested in contributing, please see [the getting started tutorial](https://gist.github.com/sjrd/e0823a5bddbcef43999cdaa032b1220c) and [the discussion](https://github.com/lampepfl/dotty/issues/7113). +- This release also features the new version of the SBT Dotty Plugin – 0.3.4. It contains some bug fixes – see [#7120](https://github.com/scala/scala3/pull/7120) for details. +- Scala Days 2019 talks related to Dotty are now [mentioned](https://dotty.epfl.ch/docs/resources/talks.html) at our website – this allows to systematize the knowledge about the next generation of Scala in one place – see [#6984](https://github.com/scala/scala3/pull/6984). +- ScalaJS needs your help! We would like to have robust support for ScalaJS in Dotty, which unfortunately is not the case so far. If you are interested in contributing, please see [the getting started tutorial](https://gist.github.com/sjrd/e0823a5bddbcef43999cdaa032b1220c) and [the discussion](https://github.com/scala/scala3/issues/7113). # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -310,7 +310,7 @@ According to `git shortlog -sn --no-merges 0.17.0-RC1..0.18.1-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-09-23-19th-dotty-milestone-release.md b/docs/_blog/_posts/2019-09-23-19th-dotty-milestone-release.md index 0de8d87b92bb..55458b5a20c6 100644 --- a/docs/_blog/_posts/2019-09-23-19th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-09-23-19th-dotty-milestone-release.md @@ -160,7 +160,7 @@ For instance, `-project-logo dotty-logo.svg` will make `/images/dotty-logo.svg` [The front page](https://dotty.epfl.ch) has been redesigned too, with a new responsive menu and improved contrast. -Overall, every page has been updated with consistent settings of fonts and colors. A more detailed comparison between the new and the old design can be found [here](https://github.com/lampepfl/dotty/pull/7153). +Overall, every page has been updated with consistent settings of fonts and colors. A more detailed comparison between the new and the old design can be found [here](https://github.com/scala/scala3/pull/7153). ## Metaprogramming Progress We're making steady progress on the Dotty metaprogramming capability. In our previous work, we've implemented a bunch of functions for working with expressions. For example, we have a capability to convert a list of expressions into an expression of list, or a tuple of expressions into an expression of tuple. @@ -179,7 +179,7 @@ Also, `x.toExpr` syntax which lifts `x` into an expression is now deprecated. It If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -206,7 +206,7 @@ According to `git shortlog -sn --no-merges 0.18.1-RC1..0.19.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-11-04-20th-dotty-milestone-release.md b/docs/_blog/_posts/2019-11-04-20th-dotty-milestone-release.md index 78cbe171ca11..e28b2304831c 100644 --- a/docs/_blog/_posts/2019-11-04-20th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-11-04-20th-dotty-milestone-release.md @@ -127,16 +127,16 @@ It is easy to forget to put `then` at the end of the line if nothing else follow ## Metaprogramming Progress We are making a steady progress developing and improving the metaprogramming features of Dotty. Here are metaprogramming highlights of this release: -- Fix #7189: Do not try to load contents if file does not exist [#7476](https://github.com/lampepfl/dotty/pull/7476) -- Add customizable names for definitions in quotes [#7346](https://github.com/lampepfl/dotty/pull/7346) -- Rename scala.quoted.matching.{Bind => Sym} [#7332](https://github.com/lampepfl/dotty/pull/7332) -- Replace AsFunction implicit class with Expr.reduce [#7299](https://github.com/lampepfl/dotty/pull/7299) +- Fix #7189: Do not try to load contents if file does not exist [#7476](https://github.com/scala/scala3/pull/7476) +- Add customizable names for definitions in quotes [#7346](https://github.com/scala/scala3/pull/7346) +- Rename scala.quoted.matching.{Bind => Sym} [#7332](https://github.com/scala/scala3/pull/7332) +- Replace AsFunction implicit class with Expr.reduce [#7299](https://github.com/scala/scala3/pull/7299) # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -173,7 +173,7 @@ According to `git shortlog -sn --no-merges 0.19.0-RC1..0.20.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-12-20-21th-dotty-milestone-release.md b/docs/_blog/_posts/2019-12-20-21th-dotty-milestone-release.md index 94d8ee61bec9..794eb875e3fc 100644 --- a/docs/_blog/_posts/2019-12-20-21th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-12-20-21th-dotty-milestone-release.md @@ -17,7 +17,7 @@ happy to announce that we are now feature complete! # Feature Complete! This release is a HUGE milestone for us, for Dotty, for Scala 3, for our community. Since that -[initial commit](https://github.com/lampepfl/dotty/commit/90962407e72d88f8f3249ade0f6bd60ff15af5ce) +[initial commit](https://github.com/scala/scala3/commit/90962407e72d88f8f3249ade0f6bd60ff15af5ce) on the 6th December of 2012 when the only feature was the basic structure of a compiler based on the DOT calculus, we have come a long way. @@ -48,7 +48,7 @@ It means that we can now put the Scala 3 compiler under heavy load, getting it ready for industrial strength applications. At the moment we have 23 projects on our community projects and we expect this number to go up! -> https://github.com/lampepfl/dotty/tree/main/community-build/community-projects +> https://github.com/scala/scala3/tree/main/community-build/community-projects This project contains tests to build and test a corpus of open sources Scala 2.x projects against Scala 3. @@ -333,7 +333,7 @@ root for `.semanticdb` files) and `-sourceroot` to calculate a relative path for If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -378,7 +378,7 @@ According to `git shortlog -sn --no-merges 0.20.0-RC1..0.21.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2020-02-05-22nd-dotty-milestone-release.md b/docs/_blog/_posts/2020-02-05-22nd-dotty-milestone-release.md index a901e83130d8..1dc100a9a741 100644 --- a/docs/_blog/_posts/2020-02-05-22nd-dotty-milestone-release.md +++ b/docs/_blog/_posts/2020-02-05-22nd-dotty-milestone-release.md @@ -55,7 +55,7 @@ println(s"Third: ${list.third}") // 3 This syntax is a completely separate one from the `given` syntax and hence is aimed to bring more clarity and disentangle the two different concepts. -For the discussion, see [PR #7917](https://github.com/lampepfl/dotty/pull/7917). For more information on how to use extension methods in general and collective extension methods in particular, see the [documentation](https://dotty.epfl.ch/docs/reference/contextual/extension-methods.html). +For the discussion, see [PR #7917](https://github.com/scala/scala3/pull/7917). For more information on how to use extension methods in general and collective extension methods in particular, see the [documentation](https://dotty.epfl.ch/docs/reference/contextual/extension-methods.html). # Kind projector syntax support [Kind projector](https://github.com/typelevel/kind-projector) is a popular compiler plugin for Scala 2. It is especially useful in the context of purely functional programming and type class derivation – everywhere where you need to work extensively with types. @@ -90,7 +90,7 @@ object tupleFunctor extends Functor[λ[x => (x, x)]] println(squared) // (1,4) ``` -For the discussion, see [PR #7775](https://github.com/lampepfl/dotty/pull/7775). Also see the GitHub [repository](https://github.com/typelevel/kind-projector) of the kind projector Scala 2 plugin for more context. +For the discussion, see [PR #7775](https://github.com/scala/scala3/pull/7775). Also see the GitHub [repository](https://github.com/typelevel/kind-projector) of the kind projector Scala 2 plugin for more context. # Further improvements to the context parameters syntax Scala 3 context parameters are successors of Scala 2 implicits. In Scala 2, they proved useful for a wide range of applications including purely functional programming, dependency injection, type class derivation, type-level programming. Because their apparent value, one of the priorities in Scala 3 for us is to improve the conceptual framework behind them. @@ -127,7 +127,7 @@ As opposed to the previous: f(2)(given 20) ``` -For the time being, the change is experimental and the old syntax is also supported. For the discussion, see [PR #8162](https://github.com/lampepfl/dotty/pull/8162). You can browse the documentation concerning the new syntax [here](https://dotty.epfl.ch/docs/reference/contextual/motivation-new.html). +For the time being, the change is experimental and the old syntax is also supported. For the discussion, see [PR #8162](https://github.com/scala/scala3/pull/8162). You can browse the documentation concerning the new syntax [here](https://dotty.epfl.ch/docs/reference/contextual/motivation-new.html). # Semantics of inline parameters changed Inline parameters is a metaprogramming feature of Dotty which allows to splice the body of the parameter on its call site. Previously, inline parameters to methods were required to be known on compile time. With this release, this constraint has been relaxed. The following: @@ -149,7 +149,7 @@ Notice how the value of the by-name parameter `b` is not inlined but is bound to So, if previously you had a macro `inline def operationOnCode(code: => Unit) = ${ mcrImpl('code) }` which did something on the AST of the passed `code`, with this release you need to change it to `inline def operationOnCode(inline code: Unit) = ${ mcrImpl('code) }`. -This change was introduced by [PR #8060](https://github.com/lampepfl/dotty/pull/8060/). +This change was introduced by [PR #8060](https://github.com/scala/scala3/pull/8060/). Another change in the semantics of the inline parameters involves the fact that the can no longer be passed as constants to macro implementations. Previously, the following was possible: @@ -169,7 +169,7 @@ inline def power(x: Double, inline n: Int) = ${ powerCode('x, 'n) } private def powerCode(x: Expr[Double], n: Expr[Int])(given QuoteContext): Expr[Double] = ??? ``` -You can obtain the constant value of `n` from within the macro implementation by calling `n.getValue` on it which returns an `Option`. This change was introduced by [PR #8061](https://github.com/lampepfl/dotty/pull/8061). +You can obtain the constant value of `n` from within the macro implementation by calling `n.getValue` on it which returns an `Option`. This change was introduced by [PR #8061](https://github.com/scala/scala3/pull/8061). For more information about the inline capability of Dotty, see [documentation](https://dotty.epfl.ch/docs/reference/metaprogramming/inline.html). @@ -194,7 +194,7 @@ The compile-time error above will say: This feature is particularly useful for data science applications. In data science, it is very easy to make a linear algebra mistake, multiply matrices of wrong dimensions and get a runtime error – sometimes after a few hours of running the model. Hence compile-time verification of the models has a great potential for saving time. With such a type-level arithmetic, Scala becomes well-positioned to implement such type-safe data science frameworks. -For the discussion, see [PR #7628](https://github.com/lampepfl/dotty/pull/7628). The documentation is available [here](https://dotty.epfl.ch/docs/reference/metaprogramming/inline.html#the-scalacompiletimeops-package). +For the discussion, see [PR #7628](https://github.com/scala/scala3/pull/7628). The documentation is available [here](https://dotty.epfl.ch/docs/reference/metaprogramming/inline.html#the-scalacompiletimeops-package). # Suggestions on missing context parameters If there's a compile-time error due to a missing context parameter and this error can be fixed with an import, the compiler will attempt to suggest such an import in the error message. Here is an example of how this error looks like: @@ -212,7 +212,7 @@ If there's a compile-time error due to a missing context parameter and this erro One area where these suggestions will make life easier is purely functional programming with type-classes, with libraries like [cats](https://typelevel.org/cats/). Having the fix for a missing type class in the error message itself is a big time-saver. -For the discussion, see [PR #7862](https://github.com/lampepfl/dotty/pull/7862). +For the discussion, see [PR #7862](https://github.com/scala/scala3/pull/7862). # TASTy Inspector library TASTy Consumer was renamed to TASTy Inspector as of this release. It was also published in a library of its own. For more information, see the [documentation](https://dotty.epfl.ch/docs/reference/metaprogramming/tasty-inspect.html) on this library. @@ -221,7 +221,7 @@ TASTy Consumer was renamed to TASTy Inspector as of this release. It was also pu If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -267,7 +267,7 @@ According to `git shortlog -sn --no-merges 0.21.0-RC1..0.22.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2020-03-18-23rd-dotty-milestone-release.md b/docs/_blog/_posts/2020-03-18-23rd-dotty-milestone-release.md index e52db993dd19..7725d7e7d254 100644 --- a/docs/_blog/_posts/2020-03-18-23rd-dotty-milestone-release.md +++ b/docs/_blog/_posts/2020-03-18-23rd-dotty-milestone-release.md @@ -52,7 +52,7 @@ In this release, we have added an aid for the programmer to detect such mistakes 1 error found ``` -You can learn more about the feature from the [documentation](https://dotty.epfl.ch/0.23.0-RC1/docs/reference/other-new-features/safe-initialization.html). For the discussion, see PR [#7789](https://github.com/lampepfl/dotty/pull/7789). +You can learn more about the feature from the [documentation](https://dotty.epfl.ch/0.23.0-RC1/docs/reference/other-new-features/safe-initialization.html). For the discussion, see PR [#7789](https://github.com/scala/scala3/pull/7789). ## Bitwise Int compiletime operations In the previous release, Dotty has [received](https://dotty.epfl.ch/blog/2020/02/05/22nd-dotty-milestone-release.html#primitive-compiletime-operations-on-singleton-types) a support for type-level arithmetic operations on integers. In this release, we are extending this support by adding bitwise operations. For example: @@ -246,7 +246,7 @@ Notice how above, we are calling `app.fun` and `app.args`. `fun` and `args` are If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -294,7 +294,7 @@ According to `git shortlog -sn --no-merges 0.22.0-RC1..0.23.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2020-04-29-24th-dotty-milestone-release.md b/docs/_blog/_posts/2020-04-29-24th-dotty-milestone-release.md index e32df8cacc55..79148254e409 100644 --- a/docs/_blog/_posts/2020-04-29-24th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2020-04-29-24th-dotty-milestone-release.md @@ -76,13 +76,13 @@ Bar 22 Bar 22 ``` -This new change, however, comes with rather intricated rules – if you are interested to learn about them in details, see [documentation](https://dotty.epfl.ch/docs/reference/metaprogramming/inline.html#rules-for-overriding) on inlines and the PR #[8543](https://github.com/lampepfl/dotty/pull/8543/files) which introduced the change. +This new change, however, comes with rather intricated rules – if you are interested to learn about them in details, see [documentation](https://dotty.epfl.ch/docs/reference/metaprogramming/inline.html#rules-for-overriding) on inlines and the PR #[8543](https://github.com/scala/scala3/pull/8543/files) which introduced the change. # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -125,7 +125,7 @@ According to `git shortlog -sn --no-merges 0.23.0-RC1..0.24.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. @@ -134,7 +134,7 @@ We are looking forward to having you join the team of contributors. Dotty now has a set of widely-used community libraries that are built against every nightly Dotty snapshot. Currently, this includes shapeless, ScalaPB, algebra, scalatest, scopt and squants. -Join our [community build](https://github.com/lampepfl/dotty/tree/main/community-build) +Join our [community build](https://github.com/scala/scala3/tree/main/community-build) to make sure that our regression suite includes your library. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_blog/_posts/2020-06-22-25th-dotty-milestone-release.md b/docs/_blog/_posts/2020-06-22-25th-dotty-milestone-release.md index dd5def04bfe9..db73513c2413 100644 --- a/docs/_blog/_posts/2020-06-22-25th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2020-06-22-25th-dotty-milestone-release.md @@ -35,13 +35,13 @@ This default budget is configurable via a compiler flag `-Ximport-suggestion-tim This change should speed up the compiler when it comes to programming with givens. -For more information, see PR [#9167](https://github.com/lampepfl/dotty/pull/9167). +For more information, see PR [#9167](https://github.com/scala/scala3/pull/9167). # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing Thank you to all the contributors who made this release possible 🎉 @@ -89,7 +89,7 @@ According to `git shortlog -sn --no-merges 0.24.0-RC1..0.25.0-RC2` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. @@ -98,7 +98,7 @@ We are looking forward to having you join the team of contributors. Dotty now has a set of widely-used community libraries that are built against every nightly Dotty snapshot. Currently, this includes shapeless, ScalaPB, algebra, scalatest, scopt and squants. -Join our [community build](https://github.com/lampepfl/dotty/tree/main/community-build) +Join our [community build](https://github.com/scala/scala3/tree/main/community-build) to make sure that our regression suite includes your library. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_blog/_posts/2020-07-27-26th-dotty-milestone-release.md b/docs/_blog/_posts/2020-07-27-26th-dotty-milestone-release.md index b0d153dded7e..06bf6fc5dabb 100644 --- a/docs/_blog/_posts/2020-07-27-26th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2020-07-27-26th-dotty-milestone-release.md @@ -35,7 +35,7 @@ extension (ss: Seq[String]): def longestString: String = longestStrings.head ``` -You can read more about the new syntax in the [documentation](https://dotty.epfl.ch/docs/reference/contextual/extension-methods.html). For the discussion, see [PR](https://github.com/lampepfl/dotty/pull/9255). +You can read more about the new syntax in the [documentation](https://dotty.epfl.ch/docs/reference/contextual/extension-methods.html). For the discussion, see [PR](https://github.com/scala/scala3/pull/9255). # Local Selectable Instances Local and anonymous classes that extend `Selectable` get more refined types than other classes. For example: @@ -78,7 +78,7 @@ val result = constValueTuple["foo" *: "bar" *: 10 *: 2.5 *: EmptyTuple] println(result) // (foo,bar,10,2.5) ``` -This feature was introduced by PR [#9209](https://github.com/lampepfl/dotty/pull/9209). +This feature was introduced by PR [#9209](https://github.com/scala/scala3/pull/9209). # Per-run time budget for import suggestions Import suggestions is a feature useful for debugging but potentially taxing for performance. Therefore, we have added the `-Ximport-suggestion-timeout ` to allow specifying the timeout (in milliseconds) after which the suggestions mechanism should stop the lookup. The timeout budget is per-run (and not per suggestion) which ensures that the performance does not degrade in case of too many suggestions. @@ -87,7 +87,7 @@ Import suggestions is a feature useful for debugging but potentially taxing for If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -119,7 +119,7 @@ According to `git shortlog -sn --no-merges 0.25.0-RC2..0.26.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. @@ -128,7 +128,7 @@ We are looking forward to having you join the team of contributors. Dotty now has a set of widely-used community libraries that are built against every nightly Dotty snapshot. Currently, this includes shapeless, ScalaPB, algebra, scalatest, scopt and squants. -Join our [community build](https://github.com/lampepfl/dotty/tree/main/community-build) +Join our [community build](https://github.com/scala/scala3/tree/main/community-build) to make sure that our regression suite includes your library. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_blog/_posts/2020-08-31-27th-dotty-milestone-release.md b/docs/_blog/_posts/2020-08-31-27th-dotty-milestone-release.md index e42e98a1385b..7d0eebe369e2 100644 --- a/docs/_blog/_posts/2020-08-31-27th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2020-08-31-27th-dotty-milestone-release.md @@ -41,30 +41,30 @@ To the best of our knowledge, cross-compiling libraries should be able to use Sc If you experience a bug with anything except the unsupported features mentioned above, please file a bug report. # Stability -As we're getting closer to the release of Scala 3, we are continuing to focus on the stability and performance of the language. In this release, we have fixed support of objects under JDK9+ (PR [#9181](https://github.com/lampepfl/dotty/pull/9181)). The issue was, due to the changes in JDK9+ compared to JDK8, our initialization scheme for objects did not work under JDK9+. The aforementioned fixed that issue, thereby unblocking JDK9+ support for Dotty. +As we're getting closer to the release of Scala 3, we are continuing to focus on the stability and performance of the language. In this release, we have fixed support of objects under JDK9+ (PR [#9181](https://github.com/scala/scala3/pull/9181)). The issue was, due to the changes in JDK9+ compared to JDK8, our initialization scheme for objects did not work under JDK9+. The aforementioned fixed that issue, thereby unblocking JDK9+ support for Dotty. -We are also continuing to work on stabilising enums. PR [#9532](https://github.com/lampepfl/dotty/pull/9532) corrects the deserialization and serialization of singleton enum values with `ObjectInputStream` and `ObjectOutputStream`. PR [#9549](https://github.com/lampepfl/dotty/pull/9549) enables overriding the `toString` method on enums – previously this was not possible because of the way enums were desugared. +We are also continuing to work on stabilising enums. PR [#9532](https://github.com/scala/scala3/pull/9532) corrects the deserialization and serialization of singleton enum values with `ObjectInputStream` and `ObjectOutputStream`. PR [#9549](https://github.com/scala/scala3/pull/9549) enables overriding the `toString` method on enums – previously this was not possible because of the way enums were desugared. # Performance We are also focusing these days on making the compiler faster and memory-efficient. For the past month, we were looking in the compiler's memory footprint. We were trying to determine what was allocated in unreasonable amounts during compilation and trying to resolve these allocation issues. The following PRs attempt to increase the performance of the compiler: -- Optimize megaphase [#9597](https://github.com/lampepfl/dotty/pull/9597) -- Cache all memberNamed results [#9633](https://github.com/lampepfl/dotty/pull/9633) -- Parallelize position pickling [#9619](https://github.com/lampepfl/dotty/pull/9619) -- Simplify TypeComparer [#9405](https://github.com/lampepfl/dotty/pull/9405) -- Optimize and simplify SourcePosition handling [#9561](https://github.com/lampepfl/dotty/pull/9561) +- Optimize megaphase [#9597](https://github.com/scala/scala3/pull/9597) +- Cache all memberNamed results [#9633](https://github.com/scala/scala3/pull/9633) +- Parallelize position pickling [#9619](https://github.com/scala/scala3/pull/9619) +- Simplify TypeComparer [#9405](https://github.com/scala/scala3/pull/9405) +- Optimize and simplify SourcePosition handling [#9561](https://github.com/scala/scala3/pull/9561) # Metaprogramming We are keeping the work on the metaprogramming API improvements. For this release, the following PRs bring better API to metaprogrammers: -- Avoid leak of internal implementation in tasty.Reflection [#9613](https://github.com/lampepfl/dotty/pull/9613) -- Redefine quoted.Expr.betaReduce [#9469](https://github.com/lampepfl/dotty/pull/9469) +- Avoid leak of internal implementation in tasty.Reflection [#9613](https://github.com/scala/scala3/pull/9613) +- Redefine quoted.Expr.betaReduce [#9469](https://github.com/scala/scala3/pull/9469) # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing Thank you to all the contributors who made this release possible 🎉 @@ -100,7 +100,7 @@ According to `git shortlog -sn --no-merges 0.26.0-RC1..0.27.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. @@ -109,7 +109,7 @@ We are looking forward to having you join the team of contributors. Dotty now has a set of widely-used community libraries that are built against every nightly Dotty snapshot. Currently, this includes shapeless, ScalaPB, algebra, scalatest, scopt and squants. -Join our [community build](https://github.com/lampepfl/dotty/tree/main/community-build) +Join our [community build](https://github.com/scala/scala3/tree/main/community-build) to make sure that our regression suite includes your library. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_blog/_posts/2020-11-09-scala3-m1.md b/docs/_blog/_posts/2020-11-09-scala3-m1.md index ffef5618f9ff..228a9f8eb99e 100644 --- a/docs/_blog/_posts/2020-11-09-scala3-m1.md +++ b/docs/_blog/_posts/2020-11-09-scala3-m1.md @@ -19,8 +19,8 @@ Below, you can find a short summary of the changes that took place during betwee Dotty 0.27.0-RC1 had introduced preliminary Scala.js support with the portable subset of Scala and native JavaScript types. Scala 3.0.0-M1 significantly expands on that support: -* support for non-native JS types ([#9774](https://github.com/lampepfl/dotty/pull/9774)), and -* better support for other JS interop features, notably their interactions with Scala 3 features such as top-level declarations and `enum`s (e.g, [#9725](https://github.com/lampepfl/dotty/pull/9725) and [#9955](https://github.com/lampepfl/dotty/pull/9955)). +* support for non-native JS types ([#9774](https://github.com/scala/scala3/pull/9774)), and +* better support for other JS interop features, notably their interactions with Scala 3 features such as top-level declarations and `enum`s (e.g, [#9725](https://github.com/scala/scala3/pull/9725) and [#9955](https://github.com/scala/scala3/pull/9955)). The only remaining feature of Scala.js that is not supported yet is JS exports: `@JSExport` and its siblings `@JSExportAll`, `@JSExportTopLevel` and `@JSExportStatic` are all ignored by Scala 3.0.0-M1. Support for JS exports will come in the next release. @@ -46,7 +46,7 @@ x match { As of Scala 3.1.0, the `@` syntax will be deprecated and the codebases should switch to `as` instead. -This change was implemented by PR [#9837](https://github.com/lampepfl/dotty/pull/9837). +This change was implemented by PR [#9837](https://github.com/scala/scala3/pull/9837). # Pattern-Bound Given Instances The syntax for `given` instances in patterns has also changed. In the `for`-comprehensions, the correct way of using `given`s is as follows: @@ -62,7 +62,7 @@ pair match case (ctx as given Context, y) => ... ``` -For more information, see [documentation](https://dotty.epfl.ch/docs/reference/contextual/givens.html#pattern-bound-given-instances), and for discussion, see PR [#10091](https://github.com/lampepfl/dotty/pull/10091). +For more information, see [documentation](https://dotty.epfl.ch/docs/reference/contextual/givens.html#pattern-bound-given-instances), and for discussion, see PR [#10091](https://github.com/scala/scala3/pull/10091). # Change wildcard given selectors This is another syntactic change which aims to simplify the code. Instead of: @@ -77,7 +77,7 @@ The correct version of the wildcard `given` import now becomes: import p.given ``` -This change was implemented by PR [#9949](https://github.com/lampepfl/dotty/pull/9949). +This change was implemented by PR [#9949](https://github.com/scala/scala3/pull/9949). # Final API for enumerations `enum` definitions are now released in their final design. since `0.27.0-RC1` we have made the following changes: @@ -125,22 +125,22 @@ val res1: Opt[?] = Nn # Keep `@alpha` optional for operators Following the discussion on [contributors](https://contributors.scala-lang.org/t/the-alpha-notation/4583), we now keep `@alpha` optional for operators. The checking behavior is still available when compiling with the `-Yrequire-alpha`. -`@alpha` annotations provide a way to define an alternate name for symbolic operators. You can learn more about `@alpha` annotations from the [documentation](https://dotty.epfl.ch/docs/reference/changed-features/operators.html#the-alpha-annotation). The change was implemented by PR [#10093](https://github.com/lampepfl/dotty/pull/10093). +`@alpha` annotations provide a way to define an alternate name for symbolic operators. You can learn more about `@alpha` annotations from the [documentation](https://dotty.epfl.ch/docs/reference/changed-features/operators.html#the-alpha-annotation). The change was implemented by PR [#10093](https://github.com/scala/scala3/pull/10093). # Optimizing the compiler During the last months, a considerable amount of effort went into investigating performance bottlenecks in the compiler and optimizing its workflow. We also work on stabilizing the compiler and porting relevant changes from the Scala 2 compiler to Scala 3. The following PRs are relevant to highlighting this work: -- Port classfile parsing improvements [#10037](https://github.com/lampepfl/dotty/pull/10037) -- Semanticdb usability enhancements [#9768](https://github.com/lampepfl/dotty/pull/9768) -- Optimize core and frontend [#9867](https://github.com/lampepfl/dotty/pull/9867) +- Port classfile parsing improvements [#10037](https://github.com/scala/scala3/pull/10037) +- Semanticdb usability enhancements [#9768](https://github.com/scala/scala3/pull/9768) +- Optimize core and frontend [#9867](https://github.com/scala/scala3/pull/9867) # Known issues -This release of Scala 3 doesn't work on JDK 14 because of a regression fixed in [#10135](https://github.com/lampepfl/dotty/pull/10135). JDK 15 doesn't work either because of [scala/bug#12172](https://github.com/scala/bug/issues/12172) which will be fixed in the new scala-library release. +This release of Scala 3 doesn't work on JDK 14 because of a regression fixed in [#10135](https://github.com/scala/scala3/pull/10135). JDK 15 doesn't work either because of [scala/bug#12172](https://github.com/scala/bug/issues/12172) which will be fixed in the new scala-library release. # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributors @@ -190,7 +190,7 @@ According to `git shortlog -sn --no-merges 0.27.0-RC1..3.0.0-M1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. @@ -199,7 +199,7 @@ We are looking forward to having you join the team of contributors. Dotty now has a set of widely-used community libraries that are built against every nightly Dotty snapshot. Currently, this includes shapeless, ScalaPB, algebra, scalatest, scopt and squants. -Join our [community build](https://github.com/lampepfl/dotty/tree/main/community-build) +Join our [community build](https://github.com/scala/scala3/tree/main/community-build) to make sure that our regression suite includes your library. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_blog/_posts/2020-12-18-scala3-m3.md b/docs/_blog/_posts/2020-12-18-scala3-m3.md index 41cfa76c0265..84fa9e823bda 100644 --- a/docs/_blog/_posts/2020-12-18-scala3-m3.md +++ b/docs/_blog/_posts/2020-12-18-scala3-m3.md @@ -19,7 +19,7 @@ You can try out the M3 version online via [Scastie](https://scastie.scala-lang.o # sbt plugin update -We published a new version of the sbt plugin `sbt-dotty`, v0.5.1. Because of the changes in PR [#10607](https://github.com/lampepfl/dotty/pull/10607), this release of Scala 3 will not work with earlier versions of sbt-dotty. You will need to upgrade sbt-dotty to 0.5.1 to be able to use Scala 3.0.0-M3. +We published a new version of the sbt plugin `sbt-dotty`, v0.5.1. Because of the changes in PR [#10607](https://github.com/scala/scala3/pull/10607), this release of Scala 3 will not work with earlier versions of sbt-dotty. You will need to upgrade sbt-dotty to 0.5.1 to be able to use Scala 3.0.0-M3. # Final syntactic tweaks ## `as` dropped from the `given` syntax @@ -57,7 +57,7 @@ given global: ExecutionContext = ForkJoinContext() given Context = ctx ``` -You can find a discussion of the above change in the [PR #10538](https://github.com/lampepfl/dotty/pull/10538). +You can find a discussion of the above change in the [PR #10538](https://github.com/scala/scala3/pull/10538). ## Drop `as` in patterns Since we dropped `as` from `given`s, we lost a strong reason for having `as` at all. Therefore, we dropped `as` from patterns as well. The following syntax, valid in Scala 3.0.0-M2, is not accepted anymore: @@ -128,16 +128,16 @@ In the meantime, the compiler will emit warnings when trying to call those metho Note that the warnings are only active with language mode `3.1-migration` or higher - see the documentation on the [Language Versions](https://dotty.epfl.ch/docs/usage/language-versions.html) to learn how to enable it. -You can read the discussion of this change in the [PR #10670](https://github.com/lampepfl/dotty/pull/10670). You can also read more about it in the [documentation](https://dotty.epfl.ch/docs/reference/other-new-features/matchable.html). +You can read the discussion of this change in the [PR #10670](https://github.com/scala/scala3/pull/10670). You can also read more about it in the [documentation](https://dotty.epfl.ch/docs/reference/other-new-features/matchable.html). # Tooling improvements As we are getting closer to a stable release of Scala 3, the focus increasingly shifts on the tooling available to get started with Scala 3. For a while now, we are not using the old dottydoc documentation tool for building the documentation. We are developing an entirely new tool, scala3doc, from scratch. This new documentation tool is more robust and faster than the old one. -As part of the tooling effort, this new Scala 3 documentation tool is rapidly improved. [PR #10522](https://github.com/lampepfl/dotty/pull/10522) proves that the doctool can generate documentation for the community build projects. You can access this documentation via the following [link](https://scala3doc.virtuslab.com/pr-master-docs/index.html). +As part of the tooling effort, this new Scala 3 documentation tool is rapidly improved. [PR #10522](https://github.com/scala/scala3/pull/10522) proves that the doctool can generate documentation for the community build projects. You can access this documentation via the following [link](https://scala3doc.virtuslab.com/pr-master-docs/index.html). -[PR #10491](https://github.com/lampepfl/dotty/pull/10491) introduced scripting support in Scala 3. Consider the following source named `Main.scala`: +[PR #10491](https://github.com/scala/scala3/pull/10491) introduced scripting support in Scala 3. Consider the following source named `Main.scala`: ```scala @main def Test(name: String): Unit = @@ -157,25 +157,25 @@ The documentation for this feature is available [here](https://dotty.epfl.ch/doc # Metaprogramming changes We have been polishing the metaprogramming API and making it more uniform. The following notable changes occurred between M2 and M3: -- Add `Expr.asTerm` [#10694](https://github.com/lampepfl/dotty/pull/10694) -- Add reflect `MatchCase` `TypeRepr` [#10735](https://github.com/lampepfl/dotty/pull/10735) -- Rework reflect Symbol fields API [#10705](https://github.com/lampepfl/dotty/pull/10705) -- Remove `Expr.StringContext.unapply` [#10675](https://github.com/lampepfl/dotty/pull/10675) -- Rename `Liftable` to `ToExpr` and `Unliftable` to `FromExpr` [#10618](https://github.com/lampepfl/dotty/pull/10618) -- Remove Unliftable[Unit] [#10570](https://github.com/lampepfl/dotty/pull/10570) -- Remove reflect.LambdaType [#10548](https://github.com/lampepfl/dotty/pull/10548) -- Add `scala.quoted.Expr.unapply` as dual of `Expr.apply` [#10580](https://github.com/lampepfl/dotty/pull/10580) -- Move `Quotes` as last parameter in `ExprMap.transform` [#10519](https://github.com/lampepfl/dotty/pull/10519) -- Rework reflect Constant API [#10753](https://github.com/lampepfl/dotty/pull/10753) -- Unify quoted.report and reflect.Reporting [#10474](https://github.com/lampepfl/dotty/pull/10474) -- Fix #10359: Add GivenSelector to reflection API [#10469](https://github.com/lampepfl/dotty/pull/10469) -- Rework reflect show API [#10661](https://github.com/lampepfl/dotty/pull/10661) -- Fix #10709: Add missing level check before inlining [#10781](https://github.com/lampepfl/dotty/pull/10781) +- Add `Expr.asTerm` [#10694](https://github.com/scala/scala3/pull/10694) +- Add reflect `MatchCase` `TypeRepr` [#10735](https://github.com/scala/scala3/pull/10735) +- Rework reflect Symbol fields API [#10705](https://github.com/scala/scala3/pull/10705) +- Remove `Expr.StringContext.unapply` [#10675](https://github.com/scala/scala3/pull/10675) +- Rename `Liftable` to `ToExpr` and `Unliftable` to `FromExpr` [#10618](https://github.com/scala/scala3/pull/10618) +- Remove Unliftable[Unit] [#10570](https://github.com/scala/scala3/pull/10570) +- Remove reflect.LambdaType [#10548](https://github.com/scala/scala3/pull/10548) +- Add `scala.quoted.Expr.unapply` as dual of `Expr.apply` [#10580](https://github.com/scala/scala3/pull/10580) +- Move `Quotes` as last parameter in `ExprMap.transform` [#10519](https://github.com/scala/scala3/pull/10519) +- Rework reflect Constant API [#10753](https://github.com/scala/scala3/pull/10753) +- Unify quoted.report and reflect.Reporting [#10474](https://github.com/scala/scala3/pull/10474) +- Fix #10359: Add GivenSelector to reflection API [#10469](https://github.com/scala/scala3/pull/10469) +- Rework reflect show API [#10661](https://github.com/scala/scala3/pull/10661) +- Fix #10709: Add missing level check before inlining [#10781](https://github.com/scala/scala3/pull/10781) # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributors @@ -231,7 +231,7 @@ We are looking forward to having you join the team of contributors. ## Library authors: Join our community build -Scala 3 is regularly tested against a sample of libraries known as the "community build". You can add your library to the [community build](https://github.com/lampepfl/dotty/tree/main/community-build) by submitting a PR. +Scala 3 is regularly tested against a sample of libraries known as the "community build". You can add your library to the [community build](https://github.com/scala/scala3/tree/main/community-build) by submitting a PR. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_blog/_posts/2021-02-17-scala3-rc1.md b/docs/_blog/_posts/2021-02-17-scala3-rc1.md index 9751f7b7461e..011dc0819107 100644 --- a/docs/_blog/_posts/2021-02-17-scala3-rc1.md +++ b/docs/_blog/_posts/2021-02-17-scala3-rc1.md @@ -11,7 +11,7 @@ Greetings from the Scala 3 team! We are delighted to announce the first release This release brings some last-minute polishings, clean-ups and changes before the big release. There were a few language changes to improve the user experience, as well as the polishings of the metaprogramming framework. We have also worked on the issues that had to be fixed before the stable release. -Overall, more than [400 PRs](https://github.com/lampepfl/dotty/pulls?q=is%3Apr+is%3Aclosed+closed%3A%3E2020-12-02+sort%3Acomments-desc) were merged after the M3 release and until today! Read more below! +Overall, more than [400 PRs](https://github.com/scala/scala3/pulls?q=is%3Apr+is%3Aclosed+closed%3A%3E2020-12-02+sort%3Acomments-desc) were merged after the M3 release and until today! Read more below! ## Allow secondary type parameter list in extension methods @@ -43,7 +43,7 @@ Or, when passing both type arguments: sumBy[String](List("a", "bb", "ccc"))[Int](_.length) ``` -For discussion, see [PR #10940](https://github.com/lampepfl/dotty/pull/10940). For more information about the extension methods, see [documentation](https://dotty.epfl.ch/docs/reference/contextual/extension-methods.html). +For discussion, see [PR #10940](https://github.com/scala/scala3/pull/10940). For more information about the extension methods, see [documentation](https://dotty.epfl.ch/docs/reference/contextual/extension-methods.html). ## New `import` syntax @@ -62,11 +62,11 @@ import scala.collection.mutable as mut import NumPy as np ``` -For the details and discussion, see [PR #11244](https://github.com/lampepfl/dotty/pull/11244). Read more about this change in the [documentation](https://dotty.epfl.ch/docs/reference/changed-features/imports.html). +For the details and discussion, see [PR #11244](https://github.com/scala/scala3/pull/11244). Read more about this change in the [documentation](https://dotty.epfl.ch/docs/reference/changed-features/imports.html). ## Use `*` for vararg splices -[PR #11240](https://github.com/lampepfl/dotty/pull/11240) changed the syntax of vararg splices in patterns and function arguments. The new syntax uses a postfix `*`, instead of `: _*`, analogously to how a vararg parameter is declared. +[PR #11240](https://github.com/scala/scala3/pull/11240) changed the syntax of vararg splices in patterns and function arguments. The new syntax uses a postfix `*`, instead of `: _*`, analogously to how a vararg parameter is declared. ## Use `uninitialized` for wildcard initializers @@ -88,7 +88,7 @@ var x: A = uninitialized This way expresses the intent of the idiom in a more verbose and easy to read way than simply writing an underscore. -For discussion, see [PR #11231](https://github.com/lampepfl/dotty/pull/11231), and the [documentation](https://dotty.epfl.ch/docs/reference/dropped-features/wildcard-init.html) is available on our website. +For discussion, see [PR #11231](https://github.com/scala/scala3/pull/11231), and the [documentation](https://dotty.epfl.ch/docs/reference/dropped-features/wildcard-init.html) is available on our website. ## Eta-expand companion object if functions are expected @@ -109,49 +109,49 @@ Results in: |The method `apply` is inserted. The auto insertion will be deprecated, please write `Foo.apply` explicitly. ``` -As the warning suggests, now you should write `Foo.apply` instead of `Foo`. See [Issue #6190](https://github.com/lampepfl/dotty/issues/6190) and [PR #7207](https://github.com/lampepfl/dotty/pull/7207) for discussion. +As the warning suggests, now you should write `Foo.apply` instead of `Foo`. See [Issue #6190](https://github.com/scala/scala3/issues/6190) and [PR #7207](https://github.com/scala/scala3/pull/7207) for discussion. ## Settling on `scaladoc` as the documentation tool We have settled on using the well-known `scaladoc` as a name for the documentation tool for Scala 3 (known previously as `scala3doc`). The obsolete `dotty-doc` (or `scala3-doc`) is removed in RC1. We have also removed all the Kotlin dependencies (Dokka, etc.) from scaladoc. -For details, see [PR #11349](https://github.com/lampepfl/dotty/pull/11349). To read more about `scaladoc`, see [documentation](https://dotty.epfl.ch/docs/usage/scaladoc/index.html) +For details, see [PR #11349](https://github.com/scala/scala3/pull/11349). To read more about `scaladoc`, see [documentation](https://dotty.epfl.ch/docs/usage/scaladoc/index.html) ## Use `future` and `future-migration` to specify language versions after 3.0 in `-source` -[PR #11355](https://github.com/lampepfl/dotty/pull/11355) changes the `-source` specifier for the Scala version(s) after 3.0 from `3.1` to `future`. I.e. it is now +[PR #11355](https://github.com/scala/scala3/pull/11355) changes the `-source` specifier for the Scala version(s) after 3.0 from `3.1` to `future`. I.e. it is now `-source future` and `-source future-migration` instead of `-source 3.1` and `-source 3.1-migration`. Language imports are changed analogously. The reason for the change is that we want to keep the possibility open to ship a `3.1` version that does not yet contain all the changes enabled under `-source future`. ## Other language changes -- Warn when matching against an opaque type [#10664](https://github.com/lampepfl/dotty/pull/10664) -- Fix [#8634](https://github.com/lampepfl/dotty/issues/8634): Support -release option [#10746](https://github.com/lampepfl/dotty/pull/10746) – the same way Scala 2 does. +- Warn when matching against an opaque type [#10664](https://github.com/scala/scala3/pull/10664) +- Fix [#8634](https://github.com/scala/scala3/issues/8634): Support -release option [#10746](https://github.com/scala/scala3/pull/10746) – the same way Scala 2 does. This setting allows you to specify a version of the Java platform (8, 9 etc) and compile the code with classes specific to the that Java platform, and emit the bytecode for that version. ## Metaprogramming changes A lot of work has been done on the metaprogramming side of things. Mostly we are cleaning up and polishing the API to prepare it for the stable release. The following are the important metaprogramming changes that took place: -- Add `scala.quoted.Expr.unapply` as dual of `Expr.apply` [#10580](https://github.com/lampepfl/dotty/pull/10580) -- Remove `Expr.StringContext.unapply` [#10675](https://github.com/lampepfl/dotty/pull/10675) -- Add reflect `MatchCase` `TypeRepr` [#10735](https://github.com/lampepfl/dotty/pull/10735) -- Rename `scala.quoted.staging.{Toolbox => Compiler}` [#11129](https://github.com/lampepfl/dotty/pull/11129) -- Fix [#10863](https://github.com/lampepfl/dotty/issues/10863): Make show `AnyKind`ed [#10988](https://github.com/lampepfl/dotty/pull/10988) -- Add ParamClause to allow multiple type param clauses [#11074](https://github.com/lampepfl/dotty/pull/11074) -- Rework reflect Symbol fields API [#10705](https://github.com/lampepfl/dotty/pull/10705) -- Rename `Liftable` to `ToExpr` and `Unliftable` to `FromExpr` [#10618](https://github.com/lampepfl/dotty/pull/10618) -- Expand non-transparent macros after Typer [#9984](https://github.com/lampepfl/dotty/pull/9984) -- Rework TastyInspector API to allow inspection of all files [#10792](https://github.com/lampepfl/dotty/pull/10792) -- Allow leading context parameters in extension methods [#10940](https://github.com/lampepfl/dotty/pull/10940) -- Rename `Not` to `NotGiven` to make its purpose clearer [#10720](https://github.com/lampepfl/dotty/pull/10720) -- Fix [#10709](https://github.com/lampepfl/dotty/issues/10709): Add missing level check before inlining [#10781](https://github.com/lampepfl/dotty/pull/10781) +- Add `scala.quoted.Expr.unapply` as dual of `Expr.apply` [#10580](https://github.com/scala/scala3/pull/10580) +- Remove `Expr.StringContext.unapply` [#10675](https://github.com/scala/scala3/pull/10675) +- Add reflect `MatchCase` `TypeRepr` [#10735](https://github.com/scala/scala3/pull/10735) +- Rename `scala.quoted.staging.{Toolbox => Compiler}` [#11129](https://github.com/scala/scala3/pull/11129) +- Fix [#10863](https://github.com/scala/scala3/issues/10863): Make show `AnyKind`ed [#10988](https://github.com/scala/scala3/pull/10988) +- Add ParamClause to allow multiple type param clauses [#11074](https://github.com/scala/scala3/pull/11074) +- Rework reflect Symbol fields API [#10705](https://github.com/scala/scala3/pull/10705) +- Rename `Liftable` to `ToExpr` and `Unliftable` to `FromExpr` [#10618](https://github.com/scala/scala3/pull/10618) +- Expand non-transparent macros after Typer [#9984](https://github.com/scala/scala3/pull/9984) +- Rework TastyInspector API to allow inspection of all files [#10792](https://github.com/scala/scala3/pull/10792) +- Allow leading context parameters in extension methods [#10940](https://github.com/scala/scala3/pull/10940) +- Rename `Not` to `NotGiven` to make its purpose clearer [#10720](https://github.com/scala/scala3/pull/10720) +- Fix [#10709](https://github.com/scala/scala3/issues/10709): Add missing level check before inlining [#10781](https://github.com/scala/scala3/pull/10781) ## Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributors @@ -225,7 +225,7 @@ According to `git shortlog -sn --no-merges 3.0.0-M3..3.0.0-RC1` these are: If you want to get your hands dirty and contribute to Scala 3, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2021-03-31-scala3-rc2.md b/docs/_blog/_posts/2021-03-31-scala3-rc2.md index 178dfabfbffc..13170adbcfad 100644 --- a/docs/_blog/_posts/2021-03-31-scala3-rc2.md +++ b/docs/_blog/_posts/2021-03-31-scala3-rc2.md @@ -6,7 +6,7 @@ authorImg: /images/anatolii.png date: 2021-03-31 --- -Hello! We are happy to announce Scala 3.0.0-RC2. With this release, we are getting ready for 3.0.0. The significance of it is to give the community the chance and time to test all the changes meant for 3.0.0 final. A lot of bug fixes found their way into this release to ensure stability for 3.0.0 – more than [250 PRs](https://github.com/lampepfl/dotty/pulls?q=is%3Apr+is%3Aclosed+closed%3A%3E2021-02-16) were merged after the 3.0.0-RC1 release and until today! +Hello! We are happy to announce Scala 3.0.0-RC2. With this release, we are getting ready for 3.0.0. The significance of it is to give the community the chance and time to test all the changes meant for 3.0.0 final. A lot of bug fixes found their way into this release to ensure stability for 3.0.0 – more than [250 PRs](https://github.com/scala/scala3/pulls?q=is%3Apr+is%3Aclosed+closed%3A%3E2021-02-16) were merged after the 3.0.0-RC1 release and until today! Read more about this release below. @@ -28,31 +28,31 @@ As mentioned above, we are currently in an issue-fixing mode. So a lot of those There are some notable changes worth mentioning. ## Restrict experimental features to unstable releases only -PR [#11920](https://github.com/lampepfl/dotty/pull/11920) restricts usage of experimental features only to nightlies and snapshots. This change ensures that changes deemed experimental will not propagate into the wider ecosystem provided that the wider ecosystem depends on stable releases. This is needed so that if an experimental feature is modified or removed from the language, the ecosystem will not be impacted. +PR [#11920](https://github.com/scala/scala3/pull/11920) restricts usage of experimental features only to nightlies and snapshots. This change ensures that changes deemed experimental will not propagate into the wider ecosystem provided that the wider ecosystem depends on stable releases. This is needed so that if an experimental feature is modified or removed from the language, the ecosystem will not be impacted. ## New `unsafeNulls` language feature -PR [#9884](https://github.com/lampepfl/dotty/pull/9884) adds a new language feature which enables unsafe null operations under explicit nulls. This is a tool to help projects migrating to full explicit nulls gradually. From now on, you can use an import `import scala.language.unsafeNulls` to create an unsafe scope. For discussion, see the PR linked above, and for more information on the feature, see the [documentation](https://dotty.epfl.ch/docs/reference/other-new-features/explicit-nulls.html). +PR [#9884](https://github.com/scala/scala3/pull/9884) adds a new language feature which enables unsafe null operations under explicit nulls. This is a tool to help projects migrating to full explicit nulls gradually. From now on, you can use an import `import scala.language.unsafeNulls` to create an unsafe scope. For discussion, see the PR linked above, and for more information on the feature, see the [documentation](https://dotty.epfl.ch/docs/reference/other-new-features/explicit-nulls.html). ## Treat Scala.js pseudo-unions as real unions -In PR [#11671](https://github.com/lampepfl/dotty/pull/11671), we now treat the `scala.scalajs.js.|[A, B]` as if it was a real Scala 3 union `A | B`, which further boosts the support for Scala.js in Scala 3. +In PR [#11671](https://github.com/scala/scala3/pull/11671), we now treat the `scala.scalajs.js.|[A, B]` as if it was a real Scala 3 union `A | B`, which further boosts the support for Scala.js in Scala 3. ## Other API changes -`-Ycheck-init` was renamed to `-Ysafe-init`. This flag is used to check safe initialization, more about which you can read in the [documentation](https://dotty.epfl.ch/docs/reference/other-new-features/safe-initialization.html). See also PR [#11920](https://github.com/lampepfl/dotty/pull/11920). +`-Ycheck-init` was renamed to `-Ysafe-init`. This flag is used to check safe initialization, more about which you can read in the [documentation](https://dotty.epfl.ch/docs/reference/other-new-features/safe-initialization.html). See also PR [#11920](https://github.com/scala/scala3/pull/11920). -PR [#11745](https://github.com/lampepfl/dotty/pull/11745) changes the `compiletime` package API a bit. `compiletime.S` was moved to `compiletime.ops.int.S` and the package object `compiletime` was removed in favor of top-level definitions. +PR [#11745](https://github.com/scala/scala3/pull/11745) changes the `compiletime` package API a bit. `compiletime.S` was moved to `compiletime.ops.int.S` and the package object `compiletime` was removed in favor of top-level definitions. ## Metaprogramming The following are some notable metaprogramming changes included into this release: -- Add quotes.Type.valueOfConstant [#11715](https://github.com/lampepfl/dotty/pull/11715) -- Remove compiletime.Widen [#11569](https://github.com/lampepfl/dotty/pull/11569) -- Add -Xcheck-macros scalac option [#11655](https://github.com/lampepfl/dotty/pull/11655) +- Add quotes.Type.valueOfConstant [#11715](https://github.com/scala/scala3/pull/11715) +- Remove compiletime.Widen [#11569](https://github.com/scala/scala3/pull/11569) +- Add -Xcheck-macros scalac option [#11655](https://github.com/scala/scala3/pull/11655) # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributors @@ -107,7 +107,7 @@ According to `git shortlog -sn --no-merges 3.0.0-RC1..3.0.0-RC2` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. @@ -116,7 +116,7 @@ We are looking forward to having you join the team of contributors. Dotty now has a set of widely-used community libraries that are built against every nightly Dotty snapshot. Currently, this includes shapeless, ScalaPB, algebra, scalatest, scopt and squants. -Join our [community build](https://github.com/lampepfl/dotty/tree/main/community-build) +Join our [community build](https://github.com/scala/scala3/tree/main/community-build) to make sure that our regression suite includes your library. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_blog/_posts/2021-04-21-scala3-rc3.md b/docs/_blog/_posts/2021-04-21-scala3-rc3.md index 8651730da93a..6eddc82e7273 100644 --- a/docs/_blog/_posts/2021-04-21-scala3-rc3.md +++ b/docs/_blog/_posts/2021-04-21-scala3-rc3.md @@ -13,16 +13,16 @@ This release also impacts the release date for 3.0.0 stable. 3.0.0 stable will g # Bug fixes included -- Fix type test for trait parameter arguments [#12066](https://github.com/lampepfl/dotty/pull/12066) -- Set file filter correctly [#12119](https://github.com/lampepfl/dotty/pull/12119) -- Provide mirror support after inlining [#12079](https://github.com/lampepfl/dotty/pull/12079) -- Revert "Recursively check nonvariant arguments of base types for realizability" [#12067](https://github.com/lampepfl/dotty/pull/12067) -- When simplifying match types, ensure fully defined before reducing [#12068](https://github.com/lampepfl/dotty/pull/12068) -- sbt-dotty: the binary version is 3 for Scala >= 3.0.0 [#12084](https://github.com/lampepfl/dotty/pull/12084) -- Fix isInstanceOf[Array[?]] returning true on non-Array [#12108](https://github.com/lampepfl/dotty/pull/12108) -- Scala2Unpickler: don't unpickle the same type parameter twice [#12129](https://github.com/lampepfl/dotty/pull/12129) -- Overloading resolution: Handle SAM types more like Java and Scala 2 [#12131](https://github.com/lampepfl/dotty/pull/12131) -- Add TermParamClause.isGiven [#12042](https://github.com/lampepfl/dotty/pull/12042) +- Fix type test for trait parameter arguments [#12066](https://github.com/scala/scala3/pull/12066) +- Set file filter correctly [#12119](https://github.com/scala/scala3/pull/12119) +- Provide mirror support after inlining [#12079](https://github.com/scala/scala3/pull/12079) +- Revert "Recursively check nonvariant arguments of base types for realizability" [#12067](https://github.com/scala/scala3/pull/12067) +- When simplifying match types, ensure fully defined before reducing [#12068](https://github.com/scala/scala3/pull/12068) +- sbt-dotty: the binary version is 3 for Scala >= 3.0.0 [#12084](https://github.com/scala/scala3/pull/12084) +- Fix isInstanceOf[Array[?]] returning true on non-Array [#12108](https://github.com/scala/scala3/pull/12108) +- Scala2Unpickler: don't unpickle the same type parameter twice [#12129](https://github.com/scala/scala3/pull/12129) +- Overloading resolution: Handle SAM types more like Java and Scala 2 [#12131](https://github.com/scala/scala3/pull/12131) +- Add TermParamClause.isGiven [#12042](https://github.com/scala/scala3/pull/12042) ## Contributors Thank you to all the contributors who made this release possible 🎉 @@ -40,7 +40,7 @@ According to `git shortlog -sn --no-merges 3.0.0-RC2..3.0.0-RC3` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. @@ -49,7 +49,7 @@ We are looking forward to having you join the team of contributors. Dotty now has a set of widely-used community libraries that are built against every nightly Dotty snapshot. Currently, this includes shapeless, ScalaPB, algebra, scalatest, scopt and squants. -Join our [community build](https://github.com/lampepfl/dotty/tree/main/community-build) +Join our [community build](https://github.com/scala/scala3/tree/main/community-build) to make sure that our regression suite includes your library. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_blog/_posts/2021-06-07-scala3.0.1-rc1-release.md b/docs/_blog/_posts/2021-06-07-scala3.0.1-rc1-release.md index e9fac2d0447c..617f175e74b7 100644 --- a/docs/_blog/_posts/2021-06-07-scala3.0.1-rc1-release.md +++ b/docs/_blog/_posts/2021-06-07-scala3.0.1-rc1-release.md @@ -21,13 +21,13 @@ The spirit of this policy is to make sure that effectively, no library published Having said that, we still encourage people to play with the experimental features from the `NIGHTLY` compiler versions and discuss their findings. Without the curious and adventurous part of the community playing with the new features, there is no way of knowing what they are good for, and no way to decide whether they should be dropped or promoted to a stable feature. -More about this change you can read in the PR [#12102](https://github.com/lampepfl/dotty/pull/12102). +More about this change you can read in the PR [#12102](https://github.com/scala/scala3/pull/12102). # Kind-projector work -This release also brings extra features for the [Kind Projector](https://docs.scala-lang.org/scala3/guides/migration/plugin-kind-projector.html) migration support. First, PR [#12378](https://github.com/lampepfl/dotty/pull/12378) allows `_` as type lambda placeholder. Second, PR [#12341](https://github.com/lampepfl/dotty/pull/12341) brings support for the variance annotations on the placeholder. This work enhances the ability to cross-compile Scala 2 code that uses the Kind Projector plugin to Scala 3. +This release also brings extra features for the [Kind Projector](https://docs.scala-lang.org/scala3/guides/migration/plugin-kind-projector.html) migration support. First, PR [#12378](https://github.com/scala/scala3/pull/12378) allows `_` as type lambda placeholder. Second, PR [#12341](https://github.com/scala/scala3/pull/12341) brings support for the variance annotations on the placeholder. This work enhances the ability to cross-compile Scala 2 code that uses the Kind Projector plugin to Scala 3. # Improved error reporting -Down the error reporting lane, match type reduction errors were improved. When using a match type, it may or may not reduce to one of its cases. If it doesn't match type is used as specified, e.g. if `M[T]` is a match type and it didn't reduce for `M[Int]`, `M[Int]` will be used. This behavior, however, is frequently not what you want: there is a lot of cases where you would expect a match type to reduce but it doesn't. In such cases, it would be nice to have some diagnostic regarding why it didn't reduce. PR [#12053](https://github.com/lampepfl/dotty/pull/12053/) adds just such a diagnostic. E.g. the following code: +Down the error reporting lane, match type reduction errors were improved. When using a match type, it may or may not reduce to one of its cases. If it doesn't match type is used as specified, e.g. if `M[T]` is a match type and it didn't reduce for `M[Int]`, `M[Int]` will be used. This behavior, however, is frequently not what you want: there is a lot of cases where you would expect a match type to reduce but it doesn't. In such cases, it would be nice to have some diagnostic regarding why it didn't reduce. PR [#12053](https://github.com/scala/scala3/pull/12053/) adds just such a diagnostic. E.g. the following code: ```scala trait A @@ -58,32 +58,32 @@ will report the following error: ``` # Scaladoc -We have updated the [documentation](http://dotty.epfl.ch/docs/usage/scaladoc/index.html) for Scaladoc making it easier for you to get started. Also, PR [#11582](https://github.com/lampepfl/dotty/pull/11582) has added the snippet compiler to ensure the snippets in your scaladoc documentation comments aren't broken. You can read more about this feature on the [mailing list](https://contributors.scala-lang.org/t/snippet-validation-in-scaladoc-for-scala-3/4976). +We have updated the [documentation](http://dotty.epfl.ch/docs/usage/scaladoc/index.html) for Scaladoc making it easier for you to get started. Also, PR [#11582](https://github.com/scala/scala3/pull/11582) has added the snippet compiler to ensure the snippets in your scaladoc documentation comments aren't broken. You can read more about this feature on the [mailing list](https://contributors.scala-lang.org/t/snippet-validation-in-scaladoc-for-scala-3/4976). # Metaprogramming A lot of metaprogramming work was focused on improving the performance. Some of the notable PRs include: -- Cache quote unpickling [#12242](https://github.com/lampepfl/dotty/pull/12242) -- Avoid pickled tasty for some captured quote reference [#12248](https://github.com/lampepfl/dotty/pull/12248) -- Improve quote matcher performance [#12418](https://github.com/lampepfl/dotty/pull/12418) -- Port scala.quoted.runtime.impl.QuoteMatcher [#12402](https://github.com/lampepfl/dotty/pull/12402) +- Cache quote unpickling [#12242](https://github.com/scala/scala3/pull/12242) +- Avoid pickled tasty for some captured quote reference [#12248](https://github.com/scala/scala3/pull/12248) +- Improve quote matcher performance [#12418](https://github.com/scala/scala3/pull/12418) +- Port scala.quoted.runtime.impl.QuoteMatcher [#12402](https://github.com/scala/scala3/pull/12402) # Issue fixing Otherwise, we are making an effort to reduce our issue tracker. Among others, the following are some of the PRs dedicated to issue fixing: -- IArray.toArray: Deprecate broken method [#12598](https://github.com/lampepfl/dotty/pull/12598) -- Fix comparison of dependent function types [#12214](https://github.com/lampepfl/dotty/pull/12214) -- Make translucentSuperType handle match types [#12153](https://github.com/lampepfl/dotty/pull/12153) -- Harden Type Inference [#12560](https://github.com/lampepfl/dotty/pull/12560) -- Reject references to self in super constructor calls [#12567](https://github.com/lampepfl/dotty/pull/12567) -- Provide mirror support after inlining [#12062](https://github.com/lampepfl/dotty/pull/12062) -- Allow export paths to see imports [#12134](https://github.com/lampepfl/dotty/pull/12134) -- Streamline given syntax [#12107](https://github.com/lampepfl/dotty/pull/12107) -- Export constructor proxies [#12311](https://github.com/lampepfl/dotty/pull/12311) -- Identify package and nested package object in isSubPrefix [#12297](https://github.com/lampepfl/dotty/pull/12297) -- Treat Refinements more like AndTypes [#12317](https://github.com/lampepfl/dotty/pull/12317) -- Fix [#9871](https://github.com/lampepfl/dotty/pull/9871): use toNestedPairs in provablyDisjoint [#10560](https://github.com/lampepfl/dotty/pull/10560) +- IArray.toArray: Deprecate broken method [#12598](https://github.com/scala/scala3/pull/12598) +- Fix comparison of dependent function types [#12214](https://github.com/scala/scala3/pull/12214) +- Make translucentSuperType handle match types [#12153](https://github.com/scala/scala3/pull/12153) +- Harden Type Inference [#12560](https://github.com/scala/scala3/pull/12560) +- Reject references to self in super constructor calls [#12567](https://github.com/scala/scala3/pull/12567) +- Provide mirror support after inlining [#12062](https://github.com/scala/scala3/pull/12062) +- Allow export paths to see imports [#12134](https://github.com/scala/scala3/pull/12134) +- Streamline given syntax [#12107](https://github.com/scala/scala3/pull/12107) +- Export constructor proxies [#12311](https://github.com/scala/scala3/pull/12311) +- Identify package and nested package object in isSubPrefix [#12297](https://github.com/scala/scala3/pull/12297) +- Treat Refinements more like AndTypes [#12317](https://github.com/scala/scala3/pull/12317) +- Fix [#9871](https://github.com/scala/scala3/pull/9871): use toNestedPairs in provablyDisjoint [#10560](https://github.com/scala/scala3/pull/10560) # Contributors @@ -147,7 +147,7 @@ According to `git shortlog -sn --no-merges 3.0.0-RC2..3.0.1-RC1`† these are: ## Library authors: Join our community build Scala 3 now has a set of widely-used community libraries that are built against every nightly Scala 3 snapshot. -Join our [community build](https://github.com/lampepfl/dotty/tree/main/community-build) +Join our [community build](https://github.com/scala/scala3/tree/main/community-build) to make sure that our regression suite includes your library. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_blog/_posts/2021-06-25-scala301-rc2.md b/docs/_blog/_posts/2021-06-25-scala301-rc2.md index 76257d1a8664..054a8dfc9d56 100644 --- a/docs/_blog/_posts/2021-06-25-scala301-rc2.md +++ b/docs/_blog/_posts/2021-06-25-scala301-rc2.md @@ -6,9 +6,9 @@ authorImg: /images/anatolii.png date: 2021-06-25 --- -This post is a quick announcement of Scala 3.0.1-RC2. This is the second release candidate for 3.0.1. The reason for this release is that a regression with respect to 3.0.0 was introduced by PR [#12519](https://github.com/lampepfl/dotty/pull/12519) which caused the compiler to fail where it shouldn't. We have fixed this regression in PR [#12827](https://github.com/lampepfl/dotty/pull/12827) and backported it to 3.0.1. This is the main reason for having 3.0.1-RC2 before 3.0.1 which is due in one week. +This post is a quick announcement of Scala 3.0.1-RC2. This is the second release candidate for 3.0.1. The reason for this release is that a regression with respect to 3.0.0 was introduced by PR [#12519](https://github.com/scala/scala3/pull/12519) which caused the compiler to fail where it shouldn't. We have fixed this regression in PR [#12827](https://github.com/scala/scala3/pull/12827) and backported it to 3.0.1. This is the main reason for having 3.0.1-RC2 before 3.0.1 which is due in one week. -Besides this main change, taking advantage of the fact that RC2 is happening, we have also included various SBT reporting improvements (PR [#12845](https://github.com/lampepfl/dotty/pull/12845)) which should improve interaction with [Metals](https://scalameta.org/metals/). Also we've backported a few infrastructural fixes even though they aren't a regression from 3.0.0. +Besides this main change, taking advantage of the fact that RC2 is happening, we have also included various SBT reporting improvements (PR [#12845](https://github.com/scala/scala3/pull/12845)) which should improve interaction with [Metals](https://scalameta.org/metals/). Also we've backported a few infrastructural fixes even though they aren't a regression from 3.0.0. @@ -29,7 +29,7 @@ According to `git shortlog -sn --no-merges 3.0.1-RC1..3.0.1-RC2` these are: ## Library authors: Join our community build Scala 3 now has a set of widely-used community libraries that are built against every nightly Scala 3 snapshot. -Join our [community build](https://github.com/lampepfl/dotty/tree/main/community-build) +Join our [community build](https://github.com/scala/scala3/tree/main/community-build) to make sure that our regression suite includes your library. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_docs/contributing/architecture/context.md b/docs/_docs/contributing/architecture/context.md index cd38ee437867..61cb88ad5494 100644 --- a/docs/_docs/contributing/architecture/context.md +++ b/docs/_docs/contributing/architecture/context.md @@ -50,4 +50,4 @@ convention is that the `Context` be an explicit parameter, to track its usage. | ... | and so on | -[Contexts]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Contexts.scala +[Contexts]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/Contexts.scala diff --git a/docs/_docs/contributing/architecture/lifecycle.md b/docs/_docs/contributing/architecture/lifecycle.md index 2cf58f477da3..30ca934ede71 100644 --- a/docs/_docs/contributing/architecture/lifecycle.md +++ b/docs/_docs/contributing/architecture/lifecycle.md @@ -78,13 +78,13 @@ tools // contains helpers and the `scala` generic runner ``` -[Phases]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Phases.scala -[CompilationUnit]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/CompilationUnit.scala +[Phases]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/Phases.scala +[CompilationUnit]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/CompilationUnit.scala -[dotty.tools]: https://github.com/lampepfl/dotty/tree/master/compiler/src/dotty/tools -[ScalaSettings]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +[dotty.tools]: https://github.com/scala/scala3/tree/master/compiler/src/dotty/tools +[ScalaSettings]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala [syntax]: https://docs.scala-lang.org/scala3/reference/syntax.html -[Main]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Main.scala -[Driver]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Driver.scala -[Compiler]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Compiler.scala -[Run]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Run.scala \ No newline at end of file +[Main]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/Main.scala +[Driver]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/Driver.scala +[Compiler]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/Compiler.scala +[Run]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/Run.scala \ No newline at end of file diff --git a/docs/_docs/contributing/architecture/phases.md b/docs/_docs/contributing/architecture/phases.md index 844ae144dddb..8e63de04dadb 100644 --- a/docs/_docs/contributing/architecture/phases.md +++ b/docs/_docs/contributing/architecture/phases.md @@ -85,24 +85,24 @@ suitable for the runtime system, with two sub-groupings: ### `backendPhases` These map the transformed trees to Java classfiles or SJSIR files. -[CompilationUnit]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/CompilationUnit.scala -[Compiler]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Compiler.scala -[Phase]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Phases.scala -[MiniPhase]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala -[Run]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Run.scala -[parser]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/parsing/ParserPhase.scala -[typer]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/typer/TyperPhase.scala -[posttyper]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/PostTyper.scala -[prepjsinterop]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/sjs/PrepJSInterop.scala -[pickler]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/Pickler.scala -[inlining]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/Inlining.scala -[postInlining]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/PostInlining.scala -[staging]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/Staging.scala -[pickleQuotes]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala -[refchecks]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/typer/RefChecks.scala -[initChecker]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/init/Checker.scala -[firstTransform]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala -[patternMatcher]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala -[erasure]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/Erasure.scala -[Mirror]: https://github.com/lampepfl/dotty/blob/master/library/src/scala/deriving/Mirror.scala +[CompilationUnit]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/CompilationUnit.scala +[Compiler]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/Compiler.scala +[Phase]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/Phases.scala +[MiniPhase]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala +[Run]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/Run.scala +[parser]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/parsing/ParserPhase.scala +[typer]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/typer/TyperPhase.scala +[posttyper]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +[prepjsinterop]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/sjs/PrepJSInterop.scala +[pickler]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/Pickler.scala +[inlining]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/Inlining.scala +[postInlining]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/PostInlining.scala +[staging]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/Staging.scala +[pickleQuotes]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala +[refchecks]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +[initChecker]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/init/Checker.scala +[firstTransform]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala +[patternMatcher]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +[erasure]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/Erasure.scala +[Mirror]: https://github.com/scala/scala3/blob/master/library/src/scala/deriving/Mirror.scala [PCP]: ../../reference/metaprogramming/macros.md#the-phase-consistency-principle diff --git a/docs/_docs/contributing/architecture/symbols.md b/docs/_docs/contributing/architecture/symbols.md index c19588a4ff12..c11c054b4967 100644 --- a/docs/_docs/contributing/architecture/symbols.md +++ b/docs/_docs/contributing/architecture/symbols.md @@ -60,11 +60,11 @@ All definition symbols will contain a `SymDenotation`. The denotation, in turn, A class symbol will instead be associated with a `ClassDenotation`, which extends `SymDenotation` with some additional fields specific for classes. -[Signature1]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Signature.scala#L9-L33 -[Symbols]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Symbols.scala -[flatten]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/Flatten.scala -[lambdaLift]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala -[CompilationUnit]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/CompilationUnit.scala -[Denotations]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Denotations.scala -[SymDenotations]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/SymDenotations.scala -[flags]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Flags.scala +[Signature1]: https://github.com/scala/scala3/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Signature.scala#L9-L33 +[Symbols]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/Symbols.scala +[flatten]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/Flatten.scala +[lambdaLift]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala +[CompilationUnit]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/CompilationUnit.scala +[Denotations]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/Denotations.scala +[SymDenotations]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +[flags]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/Flags.scala diff --git a/docs/_docs/contributing/architecture/time.md b/docs/_docs/contributing/architecture/time.md index 588b1ce40bb2..56a6cf7447a1 100644 --- a/docs/_docs/contributing/architecture/time.md +++ b/docs/_docs/contributing/architecture/time.md @@ -61,8 +61,8 @@ method foo after typer => (b: Box)(x: b.X): scala.collection.immutable.List[b. method foo after erasure => (b: Box, x: Object): scala.collection.immutable.List ``` -[runs]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/Run.scala -[periods]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Periods.scala -[Contexts]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Contexts.scala -[typer]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/typer/TyperPhase.scala -[erasure]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/Erasure.scala +[runs]: https://github.com/scala/scala3/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/Run.scala +[periods]: https://github.com/scala/scala3/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Periods.scala +[Contexts]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/Contexts.scala +[typer]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/typer/TyperPhase.scala +[erasure]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/Erasure.scala diff --git a/docs/_docs/contributing/architecture/types.md b/docs/_docs/contributing/architecture/types.md index 2dfdc33101a0..ed8995c08643 100644 --- a/docs/_docs/contributing/architecture/types.md +++ b/docs/_docs/contributing/architecture/types.md @@ -143,5 +143,5 @@ Type -+- proxy_type --+- NamedType --------+- TypeRef ``` -[Types.scala]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Types.scala -[DottyTypeStealer]: https://github.com/lampepfl/dotty/blob/master/compiler/test/dotty/tools/DottyTypeStealer.scala +[Types.scala]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/Types.scala +[DottyTypeStealer]: https://github.com/scala/scala3/blob/master/compiler/test/dotty/tools/DottyTypeStealer.scala diff --git a/docs/_docs/contributing/community-build.md b/docs/_docs/contributing/community-build.md index b382786c614e..e333e4985e36 100644 --- a/docs/_docs/contributing/community-build.md +++ b/docs/_docs/contributing/community-build.md @@ -32,14 +32,14 @@ project to the community build you can follow these steps: check out the [Scala 3 Migration Guide](https://docs.scala-lang.org/scala3/guides/migration/compatibility-intro.html). You can see the submodules in - [community-projects](https://github.com/lampepfl/dotty/tree/main/community-build/community-projects/) + [community-projects](https://github.com/scala/scala3/tree/main/community-build/community-projects/) for examples of projects that compile with Scala 3. 2. Open a PR against this repo that: - Adds your project as a new git submodule - `git submodule add https://github.com/dotty-staging/XYZ.git community-build/community-projects/XYZ` - - Add the project to [projects.scala](https://github.com/lampepfl/dotty/blob/main/community-build/src/scala/dotty/communitybuild/projects.scala) - - Adds a test in [CommunityBuildTest.scala](https://github.com/lampepfl/dotty/blob/main/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala) + - Add the project to [projects.scala](https://github.com/scala/scala3/blob/main/community-build/src/scala/dotty/communitybuild/projects.scala) + - Adds a test in [CommunityBuildTest.scala](https://github.com/scala/scala3/blob/main/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala) 3. Once the CI is green, someone from the Dotty team will fork your repo and add it to [dotty-staging](https://github.com/dotty-staging). This enables us to diff --git a/docs/_docs/contributing/debugging/ide-debugging.md b/docs/_docs/contributing/debugging/ide-debugging.md index af817826565a..8548235672af 100644 --- a/docs/_docs/contributing/debugging/ide-debugging.md +++ b/docs/_docs/contributing/debugging/ide-debugging.md @@ -74,7 +74,7 @@ To locate them on your filesystem you can run the `export scala3-library-bootstr ``` $ sbt > export scala3-library-bootstrapped/fullClasspath -/home/user/lampepfl/dotty/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar +/home/user/scala/scala3/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar [success] Total time: 1 s, completed Mar 10, 2023, 4:37:43 PM ``` @@ -93,7 +93,7 @@ Here is the final configuration: "../tests/pos/HelloWorld.scala", "-classpath", // To replace with your own paths - "/home/user/lampepfl/dotty/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar", + "/home/user/scala/scala3/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar", "-color", "never" ], @@ -112,7 +112,7 @@ You can compile more than one Scala file, by adding them in the `args`: "file1.scala", "file2.scala", "-classpath", - "/home/user/lampepfl/dotty/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar" + "/home/user/scala/scala3/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar" ] ``` @@ -132,7 +132,7 @@ And concatenate the output into the classpath argument, which should already con "args": [ "using-cats.scala", "-classpath", - "/home/user/lampepfl/dotty/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/typelevel/cats-core_3/2.9.0/cats-core_3-2.9.0.jar:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/typelevel/cats-kernel_3/2.9.0/cats-kernel_3-2.9.0.jar" + "/home/user/scala/scala3/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/typelevel/cats-core_3/2.9.0/cats-core_3-2.9.0.jar:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/typelevel/cats-kernel_3/2.9.0/cats-kernel_3-2.9.0.jar" ] ``` diff --git a/docs/_docs/contributing/debugging/inspection.md b/docs/_docs/contributing/debugging/inspection.md index a80c3d3462ae..7cb1fa68abff 100644 --- a/docs/_docs/contributing/debugging/inspection.md +++ b/docs/_docs/contributing/debugging/inspection.md @@ -181,6 +181,6 @@ class StealBox: assert(empty.name.toString == "") ``` -[DottyTypeStealer]: https://github.com/lampepfl/dotty/blob/master/compiler/test/dotty/tools/DottyTypeStealer.scala -[ScalaSettings]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala -[symbols]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +[DottyTypeStealer]: https://github.com/scala/scala3/blob/master/compiler/test/dotty/tools/DottyTypeStealer.scala +[ScalaSettings]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +[symbols]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/SymDenotations.scala diff --git a/docs/_docs/contributing/debugging/other-debugging.md b/docs/_docs/contributing/debugging/other-debugging.md index 50be43db51ab..e8b72bcca656 100644 --- a/docs/_docs/contributing/debugging/other-debugging.md +++ b/docs/_docs/contributing/debugging/other-debugging.md @@ -152,7 +152,7 @@ To print out the trees after all phases: scalac -Xprint:all ../issues/Playground.scala ``` -To find out the list of all the phases and their names, check out [this](https://github.com/lampepfl/dotty/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/Compiler.scala#L34) line in `Compiler.scala`. Each `Phase` object has `phaseName` defined on it, this is the phase name. +To find out the list of all the phases and their names, check out [this](https://github.com/scala/scala3/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/Compiler.scala#L34) line in `Compiler.scala`. Each `Phase` object has `phaseName` defined on it, this is the phase name. ## Printing out stack traces of compile time errors You can use the flag `-Ydebug-error` to get the stack trace of all the compile-time errors. Consider the following file: @@ -207,7 +207,7 @@ val YshowVarBounds = BooleanSetting("-Yshow-var-bounds" , "Print type varia val YtestPickler = BooleanSetting("-Ytest-pickler" , "self-test for pickling functionality; should be used with -Ystop-after:pickler") ``` -They are defined in [ScalaSettings.scala](https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala). E.g. `YprintPos` is defined as: +They are defined in [ScalaSettings.scala](https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala). E.g. `YprintPos` is defined as: ```scala val YprintPos: Setting[Boolean] = BooleanSetting("-Yprint-pos", "show tree positions.") @@ -244,7 +244,7 @@ package @ { ### Figuring out an object creation site #### Via ID -Every [Positioned](https://github.com/lampepfl/dotty/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/ast/Positioned.scala) (a parent class of `Tree`) object has a `uniqueId` field. It is an integer that is unique for that tree and doesn't change from compile run to compile run. You can output these IDs from any printer (such as the ones used by `.show` and `-Xprint`) via `-Yshow-tree-ids` flag, e.g.: +Every [Positioned](https://github.com/scala/scala3/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/ast/Positioned.scala) (a parent class of `Tree`) object has a `uniqueId` field. It is an integer that is unique for that tree and doesn't change from compile run to compile run. You can output these IDs from any printer (such as the ones used by `.show` and `-Xprint`) via `-Yshow-tree-ids` flag, e.g.: ```shell scalac -Xprint:typer -Yshow-tree-ids ../issues/Playground.scala @@ -355,7 +355,7 @@ if (tree.show == """println("Hello World")""") { } ``` -In other words, you have a reference to the object and want to know were it was created. To do so, go to the class definition of that object. In our case, `tree` is a [`Tree`](https://github.com/lampepfl/dotty/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/ast/Trees.scala#L52). Now, create a new `val` member of that type: +In other words, you have a reference to the object and want to know were it was created. To do so, go to the class definition of that object. In our case, `tree` is a [`Tree`](https://github.com/scala/scala3/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/ast/Trees.scala#L52). Now, create a new `val` member of that type: ```scala val tracer = Thread.currentThread.getStackTrace.mkString("\n") @@ -380,7 +380,7 @@ Dotty has a lot of debug calls scattered throughout the code, most of which are These do not follow any particular system and so probably it will be easier to go with `println` most of the times instead. #### Printers -Defined in [Printers.scala](https://github.com/lampepfl/dotty/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/config/Printers.scala) as a set of variables, each responsible for its own domain. To enable them, replace `noPrinter` with `default`. [Example](https://github.com/lampepfl/dotty/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/typer/Typer.scala#L2226) from the code: +Defined in [Printers.scala](https://github.com/scala/scala3/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/config/Printers.scala) as a set of variables, each responsible for its own domain. To enable them, replace `noPrinter` with `default`. [Example](https://github.com/scala/scala3/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/typer/Typer.scala#L2226) from the code: ```scala typr.println(i"make contextual function $tree / $pt ---> $ifun") @@ -389,13 +389,13 @@ typr.println(i"make contextual function $tree / $pt ---> $ifun") `typr` is a printer. #### Tracing -Defined in [trace.scala](https://github.com/lampepfl/dotty/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/reporting/trace.scala). [Example](https://github.com/lampepfl/dotty/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/typer/Typer.scala#L2232) from the code: +Defined in [trace.scala](https://github.com/scala/scala3/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/reporting/trace.scala). [Example](https://github.com/scala/scala3/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/typer/Typer.scala#L2232) from the code: ```scala trace(i"typing $tree", typr, show = true) { // ... ``` -To enable globally, change [tracingEnabled](https://github.com/lampepfl/dotty/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/config/Config.scala#L164) to `true` (will recompile a lot of code). +To enable globally, change [tracingEnabled](https://github.com/scala/scala3/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/config/Config.scala#L164) to `true` (will recompile a lot of code). You also need to set the printer referenced in the call (in the example, `typr`) to `default` as explained in the section on printers. @@ -406,4 +406,4 @@ trace.force(i"typing $tree", typr, show = true) { // ... ``` #### Reporter -Defined in [Reporter.scala](https://github.com/lampepfl/dotty/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/reporting/Reporter.scala). Enables calls such as `report.log`. To enable, run scalac with `-Ylog:typer` option. +Defined in [Reporter.scala](https://github.com/scala/scala3/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/reporting/Reporter.scala). Enables calls such as `report.log`. To enable, run scalac with `-Ylog:typer` option. diff --git a/docs/_docs/contributing/getting-started.md b/docs/_docs/contributing/getting-started.md index 938e7ff36d42..63e968902600 100644 --- a/docs/_docs/contributing/getting-started.md +++ b/docs/_docs/contributing/getting-started.md @@ -127,7 +127,7 @@ For more information, see the [scaladoc section](./scaladoc.md). ## Community The main development discussion channels are: -- [github.com/lampepfl/dotty/discussions](https://github.com/lampepfl/dotty/discussions) +- [github.com/scala/scala3/discussions](https://github.com/scala/scala3/discussions) - [contributors.scala-lang.org](https://contributors.scala-lang.org) - [gitter.im/scala/contributors](https://gitter.im/scala/contributors) @@ -141,5 +141,5 @@ The main development discussion channels are: [adopt]: https://adoptopenjdk.net/ [compat]: https://docs.scala-lang.org/overviews/jdk-compatibility/overview.html [scala-cla]: https://www.lightbend.com/contribute/cla/scala -[dotty-issue]: https://github.com/lampepfl/dotty/issues -[dotty-discussion]: https://github.com/lampepfl/dotty/discussions +[dotty-issue]: https://github.com/scala/scala3/issues +[dotty-discussion]: https://github.com/scala/scala3/discussions diff --git a/docs/_docs/contributing/index.md b/docs/_docs/contributing/index.md index 507149340941..965847e39a94 100644 --- a/docs/_docs/contributing/index.md +++ b/docs/_docs/contributing/index.md @@ -12,9 +12,9 @@ also documents the inner workings of the Scala 3 compiler, `dotc`. Keep in mind that the code for `dotc` is continually changing, so the ideas discussed in this guide may fall out of date. This is a living document, so please consider contributing to it on -[GitHub](https://github.com/lampepfl/dotty/tree/main/docs/_docs/contributing) if +[GitHub](https://github.com/scala/scala3/tree/main/docs/_docs/contributing) if you notice anything out of date, or report any issues -[here](https://github.com/lampepfl/dotty/issues). +[here](https://github.com/scala/scala3/issues). ### Get the most from This Guide diff --git a/docs/_docs/contributing/issues/areas.md b/docs/_docs/contributing/issues/areas.md index ce27e9c0a5aa..9206d608ffbb 100644 --- a/docs/_docs/contributing/issues/areas.md +++ b/docs/_docs/contributing/issues/areas.md @@ -55,17 +55,17 @@ See [Inliner]. #### Compiletime Ops Types See `tryCompiletimeConstantFold` in [Types]. -[Showable]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/printing/Showable.scala -[PlainPrinter]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala -[RefinedPrinter]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala -[ErrorMessageID]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala -[messages]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/reporting/messages.scala -[Synthesizer]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala -[SyntheticMembers]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala -[quotes-impl]: https://github.com/lampepfl/dotty/tree/master/compiler/src/scala/quoted/runtime/impl -[Inliner]: https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/inlines/Inliner.scala -[Types]: https://github.com/lampepfl/dotty/tree/master/compiler/src/dotty/tools/dotc/core/Types.scala -[Completion]: https://github.com/lampepfl/dotty/tree/master/compiler/src/dotty/tools/dotc/interactive/Completion.scala -[DesugarEnums]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala -[Desugar]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/ast/Desugar.scala -[Space]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +[Showable]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/printing/Showable.scala +[PlainPrinter]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +[RefinedPrinter]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +[ErrorMessageID]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala +[messages]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/reporting/messages.scala +[Synthesizer]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala +[SyntheticMembers]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala +[quotes-impl]: https://github.com/scala/scala3/tree/master/compiler/src/scala/quoted/runtime/impl +[Inliner]: https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/inlines/Inliner.scala +[Types]: https://github.com/scala/scala3/tree/master/compiler/src/dotty/tools/dotc/core/Types.scala +[Completion]: https://github.com/scala/scala3/tree/master/compiler/src/dotty/tools/dotc/interactive/Completion.scala +[DesugarEnums]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala +[Desugar]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/ast/Desugar.scala +[Space]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala diff --git a/docs/_docs/contributing/issues/cause.md b/docs/_docs/contributing/issues/cause.md index e23f6d1f747f..f96d3b6d2f8a 100644 --- a/docs/_docs/contributing/issues/cause.md +++ b/docs/_docs/contributing/issues/cause.md @@ -116,7 +116,7 @@ def myInfo: Type = myInfo_debug, def myInfo_=(x: Type) = { tracer = Thread.currentThread.getStackTrace.mkString("\n"); myInfo_debug = x } ``` -[Printers]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/config/Printers.scala -[Denotation]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Denotations.scala -[PostTyper]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/PostTyper.scala -[ScalaSettings]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +[Printers]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/config/Printers.scala +[Denotation]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/Denotations.scala +[PostTyper]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +[ScalaSettings]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala diff --git a/docs/_docs/contributing/issues/reproduce.md b/docs/_docs/contributing/issues/reproduce.md index ca5da324a867..ae031a44d76f 100644 --- a/docs/_docs/contributing/issues/reproduce.md +++ b/docs/_docs/contributing/issues/reproduce.md @@ -159,7 +159,7 @@ scala -classpath $here/out Test # Run main method of `Test` generated by the co In this section, you have seen how to reproduce an issue locally, and next you will see how to try and detect its root cause. -[lampepfl/dotty]: https://github.com/lampepfl/dotty/issues -[#7710]: https://github.com/lampepfl/dotty/issues/7710 +[lampepfl/dotty]: https://github.com/scala/scala3/issues +[#7710]: https://github.com/scala/scala3/issues/7710 [dotty-issue-workspace]: https://github.com/anatoliykmetyuk/dotty-issue-workspace [workspace-readme]: https://github.com/anatoliykmetyuk/dotty-issue-workspace#getting-started diff --git a/docs/_docs/contributing/procedures/release.md b/docs/_docs/contributing/procedures/release.md index c54bb637aff5..88e1beb1b93b 100644 --- a/docs/_docs/contributing/procedures/release.md +++ b/docs/_docs/contributing/procedures/release.md @@ -28,7 +28,7 @@ Say we want to release the 0.14.0 version. In this section we describe the proce CI is set to automatically detect the tags of the format discussed above and perform the required release operations. Precisely, it will do two things for the release tags: - Publish the release jars to Maven -- Create the drafts at the GitHub [release](https://github.com/lampepfl/dotty/releases) page of the repository with the artefacts of the release. +- Create the drafts at the GitHub [release](https://github.com/scala/scala3/releases) page of the repository with the artefacts of the release. The CI operation is entirely automatic provided you have tagged the release correctly. No need to do anything here. @@ -50,11 +50,11 @@ However, you may end up with as many as 6 tasks being run. The auxiliary tasks m ### Release Procedure Checklist Before we start the release procedure, we create an issue with a release checklist. As we go through the release, we update the checklist. To generate the checklist, run the following command: -`bash <(curl -sL https://raw.githubusercontent.com/lampepfl/dotty/main/docs/docs/contributing/checklist.sh) ` +`bash <(curl -sL https://raw.githubusercontent.com/scala/scala3/main/docs/docs/contributing/checklist.sh) ` Above, `` is the stable version being released. For example, if you are releasing `0.14.0` and `0.15.0-RC1`, this variable is `14` and the command is as follows: -`bash <(curl -sL https://raw.githubusercontent.com/lampepfl/dotty/main/docs/docs/contributing/checklist.sh) 14` +`bash <(curl -sL https://raw.githubusercontent.com/scala/scala3/main/docs/docs/contributing/checklist.sh) 14` Copy and paste the output into the release issue. @@ -73,10 +73,10 @@ After the release is done, we document it as follows: During the release process we ensure that various parts of the community are also prepared for the new version of Scala so that users can hit the ground running when the new release is announced. You can see an example of this -[here](https://github.com/lampepfl/dotty/issues/17559). +[here](https://github.com/scala/scala3/issues/17559). # Procedure in Bash Scripts -The below procedure is compiled from [this](https://github.com/lampepfl/dotty/issues/5907#issue-409313505) and [this](https://github.com/lampepfl/dotty/issues/6235#issue-429265748) checklists. It assumes we want to publish the `0.14.0` given the `0.14.0-RC1` release candidate. +The below procedure is compiled from [this](https://github.com/scala/scala3/issues/5907#issue-409313505) and [this](https://github.com/scala/scala3/issues/6235#issue-429265748) checklists. It assumes we want to publish the `0.14.0` given the `0.14.0-RC1` release candidate. Note that at the same time we will also publish the `0.15.0-RC1` release. We publish two releases at the same time as per the logic outlined at the [Example/At the Dotty Repo](#at-the-dotty-repo) and the [Model](#model) sections above: the step (5) in the algorithm outlined in the [Example](#at-the-dotty-repo) for the release cycle of `0.14.0` is the step (1) in the release cycle of `0.15.0`. @@ -101,7 +101,7 @@ git merge 0.14.x git push origin main ######## Publish the 0.15.0-RC1 unstable version – begin the release cycle for 0.15.0 ######## -# Move all the unfinished tasks from Milestone 15 to Milestone 16 on GitHub – see https://github.com/lampepfl/dotty/milestones +# Move all the unfinished tasks from Milestone 15 to Milestone 16 on GitHub – see https://github.com/scala/scala3/milestones git checkout -b 0.15.x diff --git a/docs/_docs/contributing/sending-in-a-pr.md b/docs/_docs/contributing/sending-in-a-pr.md index c99e6a28172b..0c276e2c9287 100644 --- a/docs/_docs/contributing/sending-in-a-pr.md +++ b/docs/_docs/contributing/sending-in-a-pr.md @@ -104,7 +104,7 @@ every part of CI. For example, maybe you're just updating some documentation and there is no need to run the community build for this. We skip parts of the CI by utilizing keywords inside of brackets. The most up-to-date way to see this are by looking in the `if` statements of jobs. For example you can see some -[here](https://github.com/lampepfl/dotty/blob/5d2812a5937389f8a46f9e97ab9cbfbb3f298d87/.github/workflows/ci.yaml#L54-L64). +[here](https://github.com/scala/scala3/blob/5d2812a5937389f8a46f9e97ab9cbfbb3f298d87/.github/workflows/ci.yaml#L54-L64). Below are commonly used ones: @@ -160,8 +160,8 @@ you're PR will be merged in! [pull-request]: https://docs.github.com/en?query=pull+requests [lampepfl/dotty]: https://github.com/lampepfl/dotty [cla]: http://typesafe.com/contribute/cla/scala -[issues]: https://github.com/lampepfl/dotty/issues -[full-list]: https://github.com/lampepfl/dotty/blob/master/CONTRIBUTING.md +[issues]: https://github.com/scala/scala3/issues +[full-list]: https://github.com/scala/scala3/blob/master/CONTRIBUTING.md [discord]: https://discord.gg/TSmY9zkHar [dry]: https://www.oreilly.com/library/view/97-things-every/9780596809515/ch30.html [scouts]: https://www.oreilly.com/library/view/97-things-every/9780596809515/ch08.html diff --git a/docs/_docs/contributing/setting-up-your-ide.md b/docs/_docs/contributing/setting-up-your-ide.md index 3bb7d329d50c..a02c1dee63cb 100644 --- a/docs/_docs/contributing/setting-up-your-ide.md +++ b/docs/_docs/contributing/setting-up-your-ide.md @@ -34,7 +34,7 @@ want to make sure you do two things: 1. You'll want to find and change the following under `commonBootstrappedSettings` which is found in the - [`Build.scala`](https://github.com/lampepfl/dotty/blob/main/project/Build.scala) + [`Build.scala`](https://github.com/scala/scala3/blob/main/project/Build.scala) file. ```diff diff --git a/docs/_docs/contributing/testing.md b/docs/_docs/contributing/testing.md index f755bcafcd66..039b37ead8bf 100644 --- a/docs/_docs/contributing/testing.md +++ b/docs/_docs/contributing/testing.md @@ -164,25 +164,32 @@ to load the TASTy and the runtime to load the original classfiles. The library is compiled in `scala2-library-bootstrapped` with TASTy and classfiles. These classfiles should not be used. The `scala2-library-tasty` project repackages the -JAR `scala2-library-bootstrapped` to only keep TASTy files. The `scala2-library-tasty-tests` provides some basic tests using the library TASTy JAR. - -``` -$ sbt -> scala2-library-tasty/compile -> scala2-library-tasty-tests/run -> scala2-library-tasty-tests/test -``` +JAR `scala2-library-bootstrapped` to only keep TASTy files. We can enable this library in the build using the SBT setting `useScala2LibraryTasty`. This setting can only be used by bootstrapped compiler tests and is currently only supported for `test` (or `testCompilation`) and `scalac` (or `run`). ``` $ sbt -> set ThisBuild/Build.useScala2LibraryTasty := true +> set ThisBuild/Build.scala2Library := Build.Scala2LibraryTasty > scala3-compiler-bootstrapped/scalac MyFile.scala > scala3-compiler-bootstrapped/test > scala3-compiler-bootstrapped/testCompilation ``` +By default `scala2Library` is set to `Scala2LibraryJar`. This setting can be set to stop using the Scala 2 library TASTy. +``` +> set ThisBuild/Build.scala2Library := Build.Scala2LibraryJar +``` + +#### Scala 2 library with CC TASTy tests +These follow the same structure as the _Scala 2 library TASTy tests_ but add captured checked signatures to the library. The library is compiled in `scala2-library-cc` (instead of `scala2-library-bootstrapped`) and `scala2-library-cc-tasty` (instead of `scala2-library-cc-tasty`). + +We can also enable this library in the build using the SBT setting `useScala2LibraryTasty`. +``` +> set ThisBuild/Build.scala2Library := Build.Scala2LibraryCCTasty +``` + + ### From TASTy tests `testCompilation` has an additional mode to run tests that compile code from a `.tasty` file. @@ -239,7 +246,7 @@ can enter an inconsistent state and cause spurious test failures. If you suspect you can run `rm -rf out/*` from the root of the repository and run your tests again. If that fails, you can try `git clean -xfd`. -[CompilationTests]: https://github.com/lampepfl/dotty/blob/master/compiler/test/dotty/tools/dotc/CompilationTests.scala -[compiler/test]: https://github.com/lampepfl/dotty/blob/master/compiler/test/ -[compiler/test/dotc]: https://github.com/lampepfl/dotty/tree/master/compiler/test/dotc -[SemanticdbTests]: https://github.com/lampepfl/dotty/blob/master/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala +[CompilationTests]: https://github.com/scala/scala3/blob/master/compiler/test/dotty/tools/dotc/CompilationTests.scala +[compiler/test]: https://github.com/scala/scala3/blob/master/compiler/test/ +[compiler/test/dotc]: https://github.com/scala/scala3/tree/master/compiler/test/dotc +[SemanticdbTests]: https://github.com/scala/scala3/blob/master/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala diff --git a/docs/_docs/internals/cc/handling-invariant-vars.md b/docs/_docs/internals/cc/handling-invariant-vars.md new file mode 100644 index 000000000000..e9f0dc85317c --- /dev/null +++ b/docs/_docs/internals/cc/handling-invariant-vars.md @@ -0,0 +1,125 @@ +Handling invariant capture set variables +======================================== + +This note gives a high-level overview of constraints and constraint solving in Scala's capture checker. It then describes a proposal to improve a current problem area: the handling of invariantly mapped capture set variables. + +A capture checking constraint consists of subcapturing constraints between +capture sets. Capture sets can be variable or constant. A capture set variable is either defined by itself, +or is the result of a mapping of a type map. +Depending on what part of an original type created a map result, the set `v` is classified as invariant, covariant, or contravariant. + +We can describe the syntax of capture set constraints like this: +``` +Capture set a, b, c = ac // constant, aliases bv, cc + | av // variable, aliases bv, cv + +Typemap tm = B // bijective on capabilities + | F // arbitrary + +Constraint C = a <: b // simple constraint + | a = B(b) // bimap constraint + | a >: F(b) // covariant map constraint + | a <: F(b) // contravariant map constraint + | a = F(b) // invariant map constraint +``` +Variables appearing in the left hand side of a map constraint are called +map results. In a constraint set, each map result variable appears on the left hand side of only one map constraint, the one which defines it. +We distinguish two kinds of type maps, bijective maps `B` and general maps `F`. General maps are capture-monotonic: if `A <: B` +then the capture set of `F(A)` subcaptures the capture set of `F(B)`. All considered type maps map `cap` to `cap`. + +Examples of bijective maps are substitutions of parameters of one method type +for another, or mapping local method parameter symbols to method parameters. +Examples of monotonic maps are substitutions of argument types for parameters, +avoidance, or as-seen-from. + +Bijective map constraints define variables exactly. General map constraints come in three different forms. In the form `a >: F(b)`, `a` is bounded from +below by the map's result. Such constraints are created when a part +of a type appearing in covariant position is mapped. Consequently, variables +bound that way are called _covariant_. _Contravariant_ variables are defined +by constraints of the `a <: F(b)`. Such constraints are created when a part +of a type appearing in contravariant position is mapped. Finally, _invariant_ variables are defined by constraints of the `a = F(b)`, which are created when a part of a type appearing in invariant position is mapped. + +A solution to a subcapturing constraint set consists of an assignment of capture set constants to capture set variables, so that the resulting constraint set is true. The capture checker uses an incremental propagation-based +solver where capture set variables record which references they are known to contain. When new elements +are added to a set or a new relationship between capture sets is added, elements are propagated until +a new partial solution is found, or a contradiction is detected. A contradiction arises when an attempt +is made to add an element to a constant set that is not accounted for by the set. + +The propagation actions depend on the kind of constraint and whether a new capture set `c` is propagated +to the left part `a` or the right part `b` of the constraint. In the cases where the constraint +involves a general mapping `F`, the mapping `F(r)` of a capability `r` is in general a type, not +a capability or capture set. In this case we use `F(r).CS` for the capture set of the type +`F(r)`. Likewise, if `c` is a capture set, then `F(c)` might be a capture set `c'` if `F` maps all +capabilities in `c` to capabilities. But in general it will be a set of types, and `F(c).CS` +denotes the set of capture sets of these types. Furthermore, we use `c.super` for the capture set +of the definition of the reference `c` (as it shows up in rule (sc-var)). + +The propagation rules are summarized as follows: + +``` +Constraint new relation propagation remark +--------------------------------------------------------------- + a <: b c <: a c <: b + c <: b none + + a = B(b) c <: a B^-1(c) <: b + c <: b B(c) <: a + + a >: F(b) c <: a none + c <: b F(c).CS <: a + + a <: F(b) c <: a c <: b if F(c) = c (1) + c.super <: a otherwise + c <: b none + + a = F(b) c <: a c <: b if F(c) = c (1) + c.super <: a otherwise + c <: b c' <: a if F(c) = c' + F(c).CS? <: a otherwise (2) +``` +Remarks: + +(1) If `F(c) = c`, we solve by adding `c` also to `b`. Otherwise + we try again with `c.super <: a` instead of `c <: a`. At some point + this will succeed since we assume that for all maps `F`, `F(cap) = cap`. + This is clearly sound, but loses completeness since there might be + other, smaller solutions for the constraint. But with `F` not being + bijective, we'd have to try all possible capture sets to find + a suitable set that we could add to `b` so that `c` subcaptures the mapped set. + +(2) is the hard case. If the target set `a` appears invariantly, and `F(x)` is a type, we can use neither the lower bound set `{}` nor the upper bound set `F(x).CS`. Previously, we addressed this problem by making sure case (2) could not arise using the _range_ mechanism, which is also employed for regular type inference. To explain, let's say we try to map some type `t` where `F` is not defined on `t` but we know lower and upper approximations `tl` and `tu`. If `t` appears in +co- or contravariant positions, we can return `tu` or `tl`, respectively. But if `t` +appears in invariant position, we return `Range(tl, tu)`. This is not a type, but a type interval +which will be mapped itself, and will be resolved to one of its bounds at the first +point further out where the variance is positive or negative. There's also the case +where a Range appears in argument position of a parameterized class type, where we can +map it to the wildcard type `? >: tl <: tu`. We used the same mechanism for capture +set inference, by converting invariant occurrences of mapped type arguments `t^v` to wildcard types `? >: t^v1 <: t^v2` proactively, splitting the variable `v` to `v1` and `v2`, so that all capture set constraints occurred at co- or contravariant positions. + +Unfortunately this splitting has bad consequences for type inference, since a wildcard +is usually not compatible with a single expected type. So we would like to find another +technique for solving this issue. + +The idea is to use a technique similar to ranges directly on the capture sets. This means +that we now have a new class of elements of capture sets standing for references that might or might not be in the set. We use `{x?, ...}` as notation for a reference `x` that might or might not be an element of the enclosing capture set. Like `Range`, the notation is purely internal, we +never write it in a source program. + +We now describe how to handle the missing case (2) above. Assume `F(x)` is not a tracked reference, its image `a` is invariant and its capture set `cfr` is `{x_1,...,x_n}` where `n > 0`. In this case we add to `a` the _maybe references_ `x_1?, ..., x_n?`. Generalized to sets, `c <: b` where +`F(c) != c` leads to `F(c).CS?` to be added to `a`. Here, `CS?` is the set consisting of all references `x` in `cs` converted to maybe references `x?`. + +These references behave as follows: + + - For unions, `x` subsumes `x?`, so adding both `x` and `x?` to a set means + only `x` needs to be addded. + + - For further propagation of elements up the chain in e.g. `a <: b`, a maybe reference `x?` behaves like `x`. That is, since the reference could be in the set we have to propagate it upwards to be sound. + + - For propagations from lower sets, a maybe reference is treated as if it was missing. For instance, if we have `a <: b`, `b` contains `x?` and we propagate `x` from `a` to `b`, we need to add `x` as usual to `b`, which might imply back-proagation in the case `b` is an image of a type map `F`. + + - For mappings, maybe references are handled depending on the variance of the + image set. Assume we add `x?` to `b`. If `a >: F(b)` this amounts + to adding `F(x).CS` to `a`. If `a` is contravariant, this amounts to doing nothing. If `a` is invariant, we add `F(x).CS?` to `a`. If + `CS` is a capture set variable, it's "maybe" status has to be recorded and all elements this set acquires in the future also have to be converted to maybe references. + + + diff --git a/docs/_docs/internals/coverage.md b/docs/_docs/internals/coverage.md index 162aa182a1e0..923908683721 100644 --- a/docs/_docs/internals/coverage.md +++ b/docs/_docs/internals/coverage.md @@ -5,7 +5,7 @@ title: "Code Coverage for Scala 3" ## Instrument code for coverage analysis -[PR#13880](https://github.com/lampepfl/dotty/pull/13880) has implemented code coverage support for Dotty. +[PR#13880](https://github.com/scala/scala3/pull/13880) has implemented code coverage support for Dotty. In general, code coverage "instruments" the program at compile time: code is inserted to record which statement are called. This does not change the behavior of the program. Also, a list of all the coverable statements is produced. To use this feature, add the compile option `-coverage-out:DIR`, where `DIR` is the destination of the measurement files. diff --git a/docs/_docs/internals/debug-macros.md b/docs/_docs/internals/debug-macros.md index 4d5cab52c568..a085ebbde355 100644 --- a/docs/_docs/internals/debug-macros.md +++ b/docs/_docs/internals/debug-macros.md @@ -34,7 +34,7 @@ the stack trace, we will be able to figure out where the tree is created. If the position is in the compiler, then either report a compiler bug or fix the problem with `.withSpan(tree.span)`. The following fix is an example: -- https://github.com/lampepfl/dotty/pull/6581 +- https://github.com/scala/scala3/pull/6581 ## unresolved symbols in pickling diff --git a/docs/_docs/internals/dotc-scalac.md b/docs/_docs/internals/dotc-scalac.md index 03baad375eb1..e5335c734891 100644 --- a/docs/_docs/internals/dotc-scalac.md +++ b/docs/_docs/internals/dotc-scalac.md @@ -133,6 +133,6 @@ if (sym is Flags.PackageClass) // Scala 3 (*) * `MethodType(paramSyms, resultType)` from scalac => `mt @ MethodType(paramNames, paramTypes)`. Result type is `mt.resultType` -[Denotations1]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Denotations.scala#L27-L72 -[Denotations2]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Denotations.scala#L77-L103 -[Signature1]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Signature.scala#L9-L33 +[Denotations1]: https://github.com/scala/scala3/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Denotations.scala#L27-L72 +[Denotations2]: https://github.com/scala/scala3/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Denotations.scala#L77-L103 +[Signature1]: https://github.com/scala/scala3/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Signature.scala#L9-L33 diff --git a/docs/_docs/internals/overall-structure.md b/docs/_docs/internals/overall-structure.md index ab936ddd8512..a25c287e16c9 100644 --- a/docs/_docs/internals/overall-structure.md +++ b/docs/_docs/internals/overall-structure.md @@ -235,10 +235,10 @@ Phases fall into four categories: * Code generators: These map the transformed trees to Java classfiles or .sjsir files. -[dotty.tools]: https://github.com/lampepfl/dotty/tree/main/compiler/src/dotty/tools -[dotc]: https://github.com/lampepfl/dotty/tree/main/compiler/src/dotty/tools/dotc -[Main]: https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/Main.scala -[Driver]: https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/Driver.scala -[Compiler]: https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/Compiler.scala -[Run]: https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/Run.scala -[Context]: https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/core/Contexts.scala +[dotty.tools]: https://github.com/scala/scala3/tree/main/compiler/src/dotty/tools +[dotc]: https://github.com/scala/scala3/tree/main/compiler/src/dotty/tools/dotc +[Main]: https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/Main.scala +[Driver]: https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/Driver.scala +[Compiler]: https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/Compiler.scala +[Run]: https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/Run.scala +[Context]: https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/core/Contexts.scala diff --git a/docs/_docs/internals/periods.md b/docs/_docs/internals/periods.md index 46241da0bb17..bf9c4a5fe786 100644 --- a/docs/_docs/internals/periods.md +++ b/docs/_docs/internals/periods.md @@ -88,6 +88,6 @@ object Period { As a sentinel value there's `Nowhere`, a period that is empty. -[runs]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/Run.scala -[phases]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Phases.scala -[period]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Periods.scala +[runs]: https://github.com/scala/scala3/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/Run.scala +[phases]: https://github.com/scala/scala3/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Phases.scala +[period]: https://github.com/scala/scala3/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Periods.scala diff --git a/docs/_docs/internals/type-system.md b/docs/_docs/internals/type-system.md index 8fa8912a7118..d2c0cd869e61 100644 --- a/docs/_docs/internals/type-system.md +++ b/docs/_docs/internals/type-system.md @@ -95,7 +95,7 @@ checks if `tp1` is a subtype of `tp2`. ### Type rebasing ### **FIXME**: This section is no longer accurate because -https://github.com/lampepfl/dotty/pull/331 changed the handling of refined +https://github.com/scala/scala3/pull/331 changed the handling of refined types. Consider [tests/pos/refinedSubtyping.scala][5] @@ -132,8 +132,8 @@ TODO ## Type inference via constraint solving ## TODO -[1]: https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/core/Types.scala +[1]: https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/core/Types.scala [2]: https://github.com/samuelgruetter/dotty/blob/classdiagrampdf/dotty-types.pdf [3]: https://github.com/samuelgruetter/scaladiagrams/tree/print-descendants -[4]: https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/core/TypeComparer.scala -[5]: https://github.com/lampepfl/dotty/blob/main/tests/pos/refinedSubtyping.scala +[4]: https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +[5]: https://github.com/scala/scala3/blob/main/tests/pos/refinedSubtyping.scala diff --git a/docs/_docs/reference/changed-features/eta-expansion-spec.md b/docs/_docs/reference/changed-features/eta-expansion-spec.md index 714ab37ae11a..516764ef5370 100644 --- a/docs/_docs/reference/changed-features/eta-expansion-spec.md +++ b/docs/_docs/reference/changed-features/eta-expansion-spec.md @@ -74,4 +74,4 @@ The method value syntax `m _` is deprecated. ## Reference -For more information, see [PR #2701](https://github.com/lampepfl/dotty/pull/2701). +For more information, see [PR #2701](https://github.com/scala/scala3/pull/2701). diff --git a/docs/_docs/reference/changed-features/implicit-conversions-spec.md b/docs/_docs/reference/changed-features/implicit-conversions-spec.md index dc19e10c8b8f..a70321b70c15 100644 --- a/docs/_docs/reference/changed-features/implicit-conversions-spec.md +++ b/docs/_docs/reference/changed-features/implicit-conversions-spec.md @@ -114,4 +114,4 @@ changes to implicit resolution, refer to the [Changes in Implicit Resolution](im ## Reference For more information about implicit resolution, see [Changes in Implicit Resolution](implicit-resolution.md). -Other details are available in [PR #2065](https://github.com/lampepfl/dotty/pull/2065). +Other details are available in [PR #2065](https://github.com/scala/scala3/pull/2065). diff --git a/docs/_docs/reference/changed-features/structural-types-spec.md b/docs/_docs/reference/changed-features/structural-types-spec.md index 18d0f31ee6fe..216b738ae61c 100644 --- a/docs/_docs/reference/changed-features/structural-types-spec.md +++ b/docs/_docs/reference/changed-features/structural-types-spec.md @@ -16,7 +16,7 @@ RefineStat ::= ‘val’ VarDcl | ‘def’ DefDcl | ‘type’ {nl} TypeDcl ## Implementation of Structural Types The standard library defines a universal marker trait -[`scala.Selectable`](https://github.com/lampepfl/dotty/blob/main/library/src/scala/Selectable.scala): +[`scala.Selectable`](https://github.com/scala/scala3/blob/main/library/src/scala/Selectable.scala): ```scala trait Selectable extends Any @@ -150,4 +150,4 @@ conversion that can turn `v` into a `Selectable`, and the selection methods coul ## Context -For more information, see [Rethink Structural Types](https://github.com/lampepfl/dotty/issues/1886). +For more information, see [Rethink Structural Types](https://github.com/scala/scala3/issues/1886). diff --git a/docs/_docs/reference/contextual/by-name-context-parameters.md b/docs/_docs/reference/contextual/by-name-context-parameters.md index 3515efd78fa5..7c517abe9406 100644 --- a/docs/_docs/reference/contextual/by-name-context-parameters.md +++ b/docs/_docs/reference/contextual/by-name-context-parameters.md @@ -61,5 +61,5 @@ No local given instance was generated because the synthesized argument is not re ## Reference -For more information, see [Issue #1998](https://github.com/lampepfl/dotty/issues/1998) +For more information, see [Issue #1998](https://github.com/scala/scala3/issues/1998) and the associated [Scala SIP](https://docs.scala-lang.org/sips/byname-implicits.html). diff --git a/docs/_docs/reference/contextual/multiversal-equality.md b/docs/_docs/reference/contextual/multiversal-equality.md index b51d03b10963..6258973c0cda 100644 --- a/docs/_docs/reference/contextual/multiversal-equality.md +++ b/docs/_docs/reference/contextual/multiversal-equality.md @@ -25,7 +25,7 @@ the program will still typecheck, since values of all types can be compared with But it will probably give unexpected results and fail at runtime. Multiversal equality is an opt-in way to make universal equality safer. -It uses a binary type class [`scala.CanEqual`](https://github.com/lampepfl/dotty/blob/main/library/src/scala/CanEqual.scala) +It uses a binary type class [`scala.CanEqual`](https://github.com/scala/scala3/blob/main/library/src/scala/CanEqual.scala) to indicate that values of two given types can be compared with each other. The example above would not typecheck if `S` or `T` was a class that derives `CanEqual`, e.g. @@ -71,7 +71,7 @@ given CanEqual[A, B] = CanEqual.derived given CanEqual[B, A] = CanEqual.derived ``` -The [`scala.CanEqual`](https://github.com/lampepfl/dotty/blob/main/library/src/scala/CanEqual.scala) +The [`scala.CanEqual`](https://github.com/scala/scala3/blob/main/library/src/scala/CanEqual.scala) object defines a number of `CanEqual` given instances that together define a rule book for what standard types can be compared (more details below). @@ -225,4 +225,4 @@ work under `-language:strictEquality`, since otherwise the universal `Eq[Any]` i More on multiversal equality is found in a [blog post](http://www.scala-lang.org/blog/2016/05/06/multiversal-equality.html) -and a [GitHub issue](https://github.com/lampepfl/dotty/issues/1247). +and a [GitHub issue](https://github.com/scala/scala3/issues/1247). diff --git a/docs/_docs/reference/dropped-features/auto-apply.md b/docs/_docs/reference/dropped-features/auto-apply.md index eadfe2f429ea..1a809275d4d0 100644 --- a/docs/_docs/reference/dropped-features/auto-apply.md +++ b/docs/_docs/reference/dropped-features/auto-apply.md @@ -93,4 +93,4 @@ stricter checking. ## Reference -For more information, see [Issue #2570](https://github.com/lampepfl/dotty/issues/2570) and [PR #2716](https://github.com/lampepfl/dotty/pull/2716). +For more information, see [Issue #2570](https://github.com/scala/scala3/issues/2570) and [PR #2716](https://github.com/scala/scala3/pull/2716). diff --git a/docs/_docs/reference/dropped-features/type-projection.md b/docs/_docs/reference/dropped-features/type-projection.md index 08b5ffb34eca..2c3e82ce99b8 100644 --- a/docs/_docs/reference/dropped-features/type-projection.md +++ b/docs/_docs/reference/dropped-features/type-projection.md @@ -9,7 +9,7 @@ and `A` names a type member of `T`. Scala 3 disallows this if `T` is an abstract type (class types and type aliases are fine). This change was made because unrestricted type projection -is [unsound](https://github.com/lampepfl/dotty/issues/1050). +is [unsound](https://github.com/scala/scala3/issues/1050). This restriction rules out the [type-level encoding of a combinator calculus](https://michid.wordpress.com/2010/01/29/scala-type-level-encoding-of-the-ski-calculus/). diff --git a/docs/_docs/reference/enums/adts.md b/docs/_docs/reference/enums/adts.md index 5219e062a633..36dd1daf0b59 100644 --- a/docs/_docs/reference/enums/adts.md +++ b/docs/_docs/reference/enums/adts.md @@ -170,4 +170,4 @@ The changes are specified below as deltas with respect to the Scala syntax given ## Reference -For more information, see [Issue #1970](https://github.com/lampepfl/dotty/issues/1970). +For more information, see [Issue #1970](https://github.com/scala/scala3/issues/1970). diff --git a/docs/_docs/reference/enums/enums.md b/docs/_docs/reference/enums/enums.md index 65051bdfb39f..8d4fca3268b0 100644 --- a/docs/_docs/reference/enums/enums.md +++ b/docs/_docs/reference/enums/enums.md @@ -180,7 +180,7 @@ scala> Color.Red.compareTo(Color.Green) val res15: Int = -1 ``` -For a more in-depth example of using Scala 3 enums from Java, see [this test](https://github.com/lampepfl/dotty/tree/main/tests/run/enum-java). In the test, the enums are defined in the `MainScala.scala` file and used from a Java source, `Test.java`. +For a more in-depth example of using Scala 3 enums from Java, see [this test](https://github.com/scala/scala3/tree/main/tests/run/enum-java). In the test, the enums are defined in the `MainScala.scala` file and used from a Java source, `Test.java`. ## Implementation @@ -218,5 +218,5 @@ val Red: Color = $new(0, "Red") ## Reference -For more information, see [Issue #1970](https://github.com/lampepfl/dotty/issues/1970) and -[PR #4003](https://github.com/lampepfl/dotty/pull/4003). +For more information, see [Issue #1970](https://github.com/scala/scala3/issues/1970) and +[PR #4003](https://github.com/scala/scala3/pull/4003). diff --git a/docs/_docs/reference/experimental/explicit-nulls.md b/docs/_docs/reference/experimental/explicit-nulls.md index f8f9ac8e11be..1925b0b3c925 100644 --- a/docs/_docs/reference/experimental/explicit-nulls.md +++ b/docs/_docs/reference/experimental/explicit-nulls.md @@ -1,7 +1,7 @@ --- layout: doc-page title: "Explicit Nulls" -nightlyOf: https://docs.scala-lang.org/scala3/reference/other-new-features/explicit-nulls.html +nightlyOf: https://docs.scala-lang.org/scala3/reference/experimental/explicit-nulls.html --- Explicit nulls is an opt-in feature that modifies the Scala type system, which makes reference types @@ -431,7 +431,7 @@ When dealing with local mutable variables, there are two questions: x = null ``` -See [more examples](https://github.com/lampepfl/dotty/blob/main/tests/explicit-nulls/neg/flow-varref-in-closure.scala). +See [more examples](https://github.com/scala/scala3/blob/main/tests/explicit-nulls/neg/flow-varref-in-closure.scala). Currently, we are unable to track paths with a mutable variable prefix. For example, `x.a` if `x` is mutable. diff --git a/docs/_docs/reference/experimental/tupled-function.md b/docs/_docs/reference/experimental/tupled-function.md index 0cc016953a80..de683128fb0c 100644 --- a/docs/_docs/reference/experimental/tupled-function.md +++ b/docs/_docs/reference/experimental/tupled-function.md @@ -35,7 +35,7 @@ The compiler will synthesize an instance of `TupledFunction[F, G]` if: Examples -------- `TupledFunction` can be used to generalize the `Function1.tupled`, ... `Function22.tupled` methods to functions of any arities. -The following defines `tupled` as [extension method](../contextual/extension-methods.html) ([full example](https://github.com/lampepfl/dotty/blob/main/tests/run/tupled-function-tupled.scala)). +The following defines `tupled` as [extension method](../contextual/extension-methods.html) ([full example](https://github.com/scala/scala3/blob/main/tests/run/tupled-function-tupled.scala)). ```scala /** Creates a tupled version of this function: instead of N arguments, @@ -49,7 +49,7 @@ extension [F, Args <: Tuple, R](f: F) def tupled(using tf: TupledFunction[F, Args => R]): Args => R = tf.tupled(f) ``` -`TupledFunction` can be used to generalize the `Function.untupled` to a function of any arities ([full example](https://github.com/lampepfl/dotty/blob/main/tests/run/tupled-function-untupled.scala)) +`TupledFunction` can be used to generalize the `Function.untupled` to a function of any arities ([full example](https://github.com/scala/scala3/blob/main/tests/run/tupled-function-untupled.scala)) ```scala /** Creates an untupled version of this function: instead of a single argument of type [[scala.Tuple]] with N elements, @@ -65,7 +65,7 @@ extension [F, Args <: Tuple, R](f: Args => R) def untupled(using tf: TupledFunction[F, Args => R]): F = tf.untupled(f) ``` -`TupledFunction` can also be used to generalize the [`Tuple1.compose`](https://github.com/lampepfl/dotty/blob/main/tests/run/tupled-function-compose.scala) and [`Tuple1.andThen`](https://github.com/lampepfl/dotty/blob/main/tests/run/tupled-function-andThen.scala) methods to compose functions of larger arities and with functions that return tuples. +`TupledFunction` can also be used to generalize the [`Tuple1.compose`](https://github.com/scala/scala3/blob/main/tests/run/tupled-function-compose.scala) and [`Tuple1.andThen`](https://github.com/scala/scala3/blob/main/tests/run/tupled-function-andThen.scala) methods to compose functions of larger arities and with functions that return tuples. ```scala /** Composes two instances of TupledFunction into a new TupledFunction, with this function applied last. diff --git a/docs/_docs/reference/features-classification.md b/docs/_docs/reference/features-classification.md index 36cea3b9e72d..550130780b44 100644 --- a/docs/_docs/reference/features-classification.md +++ b/docs/_docs/reference/features-classification.md @@ -72,7 +72,7 @@ These constructs are restricted to make the language safer. - [Given Imports](contextual/given-imports.md): implicits now require a special form of import, to make the import clearly visible. - [Type Projection](dropped-features/type-projection.md): only classes can be used as prefix `C` of a type projection `C#A`. Type projection on abstract types is no longer supported since it is unsound. - [Multiversal equality](contextual/multiversal-equality.md) implements an "opt-in" scheme to rule out nonsensical comparisons with `==` and `!=`. - - [infix](https://github.com/lampepfl/dotty/pull/5975) + - [infix](https://github.com/scala/scala3/pull/5975) makes method application syntax uniform across code bases. Unrestricted implicit conversions continue to be available in Scala 3.0, but will be deprecated and removed later. Unrestricted versions of the other constructs in the list above are available only under `-source 3.0-migration`. @@ -100,7 +100,7 @@ These constructs are proposed to be dropped without a new construct replacing th - [Auto application](dropped-features/auto-apply.md), - [Weak conformance](dropped-features/weak-conformance.md), - [Compound types](new-types/intersection-types.md), - - [Auto tupling](https://github.com/lampepfl/dotty/pull/4311) (implemented, but not merged). + - [Auto tupling](https://github.com/scala/scala3/pull/4311) (implemented, but not merged). The date when these constructs are dropped varies. The current status is: @@ -148,7 +148,7 @@ These are additions to the language that make it more powerful or pleasant to us - [Enums](enums/enums.md) provide concise syntax for enumerations and [algebraic data types](enums/adts.md). - [Parameter untupling](other-new-features/parameter-untupling.md) avoids having to use `case` for tupled parameter destructuring. - [Dependent function types](new-types/dependent-function-types.md) generalize dependent methods to dependent function values and types. - - [Polymorphic function types](https://github.com/lampepfl/dotty/pull/4672) generalize polymorphic methods to dependent function values and types. _Current status_: There is a proposal, and a prototype implementation, but the implementation has not been finalized or merged yet. + - [Polymorphic function types](https://github.com/scala/scala3/pull/4672) generalize polymorphic methods to dependent function values and types. _Current status_: There is a proposal, and a prototype implementation, but the implementation has not been finalized or merged yet. - [Kind polymorphism](other-new-features/kind-polymorphism.md) allows the definition of operators working equally on types and type constructors. **Status: mixed** diff --git a/docs/_docs/reference/metaprogramming/compiletime-ops.md b/docs/_docs/reference/metaprogramming/compiletime-ops.md index 048c6b6165bb..dcefb3a16ed3 100644 --- a/docs/_docs/reference/metaprogramming/compiletime-ops.md +++ b/docs/_docs/reference/metaprogramming/compiletime-ops.md @@ -259,5 +259,5 @@ val notMissing : NotMissing = summonInlineCheck(3) ## Reference -For more information about compile-time operations, see [PR #4768](https://github.com/lampepfl/dotty/pull/4768), -which explains how `summonFrom`'s predecessor (implicit matches) can be used for typelevel programming and code specialization and [PR #7201](https://github.com/lampepfl/dotty/pull/7201) which explains the new `summonFrom` syntax. +For more information about compile-time operations, see [PR #4768](https://github.com/scala/scala3/pull/4768), +which explains how `summonFrom`'s predecessor (implicit matches) can be used for typelevel programming and code specialization and [PR #7201](https://github.com/scala/scala3/pull/7201) which explains the new `summonFrom` syntax. diff --git a/docs/_docs/reference/metaprogramming/macros.md b/docs/_docs/reference/metaprogramming/macros.md index 5bfaa167a12f..b63616185285 100644 --- a/docs/_docs/reference/metaprogramming/macros.md +++ b/docs/_docs/reference/metaprogramming/macros.md @@ -452,10 +452,10 @@ The lambda arguments will replace the variables that might have been extruded. ```scala '{ ((x: Int) => x + 1).apply(2) } match - case '{ ((y: Int) => $f(y)).apply($z: Int) } => + case '{ ((y: Int) => $f(y): Int).apply($z: Int) } => // f may contain references to `x` (replaced by `$y`) - // f = (y: Expr[Int]) => '{ $y + 1 } - f(z) // generates '{ 2 + 1 } + // f = '{ (y: Int) => $y + 1 } + Expr.betaReduce('{ $f($z)}) // generates '{ 2 + 1 } ``` diff --git a/docs/_docs/reference/new-types/dependent-function-types-spec.md b/docs/_docs/reference/new-types/dependent-function-types-spec.md index f603200b1ae0..3084ff4de71c 100644 --- a/docs/_docs/reference/new-types/dependent-function-types-spec.md +++ b/docs/_docs/reference/new-types/dependent-function-types-spec.md @@ -4,7 +4,7 @@ title: "Dependent Function Types - More Details" nightlyOf: https://docs.scala-lang.org/scala3/reference/new-types/dependent-function-types-spec.html --- -Initial implementation in [PR #3464](https://github.com/lampepfl/dotty/pull/3464). +Initial implementation in [PR #3464](https://github.com/scala/scala3/pull/3464). ## Syntax @@ -46,7 +46,7 @@ same way that other functions do, see The example below defines a trait `C` and the two dependent function types `DF` and `IDF` and prints the results of the respective function applications: -[depfuntype.scala]: https://github.com/lampepfl/dotty/blob/main/tests/pos/depfuntype.scala +[depfuntype.scala]: https://github.com/scala/scala3/blob/main/tests/pos/depfuntype.scala ```scala trait C { type M; val m: M } @@ -70,7 +70,7 @@ type IDF = (x: C) ?=> x.M In the following example the depend type `f.Eff` refers to the effect type `CanThrow`: -[eff-dependent.scala]: https://github.com/lampepfl/dotty/blob/main/tests/run/eff-dependent.scala +[eff-dependent.scala]: https://github.com/scala/scala3/blob/main/tests/run/eff-dependent.scala ```scala trait Effect diff --git a/docs/_docs/reference/new-types/intersection-types-spec.md b/docs/_docs/reference/new-types/intersection-types-spec.md index 4e26626c0b36..723720fdef89 100644 --- a/docs/_docs/reference/new-types/intersection-types-spec.md +++ b/docs/_docs/reference/new-types/intersection-types-spec.md @@ -97,7 +97,7 @@ glb(A, _) = A // use first In the above, `|T|` means the erased type of `T`, `JArray` refers to the type of Java Array. -See also: [`TypeErasure#erasedGlb`](https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/core/TypeErasure.scala#L289). +See also: [`TypeErasure#erasedGlb`](https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/core/TypeErasure.scala#L289). ## Relationship with Compound Type (`with`) diff --git a/docs/_docs/reference/new-types/polymorphic-function-types.md b/docs/_docs/reference/new-types/polymorphic-function-types.md index 1754bf844831..04f4a3483896 100644 --- a/docs/_docs/reference/new-types/polymorphic-function-types.md +++ b/docs/_docs/reference/new-types/polymorphic-function-types.md @@ -33,7 +33,7 @@ In Scala 3 this is now possible. The type of the `bar` value above is This type describes function values which take a type `A` as a parameter, then take a list of type `List[A]`, and return a list of the same type `List[A]`. -[More details](https://github.com/lampepfl/dotty/pull/4672) +[More details](https://github.com/scala/scala3/pull/4672) ## Example Usage diff --git a/docs/_docs/reference/other-new-features/open-classes.md b/docs/_docs/reference/other-new-features/open-classes.md index 10af6ead669e..ff2dbac27b3b 100644 --- a/docs/_docs/reference/other-new-features/open-classes.md +++ b/docs/_docs/reference/other-new-features/open-classes.md @@ -77,4 +77,4 @@ A class that is neither `abstract` nor `open` is similar to a `sealed` class: it ## Migration -`open` is a new modifier in Scala 3. To allow cross compilation between Scala 2.13 and Scala 3.0 without warnings, the feature warning for ad-hoc extensions is produced only under `-source future`. It will be produced by default [from Scala 3.4 on](https://github.com/lampepfl/dotty/issues/16334). +`open` is a new modifier in Scala 3. To allow cross compilation between Scala 2.13 and Scala 3.0 without warnings, the feature warning for ad-hoc extensions is produced only under `-source future`. It will be produced by default [from Scala 3.4 on](https://github.com/scala/scala3/issues/16334). diff --git a/docs/_docs/reference/other-new-features/parameter-untupling-spec.md b/docs/_docs/reference/other-new-features/parameter-untupling-spec.md index fd462dd610c8..c9e1033f5ea6 100644 --- a/docs/_docs/reference/other-new-features/parameter-untupling-spec.md +++ b/docs/_docs/reference/other-new-features/parameter-untupling-spec.md @@ -56,4 +56,4 @@ Obsolete conversions could be detected and fixed by [`Scalafix`](https://scalace ## Reference -For more information, see [Issue #897](https://github.com/lampepfl/dotty/issues/897). +For more information, see [Issue #897](https://github.com/scala/scala3/issues/897). diff --git a/docs/_docs/reference/other-new-features/parameter-untupling.md b/docs/_docs/reference/other-new-features/parameter-untupling.md index e1e7afcad8fe..27e3850b309c 100644 --- a/docs/_docs/reference/other-new-features/parameter-untupling.md +++ b/docs/_docs/reference/other-new-features/parameter-untupling.md @@ -75,4 +75,4 @@ cannot subvert untupling. For more information see: * [More details](./parameter-untupling-spec.md) -* [Issue #897](https://github.com/lampepfl/dotty/issues/897). +* [Issue #897](https://github.com/scala/scala3/issues/897). diff --git a/docs/_docs/reference/overview.md b/docs/_docs/reference/overview.md index b1e8281dfc16..bdb8aa74c1aa 100644 --- a/docs/_docs/reference/overview.md +++ b/docs/_docs/reference/overview.md @@ -91,7 +91,7 @@ These constructs are proposed to be dropped without a new construct replacing th - [Auto application](dropped-features/auto-apply.md), - [Weak conformance](dropped-features/weak-conformance.md), - Compound types (replaced by [Intersection types](new-types/intersection-types.md)), -- [Auto tupling](https://github.com/lampepfl/dotty/pull/4311) (implemented, but not merged). +- [Auto tupling](https://github.com/scala/scala3/pull/4311) (implemented, but not merged). The date when these constructs are dropped varies. The current status is: diff --git a/docs/_docs/release-notes-0.1.2.md b/docs/_docs/release-notes-0.1.2.md index 98f359c83a15..c6bc9846bf07 100644 --- a/docs/_docs/release-notes-0.1.2.md +++ b/docs/_docs/release-notes-0.1.2.md @@ -18,7 +18,7 @@ Dotty 0.1.2 targets Java 8. We don't have plans to add support for earlier versi # Reporting Bugs / Known Issues -Please [file](https://github.com/lampepfl/dotty/issues) any bugs you encounter. If you’re unsure whether something is a bug, +Please [file](https://github.com/scala/scala3/issues) any bugs you encounter. If you’re unsure whether something is a bug, please ask on the Dotty [gitter channel](https://github.com/lampepfl/dotty). # Dotty Doc @@ -86,27 +86,27 @@ This release ships with the following features: [9]: http://docs.scala-lang.org/sips/pending/static-members.html [10]: http://docs.scala-lang.org/sips/pending/improved-lazy-val-initialization.html [11]: http://magarciaepfl.github.io/scala/ -[12]: https://github.com/lampepfl/dotty/commit/b2215ed23311b2c99ea638f9d7fcad9737dba588 -[13]: https://github.com/lampepfl/dotty/pull/187 -[14]: https://github.com/lampepfl/dotty/pull/217 +[12]: https://github.com/scala/scala3/commit/b2215ed23311b2c99ea638f9d7fcad9737dba588 +[13]: https://github.com/scala/scala3/pull/187 +[14]: https://github.com/scala/scala3/pull/217 [15]: reference/other-new-features/trait-parameters.html -[16]: https://github.com/lampepfl/dotty/commit/89540268e6c49fb92b9ca61249e46bb59981bf5a -[17]: https://github.com/lampepfl/dotty/pull/174 -[18]: https://github.com/lampepfl/dotty/pull/488 -[19]: https://github.com/lampepfl/dotty/pull/174 -[20]: https://github.com/lampepfl/dotty/pull/411 -[21]: https://github.com/lampepfl/dotty/pull/1364 -[22]: https://github.com/lampepfl/dotty/pull/1227 -[23]: https://github.com/lampepfl/dotty/pull/117 -[24]: https://github.com/lampepfl/dotty/pull/2532 -[25]: https://github.com/lampepfl/dotty/pull/2194 -[26]: https://github.com/lampepfl/dotty/pull/213 -[27]: https://github.com/lampepfl/dotty/pull/2513 -[28]: https://github.com/lampepfl/dotty/pull/2361 -[29]: https://github.com/lampepfl/dotty/pull/1453 +[16]: https://github.com/scala/scala3/commit/89540268e6c49fb92b9ca61249e46bb59981bf5a +[17]: https://github.com/scala/scala3/pull/174 +[18]: https://github.com/scala/scala3/pull/488 +[19]: https://github.com/scala/scala3/pull/174 +[20]: https://github.com/scala/scala3/pull/411 +[21]: https://github.com/scala/scala3/pull/1364 +[22]: https://github.com/scala/scala3/pull/1227 +[23]: https://github.com/scala/scala3/pull/117 +[24]: https://github.com/scala/scala3/pull/2532 +[25]: https://github.com/scala/scala3/pull/2194 +[26]: https://github.com/scala/scala3/pull/213 +[27]: https://github.com/scala/scala3/pull/2513 +[28]: https://github.com/scala/scala3/pull/2361 +[29]: https://github.com/scala/scala3/pull/1453 [30]: reference/contextual/context-functions.html -[31]: https://github.com/lampepfl/dotty/pull/2136 -[32]: https://github.com/lampepfl/dotty/pull/1758 +[31]: https://github.com/scala/scala3/pull/2136 +[32]: https://github.com/scala/scala3/pull/1758 [33]: reference/metaprogramming/inline.html # Contributors diff --git a/docs/_spec/APPLIEDreference/dropped-features/auto-apply.md b/docs/_spec/APPLIEDreference/dropped-features/auto-apply.md index b9aedb9f046b..95366b5e8f78 100644 --- a/docs/_spec/APPLIEDreference/dropped-features/auto-apply.md +++ b/docs/_spec/APPLIEDreference/dropped-features/auto-apply.md @@ -93,4 +93,4 @@ stricter checking. ## Reference -For more information, see [Issue #2570](https://github.com/lampepfl/dotty/issues/2570) and [PR #2716](https://github.com/lampepfl/dotty/pull/2716). +For more information, see [Issue #2570](https://github.com/scala/scala3/issues/2570) and [PR #2716](https://github.com/scala/scala3/pull/2716). diff --git a/docs/_spec/APPLIEDreference/dropped-features/this-qualifier.md b/docs/_spec/APPLIEDreference/dropped-features/this-qualifier.md index 3fcaefb7e0d8..9eb0a77e2b69 100644 --- a/docs/_spec/APPLIEDreference/dropped-features/this-qualifier.md +++ b/docs/_spec/APPLIEDreference/dropped-features/this-qualifier.md @@ -4,7 +4,7 @@ title: "Dropped: private[this] and protected[this]" nightlyOf: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html --- -The `private[this]` and `protected[this]` access modifiers will be deprecated and phased out. +The `private[this]` and `protected[this]` access modifiers will be deprecated and phased out. Migration warning will be shown in Scala 3.4+. Previously, these modifiers were needed for diff --git a/docs/_spec/APPLIEDreference/enums/enums.md b/docs/_spec/APPLIEDreference/enums/enums.md index bcab50d3a36d..d8fdbe9f1db2 100644 --- a/docs/_spec/APPLIEDreference/enums/enums.md +++ b/docs/_spec/APPLIEDreference/enums/enums.md @@ -178,5 +178,5 @@ scala> Color.Red.compareTo(Color.Green) val res15: Int = -1 ``` -For a more in-depth example of using Scala 3 enums from Java, see [this test](https://github.com/lampepfl/dotty/tree/main/tests/run/enum-java). +For a more in-depth example of using Scala 3 enums from Java, see [this test](https://github.com/scala/scala3/tree/main/tests/run/enum-java). In the test, the enums are defined in the `MainScala.scala` file and used from a Java source, `Test.java`. diff --git a/docs/_spec/APPLIEDreference/new-types/union-types.md b/docs/_spec/APPLIEDreference/new-types/union-types.md index 152505d7fc8d..f59bb6f6b851 100644 --- a/docs/_spec/APPLIEDreference/new-types/union-types.md +++ b/docs/_spec/APPLIEDreference/new-types/union-types.md @@ -59,8 +59,8 @@ be changed in the future. For example by not widening unions that have been explicitly written down by the user and not inferred, or by not widening a type argument when the corresponding type parameter is covariant. -See [PR #2330](https://github.com/lampepfl/dotty/pull/2330) and -[Issue #4867](https://github.com/lampepfl/dotty/issues/4867) for further discussions. +See [PR #2330](https://github.com/scala/scala3/pull/2330) and +[Issue #4867](https://github.com/scala/scala3/issues/4867) for further discussions. ### Example diff --git a/docs/_spec/TODOreference/changed-features/eta-expansion-spec.md b/docs/_spec/TODOreference/changed-features/eta-expansion-spec.md index a62d45df9e11..fa5c1e57a066 100644 --- a/docs/_spec/TODOreference/changed-features/eta-expansion-spec.md +++ b/docs/_spec/TODOreference/changed-features/eta-expansion-spec.md @@ -74,4 +74,4 @@ The method value syntax `m _` is deprecated. ## Reference -For more information, see [PR #2701](https://github.com/lampepfl/dotty/pull/2701). +For more information, see [PR #2701](https://github.com/scala/scala3/pull/2701). diff --git a/docs/_spec/TODOreference/changed-features/implicit-conversions-spec.md b/docs/_spec/TODOreference/changed-features/implicit-conversions-spec.md index dc19e10c8b8f..a70321b70c15 100644 --- a/docs/_spec/TODOreference/changed-features/implicit-conversions-spec.md +++ b/docs/_spec/TODOreference/changed-features/implicit-conversions-spec.md @@ -114,4 +114,4 @@ changes to implicit resolution, refer to the [Changes in Implicit Resolution](im ## Reference For more information about implicit resolution, see [Changes in Implicit Resolution](implicit-resolution.md). -Other details are available in [PR #2065](https://github.com/lampepfl/dotty/pull/2065). +Other details are available in [PR #2065](https://github.com/scala/scala3/pull/2065). diff --git a/docs/_spec/TODOreference/changed-features/structural-types-spec.md b/docs/_spec/TODOreference/changed-features/structural-types-spec.md index d456932649fb..cb48a593e831 100644 --- a/docs/_spec/TODOreference/changed-features/structural-types-spec.md +++ b/docs/_spec/TODOreference/changed-features/structural-types-spec.md @@ -16,7 +16,7 @@ RefineStat ::= ‘val’ VarDcl | ‘def’ DefDcl | ‘type’ {nl} TypeDcl ## Implementation of Structural Types The standard library defines a universal marker trait -[`scala.Selectable`](https://github.com/lampepfl/dotty/blob/main/library/src/scala/Selectable.scala): +[`scala.Selectable`](https://github.com/scala/scala3/blob/main/library/src/scala/Selectable.scala): ```scala trait Selectable extends Any @@ -150,4 +150,4 @@ conversion that can turn `v` into a `Selectable`, and the selection methods coul ## Context -For more information, see [Rethink Structural Types](https://github.com/lampepfl/dotty/issues/1886). +For more information, see [Rethink Structural Types](https://github.com/scala/scala3/issues/1886). diff --git a/docs/_spec/TODOreference/contextual/by-name-context-parameters.md b/docs/_spec/TODOreference/contextual/by-name-context-parameters.md index 3004bfb2c4c2..7a80b20592ea 100644 --- a/docs/_spec/TODOreference/contextual/by-name-context-parameters.md +++ b/docs/_spec/TODOreference/contextual/by-name-context-parameters.md @@ -61,5 +61,5 @@ No local given instance was generated because the synthesized argument is not re ## Reference -For more information, see [Issue #1998](https://github.com/lampepfl/dotty/issues/1998) +For more information, see [Issue #1998](https://github.com/scala/scala3/issues/1998) and the associated [Scala SIP](https://docs.scala-lang.org/sips/byname-implicits.html). diff --git a/docs/_spec/TODOreference/contextual/multiversal-equality.md b/docs/_spec/TODOreference/contextual/multiversal-equality.md index e9a81b95f472..fa729fda8e61 100644 --- a/docs/_spec/TODOreference/contextual/multiversal-equality.md +++ b/docs/_spec/TODOreference/contextual/multiversal-equality.md @@ -25,7 +25,7 @@ the program will still typecheck, since values of all types can be compared with But it will probably give unexpected results and fail at runtime. Multiversal equality is an opt-in way to make universal equality safer. -It uses a binary type class [`scala.CanEqual`](https://github.com/lampepfl/dotty/blob/main/library/src/scala/CanEqual.scala) +It uses a binary type class [`scala.CanEqual`](https://github.com/scala/scala3/blob/main/library/src/scala/CanEqual.scala) to indicate that values of two given types can be compared with each other. The example above would not typecheck if `S` or `T` was a class that derives `CanEqual`, e.g. @@ -70,7 +70,7 @@ given CanEqual[A, B] = CanEqual.derived given CanEqual[B, A] = CanEqual.derived ``` -The [`scala.CanEqual`](https://github.com/lampepfl/dotty/blob/main/library/src/scala/CanEqual.scala) +The [`scala.CanEqual`](https://github.com/scala/scala3/blob/main/library/src/scala/CanEqual.scala) object defines a number of `CanEqual` given instances that together define a rule book for what standard types can be compared (more details below). @@ -224,4 +224,4 @@ work under `-language:strictEquality`, since otherwise the universal `Eq[Any]` i More on multiversal equality is found in a [blog post](http://www.scala-lang.org/blog/2016/05/06/multiversal-equality.html) -and a [GitHub issue](https://github.com/lampepfl/dotty/issues/1247). +and a [GitHub issue](https://github.com/scala/scala3/issues/1247). diff --git a/docs/_spec/TODOreference/dropped-features/type-projection.md b/docs/_spec/TODOreference/dropped-features/type-projection.md index 08b5ffb34eca..2c3e82ce99b8 100644 --- a/docs/_spec/TODOreference/dropped-features/type-projection.md +++ b/docs/_spec/TODOreference/dropped-features/type-projection.md @@ -9,7 +9,7 @@ and `A` names a type member of `T`. Scala 3 disallows this if `T` is an abstract type (class types and type aliases are fine). This change was made because unrestricted type projection -is [unsound](https://github.com/lampepfl/dotty/issues/1050). +is [unsound](https://github.com/scala/scala3/issues/1050). This restriction rules out the [type-level encoding of a combinator calculus](https://michid.wordpress.com/2010/01/29/scala-type-level-encoding-of-the-ski-calculus/). diff --git a/docs/_spec/TODOreference/experimental/explicit-nulls.md b/docs/_spec/TODOreference/experimental/explicit-nulls.md index b3fa53429cfe..3be83afe967e 100644 --- a/docs/_spec/TODOreference/experimental/explicit-nulls.md +++ b/docs/_spec/TODOreference/experimental/explicit-nulls.md @@ -431,7 +431,7 @@ When dealing with local mutable variables, there are two questions: x = null ``` -See [more examples](https://github.com/lampepfl/dotty/blob/main/tests/explicit-nulls/neg/flow-varref-in-closure.scala). +See [more examples](https://github.com/scala/scala3/blob/main/tests/explicit-nulls/neg/flow-varref-in-closure.scala). Currently, we are unable to track paths with a mutable variable prefix. For example, `x.a` if `x` is mutable. diff --git a/docs/_spec/TODOreference/experimental/tupled-function.md b/docs/_spec/TODOreference/experimental/tupled-function.md index da108fc832ad..e01570e9e8a6 100644 --- a/docs/_spec/TODOreference/experimental/tupled-function.md +++ b/docs/_spec/TODOreference/experimental/tupled-function.md @@ -34,7 +34,7 @@ The compiler will synthesize an instance of `TupledFunction[F, G]` if: Examples -------- `TupledFunction` can be used to generalize the `Function1.tupled`, ... `Function22.tupled` methods to functions of any arities. -The following defines `tupled` as [extension method](../contextual/extension-methods.html) ([full example](https://github.com/lampepfl/dotty/blob/main/tests/run/tupled-function-tupled.scala)). +The following defines `tupled` as [extension method](../contextual/extension-methods.html) ([full example](https://github.com/scala/scala3/blob/main/tests/run/tupled-function-tupled.scala)). ```scala /** Creates a tupled version of this function: instead of N arguments, @@ -48,7 +48,7 @@ extension [F, Args <: Tuple, R](f: F) def tupled(using tf: TupledFunction[F, Args => R]): Args => R = tf.tupled(f) ``` -`TupledFunction` can be used to generalize the `Function.untupled` to a function of any arities ([full example](https://github.com/lampepfl/dotty/blob/main/tests/run/tupled-function-untupled.scala)) +`TupledFunction` can be used to generalize the `Function.untupled` to a function of any arities ([full example](https://github.com/scala/scala3/blob/main/tests/run/tupled-function-untupled.scala)) ```scala /** Creates an untupled version of this function: instead of a single argument of type [[scala.Tuple]] with N elements, @@ -64,7 +64,7 @@ extension [F, Args <: Tuple, R](f: Args => R) def untupled(using tf: TupledFunction[F, Args => R]): F = tf.untupled(f) ``` -`TupledFunction` can also be used to generalize the [`Tuple1.compose`](https://github.com/lampepfl/dotty/blob/main/tests/run/tupled-function-compose.scala) and [`Tuple1.andThen`](https://github.com/lampepfl/dotty/blob/main/tests/run/tupled-function-andThen.scala) methods to compose functions of larger arities and with functions that return tuples. +`TupledFunction` can also be used to generalize the [`Tuple1.compose`](https://github.com/scala/scala3/blob/main/tests/run/tupled-function-compose.scala) and [`Tuple1.andThen`](https://github.com/scala/scala3/blob/main/tests/run/tupled-function-andThen.scala) methods to compose functions of larger arities and with functions that return tuples. ```scala /** Composes two instances of TupledFunction into a new TupledFunction, with this function applied last. diff --git a/docs/_spec/TODOreference/features-classification.md b/docs/_spec/TODOreference/features-classification.md index 36cea3b9e72d..550130780b44 100644 --- a/docs/_spec/TODOreference/features-classification.md +++ b/docs/_spec/TODOreference/features-classification.md @@ -72,7 +72,7 @@ These constructs are restricted to make the language safer. - [Given Imports](contextual/given-imports.md): implicits now require a special form of import, to make the import clearly visible. - [Type Projection](dropped-features/type-projection.md): only classes can be used as prefix `C` of a type projection `C#A`. Type projection on abstract types is no longer supported since it is unsound. - [Multiversal equality](contextual/multiversal-equality.md) implements an "opt-in" scheme to rule out nonsensical comparisons with `==` and `!=`. - - [infix](https://github.com/lampepfl/dotty/pull/5975) + - [infix](https://github.com/scala/scala3/pull/5975) makes method application syntax uniform across code bases. Unrestricted implicit conversions continue to be available in Scala 3.0, but will be deprecated and removed later. Unrestricted versions of the other constructs in the list above are available only under `-source 3.0-migration`. @@ -100,7 +100,7 @@ These constructs are proposed to be dropped without a new construct replacing th - [Auto application](dropped-features/auto-apply.md), - [Weak conformance](dropped-features/weak-conformance.md), - [Compound types](new-types/intersection-types.md), - - [Auto tupling](https://github.com/lampepfl/dotty/pull/4311) (implemented, but not merged). + - [Auto tupling](https://github.com/scala/scala3/pull/4311) (implemented, but not merged). The date when these constructs are dropped varies. The current status is: @@ -148,7 +148,7 @@ These are additions to the language that make it more powerful or pleasant to us - [Enums](enums/enums.md) provide concise syntax for enumerations and [algebraic data types](enums/adts.md). - [Parameter untupling](other-new-features/parameter-untupling.md) avoids having to use `case` for tupled parameter destructuring. - [Dependent function types](new-types/dependent-function-types.md) generalize dependent methods to dependent function values and types. - - [Polymorphic function types](https://github.com/lampepfl/dotty/pull/4672) generalize polymorphic methods to dependent function values and types. _Current status_: There is a proposal, and a prototype implementation, but the implementation has not been finalized or merged yet. + - [Polymorphic function types](https://github.com/scala/scala3/pull/4672) generalize polymorphic methods to dependent function values and types. _Current status_: There is a proposal, and a prototype implementation, but the implementation has not been finalized or merged yet. - [Kind polymorphism](other-new-features/kind-polymorphism.md) allows the definition of operators working equally on types and type constructors. **Status: mixed** diff --git a/docs/_spec/TODOreference/metaprogramming/compiletime-ops.md b/docs/_spec/TODOreference/metaprogramming/compiletime-ops.md index a43c941ae943..782cd72886d5 100644 --- a/docs/_spec/TODOreference/metaprogramming/compiletime-ops.md +++ b/docs/_spec/TODOreference/metaprogramming/compiletime-ops.md @@ -290,5 +290,5 @@ val notMissing : NotMissing = summonInlineCheck(3) ## Reference -For more information about compile-time operations, see [PR #4768](https://github.com/lampepfl/dotty/pull/4768), -which explains how `summonFrom`'s predecessor (implicit matches) can be used for typelevel programming and code specialization and [PR #7201](https://github.com/lampepfl/dotty/pull/7201) which explains the new `summonFrom` syntax. +For more information about compile-time operations, see [PR #4768](https://github.com/scala/scala3/pull/4768), +which explains how `summonFrom`'s predecessor (implicit matches) can be used for typelevel programming and code specialization and [PR #7201](https://github.com/scala/scala3/pull/7201) which explains the new `summonFrom` syntax. diff --git a/docs/_spec/TODOreference/metaprogramming/staging.md b/docs/_spec/TODOreference/metaprogramming/staging.md index 6d9166e8249e..073012761513 100644 --- a/docs/_spec/TODOreference/metaprogramming/staging.md +++ b/docs/_spec/TODOreference/metaprogramming/staging.md @@ -108,7 +108,11 @@ to get a source-like representation of the expression. import scala.quoted.* // make available the necessary compiler for runtime code generation -given staging.Compiler = staging.Compiler.make(getClass.getClassLoader) +given staging.Compiler = + // We need an instance of a class that is defined in the current application (not the standard library) + // `this` can be used instead of an instance of `Dummy` if the Compiler is instantiated within one of the application classes. + object Dummy + staging.Compiler.make(Dummy.getClass.getClassLoader) val f: Array[Int] => Int = staging.run { val stagedSum: Expr[Array[Int] => Int] = diff --git a/docs/_spec/TODOreference/new-types/dependent-function-types-spec.md b/docs/_spec/TODOreference/new-types/dependent-function-types-spec.md index f3237ddf7b9a..b27346a687d6 100644 --- a/docs/_spec/TODOreference/new-types/dependent-function-types-spec.md +++ b/docs/_spec/TODOreference/new-types/dependent-function-types-spec.md @@ -4,7 +4,7 @@ title: "Dependent Function Types - More Details" nightlyOf: https://docs.scala-lang.org/scala3/reference/new-types/dependent-function-types-spec.html --- -Initial implementation in [PR #3464](https://github.com/lampepfl/dotty/pull/3464). +Initial implementation in [PR #3464](https://github.com/scala/scala3/pull/3464). ## Syntax @@ -46,7 +46,7 @@ same way that other functions do, see The example below defines a trait `C` and the two dependent function types `DF` and `IDF` and prints the results of the respective function applications: -[depfuntype.scala]: https://github.com/lampepfl/dotty/blob/main/tests/pos/depfuntype.scala +[depfuntype.scala]: https://github.com/scala/scala3/blob/main/tests/pos/depfuntype.scala ```scala trait C { type M; val m: M } @@ -70,7 +70,7 @@ type IDF = (x: C) ?=> x.M In the following example the depend type `f.Eff` refers to the effect type `CanThrow`: -[eff-dependent.scala]: https://github.com/lampepfl/dotty/blob/main/tests/run/eff-dependent.scala +[eff-dependent.scala]: https://github.com/scala/scala3/blob/main/tests/run/eff-dependent.scala ```scala trait Effect diff --git a/docs/_spec/TODOreference/new-types/polymorphic-function-types.md b/docs/_spec/TODOreference/new-types/polymorphic-function-types.md index 1754bf844831..04f4a3483896 100644 --- a/docs/_spec/TODOreference/new-types/polymorphic-function-types.md +++ b/docs/_spec/TODOreference/new-types/polymorphic-function-types.md @@ -33,7 +33,7 @@ In Scala 3 this is now possible. The type of the `bar` value above is This type describes function values which take a type `A` as a parameter, then take a list of type `List[A]`, and return a list of the same type `List[A]`. -[More details](https://github.com/lampepfl/dotty/pull/4672) +[More details](https://github.com/scala/scala3/pull/4672) ## Example Usage diff --git a/docs/_spec/TODOreference/other-new-features/parameter-untupling-spec.md b/docs/_spec/TODOreference/other-new-features/parameter-untupling-spec.md index e5165550fc0d..6133012463a1 100644 --- a/docs/_spec/TODOreference/other-new-features/parameter-untupling-spec.md +++ b/docs/_spec/TODOreference/other-new-features/parameter-untupling-spec.md @@ -86,4 +86,4 @@ Obsolete conversions could be detected and fixed by [`Scalafix`](https://scalace ## Reference -For more information, see [Issue #897](https://github.com/lampepfl/dotty/issues/897). +For more information, see [Issue #897](https://github.com/scala/scala3/issues/897). diff --git a/docs/_spec/TODOreference/other-new-features/parameter-untupling.md b/docs/_spec/TODOreference/other-new-features/parameter-untupling.md index fcc1fa11d519..09806fc169eb 100644 --- a/docs/_spec/TODOreference/other-new-features/parameter-untupling.md +++ b/docs/_spec/TODOreference/other-new-features/parameter-untupling.md @@ -74,4 +74,4 @@ cannot subvert untupling. For more information see: * [More details](./parameter-untupling-spec.md) -* [Issue #897](https://github.com/lampepfl/dotty/issues/897). +* [Issue #897](https://github.com/scala/scala3/issues/897). diff --git a/docs/_spec/TODOreference/overview.md b/docs/_spec/TODOreference/overview.md index b1e8281dfc16..bdb8aa74c1aa 100644 --- a/docs/_spec/TODOreference/overview.md +++ b/docs/_spec/TODOreference/overview.md @@ -91,7 +91,7 @@ These constructs are proposed to be dropped without a new construct replacing th - [Auto application](dropped-features/auto-apply.md), - [Weak conformance](dropped-features/weak-conformance.md), - Compound types (replaced by [Intersection types](new-types/intersection-types.md)), -- [Auto tupling](https://github.com/lampepfl/dotty/pull/4311) (implemented, but not merged). +- [Auto tupling](https://github.com/scala/scala3/pull/4311) (implemented, but not merged). The date when these constructs are dropped varies. The current status is: diff --git a/docs/_spec/_layouts/default.yml b/docs/_spec/_layouts/default.yml index 5d597cb5ea96..0f7fb24d7ce2 100644 --- a/docs/_spec/_layouts/default.yml +++ b/docs/_spec/_layouts/default.yml @@ -27,7 +27,7 @@
diff --git a/language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala b/language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala index 903a5ae3b36a..3604e38375e7 100644 --- a/language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala +++ b/language-server/src/dotty/tools/languageserver/DottyLanguageServer.scala @@ -552,13 +552,18 @@ class DottyLanguageServer extends LanguageServer override def signatureHelp(params: TextDocumentPositionParams) = computeAsync { canceltoken => val uri = new URI(params.getTextDocument.getUri) val driver = driverFor(uri) - implicit def ctx: Context = driver.currentCtx - val pos = sourcePosition(driver, uri, params.getPosition) - val trees = driver.openedTrees(uri) - val path = Interactive.pathTo(trees, pos) - val (paramN, callableN, signatures) = Signatures.signatureHelp(path, pos.span) - new SignatureHelp(signatures.map(signatureToSignatureInformation).asJava, callableN, paramN) + driver.compilationUnits.get(uri) match + case Some(unit) => + given newCtx: Context = driver.currentCtx.fresh.setCompilationUnit(unit) + val pos = sourcePosition(driver, uri, params.getPosition) + val adjustedSpan = pos.span.withEnd(pos.span.end + 1) + val path = Interactive.pathTo(ctx.compilationUnit.tpdTree, adjustedSpan) + val (paramN, callableN, signatures) = Signatures.signatureHelp(path, adjustedSpan) + + new SignatureHelp(signatures.map(signatureToSignatureInformation).asJava, callableN, paramN) + + case _ => new SignatureHelp() } @@ -930,23 +935,25 @@ object DottyLanguageServer { /** Convert `signature` to a `SignatureInformation` */ def signatureToSignatureInformation(signature: Signatures.Signature): lsp4j.SignatureInformation = { - val tparams = signature.tparams.map(Signatures.Param("", _)) val paramInfoss = - (tparams ::: signature.paramss.flatten).map(paramToParameterInformation) + (signature.paramss.flatten).map(paramToParameterInformation) val paramLists = - if signature.paramss.forall(_.isEmpty) && tparams.nonEmpty then - "" - else - signature.paramss - .map { paramList => - val labels = paramList.map(_.show) - val prefix = if paramList.exists(_.isImplicit) then "using " else "" - labels.mkString(prefix, ", ", "") - } - .mkString("(", ")(", ")") - val tparamsLabel = if (signature.tparams.isEmpty) "" else signature.tparams.mkString("[", ", ", "]") + signature.paramss + .map { paramList => + val labels = paramList.map(_.show) + val isImplicit = paramList.exists: + case p: Signatures.MethodParam => p.isImplicit + case _ => false + val prefix = if isImplicit then "using " else "" + val isTypeParams = paramList.forall(_.isInstanceOf[Signatures.TypeParam]) && paramList.nonEmpty + val wrap: String => String = label => if isTypeParams then + s"[$label]" + else + s"($label)" + wrap(labels.mkString(prefix, ", ", "")) + }.mkString val returnTypeLabel = signature.returnType.map(t => s": $t").getOrElse("") - val label = s"${signature.name}$tparamsLabel$paramLists$returnTypeLabel" + val label = s"${signature.name}$paramLists$returnTypeLabel" val documentation = signature.doc.map(DottyLanguageServer.markupContent) val sig = new lsp4j.SignatureInformation(label) sig.setParameters(paramInfoss.asJava) diff --git a/language-server/test/dotty/tools/languageserver/CompletionTest.scala b/language-server/test/dotty/tools/languageserver/CompletionTest.scala index eaff8c307843..f3794c6f3468 100644 --- a/language-server/test/dotty/tools/languageserver/CompletionTest.scala +++ b/language-server/test/dotty/tools/languageserver/CompletionTest.scala @@ -35,6 +35,20 @@ class CompletionTest { .completion(("Conversion", Class, "Conversion")) } + @Test def implicitSearchCrash: Unit = + code""" + |object Test: + | trait Foo: + | def test(): String + | given Int = ??? + | given (using ev: Int): Conversion[String, Foo] = ??? + | + | val test = { + | "".tes$m1 + | 1 + | }""" + .completion(("test", Method, "(): String")) + @Test def completionFromScalaPackageObject: Unit = { code"class Foo { val foo: BigD${m1} }" .completion( @@ -1019,11 +1033,11 @@ class CompletionTest { | val x = Bar.${m1}""" .completion( ("getClass", Method, "[X0 >: Foo.Bar.type](): Class[? <: X0]"), - ("ensuring", Method, "(cond: Boolean): A"), + ("ensuring", Method, "(cond: Boolean): Foo.Bar.type"), ("##", Method, "=> Int"), ("nn", Method, "=> Foo.Bar.type"), ("==", Method, "(x$0: Any): Boolean"), - ("ensuring", Method, "(cond: Boolean, msg: => Any): A"), + ("ensuring", Method, "(cond: Boolean, msg: => Any): Foo.Bar.type"), ("ne", Method, "(x$0: Object): Boolean"), ("valueOf", Method, "($name: String): Foo.Bar"), ("equals", Method, "(x$0: Any): Boolean"), @@ -1031,21 +1045,21 @@ class CompletionTest { ("hashCode", Method, "(): Int"), ("notifyAll", Method, "(): Unit"), ("values", Method, "=> Array[Foo.Bar]"), - ("→", Method, "[B](y: B): (A, B)"), + ("→", Method, "[B](y: B): (Foo.Bar.type, B)"), ("!=", Method, "(x$0: Any): Boolean"), ("fromOrdinal", Method, "(ordinal: Int): Foo.Bar"), ("asInstanceOf", Method, "[X0]: X0"), - ("->", Method, "[B](y: B): (A, B)"), + ("->", Method, "[B](y: B): (Foo.Bar.type, B)"), ("wait", Method, "(x$0: Long, x$1: Int): Unit"), ("`back-tick`", Field, "Foo.Bar"), ("notify", Method, "(): Unit"), ("formatted", Method, "(fmtstr: String): String"), - ("ensuring", Method, "(cond: A => Boolean, msg: => Any): A"), + ("ensuring", Method, "(cond: Foo.Bar.type => Boolean, msg: => Any): Foo.Bar.type"), ("wait", Method, "(): Unit"), ("isInstanceOf", Method, "[X0]: Boolean"), ("`match`", Field, "Foo.Bar"), ("toString", Method, "(): String"), - ("ensuring", Method, "(cond: A => Boolean): A"), + ("ensuring", Method, "(cond: Foo.Bar.type => Boolean): Foo.Bar.type"), ("eq", Method, "(x$0: Object): Boolean"), ("synchronized", Method, "[X0](x$0: X0): X0") ) @@ -1576,6 +1590,61 @@ class CompletionTest { |""" .completion(m1, Set(("TTT", Field, "T.TTT"))) + @Test def properTypeVariable: Unit = + code"""|object M: + | List(1,2,3).filterNo$m1 + |""" + .completion(m1, Set(("filterNot", Method, "(p: Int => Boolean): List[Int]"))) + + @Test def properTypeVariableForExtensionMethods: Unit = + code"""|object M: + | extension [T](x: List[T]) def test(aaa: T): T = ??? + | List(1,2,3).tes$m1 + | + |""" + .completion(m1, Set(("test", Method, "(aaa: Int): Int"))) + + @Test def properTypeVariableForExtensionMethodsByName: Unit = + code"""|object M: + | extension [T](xs: List[T]) def test(p: T => Boolean): List[T] = ??? + | List(1,2,3).tes$m1 + |""" + .completion(m1, Set(("test", Method, "(p: Int => Boolean): List[Int]"))) + + @Test def genericExtensionTypeParameterInference: Unit = + code"""|object M: + | extension [T](xs: T) def test(p: T): T = ??? + | 3.tes$m1 + |""" + .completion(m1, Set(("test", Method, "(p: Int): Int"))) + + @Test def genericExtensionTypeParameterInferenceByName: Unit = + code"""|object M: + | extension [T](xs: T) def test(p: T => Boolean): T = ??? + | 3.tes$m1 + |""" + .completion(m1, Set(("test", Method, "(p: Int => Boolean): Int"))) + + @Test def properTypeVariableForImplicitDefs: Unit = + code"""|object M: + | implicit class ListUtils[T](xs: List[T]) { + | def test(p: T => Boolean): List[T] = ??? + | } + | List(1,2,3).tes$m1 + |""" + .completion(m1, Set(("test", Method, "(p: Int => Boolean): List[Int]"))) + + @Test def properTypeParameterForImplicitDefs: Unit = + code"""|object M: + | implicit class ListUtils[T](xs: T) { + | def test(p: T => Boolean): T = ??? + | } + | new ListUtils(1).tes$m1 + | 1.tes$m2 + |""" + .completion(m1, Set(("test", Method, "(p: Int => Boolean): Int"))) + .completion(m2, Set(("test", Method, "(p: Int => Boolean): Int"))) + @Test def selectDynamic: Unit = code"""|import scala.language.dynamics |class Foo extends Dynamic { @@ -1591,4 +1660,37 @@ class CompletionTest { |""" .completion(m1, Set(("selectDynamic", Method, "(field: String): Foo"))) .completion(m2, Set(("banana", Method, "=> Int"))) + + @Test def shadowedImport: Unit = + code"""| + |import Matches.* + |object Matches { + | val Number = "".r + |} + |object Main { + | Num$m1 + |} + |""".completion(m1, Set( + ("Number", Field, "scala.util.matching.Regex"), + ("NumberFormatException", Module, "NumberFormatException"), + ("Numeric", Field, "scala.math.Numeric") + )) + + @Test def shadowedImportType: Unit = + code"""| + |import Matches.* + |object Matches { + | val Number = "".r + |} + |object Main { + | val x: Num$m1 + |} + |""".completion(m1, Set( + ("Number", Class, "Number"), + ("Number", Field, "scala.util.matching.Regex"), + ("NumberFormatException", Module, "NumberFormatException"), + ("NumberFormatException", Field, "NumberFormatException"), + ("Numeric", Field, "Numeric"), + ("Numeric", Field, "scala.math.Numeric") + )) } diff --git a/language-server/test/dotty/tools/languageserver/SignatureHelpTest.scala b/language-server/test/dotty/tools/languageserver/SignatureHelpTest.scala index 78fd99d0c3ed..433b2665c4c1 100644 --- a/language-server/test/dotty/tools/languageserver/SignatureHelpTest.scala +++ b/language-server/test/dotty/tools/languageserver/SignatureHelpTest.scala @@ -4,38 +4,21 @@ import org.junit.Test import dotty.tools.languageserver.util.Code._ -import dotty.tools.dotc.util.Signatures.{Param => P, Signature => S} +import dotty.tools.dotc.util.Signatures.{TypeParam => TP, MethodParam => P, Signature => S} class SignatureHelpTest { @Test def fromJava: Unit = { val signature = - S("codePointAt", Nil, List(List(P("x$0", "Int"))), Some("Int")) + S("codePointAt", List(List(P("x$0", "Int"))), Some("Int")) code"""object O { "hello".codePointAt($m1) }""" .signatureHelp(m1, List(signature), Some(0), 0) } - @Test def properFunctionReturnWithoutParenthesis: Unit = { - val listSignature = S("apply", List("A"), List(List(P("elems", "A*"))), Some("List[A]")) - val optionSignature = S("apply", List("A"), List(List(P("x", "A"))), Some("Option[A]")) - code"""object O { - | List(1, 2$m1 - |} - |object T { - | List(Option(1$m2 - |} - |object Z { - | List(Option(1)$m3 - |}""" - .signatureHelp(m1, List(listSignature), Some(0), 1) - .signatureHelp(m2, List(optionSignature), Some(0), 1) - .signatureHelp(m3, List(listSignature), Some(0), 1) - } - @Test def errorTypeParameter: Unit = { - val emptySignature = S("empty", List("K", "V"), Nil, Some("Map[K, V]")) + val emptySignature = S("empty", List(List(TP("K"), TP("V"))), Some("Map[K, V]")) code"""object O: | Map.empty[WrongType, $m1] """ @@ -43,8 +26,8 @@ class SignatureHelpTest { } @Test def methodTypeParameter: Unit = { - val applySignature = S("apply", List("K", "V"), List(List(P("elems", "(K, V)*"))), Some("Map[K, V]")) - val emptySignature = S("empty", List("K", "V"), Nil, Some("Map[K, V]")) + val applySignature = S("apply", List(List(TP("K"), TP("V")), List(P("elems", "(K, V)*"))), Some("Map[K, V]")) + val emptySignature = S("empty", List(List(TP("K"), TP("V"))), Some("Map[K, V]")) code"""object O: | Map[$m1] | Map.empty[$m2] @@ -56,7 +39,7 @@ class SignatureHelpTest { } @Test def classTypeParameter: Unit = { - val signature = S("Test", List("K", "V"), Nil, Some("Test")) + val signature = S("Test", List(List(TP("K"), TP("V"))), Some("Test")) code"""object O: | class Test[K, V] {} | new Test[$m1] @@ -67,7 +50,7 @@ class SignatureHelpTest { } @Test def traitTypeParameter: Unit = { - val signature = S("Test", List("K", "V"), Nil, Some("Test")) + val signature = S("Test", List(List(TP("K"), TP("V"))), Some("Test")) code"""object O: | trait Test[K, V] {} | new Test[$m1] {} @@ -78,7 +61,7 @@ class SignatureHelpTest { } @Test def typeAliasTypeParameter: Unit = { - val signature = S("Test", List("K"), Nil, Some("Test")) + val signature = S("Test", List(List(TP("K"))), Some("Test")) code"""object O: | type Test[K] = List[K] | def test(x: Test[$m1]) @@ -87,7 +70,7 @@ class SignatureHelpTest { } @Test def typeParameterIndex: Unit = { - val mapSignature = S("map", List("B"), List(List(P("f", "Int => B"))), Some("List[B]")) + val mapSignature = S("map", List(List(TP("B")), List(P("f", "Int => B"))), Some("List[B]")) code"""object O { List(1, 2, 3).map[$m1]($m2) }""" @@ -96,18 +79,18 @@ class SignatureHelpTest { } @Test def partialyFailedCurriedFunctions: Unit = { - val listSignature = S("curry", Nil, List(List(P("a", "Int"), P("b", "Int")), List(P("c", "Int"))), Some("Int")) + val listSignature = S("curry", List(List(P("a", "Int"), P("b", "Int")), List(P("c", "Int"))), Some("Int")) code"""object O { |def curry(a: Int, b: Int)(c: Int) = a | curry(1$m1)$m2(3$m3) |}""" .signatureHelp(m1, List(listSignature), Some(0), 0) - .signatureHelp(m2, List(listSignature), Some(0), 0) + .signatureHelp(m2, List(listSignature), Some(0), 2) .signatureHelp(m3, List(listSignature), Some(0), 2) } @Test def optionProperSignature: Unit = { - val signature = S("apply", List("A"), List(List(P("x", "A"))), Some("Option[A]")) + val signature = S("apply", List(List(TP("A")), List(P("x", "A"))), Some("Option[A]")) code"""object O { | Option(1, 2, 3, $m1) |}""" @@ -123,8 +106,8 @@ class SignatureHelpTest { } @Test def fromScala2: Unit = { - val applySig = S("apply", List("A"), List(List(P("elems", "A*"))), Some("List[A]")) - val mapSig = S("map", List("B"), List(List(P("f", "Int => B"))), Some("List[B]")) + val applySig = S("apply", List(List(TP("A")), List(P("elems", "A*"))), Some("List[A]")) + val mapSig = S("map", List(List(TP("B")), List(P("f", "Int => B"))), Some("List[B]")) code"""object O { List($m1) List(1, 2, 3).map($m2) @@ -134,14 +117,14 @@ class SignatureHelpTest { } @Test def typeParameterMethodApply: Unit = { - val testSig = S("method", Nil, List(List()), Some("Int")) + val testSig = S("method", List(List()), Some("Int")) code"""case class Foo[A](test: A) { | def method(): A = ??? |} |object O { | Foo(5).method($m1) |}""" - .signatureHelp(m1, List(testSig), Some(0), 0) + .signatureHelp(m1, List(testSig), Some(0), -1) } @Test def unapplyBooleanReturn: Unit = { @@ -153,11 +136,11 @@ class SignatureHelpTest { | case s @ Even(${m1}) => println(s"s has an even number of characters") | case s => println(s"s has an odd number of characters") """ - .signatureHelp(m1, Nil, Some(0), 0) + .signatureHelp(m1, Nil, Some(0), -1) } @Test def unapplyCustomClass: Unit = { - val signature = S("", Nil, List(List(P("", "Int"))), None) + val signature = S("", List(List(P("", "Int"))), None) code"""class Nat(val x: Int): | def get: Int = x @@ -174,7 +157,7 @@ class SignatureHelpTest { } @Test def unapplyTypeClass: Unit = { - val signature = S("", Nil, List(List(P("", "Int"), P("", "String"))), None) + val signature = S("", List(List(P("", "Int"), P("", "String"))), None) code"""class Two[A, B](a: A, b: B) |object Two { @@ -192,9 +175,9 @@ class SignatureHelpTest { } @Test def nestedUnapplySignature: Unit = { - val signatureOneTwo = S("", Nil, List(List(P("a", "One"), P("b", "Two"))), None) - val signatureOne = S("", Nil, List(List(P("c", "Int"))), None) - val signatureTwo = S("", Nil, List(List(P("d", "Int"))), None) + val signatureOneTwo = S("", List(List(P("a", "One"), P("b", "Two"))), None) + val signatureOne = S("", List(List(P("c", "Int"))), None) + val signatureTwo = S("", List(List(P("d", "Int"))), None) code"""case class One(c: Int) |case class Two(d: Int) @@ -216,7 +199,7 @@ class SignatureHelpTest { } @Test def properParameterIndexTest: Unit = { - val signature = S("", Nil, List(List(P("a", "Int"), P("b", "String"))), None) + val signature = S("", List(List(P("a", "Int"), P("b", "String"))), None) code"""case class Two(a: Int, b: String) | |object Main { @@ -226,13 +209,13 @@ class SignatureHelpTest { | } |}""" .signatureHelp(m1, List(signature), Some(0), 0) - .signatureHelp(m2, List(signature), Some(0), -1) - .signatureHelp(m3, List(signature), Some(0), -1) - .signatureHelp(m4, List(signature), Some(0), -1) + .signatureHelp(m2, List(signature), Some(0), 1) + .signatureHelp(m3, List(signature), Some(0), 1) + .signatureHelp(m4, List(), Some(0), 0) } @Test def unapplyClass: Unit = { - val signature = S("", Nil, List(List(P("", "Int"), P("", "String"))), None) + val signature = S("", List(List(P("", "Int"), P("", "String"))), None) code"""class Two(a: Int, b: String) |object Two { @@ -250,7 +233,7 @@ class SignatureHelpTest { } @Test def productMatch: Unit = { - val signature = S("", Nil, List(List(P("", "Char"), P("", "Char"))), None) + val signature = S("", List(List(P("", "Char"), P("", "Char"))), None) code"""class FirstChars(s: String) extends Product: | def _1 = s.charAt(0) @@ -268,7 +251,7 @@ class SignatureHelpTest { } @Test def noUnapplySignatureWhenApplyingUnapply: Unit = { - val signature = S("unapply", List("A"), List(List(P("a", "A"))), Some("Some[(A, A)]")) + val signature = S("unapply", List(List(TP("A")), List(P("a", "A"))), Some("Some[(A, A)]")) code""" |object And { @@ -282,7 +265,7 @@ class SignatureHelpTest { } @Test def nestedOptionReturnedInUnapply: Unit = { - val signature = S("", Nil, List(List(P("", "Option[Int]"))), None) + val signature = S("", List(List(P("", "Option[Int]"))), None) code"""object OpenBrowserCommand { | def unapply(command: String): Option[Option[Int]] = { @@ -298,8 +281,8 @@ class SignatureHelpTest { } @Test def unknownTypeUnapply: Unit = { - val signature = S("", Nil, List(List(P("a", "A"), P("b", "B"))), None) - val signature2 = S("", Nil, List(List(P("a", "Int"), P("b", "Any"))), None) + val signature = S("", List(List(P("a", "A"), P("b", "B"))), None) + val signature2 = S("", List(List(P("a", "Int"), P("b", "Any"))), None) code"""case class Two[A, B](a: A, b: B) |object Main { @@ -318,24 +301,22 @@ class SignatureHelpTest { } @Test def sequenceMatchUnapply: Unit = { - val signatureSeq = S("", Nil, List(List(P("", "Seq[Int]"))), None) - val signatureVariadicExtractor = S("", Nil, List(List(P("", "Int"), P("","List[Int]"))), None) + val signatureSeq = S("", List(List(P("", "Seq[Int]"))), None) + val signatureVariadicExtractor = S("", List(List(P("", "Int"), P("","List[Int]"))), None) code"""case class Two[A, B](a: A, b: B) |object Main { | Seq(1,2,3) match { | case Seq($m1) => - | case h$m2 :: t$m3 => + | case h :: t => | } |} """ .signatureHelp(m1, List(signatureSeq), Some(0), 0) - .signatureHelp(m2, List(signatureVariadicExtractor), Some(0), 0) - .signatureHelp(m3, List(signatureVariadicExtractor), Some(0), 1) } @Test def productTypeClassMatch: Unit = { - val signature = S("", Nil, List(List(P("", "String"), P("", "String"))), None) + val signature = S("", List(List(P("", "String"), P("", "String"))), None) code"""class FirstChars[A](s: A) extends Product: | def _1 = s @@ -353,8 +334,8 @@ class SignatureHelpTest { } @Test def nameBasedMatch: Unit = { - val nameBasedMatch = S("", Nil, List(List(P("", "Int"), P("", "String"))), None) - val singleMatch = S("", Nil, List(List(P("", "ProdEmpty.type"))), None) + val nameBasedMatch = S("", List(List(P("", "Int"), P("", "String"))), None) + val singleMatch = S("", List(List(P("", "ProdEmpty.type"))), None) code"""object ProdEmpty: | def _1: Int = ??? @@ -375,8 +356,8 @@ class SignatureHelpTest { } @Test def nameBasedMatchWithWrongGet: Unit = { - val nameBasedMatch = S("", Nil, List(List(P("", "Int"))), None) - val singleMatch = S("", Nil, List(List(P("", "Int"))), None) + val nameBasedMatch = S("", List(List(P("", "Int"))), None) + val singleMatch = S("", List(List(P("", "Int"))), None) code"""object ProdEmpty: | def _1: Int = ??? @@ -392,12 +373,12 @@ class SignatureHelpTest { | case _ => () """ .signatureHelp(m1, List(nameBasedMatch), Some(0), 0) - .signatureHelp(m2, List(nameBasedMatch), Some(0), -1) + .signatureHelp(m2, List(nameBasedMatch), Some(0), 0) .signatureHelp(m3, List(singleMatch), Some(0), 0) } @Test def nameBasedSingleMatchOrder: Unit = { - val signature = S("", Nil, List(List(P("", "String"))), None) + val signature = S("", List(List(P("", "String"))), None) code"""object ProdEmpty: | def _1: Int = 1 @@ -414,7 +395,7 @@ class SignatureHelpTest { } @Test def getObjectMatch: Unit = { - val signature = S("", Nil, List(List(P("", "String"))), None) + val signature = S("", List(List(P("", "String"))), None) code"""object ProdEmpty: | def isEmpty = true @@ -430,7 +411,7 @@ class SignatureHelpTest { } @Test def customSequenceMatch: Unit = { - val signature = S("", Nil, List(List(P("", "Seq[Char]"))), None) + val signature = S("", List(List(P("", "Seq[Char]"))), None) code"""object CharList: | def unapplySeq(s: String): Option[Seq[Char]] = Some(s.toList) @@ -448,7 +429,7 @@ class SignatureHelpTest { } @Test def productSequenceMatch: Unit = { - val signature = S("", Nil, List(List(P("", "String"), P("", "Seq[Int]"))), None) + val signature = S("", List(List(P("", "String"), P("", "Seq[Int]"))), None) code"""class Foo(val name: String, val children: Int*) |object Foo: @@ -468,7 +449,7 @@ class SignatureHelpTest { } @Test def productSequenceMatchForCaseClass: Unit = { - val signature = S("", Nil, List(List(P("name", "String"), P("children", "Seq[Int]"))), None) + val signature = S("", List(List(P("name", "String"), P("children", "Seq[Int]"))), None) code"""case class Foo(val name: String, val children: Int*) | @@ -485,7 +466,7 @@ class SignatureHelpTest { } @Test def unapplyManyType: Unit = { - val signature = S("", Nil, List(List(P("", "Int"), P("", "String"))), None) + val signature = S("", List(List(P("", "Int"), P("", "String"))), None) code""" |object Opt { @@ -502,7 +483,7 @@ class SignatureHelpTest { } @Test def unapplyTypeCaseClass: Unit = { - val signature = S("", Nil, List(List(P("a", "Int"), P("b", "String"))), None) + val signature = S("", List(List(P("a", "Int"), P("b", "String"))), None) code"""case class Two[A, B](a: A, b: B) | @@ -517,7 +498,7 @@ class SignatureHelpTest { } @Test def unapplyForTuple: Unit = { - val signature = S("", Nil, List(List(P("", "Int"), P("", "Int"))), None) + val signature = S("", List(List(P("", "Int"), P("", "Int"))), None) code"""object Main { | (1, 2) match | case (x${m1}, ${m2}) => @@ -527,7 +508,7 @@ class SignatureHelpTest { } @Test def unapplyCaseClass: Unit = { - val signature = S("", Nil, List(List(P("a", "Int"), P("b", "String"))), None) + val signature = S("", List(List(P("a", "Int"), P("b", "String"))), None) code"""case class Two(a: Int, b: String) | @@ -542,7 +523,7 @@ class SignatureHelpTest { } @Test def unapplyOption: Unit = { - val signature = S("", Nil, List(List(P("", "Int"))), None) + val signature = S("", List(List(P("", "Int"))), None) code"""|object Main { | Option(1) match { @@ -553,7 +534,7 @@ class SignatureHelpTest { } @Test def unapplyWithImplicits: Unit = { - val signature = S("", Nil, List(List(P("", "Int"))), None) + val signature = S("", List(List(P("", "Int"))), None) code"""| |object Opt: | def unapply[A](using String)(a: Option[A])(using Int) = a @@ -570,7 +551,7 @@ class SignatureHelpTest { } @Test def unapplyWithMultipleImplicits: Unit = { - val signature = S("", Nil, List(List(P("", "Int"))), None) + val signature = S("", List(List(P("", "Int"))), None) code"""| |object Opt: | def unapply[A](using String)(using Int)(a: Option[A]) = a @@ -587,15 +568,10 @@ class SignatureHelpTest { /** Implicit parameter lists consisting solely of DummyImplicits are hidden. */ @Test def hiddenDummyParams: Unit = { - val foo1Sig = - S("foo1", Nil, List(List(P("param0", "Int"))), Some("Int")) - val foo2Sig = - S("foo2", Nil, List(List(P("param0", "Int"))), Some("Int")) - val foo3Sig = - S("foo3", Nil, List(List(P("param0", "Int")), - List(P("dummy", "DummyImplicit"))), Some("Int")) - val foo4Sig = - S("foo4", Nil, List(List(P("param0", "Int")), + val foo1Sig = S("foo1", List(List(P("param0", "Int"))), Some("Int")) + val foo2Sig = S("foo2", List(List(P("param0", "Int"))), Some("Int")) + val foo3Sig = S("foo3", List(List(P("param0", "Int")), List(P("dummy", "DummyImplicit"))), Some("Int")) + val foo4Sig = S("foo4", List(List(P("param0", "Int")), List(P("x", "Int", isImplicit = true), P("dummy", "DummyImplicit", isImplicit = true))), Some("Int")) code"""object O { def foo1(param0: Int)(implicit dummy: DummyImplicit): Int = ??? @@ -615,7 +591,7 @@ class SignatureHelpTest { @Test def singleParam: Unit = { val signature = - S("foo", Nil, List(List(P("param0", "Int"))), Some("Int")) + S("foo", List(List(P("param0", "Int"))), Some("Int")) code"""object O { def foo(param0: Int): Int = ??? foo($m1) @@ -626,7 +602,7 @@ class SignatureHelpTest { } @Test def twoParams: Unit = { - val signature = S("foo", Nil, List(List(P("param0", "Int"), P("param1", "String"))), Some("Int")) + val signature = S("foo", List(List(P("param0", "Int"), P("param1", "String"))), Some("Int")) code"""object O { def foo(param0: Int, param1: String): Int = ??? foo($m1) @@ -639,8 +615,8 @@ class SignatureHelpTest { } @Test def noMatchingOverload: Unit = { - val sig0 = S("foo", Nil, List(List(P("param0", "Int"))), Some("Nothing")) - val sig1 = S("foo", Nil, List(List(P("param1", "String"))), Some("Nothing")) + val sig0 = S("foo", List(List(P("param0", "Int"))), Some("Nothing")) + val sig1 = S("foo", List(List(P("param1", "String"))), Some("Nothing")) code"""object O { def foo(param0: Int): Nothing = ??? @@ -655,8 +631,8 @@ class SignatureHelpTest { } @Test def singleMatchingOverload: Unit = { - val sig0 = S("foo", Nil, List(List(P("param0", "Int"), P("param1", "String"))), Some("Nothing")) - val sig1 = S("foo", Nil, List(List(P("param0", "String"), P("param1", "Int"))), Some("Nothing")) + val sig0 = S("foo", List(List(P("param0", "Int"), P("param1", "String"))), Some("Nothing")) + val sig1 = S("foo", List(List(P("param0", "String"), P("param1", "Int"))), Some("Nothing")) code"""object O { def foo(param0: Int, param1: String): Nothing = ??? def foo(param0: String, param1: Int): Nothing = ??? @@ -674,9 +650,9 @@ class SignatureHelpTest { } @Test def multipleMatchingOverloads: Unit = { - val sig0 = S("foo", Nil, List(List(P("param0", "Int"), P("param1", "Int"))), Some("Nothing")) - val sig1 = S("foo", Nil, List(List(P("param0", "Int"), P("param1", "Boolean"))), Some("Nothing")) - val sig2 = S("foo", Nil, List(List(P("param0", "String"), P("param1", "Int"))), Some("Nothing")) + val sig0 = S("foo", List(List(P("param0", "Int"), P("param1", "Int"))), Some("Nothing")) + val sig1 = S("foo", List(List(P("param0", "Int"), P("param1", "Boolean"))), Some("Nothing")) + val sig2 = S("foo", List(List(P("param0", "String"), P("param1", "Int"))), Some("Nothing")) val sigs = List(sig0, sig1, sig2) code"""object O { def foo(param0: Int, param1: Int): Nothing = ??? @@ -702,8 +678,8 @@ class SignatureHelpTest { } @Test def ambiguousOverload: Unit = { - val sig0 = S("foo", Nil, List(List(P("param0", "String")), List(P("param1", "String"))), Some("Nothing")) - val sig1 = S("foo", Nil, List(List(P("param0", "String"))), Some("Nothing")) + val sig0 = S("foo", List(List(P("param0", "String")), List(P("param1", "String"))), Some("Nothing")) + val sig1 = S("foo", List(List(P("param0", "String"))), Some("Nothing")) code"""object O { def foo(param0: String)(param1: String): Nothing = ??? def foo(param0: String): Nothing = ??? @@ -713,13 +689,12 @@ class SignatureHelpTest { }""" .signatureHelp(m1, List(sig0, sig1), None, 0) .signatureHelp(m2, List(sig0, sig1), None, 0) - .signatureHelp(m3, List(sig0, sig1), Some(1), 1) + .signatureHelp(m3, List(sig0, sig1), Some(0), 1) } @Test def multipleParameterLists: Unit = { val signature = S("foo", - Nil, List( List(P("param0", "Int"), P("param1", "Int")), List(P("param2", "Int")), @@ -744,7 +719,6 @@ class SignatureHelpTest { @Test def implicitParams: Unit = { val signature = S("foo", - Nil, List( List(P("param0", "Int"), P("param1", "Int")), List(P("param2", "Int", isImplicit = true)) @@ -764,8 +738,8 @@ class SignatureHelpTest { @Test def typeParameters: Unit = { val signature = S("foo", - List("M[X]", "T[Z] <: M[Z]", "U >: T"), List( + List(TP("M[X]"), TP("T[Z] <: M[Z]"), TP("U >: T")), List(P("p0", "M[Int]"), P("p1", "T[Int]"), P("p2", "U")) ), Some("Int")) @@ -779,7 +753,6 @@ class SignatureHelpTest { @Test def constructorCall: Unit = { val signature = S("Foo", - Nil, List( List(P("x", "Int"), P("y", "String")), List(P("z", "String")) @@ -799,7 +772,6 @@ class SignatureHelpTest { @Test def overloadedConstructorCall: Unit = { val sig0 = S("Foo", - Nil, List( List(P("x", "Int"), P("y", "String")), List(P("z", "Int")) @@ -807,7 +779,6 @@ class SignatureHelpTest { None) val sig1 = S("Foo", - Nil, List( List(P("x", "Int"), P("y", "Int")) ), @@ -829,8 +800,8 @@ class SignatureHelpTest { @Test def constructorCallDoc: Unit = { val signatures = List( - S("Foo", Nil, List(List(P("x", "Int", Some("An int")), P("y", "String", Some("A string")))), None, Some("A Foo")), - S("Foo", Nil, List(List(P("z", "Boolean", Some("A boolean")), P("foo", "Foo", Some("A Foo")))), None, Some("An alternative constructor for Foo")) + S("Foo", List(List(P("x", "Int", Some("An int")), P("y", "String", Some("A string")))), None, Some("A Foo")), + S("Foo", List(List(P("z", "Boolean", Some("A boolean")), P("foo", "Foo", Some("A Foo")))), None, Some("An alternative constructor for Foo")) ) code"""/** @@ -869,8 +840,8 @@ class SignatureHelpTest { @Test def classTypeParameters: Unit = { val signature = S("Foo", - List("M[X]", "T[Z] <: M[Z]", "U"), List( + List(TP("M[X]"), TP("T[Z] <: M[Z]"), TP("U")), List(P("p0", "M[Int]"), P("p1", "T[Int]"), P("p2", "U")), List(P("p3", "Int")) ), @@ -893,7 +864,7 @@ class SignatureHelpTest { /** Hello, world! */ def foo(param0: Int): Int = 0 foo($m1) }""" - .signatureHelp(m1, List(S("foo", Nil, List(List(P("param0", "Int"))), Some("Int"), Some("Hello, world!"))), None, 0) + .signatureHelp(m1, List(S("foo", List(List(P("param0", "Int"))), Some("Int"), Some("Hello, world!"))), None, 0) } @Test def showParamDoc: Unit = { @@ -909,7 +880,7 @@ class SignatureHelpTest { | buzz($m1) |}""" .signatureHelp(m1, List( - S("buzz", Nil, List(List( + S("buzz", List(List( P("fizz", "Int", Some("The fizz to buzz")), P("bar", "Int", Some("Buzzing limit")) )), Some("Int"), Some("Buzzes a fizz up to bar")) @@ -918,9 +889,9 @@ class SignatureHelpTest { @Test def nestedApplySignatures: Unit = { val signatures = (1 to 5).map { i => - S(s"foo$i", Nil, List(List(P("x", "Int"))), Some("Int")) + S(s"foo$i", List(List(P("x", "Int"))), Some("Int")) } - val booSignature = S(s"boo", Nil, List(List(P("x", "Int"), P("y", "Int"))), Some("Int")) + val booSignature = S(s"boo", List(List(P("x", "Int"), P("y", "Int"))), Some("Int")) code"""|object O: | def foo1(x: Int): Int = ??? | def foo2(x: Int): Int = ??? @@ -939,8 +910,8 @@ class SignatureHelpTest { } @Test def multipleNestedApplySignatures: Unit = { - val simpleSignature = S(s"simpleFoo", Nil, List(List(P("x", "Int"))), Some("Int")) - val complicatedSignature = S(s"complicatedFoo", Nil, List(List(P("x", "Int"), P("y", "Int"), P("z", "Int"))), Some("Int")) + val simpleSignature = S(s"simpleFoo", List(List(P("x", "Int"))), Some("Int")) + val complicatedSignature = S(s"complicatedFoo", List(List(P("x", "Int"), P("y", "Int"), P("z", "Int"))), Some("Int")) code"""|object O: | def simpleFoo(x: Int): Int = ??? | def complicatedFoo(x: Int, y: Int, z: Int): Int = ??? @@ -966,7 +937,7 @@ class SignatureHelpTest { } @Test def noHelpSignatureWithPositionedOnName: Unit = { - val signature = S(s"foo", Nil, List(List(P("x", "Int"))), Some("Int")) + val signature = S(s"foo", List(List(P("x", "Int"))), Some("Int")) code"""|object O: | def foo(x: Int): Int = ??? | f${m1}oo(${m2})""" @@ -974,4 +945,13 @@ class SignatureHelpTest { .signatureHelp(m2, List(signature), None, 0) } + @Test def instantiatedTypeVarInOldExtensionMethods: Unit = { + val signature = S(s"test", List(List(P("x", "Int"))), Some("List[Int]")) + code"""|object O: + | implicit class TypeVarTest[T](xs: List[T]): + | def test(x: T): List[T] = ??? + | List(1,2,3).test(${m1})""" + .signatureHelp(m1, List(signature), None, 0) + } + } diff --git a/library/src/scala/annotation/MacroAnnotation.scala b/library/src/scala/annotation/MacroAnnotation.scala index 999bc3095a69..a76289ecea61 100644 --- a/library/src/scala/annotation/MacroAnnotation.scala +++ b/library/src/scala/annotation/MacroAnnotation.scala @@ -25,7 +25,7 @@ trait MacroAnnotation extends StaticAnnotation: * #### Restrictions * - All definitions in the result must have the same owner. The owner can be recovered from `Symbol.spliceOwner`. * - Special case: an annotated top-level `def`, `val`, `var`, `lazy val` can return a `class`/`object` -definition that is owned by the package or package object. + * definition that is owned by the package or package object. * - Can not return a `type`. * - Annotated top-level `class`/`object` can not return top-level `def`, `val`, `var`, `lazy val`. * - Can not see new definition in user written code. diff --git a/library/src/scala/annotation/internal/reach.scala b/library/src/scala/annotation/internal/reachCapability.scala similarity index 100% rename from library/src/scala/annotation/internal/reach.scala rename to library/src/scala/annotation/internal/reachCapability.scala diff --git a/library/src/scala/annotation/retains.scala b/library/src/scala/annotation/retains.scala index 0387840ea8bd..4fa14e635136 100644 --- a/library/src/scala/annotation/retains.scala +++ b/library/src/scala/annotation/retains.scala @@ -13,3 +13,11 @@ package scala.annotation */ @experimental class retains(xs: Any*) extends annotation.StaticAnnotation + +/** Equivalent in meaning to `@retains(cap)`, but consumes less bytecode. + */ +@experimental +class retainsCap() extends annotation.StaticAnnotation + // This special case is needed to be able to load standard library modules without + // cyclic reference errors. Specifically, load sequences involving IterableOnce. + diff --git a/library/src/scala/quoted/Quotes.scala b/library/src/scala/quoted/Quotes.scala index f496d9cae2b2..fa96b73551d1 100644 --- a/library/src/scala/quoted/Quotes.scala +++ b/library/src/scala/quoted/Quotes.scala @@ -1637,10 +1637,11 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching => * val q: Quotes = summon[Quotes] * import q.reflect._ * //} - * val intArgs = List(Literal(Constant(1)), Literal(Constant(2))) + * val intArgs = List(Literal(IntConstant(1)), Literal(IntConstant(2))) * Typed( - * Repeated(intArgs, TypeTree.of[Int]), - * Inferred(defn.RepeatedParamClass.typeRef.appliedTo(TypeRepr.of[Int])) + * Repeated(intArgs, TypeTree.of[Int]), + * Inferred(defn.RepeatedParamClass.typeRef.appliedTo(TypeRepr.of[Int])) + * ) * //{ * } * //} diff --git a/library/src/scala/runtime/stdLibPatches/language.scala b/library/src/scala/runtime/stdLibPatches/language.scala index c0dd8a74419e..70d5f2d41907 100644 --- a/library/src/scala/runtime/stdLibPatches/language.scala +++ b/library/src/scala/runtime/stdLibPatches/language.scala @@ -13,7 +13,7 @@ object language: * code should not rely on them. * * Programmers are encouraged to try out experimental features and - * [[http://issues.scala-lang.org report any bugs or API inconsistencies]] + * [[https://github.com/scala/scala3/issues report any bugs or API inconsistencies]] * they encounter so they can be improved in future releases. * * @group experimental diff --git a/library/src/scala/util/boundary.scala b/library/src/scala/util/boundary.scala index 2edd754bbb93..3039fc70be90 100644 --- a/library/src/scala/util/boundary.scala +++ b/library/src/scala/util/boundary.scala @@ -15,14 +15,16 @@ import scala.annotation.implicitNotFound * be rewritten to jumps. * * Example usage: + * + * ```scala + * import scala.util.boundary, boundary.break * - * import scala.util.boundary, boundary.break - * - * def firstIndex[T](xs: List[T], elem: T): Int = - * boundary: - * for (x, i) <- xs.zipWithIndex do - * if x == elem then break(i) - * -1 + * def firstIndex[T](xs: List[T], elem: T): Int = + * boundary: + * for (x, i) <- xs.zipWithIndex do + * if x == elem then break(i) + * -1 + * ``` */ object boundary: diff --git a/presentation-compiler/src/main/dotty/tools/pc/CompilerSearchVisitor.scala b/presentation-compiler/src/main/dotty/tools/pc/CompilerSearchVisitor.scala index d217a0acd9b1..231960ec5116 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/CompilerSearchVisitor.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/CompilerSearchVisitor.scala @@ -9,6 +9,7 @@ import scala.meta.pc.* import scala.util.control.NonFatal import dotty.tools.dotc.core.Contexts.* +import dotty.tools.dotc.core.Flags import dotty.tools.dotc.core.Names.* import dotty.tools.dotc.core.Symbols.* @@ -19,8 +20,14 @@ class CompilerSearchVisitor( val logger: Logger = Logger.getLogger(classOf[CompilerSearchVisitor].getName().nn).nn + private def isAccessibleImplicitClass(sym: Symbol) = + val owner = sym.maybeOwner + owner != NoSymbol && owner.isClass && + owner.is(Flags.Implicit) && + owner.isStatic && owner.isPublic + private def isAccessible(sym: Symbol): Boolean = try - sym != NoSymbol && sym.isPublic && sym.isStatic + sym != NoSymbol && sym.isPublic && sym.isStatic || isAccessibleImplicitClass(sym) catch case err: AssertionError => logger.log(Level.WARNING, err.getMessage()) @@ -51,6 +58,7 @@ class CompilerSearchVisitor( .filter(denot => denot.exists) .map(_.symbol) .filter(isAccessible) + .filter(!_.is(Flags.Given)) } loop(next, tl) case Nil => owners diff --git a/presentation-compiler/src/main/dotty/tools/pc/ConvertToNamedArgumentsProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/ConvertToNamedArgumentsProvider.scala index 817ab5402c00..00bfe17cb21b 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/ConvertToNamedArgumentsProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/ConvertToNamedArgumentsProvider.scala @@ -35,7 +35,7 @@ final class ConvertToNamedArgumentsProvider( val tree = Interactive.pathTo(trees, pos)(using newctx).headOption def paramss(fun: tpd.Tree)(using Context): List[String] = - fun.tpe match + fun.typeOpt match case m: MethodType => m.paramNamess.flatten.map(_.toString) case _ => fun.symbol.rawParamss.flatten diff --git a/presentation-compiler/src/main/dotty/tools/pc/ExtractMethodProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/ExtractMethodProvider.scala index 0b5fd1b06a8f..55c4e4d9e4b6 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/ExtractMethodProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/ExtractMethodProvider.scala @@ -128,7 +128,7 @@ final class ExtractMethodProvider( yield val defnPos = stat.sourcePos val extractedPos = head.sourcePos.withEnd(expr.sourcePos.end) - val exprType = prettyPrint(expr.tpe.widen) + val exprType = prettyPrint(expr.typeOpt.widen) val name = genName(indexedCtx.scopeSymbols.map(_.decodedName).toSet, "newMethod") val (methodParams, typeParams) = diff --git a/presentation-compiler/src/main/dotty/tools/pc/HoverProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/HoverProvider.scala index 545607c0b8ff..6f39b4871a06 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/HoverProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/HoverProvider.scala @@ -36,16 +36,20 @@ object HoverProvider: val text = params.text().nn val sourceFile = SourceFile.virtual(uri, text) driver.run(uri, sourceFile) + val unit = driver.compilationUnits.get(uri) - given ctx: Context = driver.currentCtx + given ctx: Context = + val ctx = driver.currentCtx + unit.map(ctx.fresh.setCompilationUnit).getOrElse(ctx) val pos = driver.sourcePosition(params) - val trees = driver.openedTrees(uri) + val path = unit + .map(unit => Interactive.pathTo(unit.tpdTree, pos.span)) + .getOrElse(Interactive.pathTo(driver.openedTrees(uri), pos)) val indexedContext = IndexedContext(ctx) def typeFromPath(path: List[Tree]) = - if path.isEmpty then NoType else path.head.tpe + if path.isEmpty then NoType else path.head.typeOpt - val path = Interactive.pathTo(trees, pos) val tp = typeFromPath(path) val tpw = tp.widenTermRefExpr // For expression we need to find all enclosing applies to get the exact generic type @@ -72,7 +76,10 @@ object HoverProvider: |path: |- ${path.map(_.toString()).mkString("\n- ")} |trees: - |- ${trees.map(_.toString()).mkString("\n- ")} + |- ${unit + .map(u => List(u.tpdTree)) + .getOrElse(driver.openedTrees(uri).map(_.tree)) + .map(_.toString()).mkString("\n- ")} |""".stripMargin, s"$uri::$posId" ) @@ -83,15 +90,9 @@ object HoverProvider: val skipCheckOnName = !pos.isPoint // don't check isHoveringOnName for RangeHover - val printerContext = - driver.compilationUnits.get(uri) match - case Some(unit) => - val newctx = - ctx.fresh.setCompilationUnit(unit) - Interactive.contextOfPath(enclosing)(using newctx) - case None => ctx + val printerCtx = Interactive.contextOfPath(path) val printer = ShortenedTypePrinter(search, IncludeDefaultParam.Include)( - using IndexedContext(printerContext) + using IndexedContext(printerCtx) ) MetalsInteractive.enclosingSymbolsWithExpressionType( enclosing, @@ -108,7 +109,7 @@ object HoverProvider: val exprTpw = tpe.widenTermRefExpr.metalsDealias val hoverString = tpw match - // https://github.com/lampepfl/dotty/issues/8891 + // https://github.com/scala/scala3/issues/8891 case tpw: ImportType => printer.hoverSymbol(symbol, symbol.paramRef) case _ => @@ -142,7 +143,8 @@ object HoverProvider: expressionType = Some(expressionType), symbolSignature = Some(hoverString), docstring = Some(docString), - forceExpressionType = forceExpressionType + forceExpressionType = forceExpressionType, + contextInfo = printer.getUsedRenamesInfo ) ).nn case _ => @@ -176,13 +178,14 @@ object HoverProvider: new ScalaHover( expressionType = Some(tpeString), symbolSignature = Some(s"$valOrDef $name$tpeString"), + contextInfo = printer.getUsedRenamesInfo ) ) case RefinedType(parent, _, _) => findRefinement(parent) case _ => None - val refTpe = sel.tpe.widen.metalsDealias match + val refTpe = sel.typeOpt.widen.metalsDealias match case r: RefinedType => Some(r) case t: (TermRef | TypeProxy) => Some(t.termSymbol.info.metalsDealias) case _ => None diff --git a/presentation-compiler/src/main/dotty/tools/pc/IndexedContext.scala b/presentation-compiler/src/main/dotty/tools/pc/IndexedContext.scala index e31f4756b220..ad6fe9420a81 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/IndexedContext.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/IndexedContext.scala @@ -10,6 +10,7 @@ import dotty.tools.dotc.core.Names.* import dotty.tools.dotc.core.Scopes.EmptyScope import dotty.tools.dotc.core.Symbols.* import dotty.tools.dotc.core.Types.* +import dotty.tools.dotc.interactive.Interactive import dotty.tools.dotc.typer.ImportInfo import dotty.tools.pc.IndexedContext.Result import dotty.tools.pc.utils.MtagsEnrichments.* @@ -31,16 +32,33 @@ sealed trait IndexedContext: case Some(symbols) if symbols.exists(_ == sym) => Result.InScope case Some(symbols) - if symbols - .exists(s => isTypeAliasOf(s, sym) || isTermAliasOf(s, sym)) => - Result.InScope + if symbols.exists(s => isNotConflictingWithDefault(s, sym) || isTypeAliasOf(s, sym) || isTermAliasOf(s, sym)) => + Result.InScope // when all the conflicting symbols came from an old version of the file - case Some(symbols) if symbols.nonEmpty && symbols.forall(_.isStale) => - Result.Missing + case Some(symbols) if symbols.nonEmpty && symbols.forall(_.isStale) => Result.Missing case Some(_) => Result.Conflict case None => Result.Missing end lookupSym + /** + * Scala by default imports following packages: + * https://scala-lang.org/files/archive/spec/3.4/02-identifiers-names-and-scopes.html + * import java.lang.* + * { + * import scala.* + * { + * import Predef.* + * { /* source */ } + * } + * } + * + * This check is necessary for proper scope resolution, because when we compare symbols from + * index including the underlying type like scala.collection.immutable.List it actually + * is in current scope in form of type forwarder imported from Predef. + */ + private def isNotConflictingWithDefault(sym: Symbol, queriedSym: Symbol): Boolean = + sym.info.widenDealias =:= queriedSym.info.widenDealias && (Interactive.isImportedByDefault(sym)) + final def hasRename(sym: Symbol, as: String): Boolean = rename(sym) match case Some(v) => v == as @@ -49,15 +67,15 @@ sealed trait IndexedContext: // detects import scope aliases like // object Predef: // val Nil = scala.collection.immutable.Nil - private def isTermAliasOf(termAlias: Symbol, sym: Symbol): Boolean = + private def isTermAliasOf(termAlias: Symbol, queriedSym: Symbol): Boolean = termAlias.isTerm && ( - sym.info match + queriedSym.info match case clz: ClassInfo => clz.appliedRef =:= termAlias.info.resultType case _ => false ) - private def isTypeAliasOf(alias: Symbol, sym: Symbol): Boolean = - alias.isAliasType && alias.info.metalsDealias.typeSymbol == sym + private def isTypeAliasOf(alias: Symbol, queriedSym: Symbol): Boolean = + alias.isAliasType && alias.info.metalsDealias.typeSymbol == queriedSym final def isEmpty: Boolean = this match case IndexedContext.Empty => true diff --git a/presentation-compiler/src/main/dotty/tools/pc/InferredTypeProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/InferredTypeProvider.scala index 69d89d5b0d13..b37b1b6dff6c 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/InferredTypeProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/InferredTypeProvider.scala @@ -138,7 +138,7 @@ final class InferredTypeProvider( adjustOpt.foreach(adjust => endPos.setEnd(adjust.adjustedEndPos)) new TextEdit( endPos, - ": " + printType(optDealias(tpt.tpe)) + { + ": " + printType(optDealias(tpt.typeOpt)) + { if withParens then ")" else "" } ) @@ -211,7 +211,7 @@ final class InferredTypeProvider( adjustOpt.foreach(adjust => end.setEnd(adjust.adjustedEndPos)) new TextEdit( end, - ": " + printType(optDealias(tpt.tpe)) + ": " + printType(optDealias(tpt.typeOpt)) ) end typeNameEdit @@ -241,7 +241,7 @@ final class InferredTypeProvider( def baseEdit(withParens: Boolean) = new TextEdit( bind.endPos.toLsp, - ": " + printType(optDealias(body.tpe)) + { + ": " + printType(optDealias(body.typeOpt)) + { if withParens then ")" else "" } ) @@ -274,7 +274,7 @@ final class InferredTypeProvider( case Some(i @ Ident(name)) => val typeNameEdit = new TextEdit( i.endPos.toLsp, - ": " + printType(optDealias(i.tpe.widen)) + ": " + printType(optDealias(i.typeOpt.widen)) ) typeNameEdit :: imports diff --git a/presentation-compiler/src/main/dotty/tools/pc/MetalsInteractive.scala b/presentation-compiler/src/main/dotty/tools/pc/MetalsInteractive.scala index 076c1d9a9b88..381e0eaec6a5 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/MetalsInteractive.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/MetalsInteractive.scala @@ -1,19 +1,14 @@ -package dotty.tools.pc +package dotty.tools +package pc import scala.annotation.tailrec -import dotty.tools.dotc.ast.tpd -import dotty.tools.dotc.ast.tpd.* -import dotty.tools.dotc.ast.untpd -import dotty.tools.dotc.core.Contexts.* -import dotty.tools.dotc.core.Flags.* -import dotty.tools.dotc.core.Names.Name -import dotty.tools.dotc.core.StdNames -import dotty.tools.dotc.core.Symbols.* -import dotty.tools.dotc.core.Types.Type -import dotty.tools.dotc.interactive.SourceTree -import dotty.tools.dotc.util.SourceFile -import dotty.tools.dotc.util.SourcePosition +import dotc.* +import ast.*, tpd.* +import core.*, Contexts.*, Decorators.*, Flags.*, Names.*, Symbols.*, Types.* +import interactive.* +import util.* +import util.SourcePosition object MetalsInteractive: @@ -190,7 +185,7 @@ object MetalsInteractive: */ case (tpt: TypeTree) :: parent :: _ if tpt.span != parent.span && !tpt.symbol.is(Synthetic) => - List((tpt.symbol, tpt.tpe)) + List((tpt.symbol, tpt.typeOpt)) /* TypeTest class https://dotty.epfl.ch/docs/reference/other-new-features/type-test.html * compiler automatically adds unapply if possible, we need to find the type symbol @@ -205,7 +200,10 @@ object MetalsInteractive: Nil case path @ head :: tail => - if head.symbol.is(Synthetic) then + if head.symbol.is(Exported) then + val sym = head.symbol.sourceSymbol + List((sym, sym.info)) + else if head.symbol.is(Synthetic) then enclosingSymbolsWithExpressionType( tail, pos, @@ -222,7 +220,7 @@ object MetalsInteractive: then List((head.symbol, head.typeOpt)) /* Type tree for List(1) has an Int type variable, which has span * but doesn't exist in code. - * https://github.com/lampepfl/dotty/issues/15937 + * https://github.com/scala/scala3/issues/15937 */ else if head.isInstanceOf[TypeTree] then enclosingSymbolsWithExpressionType(tail, pos, indexed) diff --git a/presentation-compiler/src/main/dotty/tools/pc/PcCollector.scala b/presentation-compiler/src/main/dotty/tools/pc/PcCollector.scala index 310edd60d87e..60def237badb 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/PcCollector.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/PcCollector.scala @@ -57,13 +57,13 @@ abstract class PcCollector[T]( .pathTo(driver.openedTrees(uri), pos)(using driver.currentCtx) .dropWhile(t => // NamedArg anyway doesn't have symbol t.symbol == NoSymbol && !t.isInstanceOf[NamedArg] || - // same issue https://github.com/lampepfl/dotty/issues/15937 as below + // same issue https://github.com/scala/scala3/issues/15937 as below t.isInstanceOf[TypeTree] ) val path = rawPath match // For type it will sometimes go into the wrong tree since TypeTree also contains the same span - // https://github.com/lampepfl/dotty/issues/15937 + // https://github.com/scala/scala3/issues/15937 case TypeApply(sel: Select, _) :: tail if sel.span.contains(pos.span) => Interactive.pathTo(sel, pos.span) ::: rawPath case _ => rawPath @@ -583,7 +583,7 @@ abstract class PcCollector[T]( t } - // NOTE: Connected to https://github.com/lampepfl/dotty/issues/16771 + // NOTE: Connected to https://github.com/scala/scala3/issues/16771 // `sel.nameSpan` is calculated incorrectly in (1 + 2).toString // See test DocumentHighlightSuite.select-parentheses private def selectNameSpan(sel: Select): Span = diff --git a/presentation-compiler/src/main/dotty/tools/pc/PcDefinitionProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/PcDefinitionProvider.scala index f010c8b2d95a..0de81ec39711 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/PcDefinitionProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/PcDefinitionProvider.scala @@ -108,7 +108,7 @@ class PcDefinitionProvider( case Nil => path.headOption match case Some(value: Literal) => - definitionsForSymbol(List(value.tpe.widen.typeSymbol), pos) + definitionsForSymbol(List(value.typeOpt.widen.typeSymbol), pos) case _ => DefinitionResultImpl.empty case _ => definitionsForSymbol(typeSymbols, pos) @@ -124,7 +124,7 @@ class PcDefinitionProvider( val isLocal = sym.source == pos.source if isLocal then val defs = - Interactive.findDefinitions(List(sym), driver, false, false) + Interactive.findDefinitions(List(sym), driver, false, false).filter(_.source == sym.source) defs.headOption match case Some(srcTree) => val pos = srcTree.namePos diff --git a/presentation-compiler/src/main/dotty/tools/pc/PcSyntheticDecorationProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/PcSyntheticDecorationProvider.scala index 1ff410ad7f10..d810ce5b07cc 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/PcSyntheticDecorationProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/PcSyntheticDecorationProvider.scala @@ -39,6 +39,8 @@ final class PcSyntheticDecorationsProvider( val source = SourceFile.virtual(filePath.toString, sourceText) driver.run(uri, source) + + given InferredType.Text = InferredType.Text(text) given ctx: Context = driver.currentCtx val unit = driver.currentCtx.run.nn.units.head @@ -112,7 +114,7 @@ final class PcSyntheticDecorationsProvider( ): String = val tpdPath = Interactive.pathTo(unit.tpdTree, pos.span) - + val indexedCtx = IndexedContext(Interactive.contextOfPath(tpdPath)) val printer = ShortenedTypePrinter( symbolSearch @@ -208,7 +210,7 @@ object TypeParameters: case sel: Select if sel.isInfix => sel.sourcePos.withEnd(sel.nameSpan.end) case _ => fun.sourcePos - val tpes = args.map(_.tpe.stripTypeVar.widen.finalResultType) + val tpes = args.map(_.typeOpt.stripTypeVar.widen.finalResultType) Some((tpes, pos.endPos, fun)) case _ => None private def inferredTypeArgs(args: List[Tree]): Boolean = @@ -219,13 +221,18 @@ object TypeParameters: end TypeParameters object InferredType: - def unapply(tree: Tree)(using Context) = + opaque type Text = Array[Char] + object Text: + def apply(text: Array[Char]): Text = text + + def unapply(tree: Tree)(using text: Text, cxt: Context) = tree match case vd @ ValDef(_, tpe, _) if isValidSpan(tpe.span, vd.nameSpan) && - !vd.symbol.is(Flags.Enum) => + !vd.symbol.is(Flags.Enum) && + !isValDefBind(text, vd) => if vd.symbol == vd.symbol.sourceSymbol then - Some(tpe.tpe, tpe.sourcePos.withSpan(vd.nameSpan), vd) + Some(tpe.typeOpt, tpe.sourcePos.withSpan(vd.nameSpan), vd) else None case vd @ DefDef(_, _, tpe, _) if isValidSpan(tpe.span, vd.nameSpan) && @@ -233,7 +240,7 @@ object InferredType: !vd.symbol.isConstructor && !vd.symbol.is(Flags.Mutable) => if vd.symbol == vd.symbol.sourceSymbol then - Some(tpe.tpe, tpe.sourcePos, vd) + Some(tpe.typeOpt, tpe.sourcePos, vd) else None case bd @ Bind( name, @@ -247,6 +254,14 @@ object InferredType: nameSpan.exists && !nameSpan.isZeroExtent + /* If is left part of val definition bind: + * val <> @ ... = + */ + def isValDefBind(text: Text, vd: ValDef)(using Context) = + val afterDef = text.drop(vd.nameSpan.end) + val index = afterDef.indexAfterSpacesAndComments + index >= 0 && index < afterDef.size && afterDef(index) == '@' + end InferredType case class Synthetics( @@ -275,4 +290,4 @@ case class Synthetics( end Synthetics object Synthetics: - def empty: Synthetics = Synthetics(Nil, Set.empty) \ No newline at end of file + def empty: Synthetics = Synthetics(Nil, Set.empty) diff --git a/presentation-compiler/src/main/dotty/tools/pc/SemanticdbSymbols.scala b/presentation-compiler/src/main/dotty/tools/pc/SemanticdbSymbols.scala index c6e43186cef2..d298a88fc655 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/SemanticdbSymbols.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/SemanticdbSymbols.scala @@ -49,7 +49,16 @@ object SemanticdbSymbols: // however in scalac this method is defined only in `module Files` if typeSym.is(JavaDefined) then typeSym :: owner.info.decl(termName(value)).symbol :: Nil + /** + * Looks like decl doesn't work for: + * package a: + * implicit class <> (i: Int): + * def inc = i + 1 + */ + else if typeSym == NoSymbol then + owner.info.member(typeName(value)).symbol :: Nil else typeSym :: Nil + end if case Descriptor.Term(value) => val outSymbol = owner.info.decl(termName(value)).symbol if outSymbol.exists @@ -92,6 +101,8 @@ object SemanticdbSymbols: .map(_.symbol) .filter(sym => symbolName(sym) == s) .toList + end match + end tryMember parentSymbol.flatMap(tryMember) try @@ -107,8 +118,8 @@ object SemanticdbSymbols: b.toString /** - * Taken from https://github.com/lampepfl/dotty/blob/2db43dae1480825227eb30d291b0dd0f0494e0f6/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala#L293 - * In future might be replaced by usage of compiler implementation after merging https://github.com/lampepfl/dotty/pull/12885 + * Taken from https://github.com/scala/scala3/blob/2db43dae1480825227eb30d291b0dd0f0494e0f6/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala#L293 + * In future might be replaced by usage of compiler implementation after merging https://github.com/scala/scala3/pull/12885 */ private def addSymName(b: StringBuilder, sym: Symbol)(using Context): Unit = diff --git a/presentation-compiler/src/main/dotty/tools/pc/SignatureHelpProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/SignatureHelpProvider.scala index bfaa56138547..f7797efbfb27 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/SignatureHelpProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/SignatureHelpProvider.scala @@ -1,134 +1,149 @@ package dotty.tools.pc -import scala.jdk.CollectionConverters._ -import scala.meta.pc.OffsetParams -import scala.meta.pc.SymbolDocumentation -import scala.meta.pc.SymbolSearch - -import dotty.tools.dotc.ast.Trees.AppliedTypeTree -import dotty.tools.dotc.ast.Trees.TypeApply -import dotty.tools.dotc.ast.tpd +import dotty.tools.dotc.ast.tpd.* import dotty.tools.dotc.core.Contexts.* import dotty.tools.dotc.core.Flags import dotty.tools.dotc.core.Symbols.* import dotty.tools.dotc.interactive.Interactive import dotty.tools.dotc.interactive.InteractiveDriver +import dotty.tools.dotc.parsing.Tokens.closingRegionTokens +import dotty.tools.dotc.reporting.ErrorMessageID +import dotty.tools.dotc.reporting.ExpectedTokenButFound import dotty.tools.dotc.util.Signatures -import dotty.tools.dotc.util.Signatures.Signature import dotty.tools.dotc.util.SourceFile -import dotty.tools.dotc.util.SourcePosition +import dotty.tools.dotc.util.Spans +import dotty.tools.dotc.util.Spans.Span +import dotty.tools.pc.printer.ShortenedTypePrinter +import dotty.tools.pc.printer.ShortenedTypePrinter.IncludeDefaultParam import dotty.tools.pc.utils.MtagsEnrichments.* - import org.eclipse.lsp4j as l +import scala.jdk.CollectionConverters.* +import scala.jdk.OptionConverters.* +import scala.meta.internal.metals.ReportContext +import scala.meta.pc.OffsetParams +import scala.meta.pc.SymbolDocumentation +import scala.meta.pc.SymbolSearch + object SignatureHelpProvider: def signatureHelp( driver: InteractiveDriver, params: OffsetParams, search: SymbolSearch - ) = - val uri = params.uri() - val sourceFile = SourceFile.virtual(params.uri().nn, params.text().nn) + )(using ReportContext): l.SignatureHelp = + val uri = params.uri().nn + val text = params.text().nn + val sourceFile = SourceFile.virtual(uri, text) driver.run(uri.nn, sourceFile) - given ctx: Context = driver.currentCtx - - val pos = driver.sourcePosition(params) - val trees = driver.openedTrees(uri.nn) - - val path = Interactive.pathTo(trees, pos) - - val (paramN, callableN, alternatives) = - Signatures.signatureHelp(path, pos.span) - val infos = alternatives.flatMap { signature => - signature.denot.map { - (signature, _) - } - } - - val signatureInfos = infos.map { case (signature, denot) => - search.symbolDocumentation(denot.symbol) match - case Some(doc) => - withDocumentation( - doc, - signature, - denot.symbol.is(Flags.JavaDefined) - ).getOrElse(signature) - case _ => signature - - } - - /* Versions prior to 3.2.1 did not support type parameters - * so we need to skip them. - */ - new l.SignatureHelp( - signatureInfos.map(signatureToSignatureInformation).asJava, - callableN, - paramN - ) + driver.compilationUnits.get(uri) match + case Some(unit) => + + val pos = driver.sourcePosition(params, isZeroExtent = false) + val path = Interactive.pathTo(unit.tpdTree, pos.span)(using driver.currentCtx) + + val localizedContext = Interactive.contextOfPath(path)(using driver.currentCtx) + val indexedContext = IndexedContext(driver.currentCtx) + + given Context = localizedContext.fresh + .setCompilationUnit(unit) + .setPrinterFn(_ => ShortenedTypePrinter(search, IncludeDefaultParam.Never)(using indexedContext)) + + val (paramN, callableN, alternatives) = Signatures.signatureHelp(path, pos.span) + + val infos = alternatives.flatMap: signature => + signature.denot.map(signature -> _) + + val signatureInfos = infos.map { case (signature, denot) => + search.symbolDocumentation(denot.symbol) match + case Some(doc) => + withDocumentation( + doc, + signature, + denot.symbol.is(Flags.JavaDefined) + ).getOrElse(signature) + case _ => signature + + } + + new l.SignatureHelp( + signatureInfos.map(signatureToSignatureInformation).asJava, + callableN, + paramN + ) + case _ => new l.SignatureHelp() end signatureHelp private def withDocumentation( info: SymbolDocumentation, signature: Signatures.Signature, isJavaSymbol: Boolean - ): Option[Signature] = - val allParams = info.parameters().nn.asScala - def updateParams( - params: List[Signatures.Param], - index: Int - ): List[Signatures.Param] = + ): Option[Signatures.Signature] = + val methodParams = info.parameters().nn.asScala + val typeParams = info.typeParameters().nn.asScala + + def updateParams(params: List[Signatures.Param], typeParamIndex: Int, methodParamIndex: Int): List[Signatures.Param] = params match - case Nil => Nil - case head :: tail => - val rest = updateParams(tail, index + 1) - allParams.lift(index) match + case (head: Signatures.MethodParam) :: tail => + val rest = updateParams(tail, typeParamIndex, methodParamIndex + 1) + methodParams.lift(methodParamIndex) match case Some(paramDoc) => val newName = if isJavaSymbol && head.name.startsWith("x$") then paramDoc.nn.displayName() else head.name - head.copy( - doc = Some(paramDoc.docstring.nn), - name = newName.nn - ) :: rest + head.copy(name = newName.nn, doc = Some(paramDoc.docstring.nn)) :: rest + case _ => head :: rest + case (head: Signatures.TypeParam) :: tail => + val rest = updateParams(tail, typeParamIndex + 1, methodParamIndex) + typeParams.lift(typeParamIndex) match + case Some(paramDoc) => + head.copy(doc = Some(paramDoc.docstring.nn)) :: rest case _ => head :: rest + case _ => Nil def updateParamss( params: List[List[Signatures.Param]], - index: Int + typeParamIndex: Int, + methodParamIndex: Int ): List[List[Signatures.Param]] = params match case Nil => Nil case head :: tail => - val updated = updateParams(head, index) - updated :: updateParamss(tail, index + head.size) - val updatedParams = updateParamss(signature.paramss, 0) + val updated = updateParams(head, typeParamIndex, methodParamIndex) + val (nextTypeParamIndex, nextMethodParamIndex) = head match + case (_: Signatures.MethodParam) :: _ => (typeParamIndex, methodParamIndex + head.size) + case (_: Signatures.TypeParam) :: _ => (typeParamIndex + head.size, methodParamIndex) + case _ => (typeParamIndex, methodParamIndex) + updated :: updateParamss(tail, nextTypeParamIndex, nextMethodParamIndex) + val updatedParams = updateParamss(signature.paramss, 0, 0) Some(signature.copy(doc = Some(info.docstring().nn), paramss = updatedParams)) end withDocumentation private def signatureToSignatureInformation( signature: Signatures.Signature ): l.SignatureInformation = - val tparams = signature.tparams.map(Signatures.Param("", _)) - val paramInfoss = - (tparams ::: signature.paramss.flatten).map(paramToParameterInformation) + val paramInfoss = (signature.paramss.flatten).map(paramToParameterInformation) val paramLists = - if signature.paramss.forall(_.isEmpty) && tparams.nonEmpty then "" - else - signature.paramss - .map { paramList => - val labels = paramList.map(_.show) - val prefix = if paramList.exists(_.isImplicit) then "using " else "" - labels.mkString(prefix, ", ", "") - } - .mkString("(", ")(", ")") - val tparamsLabel = - if signature.tparams.isEmpty then "" - else signature.tparams.mkString("[", ", ", "]") + signature.paramss + .map { paramList => + val labels = paramList.map(_.show) + val isImplicit = paramList.exists: + case p: Signatures.MethodParam => p.isImplicit + case _ => false + val prefix = if isImplicit then "using " else "" + val isTypeParams = paramList.forall(_.isInstanceOf[Signatures.TypeParam]) && paramList.nonEmpty + val wrap: String => String = label => if isTypeParams then + s"[$label]" + else + s"($label)" + wrap(labels.mkString(prefix, ", ", "")) + }.mkString + + val returnTypeLabel = signature.returnType.map(t => s": $t").getOrElse("") - val label = s"${signature.name}$tparamsLabel$paramLists$returnTypeLabel" + val label = s"${signature.name}$paramLists$returnTypeLabel" val documentation = signature.doc.map(markupContent) val sig = new l.SignatureInformation(label) sig.setParameters(paramInfoss.asJava) diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionPos.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionPos.scala index a0cf6bafcf46..53d867c924a6 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionPos.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionPos.scala @@ -5,22 +5,20 @@ import java.net.URI import scala.meta.pc.OffsetParams -import dotty.tools.dotc.ast.tpd.* +import dotty.tools.dotc.ast.untpd.* import dotty.tools.dotc.ast.untpd.ImportSelector import dotty.tools.dotc.core.Contexts.* import dotty.tools.dotc.core.StdNames.* import dotty.tools.dotc.util.Chars import dotty.tools.dotc.util.SourcePosition import dotty.tools.dotc.util.Spans +import dotty.tools.dotc.interactive.Completion import dotty.tools.pc.utils.MtagsEnrichments.* import org.eclipse.lsp4j as l - -enum CompletionKind: - case Empty, Scope, Members +import scala.annotation.tailrec case class CompletionPos( - kind: CompletionKind, start: Int, end: Int, query: String, @@ -39,27 +37,21 @@ object CompletionPos: def infer( cursorPos: SourcePosition, offsetParams: OffsetParams, - treePath: List[Tree] + adjustedPath: List[Tree] )(using Context): CompletionPos = - infer(cursorPos, offsetParams.uri().nn, offsetParams.text().nn, treePath) + infer(cursorPos, offsetParams.uri().nn, offsetParams.text().nn, adjustedPath) def infer( cursorPos: SourcePosition, uri: URI, text: String, - treePath: List[Tree] + adjustedPath: List[Tree] )(using Context): CompletionPos = - val start = inferIdentStart(cursorPos, text, treePath) - val end = inferIdentEnd(cursorPos, text) - val query = text.substring(start, end) - val prevIsDot = - if start - 1 >= 0 then text.charAt(start - 1) == '.' else false - val kind = - if query.nn.isEmpty() && !prevIsDot then CompletionKind.Empty - else if prevIsDot then CompletionKind.Members - else CompletionKind.Scope + val identEnd = inferIdentEnd(cursorPos, text) + val query = Completion.completionPrefix(adjustedPath, cursorPos) + val start = cursorPos.point - query.length() - CompletionPos(kind, start, end, query.nn, cursorPos, uri) + CompletionPos(start, identEnd, query.nn, cursorPos, uri) end infer /** @@ -84,42 +76,6 @@ object CompletionPos: (i, tabIndented) end inferIndent - /** - * Returns the start offset of the identifier starting as the given offset position. - */ - private def inferIdentStart( - pos: SourcePosition, - text: String, - path: List[Tree] - )(using Context): Int = - def fallback: Int = - var i = pos.point - 1 - while i >= 0 && Chars.isIdentifierPart(text.charAt(i)) do i -= 1 - i + 1 - def loop(enclosing: List[Tree]): Int = - enclosing match - case Nil => fallback - case head :: tl => - if !head.sourcePos.contains(pos) then loop(tl) - else - head match - case i: Ident => i.sourcePos.point - case s: Select => - if s.name.toTermName == nme.ERROR || s.span.exists && pos.span.point < s.span.point - then fallback - else s.span.point - case Import(_, sel) => - sel - .collectFirst { - case ImportSelector(imported, renamed, _) - if imported.sourcePos.contains(pos) => - imported.sourcePos.point - } - .getOrElse(fallback) - case _ => fallback - loop(path) - end inferIdentStart - /** * Returns the end offset of the identifier starting as the given offset position. */ diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala index f008ea5a9dbb..710e91750362 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala @@ -13,6 +13,7 @@ import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.ast.tpd.* import dotty.tools.dotc.core.Constants.Constant import dotty.tools.dotc.core.Contexts.Context +import dotty.tools.dotc.core.Phases import dotty.tools.dotc.core.StdNames import dotty.tools.dotc.interactive.Interactive import dotty.tools.dotc.interactive.InteractiveDriver @@ -53,14 +54,16 @@ class CompletionProvider( val (items, isIncomplete) = driver.compilationUnits.get(uri) match case Some(unit) => - val newctx = ctx.fresh.setCompilationUnit(unit) + val newctx = ctx.fresh.setCompilationUnit(unit).withPhase(Phases.typerPhase(using ctx)) val tpdPath = Interactive.pathTo(newctx.compilationUnit.tpdTree, pos.span)(using newctx) + val adjustedPath = Interactive.resolveTypedOrUntypedPath(tpdPath, pos)(using newctx) - val locatedCtx = - Interactive.contextOfPath(tpdPath)(using newctx) + val locatedCtx = Interactive.contextOfPath(tpdPath)(using newctx) val indexedCtx = IndexedContext(locatedCtx) + val completionPos = - CompletionPos.infer(pos, params, tpdPath)(using newctx) + CompletionPos.infer(pos, params, adjustedPath)(using locatedCtx) + val autoImportsGen = AutoImports.generator( completionPos.sourcePos, text, @@ -69,16 +72,18 @@ class CompletionProvider( indexedCtx, config ) + val (completions, searchResult) = new Completions( pos, text, - ctx.fresh.setCompilationUnit(unit), + locatedCtx, search, buildTargetIdentifier, completionPos, indexedCtx, tpdPath, + adjustedPath, config, folderPath, autoImportsGen, @@ -94,7 +99,7 @@ class CompletionProvider( completionPos, tpdPath, indexedCtx - )(using newctx) + )(using locatedCtx) } val isIncomplete = searchResult match case SymbolSearch.Result.COMPLETE => false @@ -152,7 +157,7 @@ class CompletionProvider( // For overloaded signatures we get multiple symbols, so we need // to recalculate the description - // related issue https://github.com/lampepfl/dotty/issues/11941 + // related issue https://github.com/scala/scala3/issues/11941 lazy val kind: CompletionItemKind = completion.completionItemKind val description = completion.description(printer) val label = completion.labelWithDescription(printer) @@ -215,7 +220,7 @@ class CompletionProvider( def mkItemWithImports( v: CompletionValue.Workspace | CompletionValue.Extension | - CompletionValue.Interpolator + CompletionValue.Interpolator | CompletionValue.ImplicitClass ) = val sym = v.symbol path match @@ -238,21 +243,29 @@ class CompletionProvider( r match case IndexedContext.Result.InScope => mkItem( - ident.backticked(backtickSoftKeyword) + completionTextSuffix + v.insertText.getOrElse( + ident.backticked( + backtickSoftKeyword + ) + completionTextSuffix + ), + range = v.range, ) case _ if isInStringInterpolation => mkItem( - "{" + sym.fullNameBackticked + completionTextSuffix + "}" + "{" + sym.fullNameBackticked + completionTextSuffix + "}", + range = v.range ) case _ if v.isExtensionMethod => mkItem( - ident.backticked(backtickSoftKeyword) + completionTextSuffix + ident.backticked(backtickSoftKeyword) + completionTextSuffix, + range = v.range ) case _ => mkItem( sym.fullNameBackticked( backtickSoftKeyword - ) + completionTextSuffix + ) + completionTextSuffix, + range = v.range ) end match end match @@ -260,7 +273,7 @@ class CompletionProvider( end mkItemWithImports completion match - case v: (CompletionValue.Workspace | CompletionValue.Extension) => + case v: (CompletionValue.Workspace | CompletionValue.Extension | CompletionValue.ImplicitClass) => mkItemWithImports(v) case v: CompletionValue.Interpolator if v.isWorkspace || v.isExtension => mkItemWithImports(v) diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionValue.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionValue.scala index a5b2fb40f418..2810fe728b9a 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionValue.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionValue.scala @@ -4,7 +4,9 @@ package completions import scala.meta.internal.pc.CompletionItemData import dotty.tools.dotc.core.Contexts.Context +import dotty.tools.dotc.core.Denotations.Denotation import dotty.tools.dotc.core.Flags.* +import dotty.tools.dotc.core.StdNames.nme import dotty.tools.dotc.core.Symbols.Symbol import dotty.tools.dotc.core.Types.Type import dotty.tools.pc.printer.ShortenedTypePrinter @@ -33,6 +35,7 @@ enum CompletionSource: case MatchCompletionKind case CaseKeywordKind case DocumentKind + case ImplicitClassKind sealed trait CompletionValue: def label: String @@ -61,7 +64,8 @@ end CompletionValue object CompletionValue: sealed trait Symbolic extends CompletionValue: - def symbol: Symbol + def denotation: Denotation + val symbol = denotation.symbol def isFromWorkspace: Boolean = false override def completionItemDataKind = CompletionItemData.None def isExtensionMethod: Boolean = false @@ -105,7 +109,7 @@ object CompletionValue: s"${label}${description(printer)}" else s"$label: ${description(printer)}" - private def labelWithSuffix(printer: ShortenedTypePrinter)(using Context): String = + protected def labelWithSuffix(printer: ShortenedTypePrinter)(using Context): String = if snippetSuffix.addLabelSnippet then val printedParams = symbol.info.typeParams.map(p => @@ -114,41 +118,60 @@ object CompletionValue: s"${label}${printedParams.mkString("[", ",", "]")}" else label - override def description(printer: ShortenedTypePrinter)( - using Context - ): String = - printer.completionSymbol(symbol) + override def description(printer: ShortenedTypePrinter)(using Context): String = + printer.completionSymbol(denotation) + end Symbolic case class Compiler( label: String, - symbol: Symbol, + denotation: Denotation, override val snippetSuffix: CompletionSuffix - ) extends Symbolic { + ) extends Symbolic: override def completionItemDataKind: Integer = CompletionSource.CompilerKind.ordinal - } + case class Scope( label: String, - symbol: Symbol, + denotation: Denotation, override val snippetSuffix: CompletionSuffix, - ) extends Symbolic { + ) extends Symbolic: override def completionItemDataKind: Integer = CompletionSource.ScopeKind.ordinal - } + case class Workspace( label: String, - symbol: Symbol, + denotation: Denotation, override val snippetSuffix: CompletionSuffix, override val importSymbol: Symbol ) extends Symbolic: override def isFromWorkspace: Boolean = true override def completionItemDataKind: Integer = CompletionSource.WorkspaceKind.ordinal + override def labelWithDescription(printer: ShortenedTypePrinter)(using Context): String = + if symbol.is(Method) && symbol.name != nme.apply then + s"${labelWithSuffix(printer)} - ${printer.fullNameString(symbol.effectiveOwner)}" + else super.labelWithDescription(printer) + + /** + * CompletionValue for old implicit classes methods via SymbolSearch + */ + case class ImplicitClass( + label: String, + denotation: Denotation, + override val snippetSuffix: CompletionSuffix, + override val importSymbol: Symbol, + ) extends Symbolic: + override def completionItemKind(using Context): CompletionItemKind = + CompletionItemKind.Method + override def completionItemDataKind: Integer = CompletionSource.ImplicitClassKind.ordinal + override def description(printer: ShortenedTypePrinter)(using Context): String = + s"${printer.completionSymbol(denotation)} (implicit)" + /** * CompletionValue for extension methods via SymbolSearch */ case class Extension( label: String, - symbol: Symbol, + denotation: Denotation, override val snippetSuffix: CompletionSuffix ) extends Symbolic: override def completionItemKind(using Context): CompletionItemKind = @@ -156,7 +179,7 @@ object CompletionValue: override def completionItemDataKind: Integer = CompletionSource.ExtensionKind.ordinal override def isExtensionMethod: Boolean = true override def description(printer: ShortenedTypePrinter)(using Context): String = - s"${printer.completionSymbol(symbol)} (extension)" + s"${printer.completionSymbol(denotation)} (extension)" /** * @param shortenedNames shortened type names by `Printer`. This field should be used for autoImports @@ -169,7 +192,7 @@ object CompletionValue: case class Override( label: String, value: String, - symbol: Symbol, + denotation: Denotation, override val additionalEdits: List[TextEdit], override val filterText: Option[String], override val range: Option[Range] @@ -185,7 +208,7 @@ object CompletionValue: case class NamedArg( label: String, tpe: Type, - symbol: Symbol + denotation: Denotation ) extends Symbolic: override def insertText: Option[String] = Some(label.replace("$", "$$").nn) override def completionItemDataKind: Integer = CompletionSource.OverrideKind.ordinal @@ -235,7 +258,7 @@ object CompletionValue: CompletionItemKind.Folder case class Interpolator( - symbol: Symbol, + denotation: Denotation, label: String, override val insertText: Option[String], override val additionalEdits: List[TextEdit], @@ -251,6 +274,7 @@ object CompletionValue: )(using Context): String = if isExtension then s"${printer.completionSymbol(symbol)} (extension)" else super.description(printer) + override def isExtensionMethod: Boolean = isExtension end Interpolator case class MatchCompletion( @@ -266,7 +290,7 @@ object CompletionValue: desc case class CaseKeyword( - symbol: Symbol, + denotation: Denotation, label: String, override val insertText: Option[String], override val additionalEdits: List[TextEdit], diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala index 1e2dbb5cdaa1..d6ca15b35129 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala @@ -12,6 +12,7 @@ import scala.meta.internal.pc.{IdentifierComparator, MemberOrdering} import scala.meta.pc.* import dotty.tools.dotc.ast.tpd.* +import dotty.tools.dotc.ast.untpd import dotty.tools.dotc.ast.NavigateAST import dotty.tools.dotc.core.Comments.Comment import dotty.tools.dotc.core.Constants.Constant @@ -27,13 +28,13 @@ import dotty.tools.dotc.core.Types.* import dotty.tools.dotc.interactive.Completion import dotty.tools.dotc.interactive.Completion.Mode import dotty.tools.dotc.util.SourcePosition -import dotty.tools.dotc.util.Spans -import dotty.tools.dotc.util.Spans.Span import dotty.tools.dotc.util.SrcPos import dotty.tools.pc.AutoImports.AutoImportsGenerator import dotty.tools.pc.completions.OverrideCompletions.OverrideExtractor import dotty.tools.pc.buildinfo.BuildInfo import dotty.tools.pc.utils.MtagsEnrichments.* +import dotty.tools.dotc.core.Denotations.SingleDenotation +import dotty.tools.dotc.interactive.Interactive class Completions( pos: SourcePosition, @@ -44,6 +45,7 @@ class Completions( completionPos: CompletionPos, indexedContext: IndexedContext, path: List[Tree], + adjustedPath: List[untpd.Tree], config: PresentationCompilerConfig, workspace: Option[Path], autoImports: AutoImportsGenerator, @@ -51,16 +53,10 @@ class Completions( options: List[String] )(using ReportContext): - implicit val context: Context = ctx + given context: Context = ctx - val coursierComplete = new CoursierComplete(BuildInfo.scalaVersion) - - private lazy val adjustedPath = Completion.resolveTypedOrUntypedPath(path, pos) - private lazy val completionMode = - val mode = Completion.completionMode(adjustedPath, pos) - path match - case Literal(Constant(_: String)) :: _ => Mode.Term // literal completions - case _ => mode + private lazy val coursierComplete = new CoursierComplete(BuildInfo.scalaVersion) + private lazy val completionMode = Completion.completionMode(adjustedPath, pos) private lazy val shouldAddSnippet = path match @@ -72,8 +68,8 @@ class Completions( case _ :: (withcursor @ Select(fun, name)) :: (appl: GenericApply) :: _ if appl.fun == withcursor && name.decoded == Cursor.value => false - case (_: Import) :: _ => false - case _ :: (_: Import) :: _ => false + case (_: (Import | Export)) :: _ => false + case _ :: (_: (Import | Export)) :: _ => false case (_: Ident) :: (_: SeqLiteral) :: _ => false case _ => true @@ -122,17 +118,19 @@ class Completions( // should not show completions for toplevel case Nil | (_: PackageDef) :: _ if pos.source.file.extension != "sc" => (allAdvanced, SymbolSearch.Result.COMPLETE) - case Select(qual, _) :: _ if qual.tpe.isErroneous => + case Select(qual, _) :: _ if qual.typeOpt.isErroneous => (allAdvanced, SymbolSearch.Result.COMPLETE) case Select(qual, _) :: _ => - val (_, compilerCompletions) = Completion.completions(pos) + val compilerCompletions = Completion.rawCompletions(pos, completionMode, completionPos.query, path, adjustedPath) val (compiler, result) = compilerCompletions + .toList .flatMap(toCompletionValues) .filterInteresting(qual.typeOpt.widenDealias) (allAdvanced ++ compiler, result) case _ => - val (_, compilerCompletions) = Completion.completions(pos) + val compilerCompletions = Completion.rawCompletions(pos, completionMode, completionPos.query, path, adjustedPath) val (compiler, result) = compilerCompletions + .toList .flatMap(toCompletionValues) .filterInteresting() (allAdvanced ++ compiler, result) @@ -140,20 +138,21 @@ class Completions( val application = CompletionApplication.fromPath(path) val ordering = completionOrdering(application) - val values = application.postProcess(all.sorted(ordering)) + val sorted = all.sorted(ordering) + val values = application.postProcess(sorted) (values, result) end completions private def toCompletionValues( - completion: Completion + completion: Name, + denots: Seq[SingleDenotation] ): List[CompletionValue] = - completion.symbols.flatMap( + denots.toList.flatMap: denot => completionsWithSuffix( - _, - completion.label, - CompletionValue.Compiler(_, _, _) + denot, + completion.show, + (label, denot, suffix) => CompletionValue.Compiler(label, denot, suffix) ) - ) end toCompletionValues inline private def undoBacktick(label: String): String = @@ -228,35 +227,33 @@ class Completions( end findSuffix def completionsWithSuffix( - sym: Symbol, + denot: SingleDenotation, label: String, - toCompletionValue: (String, Symbol, CompletionSuffix) => CompletionValue + toCompletionValue: (String, SingleDenotation, CompletionSuffix) => CompletionValue ): List[CompletionValue] = - // workaround for earlier versions that force correctly detecting Java flags - - def companionSynthetic = sym.companion.exists && sym.companion.is(Synthetic) + val sym = denot.symbol // find the apply completion that would need a snippet - val methodSymbols = + val methodDenots: List[SingleDenotation] = if shouldAddSnippet && completionMode.is(Mode.Term) && - (sym.is(Flags.Module) || sym.isClass && !sym.is(Flags.Trait)) && !sym.is(Flags.JavaDefined) + (sym.is(Flags.Module) || sym.isField || sym.isClass && !sym.is(Flags.Trait)) && !sym.is(Flags.JavaDefined) then val info = /* Companion will be added even for normal classes now, * but it will not show up from classpath. We can suggest * constructors based on those synthetic applies. */ - if sym.isClass && companionSynthetic then sym.companionModule.info - else sym.info - val applSymbols = info.member(nme.apply).allSymbols - sym :: applSymbols - else List(sym) - - methodSymbols.map { methodSymbol => - val suffix = findSuffix(methodSymbol) + if sym.isClass && sym.companionModule.exists then sym.companionModule.info + else denot.info + val applyDenots = info.member(nme.apply).allSymbols.map(_.asSeenFrom(info).asSingleDenotation) + denot :: applyDenots + else denot :: Nil + + methodDenots.map { methodDenot => + val suffix = findSuffix(methodDenot.symbol) val name = undoBacktick(label) toCompletionValue( name, - methodSymbol, + methodDenot, suffix ) } @@ -441,6 +438,10 @@ class Completions( true, ) + case (tree: (Import | Export)) :: _ + if tree.selectors.exists(_.renamed.sourcePos.contains(pos)) => + (List.empty, true) + // From Scala 3.1.3-RC3 (as far as I know), path contains // `Literal(Constant(null))` on head for an incomplete program, in this case, just ignore the head. case Literal(Constant(null)) :: tl => @@ -494,44 +495,64 @@ class Completions( qualType: Type = ctx.definitions.AnyType ): Option[SymbolSearch.Result] = val query = completionPos.query - completionPos.kind match - case CompletionKind.Empty => - val filtered = indexedContext.scopeSymbols - .filter(sym => - !sym.isConstructor && (!sym.is(Synthetic) || sym.is(Module)) - ) - - filtered.map { sym => - visit(CompletionValue.Scope(sym.decodedName, sym, findSuffix(sym))) - } - Some(SymbolSearch.Result.INCOMPLETE) - case CompletionKind.Scope => - val visitor = new CompilerSearchVisitor(sym => - indexedContext.lookupSym(sym) match - case IndexedContext.Result.InScope => - visit(CompletionValue.Scope(sym.decodedName, sym, findSuffix(sym))) - case _ => - completionsWithSuffix( - sym, - sym.decodedName, - CompletionValue.Workspace(_, _, _, sym) - ).map(visit).forall(_ == true), - ) - Some(search.search(query, buildTargetIdentifier, visitor).nn) - case CompletionKind.Members => - val visitor = new CompilerSearchVisitor(sym => - if sym.is(ExtensionMethod) && - qualType.widenDealias <:< sym.extensionParam.info.widenDealias - then + if completionMode.is(Mode.Scope) && query.nonEmpty then + val visitor = new CompilerSearchVisitor(sym => + indexedContext.lookupSym(sym) match + case IndexedContext.Result.InScope => false + case _ => completionsWithSuffix( sym, sym.decodedName, - CompletionValue.Extension(_, _, _) - ).map(visit).forall(_ == true) - else false, - ) - Some(search.searchMethods(query, buildTargetIdentifier, visitor).nn) - end match + CompletionValue.Workspace(_, _, _, sym) + ).map(visit).forall(_ == true), + ) + Some(search.search(query, buildTargetIdentifier, visitor).nn) + else if completionMode.is(Mode.Member) then + val visitor = new CompilerSearchVisitor(sym => + def isExtensionMethod = sym.is(ExtensionMethod) && + qualType.widenDealias <:< sym.extensionParam.info.widenDealias + def isImplicitClass(owner: Symbol) = + val constructorParam = + owner.info + .membersBasedOnFlags( + Flags.ParamAccessor, + Flags.EmptyFlags, + ) + .headOption + .map(_.info) + owner.isClass && owner.is(Flags.Implicit) && + constructorParam.exists(p => + qualType.widenDealias <:< p.widenDealias + ) + end isImplicitClass + + def isImplicitClassMethod = sym.is(Flags.Method) && !sym.isConstructor && + isImplicitClass(sym.maybeOwner) + + if isExtensionMethod then + completionsWithSuffix( + sym, + sym.decodedName, + CompletionValue.Extension(_, _, _) + ).map(visit).forall(_ == true) + else if isImplicitClassMethod then + completionsWithSuffix( + sym, + sym.decodedName, + CompletionValue.ImplicitClass(_, _, _, sym.maybeOwner), + ).map(visit).forall(_ == true) + else false, + ) + Some(search.searchMethods(query, buildTargetIdentifier, visitor).nn) + else + val filtered = indexedContext.scopeSymbols + .filter(sym => !sym.isConstructor && (!sym.is(Synthetic) || sym.is(Module))) + + filtered.map { sym => + visit(CompletionValue.Scope(sym.decodedName, sym, findSuffix(sym))) + } + Some(SymbolSearch.Result.INCOMPLETE) + end enrichWithSymbolSearch extension (s: SrcPos) @@ -692,8 +713,8 @@ class Completions( // show the abstract members first if !ov.symbol.is(Deferred) then penalty |= MemberOrdering.IsNotAbstract penalty - case CompletionValue.Workspace(_, sym, _, _) => - symbolRelevance(sym) | (IsWorkspaceSymbol + sym.name.show.length()) + case CompletionValue.Workspace(_, denot, _, _) => + symbolRelevance(denot.symbol) | (IsWorkspaceSymbol + denot.name.show.length()) case sym: CompletionValue.Symbolic => symbolRelevance(sym.symbol) case _ => @@ -723,7 +744,7 @@ class Completions( items def forSelect(sel: Select): CompletionApplication = - val tpe = sel.qualifier.tpe + val tpe = sel.qualifier.typeOpt val members = tpe.allMembers.map(_.symbol).toSet new CompletionApplication: @@ -734,11 +755,11 @@ class Completions( isMember(symbol) && symbol.owner != tpe.typeSymbol def postProcess(items: List[CompletionValue]): List[CompletionValue] = items.map { - case CompletionValue.Compiler(label, sym, suffix) - if isMember(sym) => + case completion @ CompletionValue.Compiler(label, denot, suffix) + if isMember(completion.symbol) => CompletionValue.Compiler( label, - substituteTypeVars(sym), + substituteTypeVars(completion.symbol), suffix ) case other => other @@ -767,7 +788,8 @@ class Completions( val fuzzyCache = mutable.Map.empty[CompletionValue, Int] def compareLocalSymbols(s1: Symbol, s2: Symbol): Int = - if s1.isLocal && s2.isLocal then + if s1.isLocal && s2.isLocal && s1.sourcePos.exists && s2.sourcePos.exists + then val firstIsAfter = s1.srcPos.isAfter(s2.srcPos) if firstIsAfter then -1 else 1 else 0 @@ -809,6 +831,16 @@ class Completions( priority(o1) - priority(o2) end compareInApplyParams + def prioritizeKeywords(o1: CompletionValue, o2: CompletionValue): Int = + def priority(v: CompletionValue): Int = + v match + case _: CompletionValue.CaseKeyword => 0 + case _: CompletionValue.NamedArg => 1 + case _: CompletionValue.Keyword => 2 + case _ => 3 + + priority(o1) - priority(o2) + end prioritizeKeywords /** * Some completion values should be shown first such as CaseKeyword and * NamedArg @@ -885,7 +917,10 @@ class Completions( case _ => val byApplyParams = compareInApplyParams(o1, o2) if byApplyParams != 0 then byApplyParams - else compareByRelevance(o1, o2) + else + val keywords = prioritizeKeywords(o1, o2) + if keywords != 0 then keywords + else compareByRelevance(o1, o2) end compare end Completions diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/InterpolatorCompletions.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/InterpolatorCompletions.scala index 1d063bc6d873..95fbeec0cac0 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/InterpolatorCompletions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/InterpolatorCompletions.scala @@ -83,14 +83,13 @@ object InterpolatorCompletions: case _: Select => true case _ => false } => - val allLiterals = parent match - case SeqLiteral(elems, _) => - elems - case _ => Nil - expr.elems.zip(allLiterals.tail).collectFirst { - case (i: (Ident | Select), literal) if literal == lit => - i - } + parent match + case SeqLiteral(elems, _) if elems.size > 0 => + expr.elems.zip(elems.tail).collectFirst { + case (i: (Ident | Select), literal) if literal == lit => + i + } + case _ => None end interpolatorMemberArg /** @@ -161,16 +160,16 @@ object InterpolatorCompletions: completions.completionsWithSuffix( sym, label, - (name, s, suffix) => + (name, denot, suffix) => CompletionValue.Interpolator( - s, + denot.symbol, label, Some(newText(name, suffix.toEditOpt, identOrSelect)), Nil, Some(cursor.withStart(identOrSelect.span.start).toLsp), // Needed for VS Code which will not show the completion otherwise Some(identOrSelect.name.toString() + "." + label), - s, + denot.symbol, isExtension = isExtension ), ) @@ -291,9 +290,9 @@ object InterpolatorCompletions: completions.completionsWithSuffix( sym, label, - (name, s, suffix) => + (name, denot, suffix) => CompletionValue.Interpolator( - s, + denot.symbol, label, Some(newText(name, suffix.toEditOpt)), additionalEdits(), diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/KeywordsCompletions.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/KeywordsCompletions.scala index a052a0a2c8eb..e912bc49032f 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/KeywordsCompletions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/KeywordsCompletions.scala @@ -12,7 +12,6 @@ import dotty.tools.dotc.core.Comments import dotty.tools.dotc.core.Comments.Comment import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.util.SourcePosition -import dotty.tools.dotc.util.Spans.Span object KeywordsCompletions: diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/MatchCaseCompletions.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/MatchCaseCompletions.scala index a3d5d8814c48..edb489228d92 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/MatchCaseCompletions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/MatchCaseCompletions.scala @@ -14,6 +14,7 @@ import dotty.tools.dotc.ast.tpd.* import dotty.tools.dotc.core.Constants.Constant import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Definitions +import dotty.tools.dotc.core.Denotations.Denotation import dotty.tools.dotc.core.Flags import dotty.tools.dotc.core.Flags.* import dotty.tools.dotc.core.StdNames @@ -74,8 +75,8 @@ object CaseKeywordCompletion: val parents: Parents = selector match case EmptyTree => val seenFromType = parent match - case TreeApply(fun, _) if !fun.tpe.isErroneous => fun.tpe - case _ => parent.tpe + case TreeApply(fun, _) if !fun.typeOpt.isErroneous => fun.typeOpt + case _ => parent.typeOpt seenFromType.paramInfoss match case (head :: Nil) :: _ if definitions.isFunctionType(head) || head.isRef( @@ -84,7 +85,7 @@ object CaseKeywordCompletion: val argTypes = head.argTypes.init new Parents(argTypes, definitions) case _ => new Parents(NoType, definitions) - case sel => new Parents(sel.tpe, definitions) + case sel => new Parents(sel.typeOpt, definitions) val selectorSym = parents.selector.widen.metalsDealias.typeSymbol @@ -163,13 +164,17 @@ object CaseKeywordCompletion: (si, label) } } - val caseItems = res.map((si, label) => - completionGenerator.toCompletionValue( - si.sym, - label, - autoImportsGen.renderImports(si.importSel.toList) - ) - ) + val caseItems = + if res.isEmpty then completionGenerator.caseKeywordOnly + else + res.map((si, label) => + completionGenerator.toCompletionValue( + si.sym, + label, + autoImportsGen.renderImports(si.importSel.toList), + ) + ) + includeExhaustive match // In `List(foo).map { cas@@} we want to provide also `case (exhaustive)` completion // which works like exhaustive match. @@ -240,7 +245,7 @@ object CaseKeywordCompletion: completionPos, clientSupportsSnippets ) - val tpe = selector.tpe.widen.metalsDealias.bounds.hi match + val tpe = selector.typeOpt.widen.metalsDealias.bounds.hi match case tr @ TypeRef(_, _) => tr.underlying case t => t @@ -440,8 +445,22 @@ class CompletionValueGenerator( end if end labelForCaseMember + def caseKeywordOnly: List[CompletionValue.Keyword] = + if patternOnly.isEmpty then + val label = "case" + val suffix = + if clientSupportsSnippets then " $0 =>" + else " " + List( + CompletionValue.Keyword( + label, + Some(label + suffix), + ) + ) + else Nil + def toCompletionValue( - sym: Symbol, + denot: Denotation, label: String, autoImport: Option[l.TextEdit] ): CompletionValue.CaseKeyword = @@ -449,7 +468,7 @@ class CompletionValueGenerator( (if patternOnly.nonEmpty then "" else " ") + (if clientSupportsSnippets then "$0" else "") CompletionValue.CaseKeyword( - sym, + denot, label, Some(label + cursorSuffix), autoImport.toList, diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/NamedArgCompletions.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/NamedArgCompletions.scala index e4ae4070edb9..6f244d9a3414 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/NamedArgCompletions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/NamedArgCompletions.scala @@ -9,7 +9,6 @@ import dotty.tools.dotc.ast.untpd import dotty.tools.dotc.core.Constants.Constant import dotty.tools.dotc.core.ContextOps.localContext import dotty.tools.dotc.core.Contexts.Context -import dotty.tools.dotc.core.Definitions import dotty.tools.dotc.core.Flags import dotty.tools.dotc.core.Flags.Method import dotty.tools.dotc.core.NameKinds.DefaultGetterName @@ -17,6 +16,7 @@ import dotty.tools.dotc.core.Names.Name import dotty.tools.dotc.core.StdNames.* import dotty.tools.dotc.core.SymDenotations.NoDenotation import dotty.tools.dotc.core.Symbols +import dotty.tools.dotc.core.Symbols.defn import dotty.tools.dotc.core.Symbols.NoSymbol import dotty.tools.dotc.core.Symbols.Symbol import dotty.tools.dotc.core.Types.AndType @@ -309,15 +309,17 @@ object NamedArgCompletions: val completionSymbols = indexedContext.scopeSymbols def matchingTypesInScope(paramType: Type): List[String] = - completionSymbols - .collect { - case sym - if sym.info <:< paramType && sym.isTerm && !sym.info.isErroneous && !sym.info.isNullType && !sym.info.isNothingType && !sym - .is(Flags.Method) && !sym.is(Flags.Synthetic) => - sym.decodedName - } - .filter(name => name != "Nil" && name != "None") - .sorted + if paramType != defn.AnyType then + completionSymbols + .collect { + case sym + if sym.info <:< paramType && sym.isTerm && !sym.info.isErroneous && !sym.info.isNullType && !sym.info.isNothingType && !sym + .is(Flags.Method) && !sym.is(Flags.Synthetic) => + sym.decodedName + } + .filter(name => name != "Nil" && name != "None") + .sorted + else Nil def findDefaultValue(param: ParamSymbol): String = val matchingType = matchingTypesInScope(param.info) diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/OverrideCompletions.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/OverrideCompletions.scala index e7b1acb9aa87..8d96396999da 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/OverrideCompletions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/OverrideCompletions.scala @@ -95,7 +95,7 @@ object OverrideCompletions: // not using `td.tpe.abstractTermMembers` because those members includes // the abstract members in `td.tpe`. For example, when we type `def foo@@`, // `td.tpe.abstractTermMembers` contains `method foo: ` and it overrides the parent `foo` method. - val overridables = td.tpe.parents + val overridables = td.typeOpt.parents .flatMap { parent => parent.membersBasedOnFlags( flags, @@ -279,7 +279,7 @@ object OverrideCompletions: else "" (indent, indent, lastIndent) end calcIndent - val abstractMembers = defn.tpe.abstractTermMembers.map(_.symbol) + val abstractMembers = defn.typeOpt.abstractTermMembers.map(_.symbol) val caseClassOwners = Set("Product", "Equals") val overridables = @@ -307,7 +307,7 @@ object OverrideCompletions: if edits.isEmpty then Nil else // A list of declarations in the class/object to implement - val decls = defn.tpe.decls.toList + val decls = defn.typeOpt.decls.toList .filter(sym => !sym.isPrimaryConstructor && !sym.isTypeParam && @@ -418,7 +418,7 @@ object OverrideCompletions: // `iterator` method in `new Iterable[Int] { def iterato@@ }` // should be completed as `def iterator: Iterator[Int]` instead of `Iterator[A]`. val seenFrom = - val memInfo = defn.tpe.memberInfo(sym.symbol) + val memInfo = defn.typeOpt.memberInfo(sym.symbol) if memInfo.isErroneous || memInfo.finalResultType.isAny then sym.info.widenTermRefExpr else memInfo diff --git a/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala b/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala index 9c255d20d212..3b763523f9e6 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala @@ -7,6 +7,7 @@ import scala.meta.pc.SymbolDocumentation import scala.meta.pc.SymbolSearch import dotty.tools.dotc.core.Contexts.Context +import dotty.tools.dotc.core.Denotations.Denotation import dotty.tools.dotc.core.Flags import dotty.tools.dotc.core.Flags.* import dotty.tools.dotc.core.NameKinds.ContextBoundParamName @@ -36,7 +37,7 @@ import org.eclipse.lsp4j.TextEdit * A type printer that shortens types by replacing fully qualified names with shortened versions. * * The printer supports symbol renames found in scope and will use the rename if it is available. - * It also handlse custom renames as specified in the `renameConfigMap` parameter. + * It also handle custom renames as specified in the `renameConfigMap` parameter. */ class ShortenedTypePrinter( symbolSearch: SymbolSearch, @@ -45,7 +46,7 @@ class ShortenedTypePrinter( isTextEdit: Boolean = false, renameConfigMap: Map[Symbol, String] = Map.empty )(using indexedCtx: IndexedContext, reportCtx: ReportContext) extends RefinedPrinter(indexedCtx.ctx): - private val missingImports: mutable.Set[ImportSel] = mutable.Set.empty + private val missingImports: mutable.Set[ImportSel] = mutable.LinkedHashSet.empty private val defaultWidth = 1000 private val methodFlags = @@ -63,6 +64,13 @@ class ShortenedTypePrinter( Lazy ) + private val foundRenames = collection.mutable.LinkedHashMap.empty[Symbol, String] + + def getUsedRenamesInfo(using Context): List[String] = + foundRenames.map { (from, to) => + s"type $to = ${from.showName}" + }.toList + def expressionType(tpw: Type)(using Context): Option[String] = tpw match case t: PolyType => @@ -117,8 +125,10 @@ class ShortenedTypePrinter( prefixIterator.flatMap { owner => val prefixAfterRename = ownersAfterRename(owner) + val ownerRename = indexedCtx.rename(owner) + ownerRename.foreach(rename => foundRenames += owner -> rename) val currentRenamesSearchResult = - indexedCtx.rename(owner).map(Found(owner, _, prefixAfterRename)) + ownerRename.map(Found(owner, _, prefixAfterRename)) lazy val configRenamesSearchResult = renameConfigMap.get(owner).map(Missing(owner, _, prefixAfterRename)) currentRenamesSearchResult orElse configRenamesSearchResult @@ -181,7 +191,9 @@ class ShortenedTypePrinter( override protected def selectionString(tp: NamedType): String = indexedCtx.rename(tp.symbol) match - case Some(value) => value + case Some(value) => + foundRenames += tp.symbol -> value + value case None => super.selectionString(tp) override def toText(tp: Type): Text = @@ -239,9 +251,10 @@ class ShortenedTypePrinter( lazy val effectiveOwner = sym.effectiveOwner sym.isType && (effectiveOwner == defn.ScalaPackageClass || effectiveOwner == defn.ScalaPredefModuleClass) - def completionSymbol(sym: Symbol): String = - val info = sym.info.widenTermRefExpr + def completionSymbol(denotation: Denotation): String = + val info = denotation.info.widenTermRefExpr val typeSymbol = info.typeSymbol + val sym = denotation.symbol lazy val typeEffectiveOwner = if typeSymbol != NoSymbol then " " + fullNameString(typeSymbol.effectiveOwner) @@ -492,7 +505,7 @@ class ShortenedTypePrinter( case head :: Nil => s": $head" case many => many.mkString(": ", ": ", "") s"$keywordName$paramTypeString$bounds" - else if param.is(Flags.Given) && param.name.toString.contains('$') then + else if param.isAllOf(Given | Param) && param.name.startsWith("x$") then // For Anonymous Context Parameters // print only type string // e.g. "using Ord[T]" instead of "using x$0: Ord[T]" diff --git a/presentation-compiler/src/main/dotty/tools/pc/utils/MtagsEnrichments.scala b/presentation-compiler/src/main/dotty/tools/pc/utils/MtagsEnrichments.scala index c006dda2c652..d6c8c10f8030 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/utils/MtagsEnrichments.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/utils/MtagsEnrichments.scala @@ -36,7 +36,8 @@ object MtagsEnrichments extends CommonMtagsEnrichments: extension (driver: InteractiveDriver) def sourcePosition( - params: OffsetParams + params: OffsetParams, + isZeroExtent: Boolean = true ): SourcePosition = val uri = params.uri() val source = driver.openedFiles(uri.nn) @@ -50,6 +51,7 @@ object MtagsEnrichments extends CommonMtagsEnrichments: case offset => Spans.Span(p.offset(), p.offset()) } + case _ if !isZeroExtent => Spans.Span(params.offset(), params.offset() + 1) case _ => Spans.Span(params.offset()) new SourcePosition(source, span) @@ -230,6 +232,34 @@ object MtagsEnrichments extends CommonMtagsEnrichments: def stripBackticks: String = s.stripPrefix("`").stripSuffix("`") + extension (text: Array[Char]) + def indexAfterSpacesAndComments: Int = { + var isInComment = false + var startedStateChange = false + val index = text.indexWhere { + case '/' if !isInComment && !startedStateChange => + startedStateChange = true + false + case '*' if !isInComment && startedStateChange => + startedStateChange = false + isInComment = true + false + case '/' if isInComment && startedStateChange => + startedStateChange = false + isInComment = false + false + case '*' if isInComment && !startedStateChange => + startedStateChange = true + false + case c if isInComment || c.isSpaceChar || c == '\t' => + startedStateChange = false + false + case _ => true + } + if (startedStateChange) index - 1 + else index + } + extension (search: SymbolSearch) def symbolDocumentation(symbol: Symbol)(using Context @@ -270,10 +300,10 @@ object MtagsEnrichments extends CommonMtagsEnrichments: def seenFrom(sym: Symbol)(using Context): (Type, Symbol) = try val pre = tree.qual - val denot = sym.denot.asSeenFrom(pre.tpe.widenTermRefExpr) + val denot = sym.denot.asSeenFrom(pre.typeOpt.widenTermRefExpr) (denot.info, sym.withUpdatedTpe(denot.info)) catch case NonFatal(e) => (sym.info, sym) - + def isInfix(using ctx: Context) = tree match case Select(New(_), _) => false @@ -327,7 +357,7 @@ object MtagsEnrichments extends CommonMtagsEnrichments: case t: GenericApply if t.fun.srcPos.span.contains( pos.span - ) && !t.tpe.isErroneous => + ) && !t.typeOpt.isErroneous => tryTail(tail).orElse(Some(enclosing)) case in: Inlined => tryTail(tail).orElse(Some(enclosing)) diff --git a/presentation-compiler/test/dotty/tools/pc/base/BaseSignatureHelpSuite.scala b/presentation-compiler/test/dotty/tools/pc/base/BaseSignatureHelpSuite.scala index 0022be40a630..ca647502fabf 100644 --- a/presentation-compiler/test/dotty/tools/pc/base/BaseSignatureHelpSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/base/BaseSignatureHelpSuite.scala @@ -1,10 +1,11 @@ package dotty.tools.pc.base -import java.nio.file.Paths +import org.eclipse.lsp4j.SignatureHelp +import java.nio.file.Paths import scala.jdk.CollectionConverters.* -import scala.meta.internal.metals.CompilerOffsetParams import scala.language.unsafeNulls +import scala.meta.internal.metals.CompilerOffsetParams abstract class BaseSignatureHelpSuite extends BasePCSuite: def checkDoc( @@ -27,6 +28,10 @@ abstract class BaseSignatureHelpSuite extends BasePCSuite: ) .get() val out = new StringBuilder() + + // this is default SignatureHelp value which should only be returned on crash + assert(result != new SignatureHelp()) + if (result != null) { result.getSignatures.asScala.zipWithIndex.foreach { case (signature, i) => if (includeDocs) { @@ -38,10 +43,7 @@ abstract class BaseSignatureHelpSuite extends BasePCSuite: out .append(signature.getLabel) .append("\n") - if ( - result.getActiveSignature == i && result.getActiveParameter != null && signature.getParameters - .size() > 0 - ) { + if (result.getActiveSignature == i && result.getActiveParameter != null && signature.getParameters.size() > 0) { val param = signature.getParameters.get(result.getActiveParameter) val label = param.getLabel.getLeft() /* We need to find the label of the active parameter and show ^ at that spot diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionArgSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionArgSuite.scala index 16d54cc124ca..61239b535e1c 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionArgSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionArgSuite.scala @@ -1047,7 +1047,7 @@ class CompletionArgSuite extends BaseCompletionSuite: | bbb = 123, | aa@@ | ) - |} + |} |""".stripMargin, """|aaa = : Int |""".stripMargin, @@ -1063,7 +1063,7 @@ class CompletionArgSuite extends BaseCompletionSuite: | ccc = 123, | aa@@ | ) - |} + |} |""".stripMargin, """|aaa = : Int |""".stripMargin, @@ -1079,7 +1079,7 @@ class CompletionArgSuite extends BaseCompletionSuite: | ccc = 123, | aa@@ | ) - |} + |} |""".stripMargin, """|aaa = : Int |""".stripMargin, @@ -1105,4 +1105,18 @@ class CompletionArgSuite extends BaseCompletionSuite: """|str = : String | """.stripMargin, topLines = Some(1), + ) + + @Test def `comparison` = + check( + """package a + |object w { + | abstract class T(x: Int) { + | def met(x: Int): Unit = { + | println(x@@) + | } + | }} + |""".stripMargin, + """x: Int + |x = : Any""".stripMargin, ) \ No newline at end of file diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionCaseSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionCaseSuite.scala index b54915c56474..7a00c0397644 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionCaseSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionCaseSuite.scala @@ -542,7 +542,9 @@ class CompletionCaseSuite extends BaseCompletionSuite: | ca@@ | } |}""".stripMargin, - "" + """ + |case + |""".stripMargin ) @Test def `private-member-2` = @@ -721,4 +723,18 @@ class CompletionCaseSuite extends BaseCompletionSuite: |} |""".stripMargin, "case (Int, Int) => scala", - ) \ No newline at end of file + ) + + @Test def `keyword-only` = + check( + """ + |sealed trait Alpha + |object A { + | List.empty[Alpha].groupBy{ + | ca@@ + | } + |} + |""".stripMargin, + "case", + ) + diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionDocSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionDocSuite.scala index c419ce3946d9..45f07b5fb7b1 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionDocSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionDocSuite.scala @@ -16,14 +16,14 @@ class CompletionDocSuite extends BaseCompletionSuite: MockDocumentation("java/lang/String#join().", "join", Seq(), Seq("delimiter", "elements")), MockDocumentation("java/lang/String#substring().", "substring", Seq(), Seq("beginIndex")), MockDocumentation("java/lang/String#substring(+1).", "substring", Seq(), Seq("beginIndex", "endIndex")), - ScalaMockDocumentation("scala/collection/Iterator#sliding().", "sliding", List(MockParam("size"), MockParam("step", "1"))), - ScalaMockDocumentation("scala/collection/immutable/TreeMap#insert().", "insert", List(MockParam("key"), MockParam("value"))), + ScalaMockDocumentation("scala/collection/Iterator#sliding().", "sliding", List(), List(MockParam("size"), MockParam("step", "1"))), + ScalaMockDocumentation("scala/collection/immutable/TreeMap#insert().", "insert", List(), List(MockParam("key"), MockParam("value"))), ScalaMockDocumentation("scala/Option#isDefined().", "isDefined"), ScalaMockDocumentation("scala/util/DynamicVariable#", "DynamicVariable"), ScalaMockDocumentation("scala/util/DynamicVariable.", "DynamicVariable"), - ScalaMockDocumentation("scala/io/Source#reportWarning().", "reportWarning", List(MockParam("pos"), MockParam("msg"), MockParam("out", "Console.out"))), + ScalaMockDocumentation("scala/io/Source#reportWarning().", "reportWarning", List(), List(MockParam("pos"), MockParam("msg"), MockParam("out", "Console.out"))), ScalaMockDocumentation("scala/Predef.println().", "println"), - ScalaMockDocumentation("scala/Predef.println(+1).", "println", List(MockParam("x"))), + ScalaMockDocumentation("scala/Predef.println(+1).", "println", List(), List(MockParam("x"))), ScalaMockDocumentation("scala/Predef.", "Predef"), ScalaMockDocumentation("scala/runtime/stdLibPatches/Predef.", "Predef"), ScalaMockDocumentation("scala/util/control/Exception.Catch#", "Catch"), @@ -215,6 +215,7 @@ class CompletionDocSuite extends BaseCompletionSuite: """ |> Found documentation for scala/package.Vector. |Vector scala.collection.immutable + |Vector[A](elems: A*): Vector[A] |""".stripMargin, includeDocs = true ) @@ -316,5 +317,6 @@ class CompletionDocSuite extends BaseCompletionSuite: |} """.stripMargin, """|myNumbers: Vector[Int] + |myNumbers(i: Int): Int |""".stripMargin ) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionExtensionSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionExtensionSuite.scala index a260fe8b6e52..c01b38e7cf61 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionExtensionSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionExtensionSuite.scala @@ -20,6 +20,20 @@ class CompletionExtensionSuite extends BaseCompletionSuite: |""".stripMargin ) + @Test def `simple-old-syntax` = + check( + """|package example + | + |object Test: + | implicit class TestOps(a: Int): + | def testOps(b: Int): String = ??? + | + |def main = 100.test@@ + |""".stripMargin, + """|testOps(b: Int): String (implicit) + |""".stripMargin + ) + @Test def `simple2` = check( """|package example @@ -35,6 +49,21 @@ class CompletionExtensionSuite extends BaseCompletionSuite: filter = _.contains("(extension)") ) + @Test def `simple2-old-syntax` = + check( + """|package example + | + |object enrichments: + | implicit class TestOps(a: Int): + | def testOps(b: Int): String = ??? + | + |def main = 100.t@@ + |""".stripMargin, + """|testOps(b: Int): String (implicit) + |""".stripMargin, + filter = _.contains("(implicit)") + ) + @Test def `filter-by-type` = check( """|package example @@ -52,6 +81,22 @@ class CompletionExtensionSuite extends BaseCompletionSuite: filter = _.contains("(extension)") ) + @Test def `filter-by-type-old` = + check( + """|package example + | + |object enrichments: + | implicit class A(num: Int): + | def identity2: Int = num + 1 + | implicit class B(str: String): + | def identity: String = str + | + |def main = "foo".iden@@ + |""".stripMargin, + """|identity: String (implicit) + |""".stripMargin // identity2 won't be available + ) + @Test def `filter-by-type-subtype` = check( """|package example @@ -70,6 +115,24 @@ class CompletionExtensionSuite extends BaseCompletionSuite: filter = _.contains("(extension)") ) + @Test def `filter-by-type-subtype-old` = + check( + """|package example + | + |class A + |class B extends A + | + |object enrichments: + | implicit class Test(a: A): + | def doSomething: A = a + | + |def main = (new B).do@@ + |""".stripMargin, + """|doSomething: A (implicit) + |""".stripMargin, + filter = _.contains("(implicit)") + ) + @Test def `simple-edit` = checkEdit( """|package example @@ -92,6 +155,28 @@ class CompletionExtensionSuite extends BaseCompletionSuite: |""".stripMargin ) + @Test def `simple-edit-old` = + checkEdit( + """|package example + | + |object enrichments: + | implicit class A (num: Int): + | def incr: Int = num + 1 + | + |def main = 100.inc@@ + |""".stripMargin, + """|package example + | + |import example.enrichments.A + | + |object enrichments: + | implicit class A (num: Int): + | def incr: Int = num + 1 + | + |def main = 100.incr + |""".stripMargin + ) + @Test def `simple-edit-suffix` = checkEdit( """|package example @@ -114,6 +199,28 @@ class CompletionExtensionSuite extends BaseCompletionSuite: |""".stripMargin ) + @Test def `simple-edit-suffix-old` = + checkEdit( + """|package example + | + |object enrichments: + | implicit class A (val num: Int): + | def plus(other: Int): Int = num + other + | + |def main = 100.pl@@ + |""".stripMargin, + """|package example + | + |import example.enrichments.A + | + |object enrichments: + | implicit class A (val num: Int): + | def plus(other: Int): Int = num + other + | + |def main = 100.plus($0) + |""".stripMargin + ) + @Test def `simple-empty` = check( """|package example @@ -129,6 +236,21 @@ class CompletionExtensionSuite extends BaseCompletionSuite: filter = _.contains("(extension)") ) + @Test def `simple-empty-old` = + check( + """|package example + | + |object enrichments: + | implicit class TestOps(a: Int): + | def testOps(b: Int): String = ??? + | + |def main = 100.@@ + |""".stripMargin, + """|testOps(b: Int): String (implicit) + |""".stripMargin, + filter = _.contains("(implicit)") + ) + @Test def `directly-in-pkg1` = check( """| @@ -143,6 +265,20 @@ class CompletionExtensionSuite extends BaseCompletionSuite: |""".stripMargin ) + @Test def `directly-in-pkg1-old` = + check( + """| + |package examples: + | implicit class A(num: Int): + | def incr: Int = num + 1 + | + |package examples2: + | def main = 100.inc@@ + |""".stripMargin, + """|incr: Int (implicit) + |""".stripMargin + ) + @Test def `directly-in-pkg2` = check( """|package example: @@ -157,6 +293,20 @@ class CompletionExtensionSuite extends BaseCompletionSuite: |""".stripMargin ) + @Test def `directly-in-pkg2-old` = + check( + """|package examples: + | object X: + | def fooBar(num: Int) = num + 1 + | implicit class A (num: Int) { def incr: Int = num + 1 } + | + |package examples2: + | def main = 100.inc@@ + |""".stripMargin, + """|incr: Int (implicit) + |""".stripMargin + ) + @Test def `nested-pkg` = check( """|package a: // some comment @@ -175,7 +325,25 @@ class CompletionExtensionSuite extends BaseCompletionSuite: |""".stripMargin ) - @Test def `name-conflict` = + @Test def `nested-pkg-old` = + check( + """|package aa: // some comment + | package cc: + | implicit class A (num: Int): + | def increment2 = num + 2 + | implicit class A (num: Int): + | def increment = num + 1 + | + | + |package bb: + | def main: Unit = 123.incre@@ + |""".stripMargin, + """|increment: Int (implicit) + |increment2: Int (implicit) + |""".stripMargin + ) + + @Test def `name-conflict` = checkEdit( """ |package example diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionInterpolatorSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionInterpolatorSuite.scala index b5024e78f2e9..d70f28d08486 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionInterpolatorSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionInterpolatorSuite.scala @@ -635,7 +635,7 @@ class CompletionInterpolatorSuite extends BaseCompletionSuite: |""".stripMargin, """|class Paths |object Main { - | s"this is an interesting {java.nio.file.Paths}" + | s"this is an interesting ${java.nio.file.Paths}" |} |""".stripMargin, assertSingleItem = false, @@ -710,6 +710,26 @@ class CompletionInterpolatorSuite extends BaseCompletionSuite: filterText = "aaa.plus" ) + + @Test def `extension3` = + checkEdit( + """|trait Cursor + | + |extension (c: Cursor) def spelling: String = "hello" + |object Main { + | val c = new Cursor {} + | val x = s"$c.spelli@@" + |} + |""".stripMargin, + """|trait Cursor + | + |extension (c: Cursor) def spelling: String = "hello" + |object Main { + | val c = new Cursor {} + | val x = s"${c.spelling$0}" + |}""".stripMargin + ) + @Test def `filter-by-type` = check( """|package example diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionKeywordSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionKeywordSuite.scala index 583b138a255b..dc972ec22533 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionKeywordSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionKeywordSuite.scala @@ -38,7 +38,7 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | // tr@@ |} |""".stripMargin, - "", + "transparentTrait - scala.annotation (commit: '')", includeCommitCharacter = true ) @@ -57,7 +57,7 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | **/ |} |""".stripMargin, - "", + "transparentTrait - scala.annotation (commit: '')", includeCommitCharacter = true ) @@ -151,6 +151,8 @@ class CompletionKeywordSuite extends BaseCompletionSuite: """|value: Int |val |var + |varargs(): varargs + |varargs - scala.annotation |""".stripMargin ) @@ -167,6 +169,8 @@ class CompletionKeywordSuite extends BaseCompletionSuite: |""".stripMargin, """|val |var + |varargs(): varargs + |varargs - scala.annotation |""".stripMargin ) @@ -181,9 +185,10 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | } |} |""".stripMargin, - """|given (commit: '') - |""".stripMargin, - includeCommitCharacter = true + """given (commit: '') + |""".stripMargin, + includeCommitCharacter = true, + topLines = Some(5) ) @Test def `val-arg` = @@ -198,8 +203,8 @@ class CompletionKeywordSuite extends BaseCompletionSuite: |} |""".stripMargin, """|value: Int - |""".stripMargin, - topLines = Some(1) + |varargs(): varargs + |varargs - scala.annotation""".stripMargin ) @Test def `val-trailing-space` = @@ -406,7 +411,10 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | protected de@@ |} """.stripMargin, - "def" + """|def + |derived - scala.CanEqual + |deprecated - scala.runtime.stdLibPatches.language + |""".stripMargin, ) @Test def `protected-val` = @@ -418,9 +426,10 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | protected va@@ |} """.stripMargin, - """val - |var - |""".stripMargin + """|val + |var + |varargs - scala.annotation + |""".stripMargin ) @Test def `topLevel` = @@ -458,8 +467,13 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | def hello(u@@) |}""".stripMargin, """|using (commit: '') + |unsafe - scala.caps (commit: '') + |unsafeNulls - scala.runtime.stdLibPatches.language (commit: '') + |unused - scala.annotation (commit: '') + |unshared - scala.annotation.internal (commit: '') |""".stripMargin, - includeCommitCharacter = true + includeCommitCharacter = true, + topLines = Some(5) ) @Test def `not-using` = @@ -467,7 +481,12 @@ class CompletionKeywordSuite extends BaseCompletionSuite: """|object A{ | def hello(a: String, u@@) |}""".stripMargin, - "" + """|unsafe - scala.caps + |unsafeNulls - scala.runtime.stdLibPatches.language + |unused - scala.annotation + |unshared - scala.annotation.internal + |unspecialized - scala.annotation""".stripMargin, + topLines = Some(5) ) @Test def `extends-class` = diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionPatternSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionPatternSuite.scala index 6d2261bbfe66..df6a3f705be9 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionPatternSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionPatternSuite.scala @@ -54,7 +54,9 @@ class CompletionPatternSuite extends BaseCompletionSuite: | case ma@@ | } |}""".stripMargin, - "" + """|macros - scala.languageFeature.experimental + |macroImpl - scala.reflect.macros.internal + |""".stripMargin ) @Test def `bind2` = diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSnippetSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSnippetSuite.scala index 586b70d54006..c3e3f374c23d 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSnippetSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSnippetSuite.scala @@ -3,6 +3,7 @@ package dotty.tools.pc.tests.completion import dotty.tools.pc.base.BaseCompletionSuite import org.junit.Test +import org.junit.Ignore class CompletionSnippetSuite extends BaseCompletionSuite: @@ -76,32 +77,65 @@ class CompletionSnippetSuite extends BaseCompletionSuite: // Dotty does not currently support fuzzy completions. Please take a look at // https://github.com/lampepfl/dotty-feature-requests/issues/314 + @Ignore("Fuzzy should be provided by dotty") @Test def `type-empty` = - checkSnippet( - """ - |object Main { - | type MyType = List[Int] - | def list : MT@@ - |} - |""".stripMargin, - """|MyType - |""".stripMargin - ) + if (scala.util.Properties.isJavaAtLeast("9")) { + checkSnippet( + """ + |object Main { + | type MyType = List[Int] + | def list : MT@@ + |} + |""".stripMargin, + """|MyType + |""".stripMargin + ) + } else { + checkSnippet( + """ + |object Main { + | type MyType = List[Int] + | def list : MT@@ + |} + |""".stripMargin, + """|MyType + |MTOM + |MTOMFeature + |""".stripMargin + ) + } // Dotty does not currently support fuzzy completions. Please take a look at // https://github.com/lampepfl/dotty-feature-requests/issues/314 + @Ignore("Fuzzy should be provided by dotty") @Test def `type-new-empty` = - checkSnippet( - """ - |object Main { - | class Gen[T] - | type MyType = Gen[Int] - | new MT@@ - |} - |""".stripMargin, - """|MyType - |""".stripMargin - ) + if (scala.util.Properties.isJavaAtLeast("9")) { + checkSnippet( + """ + |object Main { + | class Gen[T] + | type MyType = Gen[Int] + | new MT@@ + |} + |""".stripMargin, + """|MyType + |""".stripMargin + ) + } else { + checkSnippet( + """ + |object Main { + | class Gen[T] + | type MyType = Gen[Int] + | new MT@@ + |} + |""".stripMargin, + """|MyType + |MTOM + |MTOMFeature + |""".stripMargin + ) + } @Test def `type` = checkSnippet( @@ -323,7 +357,8 @@ class CompletionSnippetSuite extends BaseCompletionSuite: |Widget($0) - (age: Int): Widget |Widget($0) - (name: String, age: Int): Widget |""".stripMargin, - includeDetail = true + includeDetail = true, + topLines = Some(4) ) @Test def `no-apply` = @@ -335,8 +370,13 @@ class CompletionSnippetSuite extends BaseCompletionSuite: | Wi@@ |} |""".stripMargin, - "Widget - example", - includeDetail = true + """|Widget - example + |Window - java.awt + |WindowPeer - java.awt.peer + |WithFilter - scala.collection + |""".stripMargin, + includeDetail = true, + topLines = Some(4) ) // https://github.com/scalameta/metals/issues/4004 diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala index 055363830a1b..68e9f7728a87 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala @@ -7,6 +7,7 @@ import dotty.tools.pc.base.BaseCompletionSuite import dotty.tools.pc.utils.MockEntries import org.junit.Test +import org.junit.Ignore class CompletionSuite extends BaseCompletionSuite: @@ -26,10 +27,10 @@ class CompletionSuite extends BaseCompletionSuite: |}""".stripMargin, """ |List scala.collection.immutable + |List[A](elems: A*): List[A] |List - java.awt |List - java.util - |List - scala.collection.immutable - |List[A](elems: A*): CC[A] + |ListMap[K, V](elems: (K, V)*): ListMap[K, V] |""".stripMargin, topLines = Some(5) ) @@ -109,17 +110,17 @@ class CompletionSuite extends BaseCompletionSuite: |tabulate[A](n: Int)(f: Int => A): List[A] |unapplySeq[A](x: List[A] @uncheckedVariance): UnapplySeqWrapper[A] |unfold[A, S](init: S)(f: S => Option[(A, S)]): List[A] - |->[B](y: B): (A, B) - |ensuring(cond: Boolean): A - |ensuring(cond: A => Boolean): A - |ensuring(cond: Boolean, msg: => Any): A - |ensuring(cond: A => Boolean, msg: => Any): A - |fromSpecific(from: From)(it: IterableOnce[A]): C - |fromSpecific(it: IterableOnce[A]): C - |nn: x.type & T - |toFactory(from: From): Factory[A, C] + |->[B](y: B): (List.type, B) + |ensuring(cond: Boolean): List.type + |ensuring(cond: List.type => Boolean): List.type + |ensuring(cond: Boolean, msg: => Any): List.type + |ensuring(cond: List.type => Boolean, msg: => Any): List.type + |fromSpecific(from: Any)(it: IterableOnce[Nothing]): List[Nothing] + |fromSpecific(it: IterableOnce[Nothing]): List[Nothing] + |nn: List.type & List.type + |toFactory(from: Any): Factory[Nothing, List[Nothing]] |formatted(fmtstr: String): String - |→[B](y: B): (A, B) + |→[B](y: B): (List.type, B) |iterableFactory[A]: Factory[A, List[A]] |asInstanceOf[X0]: X0 |equals(x$0: Any): Boolean @@ -146,6 +147,7 @@ class CompletionSuite extends BaseCompletionSuite: "XtensionMethod(a: Int): XtensionMethod" ) + @Ignore("This test should be handled by compiler fuzzy search") @Test def fuzzy = check( """ @@ -157,14 +159,14 @@ class CompletionSuite extends BaseCompletionSuite: |""".stripMargin ) + @Ignore("This test should be handled by compiler fuzzy search") @Test def fuzzy1 = check( """ |object A { - | new PBuil@@ + | new PBuilder@@ |}""".stripMargin, - """|ProcessBuilder java.lang - |ProcessBuilder - scala.sys.process + """|ProcessBuilder - scala.sys.process |ProcessBuilderImpl - scala.sys.process |""".stripMargin, filter = _.contains("ProcessBuilder") @@ -178,7 +180,7 @@ class CompletionSuite extends BaseCompletionSuite: | TrieMap@@ |}""".stripMargin, """|TrieMap scala.collection.concurrent - |TrieMap[K, V](elems: (K, V)*): CC[K, V] + |TrieMap[K, V](elems: (K, V)*): TrieMap[K, V] |""".stripMargin ) @@ -515,8 +517,8 @@ class CompletionSuite extends BaseCompletionSuite: """.stripMargin, """|until(end: Int): Range |until(end: Int, step: Int): Range - |until(end: T): Exclusive[T] - |until(end: T, step: T): Exclusive[T] + |until(end: Long): Exclusive[Long] + |until(end: Long, step: Long): Exclusive[Long] |""".stripMargin, postProcessObtained = _.replace("Float", "Double"), stableOrder = false @@ -618,9 +620,6 @@ class CompletionSuite extends BaseCompletionSuite: """|Some(value) scala |Some scala |Some[A](value: A): Some[A] - |SomeToExpr(x: Some[T])(using Quotes): Expr[Some[T]] - |SomeToExpr[T: Type: ToExpr]: SomeToExpr[T] - |SomeFromExpr[T](using Type[T], FromExpr[T]): SomeFromExpr[T] |""".stripMargin ) @@ -633,9 +632,6 @@ class CompletionSuite extends BaseCompletionSuite: |""".stripMargin, """|Some scala |Some[A](value: A): Some[A] - |SomeToExpr(x: Some[T])(using Quotes): Expr[Some[T]] - |SomeToExpr[T: Type: ToExpr]: SomeToExpr[T] - |SomeFromExpr[T](using Type[T], FromExpr[T]): SomeFromExpr[T] |""".stripMargin ) @@ -892,7 +888,7 @@ class CompletionSuite extends BaseCompletionSuite: topLines = Some(2) ) - // issues with scala 3 https://github.com/lampepfl/dotty/pull/13515 + // issues with scala 3 https://github.com/scala/scala3/pull/13515 @Test def ordering4 = check( s"""|class Main { @@ -1193,7 +1189,7 @@ class CompletionSuite extends BaseCompletionSuite: | val x = Bar[M](new Foo[Int]{}) | x.bar.m@@ |""".stripMargin, - """|map[B](f: A => B): Foo[B] + """|map[B](f: Int => B): Foo[B] |""".stripMargin, topLines = Some(1) ) @@ -1329,6 +1325,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension (x: Fo@@) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1349,6 +1355,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension [A <: Fo@@] |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1369,6 +1385,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension (using Fo@@) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1380,6 +1406,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension (x: Int)(using Fo@@) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1390,6 +1426,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension (using Fo@@)(x: Int)(using Foo) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1400,6 +1446,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension (using Foo)(x: Int)(using Fo@@) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1410,6 +1466,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension [A](x: Fo@@) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1420,6 +1486,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension [A](using Fo@@)(x: Int) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1430,6 +1506,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension [A](using Foo)(x: Fo@@) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1440,6 +1526,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension [A](using Foo)(x: Fo@@)(using Foo) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1545,3 +1641,96 @@ class CompletionSuite extends BaseCompletionSuite: assertSingleItem = false ) + + @Test def `multi-export` = + check( + """export scala.collection.{AbstractMap, Set@@} + |""".stripMargin, + """Set scala.collection + |SetOps scala.collection + |""".stripMargin + ) + + @Test def `multi-imports` = + check( + """import scala.collection.{AbstractMap, Set@@} + |""".stripMargin, + """Set scala.collection + |SetOps scala.collection + |""".stripMargin, + ) + + + @Test def `multi-imports-empty-query` = + check( + """import scala.collection.{AbstractMap, @@} + |""".stripMargin, + """GenIterable scala.collection + |GenMap scala.collection + |GenSeq scala.collection + |GenSet scala.collection + |GenTraversable scala.collection + |""".stripMargin, + topLines = Some(5) + ) + + @Test def `import-rename` = + check( + """import scala.collection.{AbstractMap => Set@@} + |""".stripMargin, + "" + ) + + @Ignore + @Test def `dont-crash-implicit-search` = + check( + """object M: + | Array[Int].fi@@ + |""".stripMargin, + "" + ) + + @Test def `extension-definition-type-variable-inference` = + check( + """|object M: + | extension [T](xs: List[T]) def test(p: T => Boolean): List[T] = ??? + | List(1,2,3).tes@@ + |""".stripMargin, + """|test(p: Int => Boolean): List[Int] + |""".stripMargin + ) + + @Test def `old-style-extension-type-variable-inference` = + check( + """|object M: + | implicit class ListUtils[T](xs: List[T]) { + | def test(p: T => Boolean): List[T] = ??? + | } + | List(1,2,3).tes@@ + |""".stripMargin, + """|test(p: Int => Boolean): List[Int] + |""".stripMargin + ) + + @Test def `instantiate-type-vars-in-extra-apply-completions` = + check( + """|object M: + | val fooBar = List(123) + | foo@@ + |""".stripMargin, + """|fooBar: List[Int] + |fooBar(n: Int): Int + |""".stripMargin + ) + + @Test def `show-underlying-type-instead-of-CC` = + check( + """|object M: + | List@@ + |""".stripMargin, + """|List[A](elems: A*): List[A] + |ListMap[K, V](elems: (K, V)*): ListMap[K, V] + |""".stripMargin, + filter = _.contains("[") + ) + diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionWorkspaceSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionWorkspaceSuite.scala index 98d164db87f1..82085932247d 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionWorkspaceSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionWorkspaceSuite.scala @@ -768,12 +768,33 @@ class CompletionWorkspaceSuite extends BaseCompletionSuite: | def main: Unit = incre@@ |""".stripMargin, """|increment3: Int - |increment: Int - |increment2: Int + |increment - a: Int + |increment2 - a.c: Int |""".stripMargin ) - @Test def `case_class_param` = + @Test def `indent-method` = + check( + """|package a: + | val y = 123 + | given intGiven: Int = 123 + | type Alpha = String + | class Foo(x: Int) + | object X: + | val x = 123 + | def fooBar(x: Int) = x + 1 + | package b: + | def fooBar(x: String) = x.length + | + |package c: + | def main() = foo@@ + |""".stripMargin, + """|fooBar - a(x: Int): Int + |fooBar - a.b(x: String): Int + |""".stripMargin + ) + + @Test def `case-class-param` = check( """|case class Foo(fooBar: Int, gooBar: Int) |class Bar(val fooBaz: Int, val fooBal: Int) { @@ -790,6 +811,7 @@ class CompletionWorkspaceSuite extends BaseCompletionSuite: |""".stripMargin, """|fooBar: String |fooBar: List[Int] + |fooBar(n: Int): Int |""".stripMargin, ) @@ -825,7 +847,7 @@ class CompletionWorkspaceSuite extends BaseCompletionSuite: |MyType - demo.other""".stripMargin, ) - @Test def `method-name-conflict` = + @Test def `method-name-conflict` = checkEdit( """|package demo | @@ -847,5 +869,21 @@ class CompletionWorkspaceSuite extends BaseCompletionSuite: | } |} |""".stripMargin, - filter = _.contains("mmmm(x: Int)") + filter = _.contains("mmmm - demo.O") + ) + + @Test def `method-label` = + check( + """|package demo + | + |object O { + | def method(i: Int): Int = i + 1 + |} + | + |object Main { + | val x = meth@@ + |} + |""".stripMargin, + """|method - demo.O(i: Int): Int + |""".stripMargin ) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/decorations/SyntheticDecorationsSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/decorations/SyntheticDecorationsSuite.scala index 7d4cc3cf41a4..49ffb911aaa3 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/decorations/SyntheticDecorationsSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/decorations/SyntheticDecorationsSuite.scala @@ -498,3 +498,31 @@ class SyntheticDecorationsSuite extends BaseSyntheticDecorationsSuite: |""".stripMargin ) + @Test def `val-def-with-bind` = + check( + """ + |object O { + | val tupleBound @ (one, two) = ("1", "2") + |} + |""".stripMargin, + """ + |object O { + | val tupleBound @ (one: String, two: String) = ("1", "2") + |} + |""".stripMargin + ) + + @Test def `val-def-with-bind-and-comment` = + check( + """ + |object O { + | val tupleBound /* comment */ @ (one, two) = ("1", "2") + |} + |""".stripMargin, + """ + |object O { + | val tupleBound /* comment */ @ (one: String, two: String) = ("1", "2") + |} + |""".stripMargin + ) + diff --git a/presentation-compiler/test/dotty/tools/pc/tests/definition/PcDefinitionSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/definition/PcDefinitionSuite.scala index 358e159eb539..9636aea77c2e 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/definition/PcDefinitionSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/definition/PcDefinitionSuite.scala @@ -199,6 +199,81 @@ class PcDefinitionSuite extends BasePcDefinitionSuite: |""".stripMargin ) + @Test def exportType0 = + check( + """object Foo: + | trait <> + |object Bar: + | export Foo.* + |class Test: + | import Bar.* + | def test = new Ca@@t {} + |""".stripMargin + ) + + @Test def exportType1 = + check( + """object Foo: + | trait <>[A] + |object Bar: + | export Foo.* + |class Test: + | import Bar.* + | def test = new Ca@@t[Int] {} + |""".stripMargin + ) + + @Test def exportTerm0Nullary = + check( + """trait Foo: + | def <>: Int + |class Bar(val foo: Foo): + | export foo.* + | def test(bar: Bar) = bar.me@@th + |""".stripMargin + ) + + @Test def exportTerm0 = + check( + """trait Foo: + | def <>(): Int + |class Bar(val foo: Foo): + | export foo.* + | def test(bar: Bar) = bar.me@@th() + |""".stripMargin + ) + + @Test def exportTerm1 = + check( + """trait Foo: + | def <>(x: Int): Int + |class Bar(val foo: Foo): + | export foo.* + | def test(bar: Bar) = bar.me@@th(0) + |""".stripMargin + ) + + @Test def exportTerm1Poly = + check( + """trait Foo: + | def <>[A](x: A): A + |class Bar(val foo: Foo): + | export foo.* + | def test(bar: Bar) = bar.me@@th(0) + |""".stripMargin + ) + + @Test def exportTerm1Overload = + check( + """trait Foo: + | def <>(x: Int): Int + | def meth(x: String): String + |class Bar(val foo: Foo): + | export foo.* + | def test(bar: Bar) = bar.me@@th(0) + |""".stripMargin + ) + @Test def `named-arg-local` = check( """| diff --git a/presentation-compiler/test/dotty/tools/pc/tests/edit/ConvertToNamedArgumentsSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/edit/ConvertToNamedArgumentsSuite.scala index 5285be83b537..359a63442408 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/edit/ConvertToNamedArgumentsSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/edit/ConvertToNamedArgumentsSuite.scala @@ -6,7 +6,6 @@ import java.util.concurrent.ExecutionException import scala.meta.internal.jdk.CollectionConverters.* import scala.meta.internal.metals.CompilerOffsetParams import scala.meta.internal.pc.CodeActionErrorMessages -import scala.meta.pc.DisplayableException import scala.language.unsafeNulls import dotty.tools.pc.base.BaseCodeActionSuite diff --git a/presentation-compiler/test/dotty/tools/pc/tests/edit/InsertInferredTypeSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/edit/InsertInferredTypeSuite.scala index d6707c54894e..f12cab7e65ef 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/edit/InsertInferredTypeSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/edit/InsertInferredTypeSuite.scala @@ -789,6 +789,28 @@ class InsertInferredTypeSuite extends BaseCodeActionSuite: |""".stripMargin ) + @Test def `import-rename` = + checkEdit( + """ + |package a + |import scala.collection.{AbstractMap => AB} + | + |object Main { + | def test(): AB[Int, String] = ??? + | val <> = test() + |} + |""".stripMargin, + """ + |package a + |import scala.collection.{AbstractMap => AB} + | + |object Main { + | def test(): AB[Int, String] = ??? + | val x: AB[Int, String] = test() + |} + |""".stripMargin + ) + def checkEdit( original: String, expected: String diff --git a/presentation-compiler/test/dotty/tools/pc/tests/highlight/DocumentHighlightSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/highlight/DocumentHighlightSuite.scala index 1dc2a7b156db..5d9893f6a1c1 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/highlight/DocumentHighlightSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/highlight/DocumentHighlightSuite.scala @@ -1186,7 +1186,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |""".stripMargin, ) - @Test def `constructor` = + @Test def `constructor` = check( """ |object Main { @@ -1195,7 +1195,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor1` = + @Test def `constructor1` = check( """ |object Main { @@ -1204,7 +1204,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor2` = + @Test def `constructor2` = check( """ |object Main { @@ -1214,7 +1214,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor3` = + @Test def `constructor3` = check( """ |object Main { @@ -1224,7 +1224,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor4` = + @Test def `constructor4` = check( """ |object Main { @@ -1234,7 +1234,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor5` = + @Test def `constructor5` = check( """ |object Main { @@ -1246,7 +1246,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor6` = + @Test def `constructor6` = check( """ |class <>[T](a: T) @@ -1256,7 +1256,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor7` = + @Test def `constructor7` = check( """ |object Bar { @@ -1268,7 +1268,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor8` = + @Test def `constructor8` = check( """ |object Bar { @@ -1279,3 +1279,188 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: | val x = Bar.<>[Int](2) |}""".stripMargin ) + + @Test def `i5630` = + check( + """|class MyIntOut(val value: Int) + |object MyIntOut: + | extension (i: MyIntOut) def <> = i.value % 2 == 1 + | + |val a = MyIntOut(1) + |val m = a.<> + |""".stripMargin + ) + + @Test def `i5630-2` = + check( + """|class MyIntOut(val value: Int) + |object MyIntOut: + | extension (i: MyIntOut) def <>(u: Int) = i.value % 2 == 1 + | + |val a = MyIntOut(1).<>(3) + |""".stripMargin + ) + + @Test def `i5630-infix` = + check( + """|class MyIntOut(val value: Int) + |object MyIntOut: + | extension (i: MyIntOut) def <<++>>(u: Int) = i.value + u + | + |val a = MyIntOut(1) <<+@@+>> 3 + |""".stripMargin + ) + + @Test def `i5921-1` = + check( + """|object Logarithms: + | opaque type Logarithm = Double + | extension [K](vmap: Logarithm) + | def <>(k: Logarithm): Logarithm = ??? + | + |object Test: + | val in: Logarithms.Logarithm = ??? + | in.<>(in) + |""".stripMargin + ) + + @Test def `i5921-2` = + check( + """|object Logarithms: + | opaque type Logarithm = Double + | extension [K](vmap: Logarithm) + | def <>(k: Logarithm): Logarithm = ??? + | + |object Test: + | val in: Logarithms.Logarithm = ??? + | in.<>(in) + |""".stripMargin + ) + + @Test def `i5921-3` = + check( + """|object Logarithms: + | opaque type Logarithm = Double + | extension [K](vmap: Logarithm) + | def <>(k: Logarithm): Logarithm = ??? + | (2.0).<>(1.0) + |""".stripMargin + ) + + @Test def `i5921-4` = + check( + """|object Logarithms: + | opaque type Logarithm = Double + | extension [K](vmap: Logarithm) + | def <>(k: Logarithm): Logarithm = ??? + | (2.0).<>(1.0) + |""".stripMargin + ) + + @Test def `i5977` = + check( + """ + |sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def <>[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Int](_.<>("str")) + | usage[Int](_.<>[String]("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>[String]("str")) + |} + |""".stripMargin + ) + + @Test def `i5977-1` = + check( + """ + |sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def <>[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Int](_.<>("str")) + | usage[Int](_.<>[String]("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>[String]("str")) + |} + |""".stripMargin + ) + + @Test def `i5977-2` = + check( + """ + |sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def <>[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Int](_.<>("str")) + | usage[Int](_.<>[String]("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>[String]("str")) + |} + |""".stripMargin + ) + + @Test def `i5977-3` = + check( + """ + |sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def <>[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Int](_.<>("str")) + | usage[Int](_.<>[String]("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>[String]("str")) + |} + |""".stripMargin + ) + + @Test def `i5977-4` = + check( + """ + |sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def <>[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Int](_.<>("str")) + | usage[Int](_.<>[String]("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>[String]("str")) + |} + |""".stripMargin + ) + + +end DocumentHighlightSuite diff --git a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverDefnSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverDefnSuite.scala index 84af8f21f258..7a647fa40f5f 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverDefnSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverDefnSuite.scala @@ -163,8 +163,7 @@ class HoverDefnSuite extends BaseHoverSuite: """package b.p@@kg |object Main |""".stripMargin, - // TODO, doesn's show information on packages - "" + "package b.pkg".hover, ) @Test def `pat-bind` = diff --git a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverDocSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverDocSuite.scala index 06c629467166..fc9b6835e319 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverDocSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverDocSuite.scala @@ -10,10 +10,10 @@ class HoverDocSuite extends BaseHoverSuite: override protected def mockEntries: MockEntries = new MockEntries: override def documentations: Set[SymbolDocumentation] = Set( - ScalaMockDocumentation("java/lang/String#substring().", "substring", List(MockParam("beginIndex"))), + ScalaMockDocumentation("java/lang/String#substring().", "substring", List(), List(MockParam("beginIndex"))), ScalaMockDocumentation("java/util/Collections#emptyList().", "emptyList"), - ScalaMockDocumentation("_empty_/Alpha.apply().", "apply", List(MockParam("x"))), - ScalaMockDocumentation("_empty_/Alpha#", "init", List(MockParam("x"))), + ScalaMockDocumentation("_empty_/Alpha.apply().", "apply", List(), List(MockParam("x"))), + ScalaMockDocumentation("_empty_/Alpha#", "init", List(), List(MockParam("x"))), ScalaMockDocumentation("scala/collection/LinearSeqOps#headOption().", "headOption"), ) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverNamedArgSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverNamedArgSuite.scala index f92ba9933be4..182f8e1e0644 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverNamedArgSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverNamedArgSuite.scala @@ -11,7 +11,7 @@ class HoverNamedArgSuite extends BaseHoverSuite: override protected def mockEntries: MockEntries = new MockEntries: override def documentations: Set[SymbolDocumentation] = Set( - ScalaMockDocumentation("a/b.foo().(named)", "foo", List(MockParam("named"))) + ScalaMockDocumentation("a/b.foo().(named)", "foo", List(), List(MockParam("named"))) ) @Test def `named` = diff --git a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala index 7ce81464fbd6..82fd0c657e67 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala @@ -112,7 +112,7 @@ class HoverTermSuite extends BaseHoverSuite: | } |} |""".stripMargin, - // https://github.com/lampepfl/dotty/issues/8835 + // https://github.com/scala/scala3/issues/8835 """|object num: a.Xtension |""".stripMargin.hover ) @@ -412,3 +412,228 @@ class HoverTermSuite extends BaseHoverSuite: |""".stripMargin, "def this(): tailrec".hover ) + + @Test def `i5630` = + check( + """class MyIntOut(val value: Int) + |object MyIntOut: + | extension (i: MyIntOut) def uneven = i.value % 2 == 1 + | + |object Test: + | val a = MyIntOut(1).un@@even + |""".stripMargin, + """extension (i: MyIntOut) def uneven: Boolean + |""".stripMargin.hover + ) + + @Test def `i5921` = + check( + """object Logarithms: + | trait Logarithm + | extension [K](vmap: Logarithm) + | def multiply(k: Logarithm): Logarithm = ??? + | + |object Test: + | val in: Logarithms.Logarithm = ??? + | in.multi@@ply(in) + |""".stripMargin, + "extension [K](vmap: Logarithm) def multiply(k: Logarithm): Logarithm".hover + ) + + @Test def `i5976` = + check( + """sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def noTypeArg: A + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Option[Int]](_.typeArg[Some[Int]].value.noTyp@@eArg.typeArg[Int]) + |} + |""".stripMargin, + """**Expression type**: + |```scala + |Int + |``` + |**Symbol signature**: + |```scala + |extension [A](self: A) def noTypeArg: A + |``` + |""".stripMargin + ) + + @Test def `i5976-1` = + check( + """sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def noTypeArg: A + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Option[Int]](_.type@@Arg[Some[Int]].value.noTypeArg.typeArg[Int]) + |} + |""".stripMargin, + """**Expression type**: + |```scala + |Some[Int] + |``` + |**Symbol signature**: + |```scala + |extension [A](self: A) def typeArg[B <: A]: B + |``` + |""".stripMargin + ) + + @Test def `i5977` = + check( + """sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def inferredTypeArg[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Option[Int]](_.infer@@redTypeArg("str")) + |} + |""".stripMargin, + """**Expression type**: + |```scala + |String + |``` + |**Symbol signature**: + |```scala + |extension [A](self: A) def inferredTypeArg[C](value: C): C + |``` + |""".stripMargin + ) + + @Test def `i5977-1` = + check( + """sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def inferredTypeArg[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Option[Int]](_.infer@@redTypeArg[String]("str")) + |} + |""".stripMargin, + """**Expression type**: + |```scala + |String + |``` + |**Symbol signature**: + |```scala + |extension [A](self: A) def inferredTypeArg[C](value: C): C + |``` + |""".stripMargin + ) + + @Test def `i5977-2` = + check( + """sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def inferredTypeArg[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Option[Int]](_.typeArg[Some[Int]].value.infer@@redTypeArg("str")) + |} + |""".stripMargin, + """**Expression type**: + |```scala + |String + |``` + |**Symbol signature**: + |```scala + |extension [A](self: A) def inferredTypeArg[C](value: C): C + |``` + |""".stripMargin + ) + + @Test def `i5977-3` = + check( + """sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def inferredTypeArg[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Option[Int]](_.typeArg[Some[Int]].value.infer@@redTypeArg[String]("str")) + |} + |""".stripMargin, + """**Expression type**: + |```scala + |String + |``` + |**Symbol signature**: + |```scala + |extension [A](self: A) def inferredTypeArg[C](value: C): C + |``` + |""".stripMargin + ) + + @Test def `import-rename` = + check( + """ + |import scala.collection.{AbstractMap => AB} + |import scala.collection.{Set => S} + | + |object Main { + | def test(): AB[Int, String] = ??? + | <> + |} + |""".stripMargin, + """ + |```scala + |type AB = AbstractMap + |``` + | + |```scala + |val tt: AB[Int, String] + |```""".stripMargin, + ) + + @Test def `import-rename2` = + check( + """ + |import scala.collection.{AbstractMap => AB} + |import scala.collection.{Set => S} + | + |object Main { + | <> + |} + |""".stripMargin, + """ + |```scala + |type S = Set + |type AB = AbstractMap + |``` + | + |```scala + |def test(d: S[Int], f: S[Char]): AB[Int, String] + |```""".stripMargin, + ) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTypeSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTypeSuite.scala index 2157aa891bae..c6e2590f8f29 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTypeSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTypeSuite.scala @@ -41,7 +41,7 @@ class HoverTypeSuite extends BaseHoverSuite: ) // We should produce a shorter type but: - // https://github.com/lampepfl/dotty/issues/11683 + // https://github.com/scala/scala3/issues/11683 @Test def `enums` = check( """| @@ -125,7 +125,7 @@ class HoverTypeSuite extends BaseHoverSuite: * As user can actually supply params to them by hand when * invoking the extension method, we always show them next to the * method itself. - * https://github.com/lampepfl/dotty/issues/13123 + * https://github.com/scala/scala3/issues/13123 */ @Test def `extension-methods-complex` = check( @@ -362,8 +362,35 @@ class HoverTypeSuite extends BaseHoverSuite: |object MyIntOut: | extension (i: MyIntOut) def uneven = i.value % 2 == 1 | - |val a = MyIntOut(1).un@@even + |object Test: + | val a = MyIntOut(1).un@@even |""".stripMargin, """|extension (i: MyIntOut) def uneven: Boolean |""".stripMargin.hover, ) + + @Test def `recursive-enum-without-type` = + check( + """class Wrapper(n: Int): + | extension (x: Int) + | def + (y: Int) = new Wrap@@per(x) + y + |""".stripMargin, + """```scala + |def this(n: Int): Wrapper + |``` + |""".stripMargin + ) + + @Test def `recursive-enum-without-type-1` = + check( + """class Wrapper(n: Int): + | def add(x: Int): Wrapper = ??? + | extension (x: Int) + | def + (y: Int) = Wrap@@per(x).add(5) + |""".stripMargin, + """```scala + |def this(n: Int): Wrapper + |``` + |""".stripMargin + ) + diff --git a/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpDocSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpDocSuite.scala index 7d36dc6ce23d..09b22559d35c 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpDocSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpDocSuite.scala @@ -26,13 +26,13 @@ class SignatureHelpDocSuite extends BaseSignatureHelpSuite: MockDocumentation("java/io/File#``(+1).", "", Seq(), Seq("parent", "child")), MockDocumentation("java/io/File#``(+2).", "", Seq(), Seq("parent", "child")), MockDocumentation("java/io/File#``(+3).", "", Seq(), Seq("uri")), - ScalaMockDocumentation("java/util/Collections#singleton().", "singleton", List(MockParam("o"))), + ScalaMockDocumentation("java/util/Collections#singleton().", "singleton", List(MockParam("T")), List(MockParam("o"))), ScalaMockDocumentation("scala/Some#", "Some"), - ScalaMockDocumentation("scala/Option#fold().", "fold", List(MockParam("ifEmpty"), MockParam("f"))), - ScalaMockDocumentation("scala/Option.apply().", "apply", List(MockParam("x"))), - ScalaMockDocumentation("scala/collection/immutable/List#map().", "map", List(MockParam("f"))), - ScalaMockDocumentation("scala/collection/LinearSeqOps#foldLeft().", "foldLeft", List(MockParam("z"), MockParam("op"))), - ScalaMockDocumentation("scala/util/control/Exception.Catch#", "Catch", List(MockParam("pf"), MockParam("fin"), MockParam("rethrow"))) + ScalaMockDocumentation("scala/Option#fold().", "fold", List(MockParam("B")), List(MockParam("ifEmpty"), MockParam("f"))), + ScalaMockDocumentation("scala/Option.apply().", "apply", List(), List(MockParam("x"))), + ScalaMockDocumentation("scala/collection/immutable/List#map().", "map", List(MockParam("B")), List(MockParam("f"))), + ScalaMockDocumentation("scala/collection/LinearSeqOps#foldLeft().", "foldLeft", List(MockParam("B")), List(MockParam("z"), MockParam("op"))), + ScalaMockDocumentation("scala/util/control/Exception.Catch#", "Catch", List(), List(MockParam("pf"), MockParam("fin"), MockParam("rethrow"))) ) @Test def `curry` = @@ -45,6 +45,7 @@ class SignatureHelpDocSuite extends BaseSignatureHelpSuite: s"""Found documentation for scala/Option#fold(). |fold[B](ifEmpty: => B)(f: Int => B): B | ^^^^^^^^^^^ + | @param B Found documentation for type param B | @param ifEmpty Found documentation for param ifEmpty | @param f Found documentation for param f """.stripMargin @@ -60,6 +61,7 @@ class SignatureHelpDocSuite extends BaseSignatureHelpSuite: s"""|Found documentation for scala/Option#fold(). |fold[B](ifEmpty: => B)(f: Int => B): B | ^^^^^^^^^^^^^ + | @param B Found documentation for type param B | @param ifEmpty Found documentation for param ifEmpty | @param f Found documentation for param f |""".stripMargin @@ -77,6 +79,7 @@ class SignatureHelpDocSuite extends BaseSignatureHelpSuite: """|Found documentation for scala/collection/LinearSeqOps#foldLeft(). |foldLeft[B](z: B)(op: (B, Int) => B): B | ^^^^^^^^^^^^^^^^^ + | @param B Found documentation for type param B | @param z Found documentation for param z | @param op Found documentation for param op |""".stripMargin @@ -106,6 +109,7 @@ class SignatureHelpDocSuite extends BaseSignatureHelpSuite: """|Found documentation for scala/collection/immutable/List#map(). |map[B](f: Int => B): List[B] | ^^^^^^^^^^^ + | @param B Found documentation for type param B | @param f Found documentation for param f |""".stripMargin ) @@ -134,6 +138,7 @@ class SignatureHelpDocSuite extends BaseSignatureHelpSuite: """|Found documentation for java/util/Collections#singleton(). |singleton[T](o: T): java.util.Set[T] | ^^^^ + | @param T Found documentation for type param T | @param o Found documentation for param o |""".stripMargin ) @@ -146,8 +151,8 @@ class SignatureHelpDocSuite extends BaseSignatureHelpSuite: |} """.stripMargin, """|Found documentation for scala/util/control/Exception.Catch# - |Catch[T](pf: scala.util.control.Exception.Catcher[T], fin: Option[scala.util.control.Exception.Finally], rethrow: Throwable => Boolean) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + |Catch[T](pf: Catcher[T], fin: Option[Finally], rethrow: Throwable => Boolean) + | ^^^^^^^^^^^^^^ | @param pf Found documentation for param pf | @param fin Found documentation for param fin | @param rethrow Found documentation for param rethrow @@ -161,9 +166,9 @@ class SignatureHelpDocSuite extends BaseSignatureHelpSuite: | new java.io.File(@@) |} """.stripMargin, - """|File(uri: java.net.URI) - | ^^^^^^^^^^^^^^^^^ - |File(parent: java.io.File, child: String) + """|File(uri: URI) + | ^^^^^^^^ + |File(parent: File, child: String) |File(parent: String, child: String) |File(pathname: String) |""".stripMargin diff --git a/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpInterleavingSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpInterleavingSuite.scala new file mode 100644 index 000000000000..15546d086033 --- /dev/null +++ b/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpInterleavingSuite.scala @@ -0,0 +1,518 @@ +package dotty.tools.pc.tests.signaturehelp + +import dotty.tools.pc.base.BaseSignatureHelpSuite + +import org.junit.Test +import org.junit.Ignore +import java.nio.file.Path + +class SignatureHelpInterleavingSuite extends BaseSignatureHelpSuite: + + override protected def scalacOptions(classpath: Seq[Path]): Seq[String] = + List("-language:experimental.clauseInterleaving") + + @Test def `proper-position-1` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[@@Int](1)[String]("1") + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^ + |""".stripMargin + ) + + + @Test def `proper-position-2` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[Int](@@1)[String]("1") + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^^^^ + |""".stripMargin + ) + + @Test def `proper-position-3` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[Int](1)[@@String]("1") + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^ + |""".stripMargin + ) + + @Test def `proper-position-4` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[Int](1)[String](@@"1") + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^^^^ + |""".stripMargin + ) + + @Test def `not-fully-applied-1` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[@@Int] + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^ + |""".stripMargin + ) + + + @Test def `not-fully-applied-2` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[Int](@@1) + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^^^^ + |""".stripMargin + ) + + @Test def `not-fully-applied-3` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[Int](1)[@@String] + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^ + |""".stripMargin + ) + + @Test def `error` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[Int][@@String] + """.stripMargin, + "" + ) + + @Test def `inferred-type-param-1` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair(1@@) + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^^^^ + |""".stripMargin + ) + + @Test def `inferred-type-param-2` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair(1)[String@@] + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^ + |""".stripMargin + ) + + @Test def `inferred-type-param-3` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair(1)[String]("1"@@) + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^^^^ + |""".stripMargin + ) + + @Test def `inferred-type-param-4` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair(1)("1"@@) + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^^^^ + |""".stripMargin + ) + + @Test def `empty-current-param-check` = + check( + """ + |object Test: + | def pair[A](a: A): A = ??? + | pair[@@] + """.stripMargin, + """ + |pair[A](a: A): A + | ^ + |""".stripMargin + ) + + @Test def `empty-current-param-2` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[Int](@@) + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^^^^ + |""".stripMargin + ) + + @Test def `empty-current-param-3` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[Int](1)[@@] + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^ + |""".stripMargin + ) + + @Test def `empty-current-param-4` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[Int](1)[String](@@) + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^^^^ + |""".stripMargin + ) + + @Test def `empty-current-inferred-1` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair(@@) + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^^^^ + |""".stripMargin + ) + + @Test def `empty-current-inferred-2` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair(1)(@@) + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^^^^ + |""".stripMargin + ) + + @Test def `empty-previous-1` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[](@@) + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^^^^ + |""".stripMargin + ) + + @Test def `empty-previous-2` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[]()[@@] + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^ + |""".stripMargin + ) + + @Test def `empty-previous-3` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[]()[](@@) + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^^^^ + |""".stripMargin + ) + + @Test def `empty-previous-4` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[]()[](11@@) + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^^^^ + |""".stripMargin + ) + + @Test def `empty-previous-5` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[](5@@1) + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^^^^ + |""".stripMargin + ) + + @Test def `empty-previous-6` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[String]()[@@] + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^ + |""".stripMargin + ) + + @Test def `empty-previous-7` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[String]()[Int](@@) + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^^^^ + |""".stripMargin + ) + + @Test def `error-previous-1` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[String](52)[@@] + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^ + |""".stripMargin + ) + + @Test def `error-previous-2` = + check( + """ + |object Test: + | def pair[A](a: A)[B](b: B): (A, B) = (a, b) + | pair[String](52)[Int](""@@) + """.stripMargin, + """ + |pair[A](a: A)[B](b: B): (A, B) + | ^^^^ + |""".stripMargin + ) + + @Test def `complex-1` = + check( + """ + |object Test: + | def foo[A](using a: A)(b: List[A])[C <: a.type, D](cd: (C, D))[E]: Foo[A, B, C, D, E] + | foo[Int](using 1)(List(1, 2, 3))(@@) + """.stripMargin, + """ + |foo[A](using a: A)(b: List[A])[C <: a.type, D](cd: (C, D))[E]: Foo[A, B, C, D, E] + | ^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `complex-2` = + check( + """ + |object Test: + | def foo[A](using a: A)(b: List[A])[C <: a.type, D](cd: (C, D))[E]: Foo[A, B, C, D, E] + | foo[Int](using 1)(List(1, 2, 3))((1, 2))[@@] + """.stripMargin, + """ + |foo[A](using a: A)(b: List[A])[C <: a.type, D](cd: (C, D))[E]: Foo[A, B, C, D, E] + | ^ + |""".stripMargin + ) + + @Ignore("""Clause interleaving is still experimental. It lifts this tree into series of anonymous functions, which all have the same span. + It requires further investigation to determine whether this is a bug in the compiler.""") + @Test def `clause-interleaving-empty` = + check( + """|object M: + | def test[X](x: X)[Y](y: Y): (X, Y)= ??? + | test[@@] + |""".stripMargin, + """|test[X](x: X)[Y](y: Y): (X, Y) + | ^ + |""".stripMargin + ) + + @Ignore("""Clause interleaving is still experimental. It lifts this tree into series of anonymous functions, which all have the same span. + It requires further investigation to determine whether this is a bug in the compiler.""") + @Test def `more-interleaved-params-1` = + check( + """|object M: + | def test[A](a: A)[B](b: B)[C](c: C)[D](d: D): Int = ??? + | test[@@] + |""".stripMargin, + """|test[A](a: A)[B](b: B)[C](c: C)[D](d: D): Int + | ^ + |""".stripMargin + ) + + @Test def `more-interleaved-params-2` = + check( + """|object M: + | def test[A](a: A)[B](b: B)[C](c: C)[D](d: D): Int = ??? + | test[Int](@@) + |""".stripMargin, + """|test[A](a: A)[B](b: B)[C](c: C)[D](d: D): Int + | ^^^^ + |""".stripMargin + ) + + @Ignore("""Clause interleaving is still experimental. It lifts this tree into series of anonymous functions, which all have the same span. + It requires further investigation to determine whether this is a bug in the compiler.""") + @Test def `more-interleaved-params-3` = + check( + """|object M: + | def test[A](a: A)[B](b: B)[C](c: C)[D](d: D): Int = ??? + | test[Int](1)[@@] + |""".stripMargin, + """|test[A](a: A)[B](b: B)[C](c: C)[D](d: D): Int + | ^ + |""".stripMargin + ) + + @Test def `more-interleaved-params-4` = + check( + """|object M: + | def test[A](a: A)[B](b: B)[C](c: C)[D](d: D): Int = ??? + | test[Int](1)[String](@@) + |""".stripMargin, + """|test[A](a: A)[B](b: B)[C](c: C)[D](d: D): Int + | ^^^^ + |""".stripMargin + ) + + @Ignore("""Clause interleaving is still experimental. It lifts this tree into series of anonymous functions, which all have the same span. + It requires further investigation to determine whether this is a bug in the compiler.""") + @Test def `more-interleaved-params-5` = + check( + """|object M: + | def test[A](a: A)[B](b: B)[C](c: C)[D](d: D): Int = ??? + | test[Int](1)[String]("1")[@@] + |""".stripMargin, + """|test[A](a: A)[B](b: B)[C](c: C)[D](d: D): Int + | ^ + |""".stripMargin + ) + + @Test def `more-interleaved-params-6` = + check( + """|object M: + | def test[A](a: A)[B](b: B)[C](c: C)[D](d: D): Int = ??? + | test[Int](1)[String]("1")[Int](@@) + |""".stripMargin, + """|test[A](a: A)[B](b: B)[C](c: C)[D](d: D): Int + | ^^^^ + |""".stripMargin + ) + + @Test def `more-interleaved-params-7` = + check( + """|object M: + | def test[A](a: A)[B](b: B)[C](c: C)[D](d: D): Int = ??? + | test[Int](1)[String]("1")[Int](2)[@@] + |""".stripMargin, + """|test[A](a: A)[B](b: B)[C](c: C)[D](d: D): Int + | ^ + |""".stripMargin + ) + + @Test def `more-interleaved-params-8` = + check( + """|object M: + | def test[A](a: A)[B](b: B)[C](c: C)[D](d: D): Int = ??? + | test[Int](1)[String]("1")[Int](2)[String](@@) + |""".stripMargin, + """|test[A](a: A)[B](b: B)[C](c: C)[D](d: D): Int + | ^^^^ + |""".stripMargin + ) + + @Test def `interleaving-with-implicit` = + check( + """|object M: + | def test[A](a: A)(using Int)[B](b: B)[C](c: C)[D](d: D): Int = ??? + | test[Int](1)(using 5)[String]("1")[Int](@@) + |""".stripMargin, + """|test[A](a: A)(using Int)[B](b: B)[C](c: C)[D](d: D): Int + | ^^^^ + |""".stripMargin + ) + + @Test def `interleaving-with-implicit-recovery` = + check( + """|object M: + | def test[A](a: A)(using Int)[B](b: B)[C](c: C)[D](d: D): Int = ??? + | test[Int](1)(5)[String]("1")[Int](@@) + |""".stripMargin, + """|test[A](a: A)(using Int)[B](b: B)[C](c: C)[D](d: D): Int + | ^^^^ + |""".stripMargin + ) + diff --git a/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpNamedArgsSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpNamedArgsSuite.scala new file mode 100644 index 000000000000..1906e12a0254 --- /dev/null +++ b/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpNamedArgsSuite.scala @@ -0,0 +1,300 @@ +package dotty.tools.pc.tests.signaturehelp + +import dotty.tools.pc.base.BaseSignatureHelpSuite + +import org.junit.Test + +class SignatureHelpNamedArgsSuite extends BaseSignatureHelpSuite: + + + @Test def `new-named-param-style-1` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(paramA = 1, @@) + |""".stripMargin, + """|method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit + | ^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `new-named-param-style-double-space` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(paramA = 1, @@) + |""".stripMargin, + """|method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit + | ^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `new-named-param-style-before-equal` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(paramA = 1, paramB @@) + |""".stripMargin, + """|method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit + | ^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `new-named-param-style-before-equal-something-after` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(paramA = 1, paramB @@) + | def test: Unit = () + |""".stripMargin, + """|method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit + | ^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `new-named-param-style-at-equal` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(paramA = 1, paramB =@@) + |""".stripMargin, + """|method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit + | ^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `new-named-param-style-after-equal` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(paramA = 1, paramB = 1@@) + |""".stripMargin, + """|method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit + | ^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `new-named-param-style-2` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(paramB = 1, @@) + |""".stripMargin, + """|method([paramB: Int], [paramA: Int], [paramC: Int], [paramD: Int]): Unit + | ^^^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `new-named-param-style-3` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(paramB = 1, paramC = 2, paramD = 3, @@) + |""".stripMargin, + """|method([paramB: Int], [paramC: Int], [paramD: Int], [paramA: Int]): Unit + | ^^^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `new-named-param-style-4` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(1, 2, @@) + |""".stripMargin, + """|method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit + | ^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `new-named-param-style-5` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(1, paramB = 2, @@) + |""".stripMargin, + """|method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit + | ^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `new-named-param-style-6` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(paramA = 1, 2, @@) + |""".stripMargin, + """|method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit + | ^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `new-named-param-style-7` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(paramA = 1, paramB = 2, @@) + |""".stripMargin, + """|method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit + | ^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `new-named-param-style-8` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(paramB = 2, paramA = 1, @@) + |""".stripMargin, + """|method([paramB: Int], [paramA: Int], [paramC: Int], [paramD: Int]): Unit + | ^^^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `new-named-param-style-9` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(paramC = 3, paramA = 1, @@) + |""".stripMargin, + """|method([paramC: Int], [paramA: Int], [paramB: Int], [paramD: Int]): Unit + | ^^^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `new-named-param-style-10` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(paramC = 3, @@ ,paramA = 1) + |""".stripMargin, + """|method([paramC: Int], [paramB: Int], [paramA: Int], [paramD: Int]): Unit + | ^^^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `new-named-param-style-11` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(paramC = 3, paramB = 1, @@ ,paramA = 1) + |""".stripMargin, + """|method([paramC: Int], [paramB: Int], [paramD: Int], [paramA: Int]): Unit + | ^^^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `named-param-before-first` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(@@paramC = 3) + |""".stripMargin, + """|method([paramC: Int], [paramA: Int], [paramB: Int], [paramD: Int]): Unit + | ^^^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `named-param-inside-reordered-last-arg` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(paramB = 3, paramA = 1, @@paramD = 3, paramC = 1) + |""".stripMargin, + """|method([paramB: Int], [paramA: Int], [paramD: Int], [paramC: Int]): Unit + | ^^^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `named-param-inside-reorderded-last-arg-1` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(paramB = 3, paramA = 1, p@@aramD = 3, paramC = 1) + |""".stripMargin, + """|method([paramB: Int], [paramA: Int], [paramD: Int], [paramC: Int]): Unit + | ^^^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `named-param-before-reorderded-last-arg-1` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(paramB = 3, paramA = 1,@@ paramD = 3, paramC = 1) + |""".stripMargin, + """|method([paramB: Int], [paramA: Int], [paramD: Int], [paramC: Int]): Unit + | ^^^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `named-param-properly-order-1` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(par@@amB = 3, paramA = 1, paramD = 3, paramC = 1) + |""".stripMargin, + """|method([paramB: Int], [paramA: Int], [paramD: Int], [paramC: Int]): Unit + | ^^^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `named-param-properly-order-2` = + check( + """|object O: + | def method(paramA: Int, paramB: Int, paramC: Int, paramD: Int): Unit = ??? + | method(paramB = 3, par@@amA = 1, paramD = 3, paramC = 1) + |""".stripMargin, + """|method([paramB: Int], [paramA: Int], [paramD: Int], [paramC: Int]): Unit + | ^^^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `named-with-type-args` = + check( + """|object Main: + | def test[T, F](aaa: Int, bbb: T, ccc: F): T = ??? + | val x = test(1, ccc = 2, b@@) + |""".stripMargin, + """|test[T, F](aaa: Int, [ccc: F], [bbb: T]): T + | ^^^^^^^^ + |""".stripMargin + ) + + @Test def `named-newline` = + check( + """|object Main: + | def test2(aaa: Int, bbb: Int, ccc: Int): Int = ??? + | val x = test2( + | 1, + | @@ + | ) + |""".stripMargin, + """|test2(aaa: Int, bbb: Int, ccc: Int): Int + | ^^^^^^^^ + |""".stripMargin + ) + + @Test def `named-before-comma` = + check( + """|object Main: + | def test2(aaa: Int, bbb: Int, ccc: Int): Int = ??? + | val x = test2(aaa = 2@@, ccc = 1) + |""".stripMargin, + """|test2(aaa: Int, [ccc: Int], [bbb: Int]): Int + | ^^^^^^^^ + |""".stripMargin + ) + + @Test def `named-on-whitespaces-between-args` = + check( + """|object Main: + | def test2(aaa: Int, bbb: Int, ccc: Int): Int = ??? + | val x = test2(aaa = 2, @@ ccc = 1, bbb = 3) + | + |""".stripMargin, + """|test2(aaa: Int, [ccc: Int], [bbb: Int]): Int + | ^^^^^^^^^^ + |""".stripMargin + ) + diff --git a/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpPatternSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpPatternSuite.scala index f8a368a5ea3a..d01145510367 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpPatternSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpPatternSuite.scala @@ -202,23 +202,6 @@ class SignatureHelpPatternSuite extends BaseSignatureHelpSuite: |""".stripMargin ) - @Test def `pat4` = - check( - """ - |object & { - | def unapply[A](a: A): Some[(A, A)] = Some((a, a)) - |} - |object a { - | "" match { - | case "" & s@@ - | } - |} - """.stripMargin, - """|(String, String) - | ^^^^^^ - |""".stripMargin - ) - @Test def `pat5` = check( """ @@ -255,6 +238,24 @@ class SignatureHelpPatternSuite extends BaseSignatureHelpSuite: |""".stripMargin ) + @Test def `shortened` = + check( + """ + |object Test { + | def unapply(command: java.io.File): Option[java.io.File] = { + | Some(Some(1)) + | } + | + | "" match { + | case Test(@@) => + | } + |} + """.stripMargin, + """|(File) + | ^^^^ + |""".stripMargin + ) + @Test def `pat-negative` = check( """ diff --git a/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpSuite.scala index 906a0bd9b72e..c1b51b127fd6 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpSuite.scala @@ -66,7 +66,7 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: """|Random() |Random(seed: Int) |Random(seed: Long) - |Random(self: java.util.Random) + |Random(self: Random) |""".stripMargin ) @@ -103,9 +103,9 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: | new File(@@) |} """.stripMargin, - """|File(x$0: java.net.URI) - | ^^^^^^^^^^^^^^^^^ - |File(x$0: java.io.File, x$1: String) + """|File(x$0: URI) + | ^^^^^^^^ + |File(x$0: File, x$1: String) |File(x$0: String, x$1: String) |File(x$0: String) |""".stripMargin @@ -118,9 +118,9 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: | new java.io.File(@@) |} """.stripMargin, - """|File(x$0: java.net.URI) - | ^^^^^^^^^^^^^^^^^ - |File(x$0: java.io.File, x$1: String) + """|File(x$0: URI) + | ^^^^^^^^ + |File(x$0: File, x$1: String) |File(x$0: String, x$1: String) |File(x$0: String) |""".stripMargin @@ -191,12 +191,12 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: |""".stripMargin ) - // https://github.com/lampepfl/dotty/issues/15244 + // https://github.com/scala/scala3/issues/15244 @Test def `vararg` = check( """ |object a { - | List(1, 2@@ + | List(1, 2@@) |} """.stripMargin, """|apply[A](elems: A*): List[A] @@ -323,9 +323,9 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: | } yield k |} """.stripMargin, - """|to(end: Int): scala.collection.immutable.Range.Inclusive + """|to(end: Int): Inclusive | ^^^^^^^^ - |to(end: Int, step: Int): scala.collection.immutable.Range.Inclusive + |to(end: Int, step: Int): Inclusive |""".stripMargin, stableOrder = false ) @@ -388,7 +388,7 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: | | """.stripMargin, - """|apply(viewId: String, nodeUri: String, label: String, command: String, icon: String, tooltip: String, collapseState: String): TreeViewNode + """|apply(viewId: String, nodeUri: String, label: String, [collapseState: String], [command: String], [icon: String], [tooltip: String]): TreeViewNode | ^^^^^^^^^^^^^^ |""".stripMargin ) @@ -424,7 +424,7 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: | | """.stripMargin, - """|apply(viewId: String, nodeUri: String, label: String, command: String, collapseState: String): TreeViewNode + """|apply(viewId: String, nodeUri: String, label: String, [collapseState: String], [command: String]): TreeViewNode | ^^^^^^^^^^^^^^ |""".stripMargin ) @@ -437,8 +437,8 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: | User(age = 1, @@) |} """.stripMargin, - """|apply(name: String, age: Int): User - | ^^^^^^^^ + """|apply([age: Int], [name: String]): User + | ^^^^^^^^^^^^^^ |""".stripMargin ) @@ -477,8 +477,8 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: | def x = user(str@@eet = 42, name = "", age = 2) |} """.stripMargin, - """|user(name: String, age: Int, street: Int): Int - | ^^^^^^^^^^^ + """|user([street: Int], [name: String], [age: Int]): Int + | ^^^^^^^^^^^^^ |user(name: String, age: Int): Int |""".stripMargin ) @@ -502,9 +502,8 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: | new scala.util.control.Exception.Catch(@@) |} """.stripMargin, - // TODO short names are not supported yet - """|Catch[T](pf: scala.util.control.Exception.Catcher[T], fin: Option[scala.util.control.Exception.Finally], rethrow: Throwable => Boolean) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + """|Catch[T](pf: Catcher[T], fin: Option[Finally], rethrow: Throwable => Boolean) + | ^^^^^^^^^^^^^^ |""".stripMargin ) @@ -515,7 +514,7 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: | new java.util.HashMap[String, Int]().computeIfAbsent(@@) |} """.stripMargin, - // TODO short names are not supported yet + // This is the correct result, as there is a conflict at Function: scala.Function and java.util.function.Function """|computeIfAbsent(x$0: String, x$1: java.util.function.Function[? >: String, ? <: Int]): Int | ^^^^^^^^^^^ |""".stripMargin @@ -650,9 +649,7 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: | identity(42)@@ |} |""".stripMargin, - """|identity[A](x: A): A - | ^^^^ - |""".stripMargin + "" ) @Test def `off-by-one2` = @@ -675,7 +672,7 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: |} |""".stripMargin, """|fold[B](ifEmpty: => B)(f: Int => B): B - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^ |""".stripMargin ) @@ -763,24 +760,13 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: """|object O: | implicit class Test[T](xs: List[T]): | def test(x: T): List[T] = ??? - | List(1,2,3).test(@@""".stripMargin, + | List(1,2,3).test(s@@)""".stripMargin, """|test(x: Int): List[Int] | ^^^^^^ |""".stripMargin ) @Test def `instantiated-type-var-old-ext-2` = - check( - """|object O: - | implicit class Test[T](xs: List[T]): - | def test(x: T): List[T] = ??? - | List(1,2,3).test(s@@""".stripMargin, - """|test(x: Int): List[Int] - | ^^^^^^ - |""".stripMargin - ) - - @Test def `instantiated-type-var-old-ext-3` = check( """|object O: | implicit class Test[T](xs: List[T]): @@ -791,7 +777,7 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: |""".stripMargin ) - @Test def `instantiated-type-var-old-ext-4` = + @Test def `instantiated-type-var-old-ext-3` = check( """|object O: | implicit class Test[T](xs: List[T]): @@ -804,7 +790,7 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: |""".stripMargin ) - @Test def `instantiated-type-var-old-ext-5` = + @Test def `instantiated-type-var-old-ext-4` = check( """|object O: | implicit class Test[T](xs: List[T]): @@ -818,7 +804,7 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: |""".stripMargin ) - @Test def `instantiated-type-var-old-ext-6` = + @Test def `instantiated-type-var-old-ext-5` = check( """|object O: | implicit class Test[T](xs: List[T]): @@ -829,3 +815,687 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: | ^^^^^^ |""".stripMargin ) + + @Test def `multiline-before` = + check( + """|object Main { + | def deployment( + | fst: String, + | snd: Int = 1, + | ): Option[Int] = ??? + | val abc = deployment(@@ + | fst = "abc", + | snd = 1 + | ) + |} + |""".stripMargin, + """|deployment(fst: String, snd: Int): Option[Int] + | ^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `multiline-after-first` = + check( + """|object Main { + | def deployment( + | fst: String, + | snd: Int = 1, + | ): Option[Int] = ??? + | val abc = deployment( + | fst = "abc", @@ + | snd = 1 + | ) + |} + |""".stripMargin, + """|deployment(fst: String, snd: Int): Option[Int] + | ^^^^^^^^ + |""".stripMargin + ) + + @Test def `multiline-between-first-and-second-a` = + check( + """|object Main { + | def deployment( + | fst: String, + | snd: Int = 1, + | ): Option[Int] = ??? + | val abc = deployment( + | fst = "abc" + | @@ + | + | ,snd = 1 + | ) + |} + |""".stripMargin, + """|deployment(fst: String, snd: Int): Option[Int] + | ^^^^^^^^^^^ + |""".stripMargin + ) + + @Test def `multiline-between-first-and-second-b` = + check( + """|object Main { + | def deployment( + | fst: String, + | snd: Int = 1, + | ): Option[Int] = ??? + | val abc = deployment( + | fst = "abc", + | @@ + | + | snd = 1 + | ) + |} + |""".stripMargin, + """|deployment(fst: String, snd: Int): Option[Int] + | ^^^^^^^^ + |""".stripMargin + ) + + @Test def `multiline-end` = + check( + """|object Main { + | def deployment( + | fst: String, + | snd: Int = 1, + | ): Option[Int] = ??? + | val abc = deployment( + | fst = "abc", + | snd = 1 + | @@) + |} + |""".stripMargin, + """|deployment(fst: String, snd: Int): Option[Int] + | ^^^^^^^^ + |""".stripMargin + ) + + @Test def `type-var-multiline-before` = + check( + """|object Main { + | def deployment[A, B]( + | fst: A, + | snd: B, + | ): Option[Int] = ??? + | val abc = deployment[@@ + Int, + | String, + | ]( + | fst = "abc", + | snd = 1 + | ) + |} + |""".stripMargin, + """|deployment[A, B](fst: A, snd: B): Option[Int] + | ^ + |""".stripMargin + ) + + @Test def `type-var-multiline-after` = + check( + """|object Main { + | def deployment[A, B]( + | fst: A, + | snd: B, + | ): Option[Int] = ??? + | val abc = deployment[ + | Int, @@ + | String, + | ]( + | fst = "abc", + | snd = 1 + | ) + |} + |""".stripMargin, + """|deployment[A, B](fst: A, snd: B): Option[Int] + | ^ + |""".stripMargin + ) + + @Test def `type-var-multiline-between-first-and-second-a` = + check( + """|object Main { + | def deployment[A, B]( + | fst: A, + | snd: B, + | ): Option[Int] = ??? + | val abc = deployment[ + | Int + | @@ + | + | ,String + | ]( + | fst = "abc", + | snd = 1 + | ) + |} + |""".stripMargin, + """|deployment[A, B](fst: A, snd: B): Option[Int] + | ^ + |""".stripMargin + ) + + @Test def `type-var-multiline-between-first-and-second-b` = + check( + """|object Main { + | def deployment[A, B]( + | fst: A, + | snd: B, + | ): Option[Int] = ??? + | val abc = deployment[ + | Int, + | @@ + | + | String, + | ]( + | fst = "abc", + | snd = 1 + | ) + |} + |""".stripMargin, + """|deployment[A, B](fst: A, snd: B): Option[Int] + | ^ + |""".stripMargin + ) + + @Test def `type-var-multiline-end` = + check( + """|object Main { + | def deployment[A, B]( + | fst: A, + | snd: B, + | ): Option[Int] = ??? + | val abc = deployment[ + | String, + | Int, + | @@]( + | fst = "abc", + | snd = 1 + | ) + |} + |""".stripMargin, + """|deployment[A, B](fst: A, snd: B): Option[Int] + | ^ + |""".stripMargin + ) + + @Test def `dont-show-directly-after-parenthesis` = + check( + """|object Main { + | def test(a: Int, b: Int): Int = ??? + | test(1, 2)@@ + |} + |""".stripMargin, + "" + ) + + @Test def `dont-show-directly-after-parenthesis-2` = + check( + """|object Main { + | def test(a: Int, b: Int): Int = ??? + | test(1, 2)@@ + |""".stripMargin, + "" + ) + + @Test def `dont-show-directly-when-unclosed` = + check( + """|object Main { + | def test(a: Int, b: Int): Int = ??? + | test(1, (2 + 1)@@ + |} + |""".stripMargin, + "" + ) + + @Test def `dont-show-after-parenthesis-1` = + check( + """|object Main { + | def test(a: Int, b: Int): Int = ??? + | test(1, 2) @@ + |} + |""".stripMargin, + "" + ) + + @Test def `dont-show-after-parenthesis-2` = + check( + """|object Main { + | def test(a: Int, b: Int): Int = ??? + | test(1, 2) @@ + |} + |""".stripMargin, + "" + ) + + @Test def `dont-show-after-parenthesis-newline` = + check( + """|object Main { + | def test(a: Int, b: Int): Int = ??? + | test(1, 2) + |@@ + |} + |""".stripMargin, + "" + ) + + @Test def `dont-show-after-parenthesis-newline-last-statement` = + check( + """|object Main: + | def test(a: Int, b: Int): Int = ??? + | test(1, 2) + | + |@@ + | + |""".stripMargin, + "" + ) + + @Test def `dont-show-after-parenthesis-newline-last-statement-unclosed-1` = + check( + """|object Main: + | def test(a: Int, b: Int): Int = ??? + | test(1, 2 + | + |@@ + | + |""".stripMargin, + "" + ) + + @Test def `dont-show-after-parenthesis-newline-last-statement-unclosed-2` = + check( + """|object Main: + | def test(a: Int, b: Int): Int = ??? + | test(1, (1 + 2) + | + |@@ + | + |""".stripMargin, + "" + ) + + @Test def `dont-show-after-parenthesis-unclosed-2` = + check( + """|object Main { + | def test(a: Int, b: Int): Int = ??? + | test(1, 2 + | + | @@ + |} + |""".stripMargin, + "" + ) + + @Test def `select-arg-detection` = + check( + """|object Main: + | object Foo: + | case class Test(x: Int) + | def test(a: Foo.Test, b: Foo.Test): Int = ??? + | test(Foo.Test(1), @@) + |""".stripMargin, + """|test(a: Test, b: Test): Int + | ^^^^^^^ + |""".stripMargin + ) + + @Test def `singature-help-works-in-select` = + check( + """|object Main: + | object Foo: + | class Test(x: Int, y: Int) + | new Foo.Test(1, @@) + |""".stripMargin, + """|Test(x: Int, y: Int) + | ^^^^^^ + |""".stripMargin + ) + + @Test def `curried-help-works-in-select` = + check( + """|object Main: + | def test(xxx: Int, yyy: Int)(zzz: Int): Int = ??? + | test(yyy = 5, xxx = 7)(@@) + |""".stripMargin, + """|test([yyy: Int], [xxx: Int])(zzz: Int): Int + | ^^^^^^^^ + |""".stripMargin + ) + + @Test def `no-signature-help-for-parameterless-method` = + check( + """|object Main: + | def test: Int = ??? + | test(@@) + |""".stripMargin, + "" + ) + + @Test def `show-methods-returning-tuples` = + check( + """|object Main: + | def test(): (Int, Int) = ??? + | test(@@) + |""".stripMargin, + "test(): (Int, Int)" + ) + + @Test def `show-methods-returning-tuples-2` = + check( + """|object Main: + | def test(x: Int): (Int, Int) = ??? + | test(@@) + |""".stripMargin, + """|test(x: Int): (Int, Int) + | ^^^^^^ + |""".stripMargin + ) + + @Test def `dont-show-tuples-application` = + check( + """|object Main: + | (1, @@) + |""".stripMargin, + "" + ) + + // Improvement would be to create synthetic signature help showing + // add(x: Int)(y: Int): Int + @Test def `dont-show-functionN` = + check( + """|object Main: + | val add = (x: Int) => (y: Int) => x + y + | add(@@) + |""".stripMargin, + "" + ) + + @Test def `dont-show-functionN-2` = + check( + """|object Main: + | val add = (x: Int) => (y: Int) => x + y + | add(1, @@) + |""".stripMargin, + "" + ) + + @Test def `type-param-start` = + check( + """|object Main: + | def test[A](x: A): A = ??? + | test[@@] + |""".stripMargin, + """|test[A](x: A): A + | ^ + |""".stripMargin + ) + + @Test def `error-recovery-1` = + check( + """|object Main: + | def test[A](x: A): Foo[A] = ??? + | test[@@] + |""".stripMargin, + """|test[A](x: A): Foo[A] + | ^ + |""".stripMargin + ) + + @Test def `error-recovery-2` = + check( + """|object Main: + | def test[A](x: A): Foo[A] = ??? + | test[Int](@@) + |""".stripMargin, + """|test[A](x: A): Foo[A] + | ^^^^ + |""".stripMargin + ) + + @Test def `type-param-shortening` = + check( + """|object M: + | def test[T <: java.io.File](x: Int): Int = ??? + | test(@@) + |""".stripMargin, + """|test[T <: File](x: Int): Int + | ^^^^^^ + |""".stripMargin + ) + + @Test def `implicit-param` = + check( + """|object M: + | trait Context + | def test(x: Int)(using ctx: Context): Int = ??? + | test(@@) + |""".stripMargin, + """|test(x: Int)(using ctx: Context): Int + | ^^^^^^ + |""".stripMargin + ) + + @Test def `context-param` = + check( + """|object M: + | def test(x: Int, y: Int = 7)(z: Int ?=> Int): Int = ??? + | test(@@) + |""".stripMargin, + """|test(x: Int, y: Int)(z: (Int) ?=> Int): Int + | ^^^^^^ + |""".stripMargin + ) + + @Test def `empty-implicit-params` = + check( + """|object M: + | def test(x: Int)(using String): Int = ??? + | test(1)(@@) + |""".stripMargin, + """|test(x: Int)(using String): Int + | ^^^^^^ + |""".stripMargin + ) + + @Test def `multiple-implicits-1` = + check( + """|object M: + | def a(using Int)(using String): Int = ??? + | a(@@) + |""".stripMargin, + """|a(using Int)(using String): Int + | ^^^ + |""".stripMargin + ) + + + @Test def `multiple-implicits-2` = + check( + """|object M: + | def a(using Int)(using String): Int = ??? + | a(using 5)(@@) + |""".stripMargin, + """|a(using Int)(using String): Int + | ^^^^^^ + |""".stripMargin + ) + + @Test def `multiple-implicits-3` = + check( + """|object M: + | def a(using Int)(using String)(x: Int): Int = ??? + | a(@@) + |""".stripMargin, + """|a(using Int)(using String)(x: Int): Int + | ^^^ + |""".stripMargin + ) + + @Test def `multiple-implicits-4` = + check( + """|object M: + | def a(using Int)(using String)(x: Int): Int = ??? + | a(using 5)(@@) + |""".stripMargin, + """|a(using Int)(using String)(x: Int): Int + | ^^^^^^ + |""".stripMargin + ) + + @Test def `multiple-implicits-error-1` = + check( + """|object M: + | def a(using Int)(using String)(x: Int): Int = ??? + | a(5)(@@) + |""".stripMargin, + """| + |a(using Int)(using String)(x: Int): Int + | ^^^^^^ + |""".stripMargin + ) + + @Test def `multiple-implicits-error-2` = + check( + """|object M: + | def a(using Int)(using String)(x: Int): Int = ??? + | a(5)(@@) + |""".stripMargin, + """|a(using Int)(using String)(x: Int): Int + | ^^^^^^ + |""".stripMargin + ) + + @Test def `dont-crash-at-last-position` = + check( + """|object M: + | def test(x: Int): Int = ??? + | test(@@""".stripMargin, + "" + ) + + @Test def `type-var-position` = + check( + """|trait Test[A, B]: + | def doThing[C](f: B => Test[A@@, C]) = ??? + |""".stripMargin, + """|Test[A, B]: Test + | ^ + |""".stripMargin + ) + + @Test def `type-var-position-1` = + check( + """|trait Test[A, B]: + | def doThing[C](f: B => Test[@@A, C]) = ??? + |""".stripMargin, + """|Test[A, B]: Test + | ^ + |""".stripMargin + ) + + @Test def `type-var-position-2` = + check( + """|trait Test[A, B]: + | def doThing[C](f: B => Test[A@@ + | , C]) = ??? + |""".stripMargin, + """|Test[A, B]: Test + | ^ + |""".stripMargin + ) + + @Test def `type-var-position-3` = + check( + """|trait Test[A, B]: + | def doThing[C](f: B => Test[A, C@@]) = ??? + |""".stripMargin, + """|Test[A, B]: Test + | ^ + |""".stripMargin + ) + + @Test def `type-var-position-4` = + check( + """|trait Test[A, B]: + | def doThing[C](f: B => Test[A,@@ C]) = ??? + |""".stripMargin, + """|Test[A, B]: Test + | ^ + |""".stripMargin + ) + + @Test def `type-var-position-5` = + check( + """|trait Test[A, B]: + | def doThing[C](f: B => Test[A, @@C]) = ??? + |""".stripMargin, + """|Test[A, B]: Test + | ^ + |""".stripMargin + ) + + @Test def `type-var-position-6` = + check( + """|trait Test[A, B]: + | def doThing[C](f: B => Test[ + | A@@, + | C + | ]) = ??? + |""".stripMargin, + """|Test[A, B]: Test + | ^ + |""".stripMargin + ) + + @Test def `type-var-position-7` = + check( + """|trait Test[A, B]: + | def doThing[C](f: B => Test[ + | A, + | C@@ + | ]) = ??? + |""".stripMargin, + """|Test[A, B]: Test + | ^ + |""".stripMargin + ) + + @Test def `type-var-position-8` = + check( + """|trait Test[A, B]: + | def doThing[C](f: B => Test[ + | A, + | @@C + | ]) = ??? + |""".stripMargin, + """|Test[A, B]: Test + | ^ + |""".stripMargin + ) + + @Test def `type-var-position-9` = + check( + """|trait Test[A, B]: + | def doThing[C](f: B => Test[ + | A, + | C + | @@]) = ??? + |""".stripMargin, + """|Test[A, B]: Test + | ^ + |""".stripMargin + ) + + @Test def `type-var-position-10` = + check( + """|trait Test[A, B]: + | def doThing[C](f: B => Test[@@ + | A, + | C + | ]) = ??? + |""".stripMargin, + """|Test[A, B]: Test + | ^ + |""".stripMargin + ) 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 e18e37188141..fd90a8dfaca0 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/tokens/SemanticTokensSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/tokens/SemanticTokensSuite.scala @@ -285,7 +285,7 @@ class SemanticTokensSuite extends BaseSemanticTokensSuite: |}""".stripMargin ) - @Test def `predef1` = + @Test def `predef1` = check( """ |object <
>/*class*/ { @@ -296,7 +296,7 @@ class SemanticTokensSuite extends BaseSemanticTokensSuite: |""".stripMargin ) - @Test def `val-object` = + @Test def `val-object` = check( """ |case class <>/*class*/(<>/*variable,declaration,readonly*/: <>/*class,abstract*/) @@ -411,4 +411,24 @@ class SemanticTokensSuite extends BaseSemanticTokensSuite: | } | val <>/*variable,definition,readonly*/ = <>/*class*/(123, 456) |}""".stripMargin + ) + + @Test def `i5977` = + check( + """ + |sealed trait <>/*interface,abstract*/ { + | extension [<>/*typeParameter,definition,abstract*/] (<>/*parameter,declaration,readonly*/: <>/*typeParameter,abstract*/) { + | def <>/*method,declaration*/[<>/*typeParameter,definition,abstract*/]: <>/*typeParameter,abstract*/ + | def <>/*method,declaration*/[<>/*typeParameter,definition,abstract*/](<>/*parameter,declaration,readonly*/: <>/*typeParameter,abstract*/): <>/*typeParameter,abstract*/ + |} + | + |object <>/*class*/ { + | def <>/*method,definition*/[<>/*typeParameter,definition,abstract*/](<>/*parameter,declaration,readonly*/: <>/*interface,abstract*/ ?=> <>/*typeParameter,abstract*/ => <>/*class,abstract*/): <>/*class,abstract*/ = <>/*method*/ + | + | <>/*method*/[<>/*class,abstract*/](<<_>>/*parameter,readonly*/.<>/*method*/("str")) + | <>/*method*/[<>/*class,abstract*/](<<_>>/*parameter,readonly*/.<>/*method*/[<>/*type*/]("str")) + | <>/*method*/[<