├── .github └── workflows │ ├── deploy-website.yml │ └── tests.yml ├── .gitignore ├── .scala-steward.conf ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── build.sbt ├── docs ├── assets │ ├── compatibility │ │ ├── 2to3.svg │ │ ├── 2toMacro3.svg │ │ ├── 2toMacro3bis.svg │ │ ├── 3to2.svg │ │ ├── 3toMacro2.svg │ │ ├── 3toMacro2bis.svg │ │ ├── sharedMacroAPI.svg │ │ └── standardlib.svg │ └── macros │ │ ├── cross-building.svg │ │ └── mixing.svg ├── compatibility │ ├── classpath.md │ ├── metaprogramming.md │ ├── runtime.md │ └── source.md ├── compiler-options │ ├── compiler-options-table.md │ └── new-compiler-options.md ├── contributing.md ├── external-resources │ └── moving-from-scala-2-to-scala-3.md ├── get-started.md ├── incompat-31.md ├── incompatibilities │ ├── contextual-abstractions.md │ ├── dropped-features.md │ ├── incompatibility-table.md │ ├── other-changed-features.md │ ├── syntactic-changes.md │ ├── type-checker.md │ └── type-inference.md ├── macros │ └── macro-libraries.md ├── tooling │ ├── migration-tools.md │ ├── scala-3-migrate-plugin.md │ ├── scala-3-migration-mode.md │ └── scala-3-syntax-rewrites.md └── tutorials │ ├── kind-projector.md │ ├── macro-cross-building.md │ ├── macro-mixing.md │ ├── prerequisites.md │ └── sbt-migration.md ├── incompat-3-future ├── alphanumeric-infix │ └── src │ │ └── main │ │ ├── scala-3.0 │ │ └── alphanumeric-infix.scala │ │ └── scala │ │ └── alphanumeric-infix.scala ├── context-bound-arg │ └── src │ │ └── main │ │ ├── scala-3.0 │ │ └── context-bound-arg.scala │ │ └── scala │ │ └── context-bound-arg.scala ├── eta-expansion │ └── src │ │ └── main │ │ ├── scala-3.0 │ │ └── eta-expansion.scala │ │ └── scala │ │ └── eta-expansion.scala ├── implicit-lambda-param │ └── src │ │ └── main │ │ ├── scala-3.0 │ │ └── implicit-lambda-param.scala │ │ └── scala │ │ └── implicit-lambda-param.scala ├── pattern-binding │ └── src │ │ └── main │ │ ├── scala-3.0 │ │ └── pattern-binding.scala │ │ └── scala │ │ └── pattern-binding.scala └── wildcard │ └── src │ └── main │ ├── scala-3.0 │ └── wildcard.scala │ └── scala │ └── wildcard.scala ├── incompat-3 ├── README.md ├── abstract-override │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── abstract-override.scala │ │ └── scala │ │ └── abstract-override.scala ├── access-modifier │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── access-modifier.scala │ │ └── scala │ │ └── access-modifier.scala ├── ambiguous-conversion │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── ambiguous-conversion.scala │ │ └── scala │ │ └── ambiguous-conversion.scala ├── anonymous-type-param │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── anonymous-type-param.scala │ │ └── scala │ │ └── anonymous-type-param.scala ├── any2stringadd-conversion │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── any2stringadd-conversion.scala │ │ └── scala │ │ └── any2stringadd-conversion.scala ├── auto-application │ ├── .scalafix.conf │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── auto-application.scala │ │ └── scala │ │ └── auto-application.scala ├── bean-property │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── bean-property.scala │ │ └── scala │ │ └── bean-property.scala ├── by-name-param-type-infer │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── by-name-param-type-infer.scala │ │ └── scala │ │ └── by-name-param-type-infer.scala ├── case-class-companion │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── case-class-companion.scala │ │ └── scala │ │ └── case-class-companion.scala ├── do-while │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── do-while.scala │ │ └── scala │ │ └── do-while.scala ├── early-initializer │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── early-initializer.scala │ │ └── scala │ │ └── early-initializer.scala ├── existential-type │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── existential-type.scala │ │ └── scala │ │ └── existential-type.scala ├── explicit-call-to-unapply │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── explicit-call-to-unapply.scala │ │ └── scala │ │ └── explicit-call-to-unapply.scala ├── implicit-view │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── implicit-view.scala │ │ └── scala │ │ └── implicit-view.scala ├── indent-argument │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── indent-argument.scala │ │ └── scala │ │ └── indent-argument.scala ├── indentation │ ├── README.md │ └── indentation-1 │ │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── indentation.scala │ │ └── scala │ │ └── indentation.scala ├── infer-return-type │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── infer-return-type.scala │ │ └── scala │ │ └── infer-return-type.scala ├── inheritance-shadowing │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── inheritance-shadowing.scala │ │ └── scala │ │ └── inheritance-shadowing.scala ├── keywords │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── keywords.scala │ │ └── scala │ │ └── keywords.scala ├── lambda-params │ ├── .scalafix.conf │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── lambda-params.scala │ │ └── scala │ │ └── lambda-params.scala ├── pattern-match │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── pattern-match.scala │ │ └── scala │ │ └── pattern-match.scala ├── procedure-syntax │ ├── .scalafix.conf │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── procedure-syntax.scala │ │ └── scala │ │ └── procedure-syntax.scala ├── reflective-call │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── reflective-call.scala │ │ └── scala │ │ └── reflective-call.scala ├── restricted-operator │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── restricted-operator.scala │ │ └── scala │ │ └── restricted-operator.scala ├── symbol-literals │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── symbol-literals.scala │ │ └── scala │ │ └── symbol-literals.scala ├── type-infer-10 │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── type-infer.scala │ │ └── scala │ │ └── type-infer.scala ├── type-infer-3 │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── type-infer.scala │ │ └── scala │ │ └── type-infer.scala ├── type-infer-4 │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── type-infer.scala │ │ └── scala │ │ └── type-infer.scala ├── type-infer-5 │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── type-infer.scala │ │ └── scala │ │ └── type-infer.scala ├── type-infer-9 │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── type-infer.scala │ │ └── scala │ │ └── type-infer.scala ├── type-of-implicit-def │ ├── .scalafix.conf │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── type-of-implicit-def.scala │ │ └── scala │ │ └── type-of-implicit-def.scala ├── type-param-identifier │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── type-param-identifier.scala │ │ └── scala │ │ └── type-param-identifier.scala ├── value-eta-expansion │ ├── .scalafix.conf │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── value-eta-expansion.scala │ │ └── scala │ │ └── value-eta-expansion.scala ├── variance │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── variance.scala │ │ └── scala │ │ └── variance.scala ├── view-bound │ ├── README.md │ └── src │ │ └── main │ │ ├── scala-2.13 │ │ └── view-bound.scala │ │ └── scala │ │ └── view-bound.scala └── wildcard-argument │ ├── README.md │ └── src │ └── main │ ├── scala-2.13 │ └── wildcard-argument.scala │ └── scala │ └── wildcard-argument.scala ├── incompat.sbt ├── mdoc └── src │ └── main │ └── scala │ └── docs │ ├── FileModifier.scala │ └── Main.scala ├── project ├── Assert.scala ├── FileChecker.scala ├── IncompatSettings.scala ├── Versions.scala ├── build.properties └── plugins.sbt ├── tutorials.sbt ├── tutorials ├── macro-cross-building │ └── example │ │ └── src │ │ ├── main │ │ ├── scala-2 │ │ │ └── location │ │ │ │ └── Macros.scala │ │ ├── scala-3 │ │ │ └── location │ │ │ │ └── Macros.scala │ │ └── scala │ │ │ └── location │ │ │ └── Location.scala │ │ └── test │ │ └── scala │ │ └── location │ │ └── MacrosSpec.scala ├── macro-mixing │ ├── example-compat │ │ └── src │ │ │ └── main │ │ │ └── scala │ │ │ └── location │ │ │ └── Location.scala │ ├── example-test │ │ └── src │ │ │ └── test │ │ │ └── scala │ │ │ └── location │ │ │ └── MacrosSpec.scala │ └── example │ │ └── src │ │ └── main │ │ └── scala │ │ └── location │ │ └── Macros.scala └── sbt-migration │ └── src │ └── main │ └── scala │ └── app │ └── Main.scala └── website ├── core └── Footer.js ├── i18n └── en.json ├── package.json ├── pages └── en │ └── index.js ├── sidebars.json ├── siteConfig.js └── static ├── css └── custom.css └── img ├── dotty-logo-white.svg ├── dotty-logo.svg ├── favicon.png ├── home-bg.png ├── magnifying-primary.svg ├── puzzle-primary.svg ├── scalacenter.png ├── scalacenter2x.png ├── tilde.svg └── tools-primary.svg /.github/workflows/deploy-website.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Website 2 | on: 3 | push: 4 | branches: [main] 5 | jobs: 6 | publish: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | - uses: olafurpg/setup-scala@v10 11 | - name: Publish ${{ github.ref }} 12 | run: sbt website/docusaurusPublishGhpages 13 | env: 14 | GITHUB_DEPLOY_KEY: ${{ secrets.DOC }} -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | on: 3 | pull_request: 4 | branches: [main] 5 | push: 6 | branches: [main] 7 | jobs: 8 | incompat: 9 | name: Test Incompatibilities 10 | runs-on: ubuntu-latest 11 | strategy: 12 | fail-fast: false 13 | steps: 14 | - uses: actions/checkout@v2 15 | - uses: olafurpg/setup-scala@v10 16 | - name: Test Incompatibilities 17 | run: sbt '++3.3.0; incompat-3 / test; ++2.13.11; incompat-3 / test' 18 | - name: Test Future Incompatibilities 19 | run: sbt 'incompat-3-future / test' 20 | tutorials: 21 | name: Check Tutorials 22 | runs-on: ubuntu-latest 23 | strategy: 24 | fail-fast: false 25 | steps: 26 | - uses: actions/checkout@v2 27 | - uses: olafurpg/setup-scala@v10 28 | - name: Sbt Migration Tutorial 29 | run: sbt '++3.3.0; sbt-migration-tutorial / run; ++2.13.11; sbt-migration-tutorial / run' 30 | - name: Macro Cross-Building 31 | run: sbt '++3.3.0; macro-cross-building-example / test; ++2.13.11; macro-cross-building-example / test' 32 | - name: Macro Mixing 33 | run: sbt '++3.3.0; macro-mixing-example-test / test; ++2.13.11; macro-mixing-example-test / test' 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .metals/ 2 | .vscode/ 3 | target/ 4 | .bloop/ 5 | .bsp/ 6 | **/project/metals.sbt 7 | 8 | # Scala-IDE specific 9 | .scala_dependencies 10 | .worksheet 11 | .idea 12 | node_modules 13 | 14 | 15 | website/build/ 16 | website/yarn.lock 17 | website/node_modules 18 | website/i18n/* 19 | !website/i18n/en.json 20 | -------------------------------------------------------------------------------- /.scala-steward.conf: -------------------------------------------------------------------------------- 1 | updates.ignore = [ { groupId = "org.typelevel", artifactId = "cats-core_2.13" } ] -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Migration to Scala 3 will eventually concern each and every member of the Scala community. 4 | 5 | Collaboration is key to make the migration a success. 6 | 7 | There are lots of ways to contribute to the Scala 3 migration: 8 | - Proof-read the migration guide 9 | - Fix the typos and improve the poor wording 10 | - Migrate your projects and share your feedback 11 | - Report missing incompatibilities 12 | - Report missing macro libraries 13 | 14 | ## Share your feedback 15 | 16 | Your experience in migrating to Scala 3, whether it is bad or pleasant, is valuable to the community. 17 | 18 | You can share it [here](https://github.com/scalacenter/scala-3-migration-guide/discussions)! 19 | 20 | ## Issues and Pull Requests 21 | 22 | If you have found a typo, a missing incompatibility or a missing macro library, please [open an issue](https://github.com/scalacenter/scala-3-migration-guide/issues). 23 | 24 | You are also invited to clone [the repository](https://github.com/scalacenter/scala-3-migration-guide) and to open a pull-request. 25 | This will greatly help us and make things move faster. 26 | 27 | ## Github Discussions 28 | 29 | You have a question to ask, or an idea to share with us. 30 | You want to notify us about something, to promote your work realted to the Scala 3 migration. 31 | 32 | Please do so by creating a new [Github Discussion](https://github.com/scalacenter/scala-3-migration-guide/discussions) 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Scala 3 migration guide 2 | 3 | > The content of the Scala 3 migration guide has moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/compatibility-intro.html) 4 | 5 | This repository is a continuously evolving guide to support the migration to Scala 3. 6 | As a member of the community you are encouraged to participate the effort by sharing your migrating experience. 7 | 8 | Visit [**the Scala 3 Migration website**](https://scalacenter.github.io/scala-3-migration-guide) to learn more about the migration. 9 | 10 | A number of complementary initiatives are being undertaken to ease the migration. 11 | This repository is not a replacement of those initiatives. 12 | Its purpose is to gather knowledge, to collect feedback and to encourage the collaboration. 13 | The ultimate goal being to drive the effort of the community toward the release of Scala 3.0.0. 14 | 15 | All information you may want to know before starting the migration of your codebase should be available in this guide. 16 | If not you may want to [contribute](docs/contributing.md). 17 | 18 | ## Content 19 | 20 | This repository contains: 21 | - [`incompat-30/`](incompat-30/): A corpus of incompatibilities between Scala 2.13 and Scala 3.0 with proposed solution. It also contains the tests of the Scala 3.0 migration rewrites for 3.0. 22 | - [`incompat-31/`](incompat-31/): The tests of the Dotty migration rewrites that are already implemented for 3.1. 23 | - [`docs/`](docs/): The documentation that is still published to the [deprecated website](https://scalacenter.github.io/scala-3-migration-guide/) 24 | - [`website/`](website/): The website skeleton powered by [Docusaurus](https://docusaurus.io/en/). 25 | 26 | ## Additional Resources 27 | 28 | - [The Scala website](https://scala-lang.org/) 29 | - [The Dotty website](https://dotty.epfl.ch/) 30 | - [The Scala 3 example project](https://github.com/lampepfl/scala3-example-project) 31 | - [The Scala 3 community projects](https://github.com/lampepfl/dotty/tree/master/community-build/community-projects) 32 | - [The Scala 3 Migration Plugin](https://github.com/scalacenter/scala3-migrate) for sbt 33 | -------------------------------------------------------------------------------- /build.sbt: -------------------------------------------------------------------------------- 1 | import Versions._ 2 | 3 | lazy val website = project 4 | .in(file("mdoc")) 5 | .settings( 6 | publish / skip := true, 7 | mdoc := (Compile / run).evaluated, 8 | mdocVariables := Map( 9 | "scala3" -> scala3, 10 | "scala3Binary" -> scala3, 11 | "scala213" -> scala213, 12 | "sbtDotty" -> sbtDotty, 13 | "scala3Migrate" -> scala3Migrate, 14 | "catsCore" -> "2.3.0-M2", 15 | "osLib" -> osLib, 16 | "sourcecode" -> sourcecode, 17 | "munit" -> munit 18 | ) 19 | ) 20 | .enablePlugins(DocusaurusPlugin) 21 | -------------------------------------------------------------------------------- /docs/assets/compatibility/2to3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | bar_3bar_3foo_2.13foo_2.13Viewer does not support full SVG 1.1 -------------------------------------------------------------------------------- /docs/assets/compatibility/2toMacro3bis.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | macro-bar_3macro-bar_3...bar_3bar_3inline def bar: Bar = ${ barImpl }inline def bar: Bar = ${ barImpl }foo_2.13foo_2.13Viewer does not support full SVG 1.1 -------------------------------------------------------------------------------- /docs/assets/compatibility/3to2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | bar_2.13bar_2.13foo_3foo_3Viewer does not support full SVG 1.1 -------------------------------------------------------------------------------- /docs/assets/compatibility/3toMacro2bis.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | macro-bar_2.13macro-bar_2.13...bar_2.13bar_2.13def bar: Bar = macro barImpldef bar: Bar = macro barImplfoo_3foo_3Viewer does not support full SVG 1.1 -------------------------------------------------------------------------------- /docs/assets/compatibility/sharedMacroAPI.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | macro-bar_3macro-bar_3...bar-impl_2.13bar-impl_2.13inline def bar: Bar = ${ barImpl }inline def bar: Bar = ${ barImpl }def bar: Bar = macro Scala2Macros.barImpldef bar: Bar = macro Scala2Macros.barImpl Viewer does not support full SVG 1.1 -------------------------------------------------------------------------------- /docs/assets/compatibility/standardlib.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | scala-library % 2.13.5scala-library % 2.13.5foo_3foo_3Viewer does not support full SVG 1.1 -------------------------------------------------------------------------------- /docs/assets/macros/cross-building.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | example_2.13example_2.13app_2.13app_2.13example_3example_3app_3app_3Viewer does not support full SVG 1.1 -------------------------------------------------------------------------------- /docs/assets/macros/mixing.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | example-compat_2.13example-compat_2.13example_3example_3app_2.13app_2.13app_3app_3Viewer does not support full SVG 1.1 -------------------------------------------------------------------------------- /docs/compatibility/classpath.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: classpath 3 | title: Classpath Level 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/compatibility-classpath.html). 7 | -------------------------------------------------------------------------------- /docs/compatibility/metaprogramming.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: metaprogramming 3 | title: Metaprogramming 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/compatibility-metaprogramming.html). 7 | -------------------------------------------------------------------------------- /docs/compatibility/runtime.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: runtime 3 | title: Runtime 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/compatibility-runtime.html). 7 | -------------------------------------------------------------------------------- /docs/compatibility/source.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: source 3 | title: Source Level 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/compatibility-source.html). 7 | -------------------------------------------------------------------------------- /docs/compiler-options/compiler-options-table.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: compiler-options-table 3 | title: Compiler Options Table 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/options-lookup.html). 7 | -------------------------------------------------------------------------------- /docs/compiler-options/new-compiler-options.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: new-compiler-options 3 | title: New Scala 3 compiler options 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/options-new.html). 7 | -------------------------------------------------------------------------------- /docs/contributing.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: contributing 3 | title: Contributing 4 | --- 5 | 6 | ```scala mdoc:file:CONTRIBUTING.md:skip-first-line 7 | ``` 8 | -------------------------------------------------------------------------------- /docs/external-resources/moving-from-scala-2-to-scala-3.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: moving-from-scala-2-to-scala-3 3 | title: Moving from Scala 2 to Scala 3 4 | --- 5 | 6 | If you're a Scala 2 application developer who's looking at getting up-to-speed on Scala 3 or who's considering a migration of an existing Scala 2 application to Scala 3, Lunatech's [_"Moving from Scala 2 to Scala 3"_](https://github.com/lunatech-labs/lunatech-scala-2-to-scala3-course) course is a good way to get started. 7 | 8 | This course guides you through a migration of a single-module Akka Typed Sudoku solver in a series of about 10 steps. It covers the practical application of the following Scala 3 features: 9 | 10 | - New Control Structure syntax 11 | - Indentation Based syntax 12 | - Syntax rewriting by the Scala 3 compiler 13 | - Top Level definitions 14 | - Parameter untupling 15 | - Contextual Abstractions 16 | - Extension methods new syntax 17 | - Given instances and Using clauses 18 | - Enumerations and Export clauses 19 | - Intersection and Union Types 20 | - Opaque Type Aliases 21 | - Multiversal Equality 22 | 23 | -------------------------------------------------------------------------------- /docs/get-started.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: get-started 3 | title: Introduction 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/compatibility-intro.html). 7 | -------------------------------------------------------------------------------- /docs/incompat-31.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: incompat-31 3 | title: Dotty future-migration Mode 4 | --- 5 | ## Looking ahead to Scala 3.1 6 | 7 | Some deprecations have been postponed to 3.1 to facilitate the migration from 2.13 to 3.0 and then from 3.0 to 3.1. 8 | However some of the migration rules are already available and you are likely to be able to apply them in your codebase. 9 | In this way you get accustomed to the new syntax and prepared for 3.1. 10 | 11 | Beware though that some of the `future-migration` rewrites break the source compatibility with Scala 2.13. 12 | 13 | ### Rule 1 - Replace wildcard type argument '_' with '?' 14 | 15 | The deprecation of the `_` syntax for wildcard type arguments has be postponed to Scala 3.1 and it will be replaced by the `?` syntax. You can find the motivation for this in the [Dotty reference](https://dotty.epfl.ch/docs/reference/changed-features/wildcards.html). 16 | 17 | However there already is a migration rule that you can apply using some slightly different options than before: `dotc -source:future-migration -rewrite`. Note the `3.1` version mentioned here. 18 | 19 | For example: 20 | 21 | ```scala 22 | def compare(x: Container[_], y: Container[_]): Int = { 23 | x.weight - y.weight 24 | } 25 | ``` 26 | 27 | Is rewritten into 28 | 29 | ```scala 30 | def compare(x: Container[?], y: Container[?]): Int = { 31 | x.weight - y.weight 32 | } 33 | ``` 34 | 35 | ### Rule 2 - Add Parentheses around the implicit parameter of a lambda 36 | 37 | *Will be available in Dotty 0.26.0 or Dotty 0.27.0-RC1* 38 | 39 | Starting from Scala 3.1, it will be required to enclose the implicit parameter of a lambda in parentheses, making the following Scala 3 code illegal. 40 | 41 | ```scala 42 | val f = { implicit x: Context => ??? } 43 | ``` 44 | 45 | Compiling with `dotc -source:future-migration -rewrite` rewrites it into: 46 | 47 | ```scala 48 | val f = { (implicit x: Context) => ??? } 49 | ``` 50 | 51 | ### Rule 3 (deprecation) - Backquote alphanumeric methods used as infix operator 52 | 53 | Starting from Scala 3.1, alphanumeric methods should be annotated with `@infix` to be used as infix operators (see [Dotty documentation](https://dotty.epfl.ch/docs/reference/changed-features/operators.html#the-infix-annotation)). 54 | The `-deprecation` mode of the compiler will warn you foreach infix call of un-annotated methods. 55 | 56 | Here, the call of the `difference` method is deprecated: 57 | 58 | ```scala 59 | trait MultiSet { 60 | def difference(other: MultiSet): MultiSet 61 | } 62 | 63 | def test(s1: MultiSet, s2: MultiSet): MultiSet = 64 | s1 difference s2 65 | ``` 66 | 67 | The compiler can backquote the method call under the `-source:3.1 -deprecation -rewrite` options. 68 | 69 | ```scala 70 | trait MultiSet { 71 | def difference(other: MultiSet): MultiSet 72 | } 73 | 74 | def test(s1: MultiSet, s2: MultiSet): MultiSet = 75 | s1 `difference` s2 76 | ``` 77 | 78 | ### Rule 4 - Unchecked pattern bindings 79 | 80 | *Will be available in Dotty 0.26.0 or Dotty 0.27.0-RC1* 81 | 82 | From Scala 3.1 on, pattern binding will require to be type consistent in order to prevent undesired runtime errors. 83 | See [Dotty documentation](https://dotty.epfl.ch/docs/reference/changed-features/pattern-bindings.html) for more information on this. 84 | 85 | This piece of code compiles in Scala 2.13 and Scala 3.0 but not in Scala 3.1: 86 | 87 | ```scala 88 | val list: List[Int] = List(1) 89 | val head :: _ = list 90 | ``` 91 | 92 | You can use the `@unchecked` annotation to tell the compiler to ignore that the binding can fail. 93 | Compiling with `dotc -source:future-migration -rewrite` can write it automatically. 94 | 95 | ```scala 96 | val list: List[Int] = List(1) 97 | val head :: _: @unchecked = list 98 | ``` 99 | 100 | Similarly, in a `for` expression, this piece of code compiles in Scala 2.13 and Scala 3.0 but not in Scala 3.1: 101 | 102 | ```scala 103 | val listOpt: List[Option[Int]] = List(Some(1), None) 104 | for (Some(value) <- listOpt) println(value) 105 | ``` 106 | 107 | In Scala 2 and Scala 3.0, the elements of `listOpt` are filtered to retain only the value of type `Some` . 108 | 109 | In Scala 3.1, this syntax does not induce filtering, but the binding is type checked to prevent runtime errors. 110 | You can still have the same behavior than Scala 2 by adding the `case` keyword. 111 | Compiling with `dotc -source:future-migration -rewrite` can add it for you automatically. 112 | 113 | ```scala 114 | val listOpt: List[Option[Int]] = List(Some(1), None) 115 | for (case Some(value) <- listOpt) println(value) 116 | ``` 117 | 118 | ### Rule 5 - Remove method value syntax for eta-expansion 119 | 120 | *This rule breaks the source compatibility with Scala 2.13.* 121 | 122 | The method value syntax `m _` will no longer be supported in Scala 3.1, since we now have [automatic eta-expansion](https://dotty.epfl.ch/docs/reference/changed-features/eta-expansion-spec.html). 123 | 124 | In general you can simply drop the `_` symbol. 125 | Compiling with `dotc -source:future-migration -rewrite` rewrites 126 | 127 | ```scala 128 | def foo(x: Int)(y: Int): Int = x + y 129 | val f = foo _ 130 | ``` 131 | 132 | Into 133 | 134 | ```scala 135 | def foo(x: Int)(y: Int): Int = x + y 136 | val f = foo 137 | ``` 138 | 139 | In the special case of a nullary method, the rewrite rule transforms 140 | 141 | ```scala 142 | def bar(): Int = 3 143 | val g = bar _ 144 | ``` 145 | 146 | Into 147 | 148 | ```scala 149 | def bar(): Int = 3 150 | val g = (() => bar()) 151 | ``` 152 | 153 | ### Rule 6 - Add `using` clause to pass explicit arguments to context bound 154 | 155 | *This rule breaks the source compatibility with Scala 2.13.* 156 | 157 | From Scala 3.1 on, context bounds will map to context parameters. 158 | Thus a `using` clause is needed to pass explicit arguments to them. 159 | 160 | Compiling with `dotc -source:future-migration -rewrite` rewrites 161 | 162 | ```scala 163 | def show[T: Show](value: T): String = ??? 164 | val intShow = new Show[Int] {} 165 | show(5)(intShow) 166 | ``` 167 | 168 | Into 169 | 170 | ```scala 171 | def show[T: Show](value: T): String = ??? 172 | val intShow = new Show[Int] {} 173 | show(5)(using intShow) 174 | ``` -------------------------------------------------------------------------------- /docs/incompatibilities/contextual-abstractions.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: contextual-abstractions 3 | title: Contextual Abstractions 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/incompat-contextual-abstractions.html). 7 | -------------------------------------------------------------------------------- /docs/incompatibilities/dropped-features.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: dropped-features 3 | title: Dropped Features 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/incompat-dropped-features.html). 7 | -------------------------------------------------------------------------------- /docs/incompatibilities/incompatibility-table.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: incompatibility-table 3 | title: Incompatibility Table 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/incompatibility-table.html). 7 | -------------------------------------------------------------------------------- /docs/incompatibilities/other-changed-features.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: other-changed-features 3 | title: Other Changed Features 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/incompat-other-changes.html). 7 | -------------------------------------------------------------------------------- /docs/incompatibilities/syntactic-changes.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: syntactic-changes 3 | title: Syntactic Changes 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/incompat-syntactic.html). 7 | -------------------------------------------------------------------------------- /docs/incompatibilities/type-checker.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: type-checker 3 | title: Type Checker 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/incompat-type-checker.html). 7 | 8 | -------------------------------------------------------------------------------- /docs/incompatibilities/type-inference.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: type-inference 3 | title: Type Inference 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/incompat-type-inference.html). 7 | -------------------------------------------------------------------------------- /docs/macros/macro-libraries.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: macro-libraries 3 | title: Scala Macro Libraries 4 | --- 5 | 6 | While being experimental, the Scala community has largely adopted the Scala 2 [Def Macro](https://docs.scala-lang.org/overviews/macros/overview.html) feature in multiple of ways: code generation, optimizations, ergonomic DSLs... 7 | 8 | A large part of the ecosystem now depends on Scala 2.13 macros defined in external libraries. 9 | Identifying those library dependencies is key to establish that a project is ready to be migrated to Scala 3. 10 | 11 | > The Scala 3 compiler cannot execute Scala 2.13 macro definitions. 12 | > 13 | > However, the handy `-Xignore-scala2-macros` option can be used to ignore them and type check the rest of the code. 14 | > 15 | > ```scala 16 | > [error] -- Error: /src/main/scala/foo/Foo.scala:10:45 17 | > [error] 10 | implicit val foo: Foo[List[Int]] = Foo.make 18 | > [error] | ^ 19 | > [error] |Scala 2 macro cannot be used in Scala 3. See https://dotty.epfl.ch/docs/reference/dropped-features/macros.html 20 | > [error] |To turn this error into a warning, pass -Xignore-scala2-macros to the compiler 21 | > ``` 22 | > 23 | > Beware that `-Xignore-scala2-macros` will produce bytecode that will fail at runtime. 24 | > 25 | 26 | ## Macro Libraries 27 | 28 | The following table contains an incomplete list of macro libraries and their migration status. 29 | 30 | | Project | Status | Comments | 31 | |-|-|-| 32 | | [adamw/scala-macro-debug](https://index.scala-lang.org/adamw/scala-macro-debug) | | | 33 | | [ajozwik/quill-generic](https://index.scala-lang.org/ajozwik/quill-generic) | | | 34 | | [argonaut-io/argonaut](https://index.scala-lang.org/argonaut-io/argonaut) | | Since version `6.3.2` | 35 | | [backuity/ansi-interpolator](https://index.scala-lang.org/backuity/ansi-interpolator) | | | 36 | | [typelevel/log4cats](https://index.scala-lang.org/typelevel/log4cats) | | Since version `1.3.1` | 37 | | [circe/circe](https://index.scala-lang.org/circe/circe) | | Since version `0.14.0` | 38 | | [dmytromitin/auxify](https://index.scala-lang.org/dmytromitin/auxify) | | | 39 | | [fthomas/refined](https://index.scala-lang.org/fthomas/refined) | | refined macros not yet available | 40 | | [jokade/slogging](https://index.scala-lang.org/jokade/slogging) | | | 41 | | [getquill/quill](https://index.scala-lang.org/getquill/quill/) | | Since version `3.13.0` | 42 | | [giiita/refuel](https://index.scala-lang.org/giiita/refuel/) | | Since version `2.0.2` | 43 | | [lightbend/scala-logging](https://index.scala-lang.org/lightbend/scala-logging) | | Since version `3.9.4` | 44 | | [lihaoyi/autowire](https://index.scala-lang.org/lihaoyi/autowire) | | | 45 | | [lihaoyi/fastparse](https://index.scala-lang.org/lihaoyi/fastparse) | | Since version `3.0.0`| 46 | | [lihaoyi/mill](https://index.scala-lang.org/lihaoyi/mill) | | | 47 | | [lihaoyi/pprint](https://index.scala-lang.org/lihaoyi/pprint) | | Since version `0.6.0` | 48 | | [lihaoyi/sourcecode](https://index.scala-lang.org/lihaoyi/sourcecode) | | Since version `0.1.8` | 49 | | [lihaoyi/upickle](https://github.com/lihaoyi/upickle) | | Since version `1.2.0` | 50 | | [lihaoyi/utest](https://index.scala-lang.org/lihaoyi/utest) | | Since version `0.7.3` | 51 | | [lloydmeta/enumeratum](https://index.scala-lang.org/lloydmeta/enumeratum) | | Since version `1.7.1` | 52 | | [log4s/log4s](https://index.scala-lang.org/log4s/log4s) | | Since version `1.10.0-M1` | 53 | | [macro-peg/macro_peg](https://index.scala-lang.org/kmizu/macro_peg) | | | 54 | | [milessabin/shapeless](https://index.scala-lang.org/milessabin/shapeless) | | Being rewritten into Shapeless 3 Since version `3.0.0` ([typelevel/shapeless-3](https://github.com/typelevel/shapeless-3)) | 55 | | [monix/minitest](https://index.scala-lang.org/monix/minitest) | | Since `2.9.0` | 56 | | [mpollmeier/gremlin-scala](https://index.scala-lang.org/mpollmeier/gremlin-scala) | | `macros` module not available for Scala 3.0 | 57 | | [nevillelyh/parquet-avro-extra](https://index.scala-lang.org/nevillelyh/parquet-avro-extra) | | | 58 | | [non/imp](https://index.scala-lang.org/non/imp) | | | 59 | | [optics-dev/Monocle](https://index.scala-lang.org/optics-dev/Monocle) | | Since `3.0.0` | 60 | | [payalabs/scalajs-react-bridge](https://index.scala-lang.org/payalabs/scalajs-react-bridge) | | | 61 | | [playframework/play-json](https://index.scala-lang.org/playframework/play-json) | | Since version `2.10.0-RC5` | 62 | | [plokhotnyuk/expression-evaluator](https://index.scala-lang.org/plokhotnyuk/expression-evaluator) | | No replacement for `Evals.eval` | 63 | | [plokhotnyuk/fast-string-interpolator](https://index.scala-lang.org/plokhotnyuk/fast-string-interpolator) | | Since version `0.6.2` | 64 | | [plokhotnyuk/jsoniter-scala](https://index.scala-lang.org/plokhotnyuk/jsoniter-scala) | | Since version `2.12.1` | 65 | | [softwaremill/magnolia](https://index.scala-lang.org/softwaremill/magnolia) | | Since version `1.0.0` | 66 | | [pureconfig/pureconfig](https://index.scala-lang.org/pureconfig/pureconfig) | | Since version `0.17.2` | 67 | | [sangria-graphql/sangria](https://index.scala-lang.org/sangria-graphql/sangria) | | Since version `3.3.0` | 68 | | [scalalandio/chimney](https://index.scala-lang.org/scalalandio/chimney) | | Since version `0.8.0` | 69 | | [scalameta/munit](https://index.scala-lang.org/scalameta/munit) | | Since `0.3.0` | 70 | | [scalatest/scalatest](https://index.scala-lang.org/scalatest/scalatest) | | Since version `3.1.0` | 71 | | [scalatest/scalatestplus-junit](https://index.scala-lang.org/scalatest/scalatestplus-junit) | | Since version `3.1.0` | 72 | | [scalikejdbc/scalikejdbc](https://index.scala-lang.org/scalikejdbc/scalikejdbc) | | Since `4.0.0` | 73 | | [scodec/scodec-bits](https://index.scala-lang.org/scodec/scodec-bits) | | Since version `1.1.18` | 74 | | [sirthias/parboiled2](https://index.scala-lang.org/sirthias/parboiled2) | | Since version `2.4.0` | 75 | | [sirthias/borer](https://index.scala-lang.org/sirthias/borer) | | Since version `1.10.0` | 76 | | [slick/slick](https://index.scala-lang.org/slick/slick) | | Since version `3.5.0-M4` | 77 | | [softwaremill/macwire](https://index.scala-lang.org/softwaremill/macwire) | | Since version `2.4.0` | 78 | | [thoughtworksinc/each](https://index.scala-lang.org/thoughtworksinc/each) | | | 79 | | [tersesystems/blindsight](https://index.scala-lang.org/tersesystems/blindsight) | | Since version [`1.5.2`](https://github.com/tersesystems/blindsight/releases/tag/v1.5.2) | 80 | | [typelevel/claimant](https://index.scala-lang.org/typelevel/claimant) | | No longer maintained | 81 | | [typelevel/spire](https://index.scala-lang.org/typelevel/spire) | | Since version 0.18.0 | 82 | | [wix/accord](https://index.scala-lang.org/wix/accord) | | No longer maintained | 83 | | [wvlet/airframe](https://index.scala-lang.org/wvlet/airframe) | | Since version [`20.12.1`](https://wvlet.org/airframe/docs/release-notes#20121) | 84 | | [zio/izumi-reflect](https://index.scala-lang.org/zio/izumi-reflect) | | Does not yet support path-dependent type | 85 | | [zio/zio](https://index.scala-lang.org/zio/zio) | | Since version [`1.0.4`](https://github.com/zio/zio/releases/tag/v1.0.4) | 86 | | [zero-deps/proto](https://index.scala-lang.org/zero-deps/proto) | | Since version [`2.1.0`](https://github.com/zero-deps/proto/releases/tag/2.1) | 87 | 88 | If you find any macro library that is not listed here you are invited to [open an issue](https://github.com/scalacenter/scala-3-migration-guide/issues). 89 | 90 | ## Macro Annotations Libraries 91 | 92 | Macro annotations are not supported in Scala 3. 93 | The following table contains a incomplete list of Scala 2.13 libraries that provide macro annotations. 94 | Scala 3 compatible alternatives are proposed when available. 95 | 96 | | Project | Alternative Solutions | 97 | |-|-| 98 | | [dmytromitin/auxify](https://index.scala-lang.org/dmytromitin/auxify) | | 99 | | [julianpeeters/avro-scala-macro-annotations](https://index.scala-lang.org/julianpeeters/avro-scala-macro-annotations) | | 100 | | [manatki/derevo](https://index.scala-lang.org/manatki/derevo) | | 101 | | [typelevel/simulacrum](https://index.scala-lang.org/typelevel/simulacrum) | Source generation using [simulacrum-scalafix](https://index.scala-lang.org/typelevel/simulacrum-scalafix/simulacrum-scalafix/0.5.0?target=_2.12) | 102 | 103 | [Contributors welcome!](../contributing.md) 104 | -------------------------------------------------------------------------------- /docs/tooling/migration-tools.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: migration-tools 3 | title: Tour of the Migration Tools 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/tooling-tour.html). 7 | -------------------------------------------------------------------------------- /docs/tooling/scala-3-migrate-plugin.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: scala-3-migrate-plugin 3 | title: Scala 3 Migrate Plugin 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/scala3-migrate.html). 7 | -------------------------------------------------------------------------------- /docs/tooling/scala-3-migration-mode.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: scala-3-migration-mode 3 | title: Scala 3 Migration Mode 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/tooling-migration-mode.html). 7 | -------------------------------------------------------------------------------- /docs/tooling/scala-3-syntax-rewrites.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: scala-3-syntax-rewrites 3 | title: Scala 3 Syntax Rewriting 4 | --- 5 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/tooling-syntax-rewriting.html). 6 | -------------------------------------------------------------------------------- /docs/tutorials/kind-projector.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: kind-projector 3 | title: kind-projector Migration Tutorial 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/plugin-kind-projector.html). 7 | -------------------------------------------------------------------------------- /docs/tutorials/macro-cross-building.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: macro-cross-building 3 | title: Cross-Building a Macro Library 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/tutorial-macro-cross-building.html). 7 | -------------------------------------------------------------------------------- /docs/tutorials/macro-mixing.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: macro-mixing 3 | title: Mixing Scala 2.13 and Scala 3 Macros 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/tutorial-macro-mixing.html). 7 | -------------------------------------------------------------------------------- /docs/tutorials/prerequisites.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: prerequisites 3 | title: Project Prerequisites 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/tutorial-prerequisites.html). 7 | -------------------------------------------------------------------------------- /docs/tutorials/sbt-migration.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: sbt-migration 3 | title: sbt Migration Tutorial 4 | --- 5 | 6 | Moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/tutorial-sbt.html). 7 | -------------------------------------------------------------------------------- /incompat-3-future/alphanumeric-infix/src/main/scala-3.0/alphanumeric-infix.scala: -------------------------------------------------------------------------------- 1 | object AlphanumericInfix { 2 | trait MultiSet { 3 | def difference(other: MultiSet): MultiSet 4 | } 5 | 6 | def test(s1: MultiSet, s2: MultiSet): MultiSet = 7 | s1 difference s2 8 | } 9 | -------------------------------------------------------------------------------- /incompat-3-future/alphanumeric-infix/src/main/scala/alphanumeric-infix.scala: -------------------------------------------------------------------------------- 1 | object AlphanumericInfix { 2 | trait MultiSet { 3 | def difference(other: MultiSet): MultiSet 4 | } 5 | 6 | def test(s1: MultiSet, s2: MultiSet): MultiSet = 7 | s1 `difference` s2 8 | } 9 | -------------------------------------------------------------------------------- /incompat-3-future/context-bound-arg/src/main/scala-3.0/context-bound-arg.scala: -------------------------------------------------------------------------------- 1 | object ContextBoundArg { 2 | trait Show[T] 3 | 4 | def show[T: Show](value: T): String = ??? 5 | 6 | val intShow = new Show[Int] {} 7 | 8 | show(5)(intShow) 9 | } 10 | -------------------------------------------------------------------------------- /incompat-3-future/context-bound-arg/src/main/scala/context-bound-arg.scala: -------------------------------------------------------------------------------- 1 | object ContextBoundArg { 2 | trait Show[T] 3 | 4 | def show[T: Show](value: T): String = ??? 5 | 6 | val intShow = new Show[Int] {} 7 | 8 | show(5)(using intShow) 9 | } 10 | -------------------------------------------------------------------------------- /incompat-3-future/eta-expansion/src/main/scala-3.0/eta-expansion.scala: -------------------------------------------------------------------------------- 1 | object EtaExpansion { 2 | def foo(x: Int)(y: Int): Int = x + y 3 | val f = foo _ 4 | 5 | def bar(): Int = 3 6 | val g = bar _ 7 | } 8 | -------------------------------------------------------------------------------- /incompat-3-future/eta-expansion/src/main/scala/eta-expansion.scala: -------------------------------------------------------------------------------- 1 | object EtaExpansion { 2 | def foo(x: Int)(y: Int): Int = x + y 3 | val f = foo 4 | 5 | def bar(): Int = 3 6 | val g = (() => bar()) 7 | } 8 | -------------------------------------------------------------------------------- /incompat-3-future/implicit-lambda-param/src/main/scala-3.0/implicit-lambda-param.scala: -------------------------------------------------------------------------------- 1 | // TODO: Uncomment on Dotty 0.27.0-RC1 2 | 3 | // object ImplicitLambdaParam { 4 | // trait Context 5 | 6 | // val f = { implicit ctx: Context => ??? } 7 | // } 8 | -------------------------------------------------------------------------------- /incompat-3-future/implicit-lambda-param/src/main/scala/implicit-lambda-param.scala: -------------------------------------------------------------------------------- 1 | // TODO: Uncomment on Dotty 0.27.0-RC1 2 | 3 | // object ImplicitLambdaParam { 4 | // trait Context 5 | 6 | // val f = { implicit ctx: Context => ??? } 7 | // } 8 | -------------------------------------------------------------------------------- /incompat-3-future/pattern-binding/src/main/scala-3.0/pattern-binding.scala: -------------------------------------------------------------------------------- 1 | // TODO Uncomment on Dotty 0.27.0-RC1 2 | 3 | // object PatternBinding { 4 | // val list: List[Int] = List(1) 5 | // val head :: _ = list 6 | 7 | // val listOpt: List[Option[Int]] = List(Some(1), None) 8 | // for (Some(value) <- listOpt) 9 | // println(value) 10 | // } 11 | -------------------------------------------------------------------------------- /incompat-3-future/pattern-binding/src/main/scala/pattern-binding.scala: -------------------------------------------------------------------------------- 1 | // TODO Uncomment on Dotty 0.27.0-RC1 2 | 3 | // object PatternBinding { 4 | // val list: List[Int] = List(1) 5 | // val head :: _ = list 6 | 7 | // val listOpt: List[Option[Int]] = List(Some(1), None) 8 | // for (Some(value) <- listOpt) 9 | // println(value) 10 | // } 11 | -------------------------------------------------------------------------------- /incompat-3-future/wildcard/src/main/scala-3.0/wildcard.scala: -------------------------------------------------------------------------------- 1 | trait Container[A] { 2 | def weight: Int 3 | } 4 | 5 | object Container { 6 | def compare(x: Container[_], y: Container[_]): Int = { 7 | x.weight - y.weight 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /incompat-3-future/wildcard/src/main/scala/wildcard.scala: -------------------------------------------------------------------------------- 1 | trait Container[A] { 2 | def weight: Int 3 | } 4 | 5 | object Container { 6 | def compare(x: Container[?], y: Container[?]): Int = { 7 | x.weight - y.weight 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /incompat-3/README.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | In this folder we track all the found incompatibilities between Scala 2.13 and Scala 3.0. 4 | 5 | Each incompatibility lives in its own subfolder and sbt subproject. It is described by: 6 | - a short `README.md` detailing the origin, the compiler message, the related documentation, the related issues and PRs... 7 | - a `src/main/scala-2.13` source directory that must compile in Scala 2.13 but not in Scala 3.0 8 | - a proposed solution under `src/main/scala/` that must compile with Scala 2.13 **and** Scala 3.0 9 | 10 | The sbt `/test` task ensures both that the `scala-2.13` sources do not compile and that the `scala` sources compile with Scala 3.0. It will help us maintain an up-to-date view of the incompatibilities because, as Scala 3.0 progresses towards the release, we expect some of these incompatibilites to be solved at the compiler side. 11 | 12 | The `implicitView` incompatibility is different because it is a runtime incompatibility, meaning that the code compiles but the runtime behavior change. In this case the `implicitView/test` task checks that the `scala-2.13` runtime behavior is wrong and that the `scala` runtime behavior is correct. 13 | 14 | The sbt `incompat-30` project is an aggregate of all the incompatibility projects. You can check all the incompatibilities by running `incompat-30/test`. 15 | 16 | ## Motivation 17 | 18 | This set of incompatibilities will be used to track the progress of the migration guide and migration tooling. 19 | 20 | The [Incompatibility Table](https://scalacenter.github.io/scala-3-migration-guide/docs/incompatibilities/table.html) shows the status of those incomaptibility: 21 | - Does it produce a feature or deprecation warning in 2.13? 22 | - Do we have a Scala 3.0 migration rewrite? 23 | - Do we have a Scalafix rule to handle it? 24 | -------------------------------------------------------------------------------- /incompat-3/abstract-override/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-other-changes.html#abstract-override). -------------------------------------------------------------------------------- /incompat-3/abstract-override/src/main/scala-2.13/abstract-override.scala: -------------------------------------------------------------------------------- 1 | package foo 2 | 3 | trait A { 4 | def bar(x: Int): Int = x + 3 5 | } 6 | 7 | trait B extends A { 8 | def bar(x: Int): Int 9 | } 10 | 11 | class C extends B 12 | -------------------------------------------------------------------------------- /incompat-3/abstract-override/src/main/scala/abstract-override.scala: -------------------------------------------------------------------------------- 1 | package foo 2 | 3 | trait A { 4 | def bar(x: Int): Int = x + 3 5 | } 6 | 7 | trait B extends A { 8 | } 9 | 10 | class C extends B 11 | -------------------------------------------------------------------------------- /incompat-3/access-modifier/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-other-changes.html#non-private-constructor-in-private-class). -------------------------------------------------------------------------------- /incompat-3/access-modifier/src/main/scala-2.13/access-modifier.scala: -------------------------------------------------------------------------------- 1 | package foo 2 | 3 | object Foo { 4 | private class Bar private[foo] () 5 | } 6 | -------------------------------------------------------------------------------- /incompat-3/access-modifier/src/main/scala/access-modifier.scala: -------------------------------------------------------------------------------- 1 | package foo 2 | 3 | object Foo { 4 | private class Bar() 5 | } 6 | -------------------------------------------------------------------------------- /incompat-3/ambiguous-conversion/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-contextual-abstractions.html#ambiguous-conversion-on-a-and--a). -------------------------------------------------------------------------------- /incompat-3/ambiguous-conversion/src/main/scala-2.13/ambiguous-conversion.scala: -------------------------------------------------------------------------------- 1 | trait Foo { 2 | def foo(): Unit 3 | } 4 | 5 | object Foo { 6 | implicit def boolFoo(bool: Boolean): Foo = ??? 7 | implicit def lazyBoolFoo(lazyBool: => Boolean): Foo = ??? 8 | 9 | true.foo() 10 | } 11 | -------------------------------------------------------------------------------- /incompat-3/ambiguous-conversion/src/main/scala/ambiguous-conversion.scala: -------------------------------------------------------------------------------- 1 | trait Foo { 2 | def foo(): Unit 3 | } 4 | 5 | object Foo { 6 | implicit def boolFoo(bool: Boolean): Foo = ??? 7 | implicit def lazyBoolFoo(lazyBool: => Boolean): Foo = ??? 8 | 9 | boolFoo(true).foo() 10 | } 11 | -------------------------------------------------------------------------------- /incompat-3/anonymous-type-param/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-syntactic.html#_-as-a-type-parameter). -------------------------------------------------------------------------------- /incompat-3/anonymous-type-param/src/main/scala-2.13/anonymous-type-param.scala: -------------------------------------------------------------------------------- 1 | trait Foo[T] 2 | 3 | object Foo { 4 | def foo[_: Foo]: Unit = () 5 | } 6 | -------------------------------------------------------------------------------- /incompat-3/anonymous-type-param/src/main/scala/anonymous-type-param.scala: -------------------------------------------------------------------------------- 1 | trait Foo[T] 2 | 3 | object Foo { 4 | def foo[T: Foo]: Unit = () 5 | } 6 | -------------------------------------------------------------------------------- /incompat-3/any2stringadd-conversion/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-dropped-features.html#any2stringadd-conversion). -------------------------------------------------------------------------------- /incompat-3/any2stringadd-conversion/src/main/scala-2.13/any2stringadd-conversion.scala: -------------------------------------------------------------------------------- 1 | object Test { 2 | val str = new AnyRef + "foo" 3 | } 4 | -------------------------------------------------------------------------------- /incompat-3/any2stringadd-conversion/src/main/scala/any2stringadd-conversion.scala: -------------------------------------------------------------------------------- 1 | object Test { 2 | val str = "" + new AnyRef + "foo" 3 | } 4 | -------------------------------------------------------------------------------- /incompat-3/auto-application/.scalafix.conf: -------------------------------------------------------------------------------- 1 | rules = [ 2 | fix.scala213.ExplicitNonNullaryApply 3 | ] 4 | -------------------------------------------------------------------------------- /incompat-3/auto-application/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-dropped-features.html#auto-application). 2 | -------------------------------------------------------------------------------- /incompat-3/auto-application/src/main/scala-2.13/auto-application.scala: -------------------------------------------------------------------------------- 1 | object Test { 2 | object Hello { 3 | def message(): String = "Hello" 4 | } 5 | 6 | println(Hello.message) 7 | } 8 | -------------------------------------------------------------------------------- /incompat-3/auto-application/src/main/scala/auto-application.scala: -------------------------------------------------------------------------------- 1 | object Test { 2 | object Hello { 3 | def message(): String = "Hello" 4 | } 5 | 6 | println(Hello.message()) 7 | } 8 | -------------------------------------------------------------------------------- /incompat-3/bean-property/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-other-changes.html#invisible-bean-property). -------------------------------------------------------------------------------- /incompat-3/bean-property/src/main/scala-2.13/bean-property.scala: -------------------------------------------------------------------------------- 1 | import scala.beans.BeanProperty 2 | 3 | class Pojo { 4 | @BeanProperty var fooBar: String = "" 5 | } 6 | 7 | object Test { 8 | def test(): Unit = { 9 | val pojo = new Pojo 10 | println(pojo.getFooBar()) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /incompat-3/bean-property/src/main/scala/bean-property.scala: -------------------------------------------------------------------------------- 1 | import scala.beans.BeanProperty 2 | 3 | class Pojo { 4 | @BeanProperty var fooBar: String = "" 5 | } 6 | 7 | object Test { 8 | def test(): Unit = { 9 | val pojo = new Pojo 10 | println(pojo.fooBar) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /incompat-3/by-name-param-type-infer/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-other-changes.html#-t-as-type-argument). -------------------------------------------------------------------------------- /incompat-3/by-name-param-type-infer/src/main/scala-2.13/by-name-param-type-infer.scala: -------------------------------------------------------------------------------- 1 | object Test { 2 | val f: Int => (=> Int) => Int = x => y => x 3 | val g: (Int, => Int) => Int = Function.uncurried(f) 4 | } 5 | -------------------------------------------------------------------------------- /incompat-3/by-name-param-type-infer/src/main/scala/by-name-param-type-infer.scala: -------------------------------------------------------------------------------- 1 | object Test { 2 | val f: Int => (=> Int) => Int = x => y => x 3 | val g: (Int, => Int) => Int = (x, y) => x 4 | } 5 | -------------------------------------------------------------------------------- /incompat-3/case-class-companion/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-other-changes.html#case-class-companion). -------------------------------------------------------------------------------- /incompat-3/case-class-companion/src/main/scala-2.13/case-class-companion.scala: -------------------------------------------------------------------------------- 1 | package foo 2 | 3 | case class Foo(x: Int, b: Boolean) 4 | 5 | object Bar { 6 | val f1 = Foo.curried(1)(true) 7 | val f2 = Foo.tupled((2, false)) 8 | } 9 | -------------------------------------------------------------------------------- /incompat-3/case-class-companion/src/main/scala/case-class-companion.scala: -------------------------------------------------------------------------------- 1 | package foo 2 | 3 | case class Foo(x: Int, b: Boolean) 4 | 5 | object Bar { 6 | val f1 = (Foo.apply _).curried(1)(true) 7 | val f2 = (Foo.apply _).tupled((1, true)) 8 | 9 | val fooCtr: (Int, Boolean) => Foo = (x, b) => Foo(x, b) 10 | 11 | val f1Bis = fooCtr.curried(1)(true) 12 | val f2Bis = fooCtr.tupled((2, false)) 13 | } 14 | -------------------------------------------------------------------------------- /incompat-3/do-while/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-dropped-features.html#do-while-construct). -------------------------------------------------------------------------------- /incompat-3/do-while/src/main/scala-2.13/do-while.scala: -------------------------------------------------------------------------------- 1 | object DoWhile { 2 | def foo(f: Int => Int): Int = { 3 | var i = 0 4 | do { 5 | i += 1 6 | } while (f(i) == 0) 7 | i 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /incompat-3/do-while/src/main/scala/do-while.scala: -------------------------------------------------------------------------------- 1 | object DoWhile { 2 | def foo(f: Int => Int): Int = { 3 | var i = 0 4 | while ({ { 5 | i += 1 6 | } ; f(i) == 0}) () 7 | i 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /incompat-3/early-initializer/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-dropped-features.html#early-initializer). -------------------------------------------------------------------------------- /incompat-3/early-initializer/src/main/scala-2.13/early-initializer.scala: -------------------------------------------------------------------------------- 1 | trait Bar { 2 | val name: String 3 | val size: Int = name.size 4 | } 5 | 6 | object Foo extends { 7 | val name = "Foo" 8 | } with Bar 9 | -------------------------------------------------------------------------------- /incompat-3/early-initializer/src/main/scala/early-initializer.scala: -------------------------------------------------------------------------------- 1 | trait Bar { 2 | val name: String 3 | val size: Int = name.size 4 | } 5 | 6 | abstract class BarEarlyInit(val name: String) extends Bar 7 | 8 | object Foo extends BarEarlyInit("Foo") 9 | -------------------------------------------------------------------------------- /incompat-3/existential-type/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-dropped-features.html#existential-type). -------------------------------------------------------------------------------- /incompat-3/existential-type/src/main/scala-2.13/existential-type.scala: -------------------------------------------------------------------------------- 1 | trait Foo { 2 | def foo: List[Class[T]] forSome { type T } 3 | } 4 | -------------------------------------------------------------------------------- /incompat-3/existential-type/src/main/scala/existential-type.scala: -------------------------------------------------------------------------------- 1 | trait Bar { 2 | type T 3 | val value: List[Class[T]] 4 | } 5 | 6 | trait Foo { 7 | def foo: Bar 8 | } 9 | -------------------------------------------------------------------------------- /incompat-3/explicit-call-to-unapply/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-other-changes.html#explicit-call-to-unapply). -------------------------------------------------------------------------------- /incompat-3/explicit-call-to-unapply/src/main/scala-2.13/explicit-call-to-unapply.scala: -------------------------------------------------------------------------------- 1 | case class Location(lat: Int, lon: Int) 2 | 3 | object Location { 4 | def tuple(location: Location): (Int, Int) = { 5 | Location.unapply(location).get 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /incompat-3/explicit-call-to-unapply/src/main/scala/explicit-call-to-unapply.scala: -------------------------------------------------------------------------------- 1 | case class Location(lat: Int, lon: Int) 2 | 3 | object Location { 4 | def tuple(location: Location): (Int, Int) = { 5 | locally { 6 | val Location(lat, lon) = location 7 | (lat, lon) 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /incompat-3/implicit-view/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-contextual-abstractions.html#implicit-views). -------------------------------------------------------------------------------- /incompat-3/implicit-view/src/main/scala-2.13/implicit-view.scala: -------------------------------------------------------------------------------- 1 | trait Pretty { 2 | val print: String 3 | } 4 | 5 | object Pretty { 6 | implicit def anyPretty(any: Any): Pretty = new Pretty { val print = "any" } 7 | def pretty[A](a: A)(implicit ev: A => Pretty): String = a.print 8 | } 9 | 10 | object Test extends App { 11 | assert(Pretty.pretty("foo")(str => new Pretty { val print = str }) == "foo") 12 | } 13 | -------------------------------------------------------------------------------- /incompat-3/implicit-view/src/main/scala/implicit-view.scala: -------------------------------------------------------------------------------- 1 | trait Pretty { 2 | val print: String 3 | } 4 | 5 | object Pretty { 6 | implicit def anyPretty(any: Any): Pretty = new Pretty { val print = "any" } 7 | def pretty[A](a: A)(implicit ev: A => Pretty): String = ev(a).print 8 | } 9 | 10 | object Test extends App { 11 | assert(Pretty.pretty("foo")(str => new Pretty { val print = str }) == "foo") 12 | } 13 | -------------------------------------------------------------------------------- /incompat-3/indent-argument/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-syntactic.html#open-brace-indentation-for-passing-an-argument). -------------------------------------------------------------------------------- /incompat-3/indent-argument/src/main/scala-2.13/indent-argument.scala: -------------------------------------------------------------------------------- 1 | object IndentArgument { 2 | def test(title: String)(body: => Unit) = ??? 3 | 4 | test("my test") 5 | { 6 | assert(1 == 1) 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /incompat-3/indent-argument/src/main/scala/indent-argument.scala: -------------------------------------------------------------------------------- 1 | object IndentArgument { 2 | def test(title: String)(body: => Unit) = ??? 3 | 4 | test("my test") 5 | { 6 | assert(1 == 1) 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /incompat-3/indentation/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-syntactic.html#wrong-indentation). -------------------------------------------------------------------------------- /incompat-3/indentation/indentation-1/src/main/scala-2.13/indentation.scala: -------------------------------------------------------------------------------- 1 | object Foo { 2 | def bar: (Int, Int) = { 3 | val foo = 1.0 4 | val bar = foo 5 | (1, 1) 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /incompat-3/indentation/indentation-1/src/main/scala/indentation.scala: -------------------------------------------------------------------------------- 1 | object Foo { 2 | def bar: (Int, Int) = { 3 | val foo = 1.0 4 | val bar = foo 5 | (1, 1) 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /incompat-3/infer-return-type/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-type-inference.html#return-type-of-an-override-method). -------------------------------------------------------------------------------- /incompat-3/infer-return-type/src/main/scala-2.13/infer-return-type.scala: -------------------------------------------------------------------------------- 1 | class Foo 2 | class RichFoo(foo: Foo) extends Foo { 3 | def show: String = "" 4 | } 5 | 6 | class Parent { 7 | def foo: Foo = new Foo 8 | } 9 | 10 | class Child extends Parent { 11 | override def foo = new RichFoo(super.foo) 12 | } 13 | 14 | object Test { 15 | (new Child).foo.show 16 | } 17 | -------------------------------------------------------------------------------- /incompat-3/infer-return-type/src/main/scala/infer-return-type.scala: -------------------------------------------------------------------------------- 1 | class Foo 2 | class RichFoo(foo: Foo) extends Foo { 3 | def show: String = "" 4 | } 5 | 6 | class Parent { 7 | def foo: Foo = new Foo 8 | } 9 | 10 | class Child extends Parent { 11 | override def foo: RichFoo = new RichFoo(super.foo) 12 | } 13 | 14 | object Test { 15 | (new Child).foo.show 16 | } 17 | -------------------------------------------------------------------------------- /incompat-3/inheritance-shadowing/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-other-changes.html#inheritance-shadowing). -------------------------------------------------------------------------------- /incompat-3/inheritance-shadowing/src/main/scala-2.13/inheritance-shadowing.scala: -------------------------------------------------------------------------------- 1 | object InheritShadowing { 2 | class A { 3 | val x = 2 4 | } 5 | 6 | object B { 7 | val x = 1 8 | class C extends A { 9 | println(x) 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /incompat-3/inheritance-shadowing/src/main/scala/inheritance-shadowing.scala: -------------------------------------------------------------------------------- 1 | object InheritShadowing { 2 | class A { 3 | val x = 2 4 | } 5 | 6 | object B { 7 | val x = 1 8 | class C extends A { 9 | println(this.x) 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /incompat-3/keywords/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-syntactic.html#restricted-keywords). 2 | -------------------------------------------------------------------------------- /incompat-3/keywords/src/main/scala-2.13/keywords.scala: -------------------------------------------------------------------------------- 1 | object given { 2 | val enum = ??? 3 | 4 | def foo = println(enum) 5 | } 6 | -------------------------------------------------------------------------------- /incompat-3/keywords/src/main/scala/keywords.scala: -------------------------------------------------------------------------------- 1 | object `given` { 2 | val `enum` = ??? 3 | 4 | def foo = println(`enum`) 5 | } 6 | -------------------------------------------------------------------------------- /incompat-3/lambda-params/.scalafix.conf: -------------------------------------------------------------------------------- 1 | rule = fix.scala213.ParensAroundLambda 2 | -------------------------------------------------------------------------------- /incompat-3/lambda-params/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-syntactic.html#parentheses-around-lambda-parameter). -------------------------------------------------------------------------------- /incompat-3/lambda-params/src/main/scala-2.13/lambda-params.scala: -------------------------------------------------------------------------------- 1 | object LambdaParam { 2 | val f = { x: Int => x * x } 3 | } 4 | -------------------------------------------------------------------------------- /incompat-3/lambda-params/src/main/scala/lambda-params.scala: -------------------------------------------------------------------------------- 1 | object LambdaParam { 2 | val f = { (x: Int) => x * x } 3 | } 4 | -------------------------------------------------------------------------------- /incompat-3/pattern-match/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-type-checker.html#unsoundness-fixes-in-pattern-matching). -------------------------------------------------------------------------------- /incompat-3/pattern-match/src/main/scala-2.13/pattern-match.scala: -------------------------------------------------------------------------------- 1 | trait Request 2 | case class Fetch[A](ids: Set[A]) extends Request 3 | 4 | object Request { 5 | def combineFetch[A](x: Fetch[A], y: Fetch[A]): Fetch[A] = Fetch(x.ids ++ y.ids) 6 | 7 | def combineReq(x: Request, y: Request): Request = { 8 | (x, y) match { 9 | case (x @ Fetch(_), y @ Fetch(_)) => combineFetch(x, y) 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /incompat-3/pattern-match/src/main/scala/pattern-match.scala: -------------------------------------------------------------------------------- 1 | trait Request 2 | case class Fetch[A](ids: Set[A]) extends Request 3 | 4 | object Request { 5 | def combineFetch[A](x: Fetch[_ <: A], y: Fetch[_ <: A]): Fetch[A] = Fetch(x.ids ++ y.ids) 6 | 7 | def combineReq(x: Request, y: Request): Request = { 8 | (x, y) match { 9 | case (x @ Fetch(_), y @ Fetch(_)) => combineFetch(x, y) 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /incompat-3/procedure-syntax/.scalafix.conf: -------------------------------------------------------------------------------- 1 | rules = [ 2 | ProcedureSyntax, 3 | fix.scala213.ConstructorProcedureSyntax 4 | ] 5 | -------------------------------------------------------------------------------- /incompat-3/procedure-syntax/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-syntactic.html#procedure-syntax). -------------------------------------------------------------------------------- /incompat-3/procedure-syntax/src/main/scala-2.13/procedure-syntax.scala: -------------------------------------------------------------------------------- 1 | // Here Dotty adds useless blank character 2 | // trait Foo { 3 | // def print() 4 | // } 5 | 6 | class Bar(a: String) { 7 | def this() { 8 | this("bar") 9 | print() 10 | } 11 | 12 | def print() { 13 | println(a) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /incompat-3/procedure-syntax/src/main/scala/procedure-syntax.scala: -------------------------------------------------------------------------------- 1 | // Here Dotty adds useless blank character 2 | // trait Foo { 3 | // def print() 4 | // } 5 | 6 | class Bar(a: String) { 7 | def this() = { 8 | this("bar") 9 | print() 10 | } 11 | 12 | def print(): Unit = { 13 | println(a) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /incompat-3/reflective-call/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-type-inference.html#reflective-type). -------------------------------------------------------------------------------- /incompat-3/reflective-call/src/main/scala-2.13/reflective-call.scala: -------------------------------------------------------------------------------- 1 | import scala.language.reflectiveCalls 2 | 3 | object Foo { 4 | val foo = new { 5 | def bar: Unit = ??? 6 | } 7 | 8 | foo.bar 9 | } 10 | -------------------------------------------------------------------------------- /incompat-3/reflective-call/src/main/scala/reflective-call.scala: -------------------------------------------------------------------------------- 1 | import scala.language.reflectiveCalls 2 | 3 | object Foo { 4 | val foo: { def bar: Unit } = new { 5 | def bar: Unit = ??? 6 | } 7 | 8 | foo.bar 9 | } 10 | -------------------------------------------------------------------------------- /incompat-3/restricted-operator/README.md: -------------------------------------------------------------------------------- 1 | This incompatibility is inspired by [this commit](https://github.com/scalaz/scalaz/commit/56b5cbb39ba82ae1a3641bbadda419b17171a219) in [scalaz](https://github.com/scalaz/scalaz) 2 | 3 | `=>>` is not valid identifier anymore and the dotc rewrite feature does not handle this case. 4 | 5 | As of `0.25.0-RC2` the error message is 6 | ``` 7 | [error] -- [E040] Syntax Error: /src/main/scala/restricted-operator.scala:2:6 8 | [error] 2 | def =>> : Unit 9 | [error] | ^^^ 10 | [error] | an identifier expected, but '=>>' found 11 | ``` 12 | -------------------------------------------------------------------------------- /incompat-3/restricted-operator/src/main/scala-2.13/restricted-operator.scala: -------------------------------------------------------------------------------- 1 | trait Foo { 2 | def =>> : Unit 3 | } 4 | -------------------------------------------------------------------------------- /incompat-3/restricted-operator/src/main/scala/restricted-operator.scala: -------------------------------------------------------------------------------- 1 | trait Foo { 2 | def `=>>` : Unit 3 | } 4 | -------------------------------------------------------------------------------- /incompat-3/symbol-literals/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-dropped-features.html#symbol-literals). -------------------------------------------------------------------------------- /incompat-3/symbol-literals/src/main/scala-2.13/symbol-literals.scala: -------------------------------------------------------------------------------- 1 | object SymbolLitterals { 2 | val values: Map[Symbol, Int] = Map('abc -> 1) 3 | 4 | val abc = values('abc) 5 | } 6 | -------------------------------------------------------------------------------- /incompat-3/symbol-literals/src/main/scala/symbol-literals.scala: -------------------------------------------------------------------------------- 1 | object SymbolLitterals { 2 | val values: Map[Symbol, Int] = Map(Symbol("abc") -> 1) 3 | 4 | val abc = values(Symbol("abc")) 5 | } 6 | -------------------------------------------------------------------------------- /incompat-3/type-infer-10/README.md: -------------------------------------------------------------------------------- 1 | This incompatibility is inspired by [this commit](https://github.com/zio/zio/commit/47354b798aaf1969d2980feda1d7bbe829c45429#diff-3c34fedc744e163210b0e536329e4598) from [zio](https://github.com/zio/zio). 2 | 3 | As of `3.0.0-RC1` the error message is 4 | ``` 5 | [error] -- [E007] Type Mismatch Error: /home/piquerez/scalacenter/scala-3-migration-guide/incompat-30/type-infer-10/src/main/scala/type-infer.scala:11:41 6 | [error] 11 | case Executing(observer) => notify(observer) 7 | [error] | ^^^^^^^^ 8 | [error] | Found: (observer : Callback[Option[A$1]]) 9 | [error] | Required: Callback[Option[A]] 10 | [error] | 11 | [error] | where: A is a type in class Test with bounds >: A$1 12 | [error] | A$1 is a type in method test with bounds <: A 13 | ``` 14 | 15 | Precising that `Callback` is covariant in `A` fixes the warning and even more it makes the type annotation useless. 16 | -------------------------------------------------------------------------------- /incompat-3/type-infer-10/src/main/scala-2.13/type-infer.scala: -------------------------------------------------------------------------------- 1 | sealed trait Callback[A] 2 | 3 | sealed trait State[+A] 4 | final case class Executing[A](observer: Callback[Option[A]]) extends State[A] 5 | 6 | class Test[A](state: State[A]) { 7 | def notify(observer: Callback[Option[A]]): Unit = ??? 8 | 9 | def test(): Unit = { 10 | state match { 11 | case Executing(observer) => notify(observer) 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /incompat-3/type-infer-10/src/main/scala/type-infer.scala: -------------------------------------------------------------------------------- 1 | sealed trait Callback[A] 2 | 3 | sealed trait State[+A] 4 | final case class Executing[A](observer: Callback[Option[A]]) extends State[A] 5 | 6 | class Test[A](state: State[A]) { 7 | def notify(observer: Callback[Option[A]]): Unit = ??? 8 | 9 | def test(): Unit = { 10 | state match { 11 | case executing: Executing[A] => notify(executing.observer) 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /incompat-3/type-infer-3/README.md: -------------------------------------------------------------------------------- 1 | This incompatibility is inspired by the [dotty-staging-fork](https://github.com/dotty-staging/geny/tree/eabca8efc9b76516003f686b3c20f798b5ac011e) of [geny](https://github.com/lihaoyi/geny) from this [original commit](https://github.com/dotty-staging/geny/commit/d62edce1ec69c6ecd2061da6b4bf22bd4dba6230#diff-d2df9cc4eedc3f846d7431c70df2ff81). 2 | 3 | As of `0.25.0-RC2` the error message is: 4 | 5 | ``` 6 | [error] -- Error: /home/piquerez/scalacenter/scala-3-migration-guide/incompat/type-infer-3/src/main/scala-2.13/type-infer.scala:14:12 7 | [error] 14 | from(Fizz) 8 | [error] | ^ 9 | [error] |no implicit argument of type Context[Bar] was found for parameter ctx of method from in object Test 10 | ``` 11 | -------------------------------------------------------------------------------- /incompat-3/type-infer-3/src/main/scala-2.13/type-infer.scala: -------------------------------------------------------------------------------- 1 | trait Context[M[_]] 2 | 3 | trait Foo[T] 4 | trait Bar[T] 5 | object Fizz extends Foo[Int] with Bar[Int] 6 | 7 | object Foo { 8 | implicit val ctx: Context[Foo] = ??? 9 | } 10 | 11 | object Test { 12 | def from[M[_], T](m: M[T])(implicit ctx: Context[M]): Unit = ??? 13 | 14 | from(Fizz) 15 | } 16 | -------------------------------------------------------------------------------- /incompat-3/type-infer-3/src/main/scala/type-infer.scala: -------------------------------------------------------------------------------- 1 | trait Context[M[_]] 2 | 3 | trait Foo[T] 4 | trait Bar[T] 5 | object Fizz extends Foo[Int] with Bar[Int] 6 | 7 | object Foo { 8 | implicit val ctx: Context[Foo] = ??? 9 | } 10 | 11 | object Test { 12 | def from[M[_], T](m: M[T])(implicit ctx: Context[M]): Unit = ??? 13 | 14 | from[Foo, Int](Fizz) 15 | } 16 | -------------------------------------------------------------------------------- /incompat-3/type-infer-4/README.md: -------------------------------------------------------------------------------- 1 | This incompatibility is inspired by [this commit](https://github.com/scalaz/scalaz/commit/45ec3197db959794b0c4642889c8fb1f133a8b3b) in [scalaz](https://github.com/scalaz/scalaz). 2 | 3 | As of `0.25.0-RC2` the error message is: 4 | 5 | ``` 6 | [error] -- [E007] Type Mismatch Error: /home/piquerez/scalacenter/scala-3-migration-guide/incompat/type-infer-4/src/main/scala-2.13/type-infer.scala:9:62 7 | [error] 9 | def buzz[A, B](foo: Foo[A]): Option[Bar[B]] = fizz(foo).map(toBar) 8 | [error] | ^^^^^ 9 | [error] | Found: Bar[Any] 10 | [error] | Required: Bar[B] 11 | ``` 12 | -------------------------------------------------------------------------------- /incompat-3/type-infer-4/src/main/scala-2.13/type-infer.scala: -------------------------------------------------------------------------------- 1 | trait Foo[A] 2 | trait Bar[A] 3 | 4 | object Test { 5 | def toBar[A](foo: Foo[A]): Bar[A] = ??? 6 | 7 | def fizz[A, B](foo: Foo[A]): Option[Foo[B]] = ??? 8 | 9 | def buzz[A, B](foo: Foo[A]): Option[Bar[B]] = fizz(foo).map(toBar) 10 | } 11 | -------------------------------------------------------------------------------- /incompat-3/type-infer-4/src/main/scala/type-infer.scala: -------------------------------------------------------------------------------- 1 | trait Foo[A] 2 | trait Bar[A] 3 | 4 | object Test { 5 | def toBar[A](foo: Foo[A]): Bar[A] = ??? 6 | 7 | def fizz[A, B](foo: Foo[A]): Option[Foo[B]] = ??? 8 | 9 | def buzz[A, B](foo: Foo[A]): Option[Bar[B]] = fizz[A, B](foo).map(toBar) 10 | } 11 | -------------------------------------------------------------------------------- /incompat-3/type-infer-5/README.md: -------------------------------------------------------------------------------- 1 | This incompatibility is inspired by [this commit](https://github.com/scalaz/scalaz/commit/bf4710dca45842b0833d83806353dc21b4ee2c2c) in [scalaz](https://github.com/scalaz/scalaz). 2 | 3 | As of `0.25.0-RC2` the error message is: 4 | ``` 5 | [error] -- [E007] Type Mismatch Error: /home/piquerez/scalacenter/scala-3-migration-guide/incompat/type-infer-5/src/main/scala-2.13/type-infer.scala:6:4 6 | [error] 6 | result 7 | [error] | ^^^^^^ 8 | [error] | Found: (result : Array[Nothing]) 9 | [error] | Required: Array[A] 10 | ``` 11 | -------------------------------------------------------------------------------- /incompat-3/type-infer-5/src/main/scala-2.13/type-infer.scala: -------------------------------------------------------------------------------- 1 | import reflect.ClassTag 2 | 3 | object Test { 4 | def newArray[A: ClassTag]: Array[A] = { 5 | val result = new Array(5) 6 | result 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /incompat-3/type-infer-5/src/main/scala/type-infer.scala: -------------------------------------------------------------------------------- 1 | import reflect.ClassTag 2 | 3 | object Test { 4 | def newArray[A: ClassTag]: Array[A] = { 5 | val result = new Array[A](5) 6 | result 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /incompat-3/type-infer-9/README.md: -------------------------------------------------------------------------------- 1 | This incompatibility is inspired by [this commit](https://github.com/zio/zio/commit/47354b798aaf1969d2980feda1d7bbe829c45429#diff-36069d491b953beec25f10121bf83d38) from [zio](https://github.com/zio/zio) 2 | 3 | The original incompatible was later solved, in this [commit](https://github.com/zio/zio/commit/9452227590657a992d66f77d348be6b4be5055ff), by precising the variance of the related types, making the type annotation useless. However I was not able to reproduce this alternative fix in the present incompatibility. 4 | 5 | As of `0.25.0-RC2` the error message is 6 | ``` 7 | [error] -- [E007] Type Mismatch Error: /home/piquerez/scalacenter/scala-3-migration-guide/incompat/type-infer-9/src/main/scala-2.13/type-infer.scala:16:58 8 | [error] 16 | def foo(io: IO[Nothing]): IO[Nothing] = acquire(cleanup)(io) 9 | [error] | ^^^^^^^^^^^^^^^^^^^^ 10 | [error] | Found: IO[Any] 11 | [error] | Required: IO[Nothing] 12 | ``` 13 | -------------------------------------------------------------------------------- /incompat-3/type-infer-9/src/main/scala-2.13/type-infer.scala: -------------------------------------------------------------------------------- 1 | trait IO[+E] 2 | 3 | trait Acquire[+E] { 4 | def apply[E1 >: E](release: E1 => IO[Nothing]): Release[E] 5 | } 6 | 7 | trait Release[+E] { 8 | def apply[E1 >: E](io: IO[E1]): IO[E1] 9 | } 10 | 11 | 12 | object IO { 13 | def cleanup[E](e: E): IO[Nothing] = ??? 14 | def acquire[E]: Acquire[E] = ??? 15 | 16 | def foo(io: IO[Nothing]): IO[Nothing] = acquire(cleanup)(io) 17 | } 18 | -------------------------------------------------------------------------------- /incompat-3/type-infer-9/src/main/scala/type-infer.scala: -------------------------------------------------------------------------------- 1 | trait IO[+E] 2 | 3 | trait Acquire[+E] { 4 | def apply[E1 >: E](release: E1 => IO[Nothing]): Release[E] 5 | } 6 | 7 | trait Release[+E] { 8 | def apply[E1 >: E](io: IO[E1]): IO[E1] 9 | } 10 | 11 | 12 | object IO { 13 | def cleanup[E](e: E): IO[Nothing] = ??? 14 | def acquire[E]: Acquire[E] = ??? 15 | 16 | def foo(io: IO[Nothing]): IO[Nothing] = acquire[Nothing](cleanup)(io) 17 | } 18 | -------------------------------------------------------------------------------- /incompat-3/type-of-implicit-def/.scalafix.conf: -------------------------------------------------------------------------------- 1 | rules = [ 2 | ExplicitImplicitTypes 3 | ] 4 | -------------------------------------------------------------------------------- /incompat-3/type-of-implicit-def/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-contextual-abstractions.html#type-of-implicit-definition). -------------------------------------------------------------------------------- /incompat-3/type-of-implicit-def/src/main/scala-2.13/type-of-implicit-def.scala: -------------------------------------------------------------------------------- 1 | trait Context 2 | 3 | object Context { 4 | implicit val context = new Context {} 5 | } 6 | -------------------------------------------------------------------------------- /incompat-3/type-of-implicit-def/src/main/scala/type-of-implicit-def.scala: -------------------------------------------------------------------------------- 1 | trait Context 2 | 3 | object Context { 4 | implicit val context: Context = new Context {} 5 | } 6 | -------------------------------------------------------------------------------- /incompat-3/type-param-identifier/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-syntactic.html#-and---as-type-parameters). 2 | -------------------------------------------------------------------------------- /incompat-3/type-param-identifier/src/main/scala-2.13/type-param-identifier.scala: -------------------------------------------------------------------------------- 1 | trait Foo { 2 | def foo[+]: + 3 | } 4 | -------------------------------------------------------------------------------- /incompat-3/type-param-identifier/src/main/scala/type-param-identifier.scala: -------------------------------------------------------------------------------- 1 | trait Foo { 2 | def foo[x]: x 3 | } 4 | -------------------------------------------------------------------------------- /incompat-3/value-eta-expansion/.scalafix.conf: -------------------------------------------------------------------------------- 1 | rules = [ 2 | fix.scala213.ExplicitNullaryEtaExpansion 3 | ] 4 | -------------------------------------------------------------------------------- /incompat-3/value-eta-expansion/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-dropped-features.html#value-eta-expansion). -------------------------------------------------------------------------------- /incompat-3/value-eta-expansion/src/main/scala-2.13/value-eta-expansion.scala: -------------------------------------------------------------------------------- 1 | object ValueEtaExpansion { 2 | val x = 1 3 | val f: () => Int = x _ 4 | } 5 | -------------------------------------------------------------------------------- /incompat-3/value-eta-expansion/src/main/scala/value-eta-expansion.scala: -------------------------------------------------------------------------------- 1 | object ValueEtaExpansion { 2 | val x = 1 3 | val f: () => Int = (() => x) 4 | } 5 | -------------------------------------------------------------------------------- /incompat-3/variance/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-type-checker.html#unsoundness-fixes-in-variance-checks). -------------------------------------------------------------------------------- /incompat-3/variance/src/main/scala-2.13/variance.scala: -------------------------------------------------------------------------------- 1 | class Foo[-A](x: List[A]) { 2 | def f[B](y: List[B] = x): Unit = ??? 3 | } 4 | 5 | class Outer[+A](x: A) { 6 | class Inner(y: A) 7 | } 8 | -------------------------------------------------------------------------------- /incompat-3/variance/src/main/scala/variance.scala: -------------------------------------------------------------------------------- 1 | class Foo[-A](x: List[A]) { 2 | def f[B](y: List[B]): Unit = ??? 3 | def f(): Unit = f(x) 4 | } 5 | 6 | class Outer[+A](x: A) { 7 | class Inner[B >: A](y: B) 8 | } 9 | -------------------------------------------------------------------------------- /incompat-3/view-bound/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-contextual-abstractions.html#view-bounds). -------------------------------------------------------------------------------- /incompat-3/view-bound/src/main/scala-2.13/view-bound.scala: -------------------------------------------------------------------------------- 1 | trait Foo { 2 | def foo[A <% Long](a: A): Long = a 3 | } 4 | -------------------------------------------------------------------------------- /incompat-3/view-bound/src/main/scala/view-bound.scala: -------------------------------------------------------------------------------- 1 | trait Foo { 2 | def foo[A](a: A)(implicit ev: A => Long): Long = ev(a) 3 | } 4 | -------------------------------------------------------------------------------- /incompat-3/wildcard-argument/README.md: -------------------------------------------------------------------------------- 1 | Description [here](https://docs.scala-lang.org/scala3/guides/migration/incompat-other-changes.html#wildcard-type-argument) -------------------------------------------------------------------------------- /incompat-3/wildcard-argument/src/main/scala-2.13/wildcard-argument.scala: -------------------------------------------------------------------------------- 1 | trait Example { 2 | type Foo[A] 3 | 4 | def f(foos: Seq[Foo[_]]): Unit 5 | } 6 | -------------------------------------------------------------------------------- /incompat-3/wildcard-argument/src/main/scala/wildcard-argument.scala: -------------------------------------------------------------------------------- 1 | trait Example { 2 | type Foo[A] 3 | 4 | class FooWrapper[A](foo: Foo[A]) 5 | 6 | def f(foos: Seq[FooWrapper[_]]): Unit 7 | } 8 | -------------------------------------------------------------------------------- /incompat.sbt: -------------------------------------------------------------------------------- 1 | import Versions._ 2 | import IncompatSettings._ 3 | 4 | // scalafix configuration 5 | ThisBuild / scalaVersion := scala213 6 | ThisBuild / scalafixDependencies ++= Seq( 7 | "com.sandinh" %% "scala-rewrites" % "0.1.10-sd", 8 | "org.scala-lang" %% "scala-rewrites" % "0.1.2" 9 | ) 10 | ThisBuild /scalafixScalaBinaryVersion := CrossVersion.binaryScalaVersion(scalaVersion.value) 11 | 12 | /* 13 | List of all incompatibilities between Scala 2.13 and Scala 3.0 14 | 15 | You can run: 16 | - `++3.3.0; / test` to validate the incompatibility as well as the Dotty rewrite if it has one 17 | - `++2.13.3; / test` to cross-compile the proposed solution and validate the scalafix rule if it has one 18 | where can be a single incompatibility or `incompat3` for all incompatibilities 19 | */ 20 | lazy val `incompat-3` = project.in(file("incompat-3")) 21 | .configs(CompileBackward) 22 | .aggregate(dotty3MigrationRewrites: _*) 23 | .aggregate(typeInferIncompats: _*) 24 | .aggregate(otherIncompats: _*) 25 | 26 | /* 27 | List of all incompatibilities between Scala 3.0 and Scala 3.1 28 | It only contains the already existing future-migration rewrites in Dotty 29 | 30 | You can run: 31 | - `++3.3.0; / test` to validate the Dotty rewrite 32 | where can be a single incompatibility or `incompat3Future` for all incompatibilities 33 | */ 34 | lazy val `incompat-3-future` = project.in(file("incompat-3-future")) 35 | .configs(CompileBackward) 36 | .aggregate(dotty3FutureMigrationRewrites: _*) 37 | 38 | /* 39 | Dotty migration rewrites between 2.13 and 3.0 40 | `dotc -source:3.0-migration -rewrite` 41 | */ 42 | lazy val dotty3MigrationRewrites = Seq[ProjectReference]( 43 | keywords, 44 | lambdaParams, 45 | symbolLiterals, 46 | indentArgument, 47 | doWhile, 48 | procedureSyntax, 49 | autoApplication, 50 | inheritanceShadowing, 51 | valueEtaExpansion 52 | ) 53 | 54 | lazy val keywords = project.in(file("incompat-3/keywords")).dotty3MigrationRewriteSettings 55 | lazy val lambdaParams = 56 | project.in(file("incompat-3/lambda-params")) 57 | .dotty3MigrationRewriteSettings 58 | .settings(scalafixRewrite := true) 59 | 60 | lazy val symbolLiterals = project.in(file("incompat-3/symbol-literals")).dotty3MigrationRewriteSettings 61 | lazy val indentArgument = project.in(file("incompat-3/indent-argument")).dotty3MigrationRewriteSettings 62 | lazy val doWhile = project.in(file("incompat-3/do-while")).dotty3MigrationRewriteSettings 63 | lazy val procedureSyntax = 64 | project.in(file("incompat-3/procedure-syntax")) 65 | .dotty3MigrationRewriteSettings 66 | .settings(scalafixRewrite := true) 67 | lazy val autoApplication = 68 | project.in(file("incompat-3/auto-application")) 69 | .dotty3MigrationRewriteSettings 70 | .settings(scalafixRewrite := true) 71 | lazy val inheritanceShadowing = project.in(file("incompat-3/inheritance-shadowing")).dotty3MigrationRewriteSettings 72 | lazy val valueEtaExpansion = 73 | project.in(file("incompat-3/value-eta-expansion")) 74 | .dotty3MigrationRewriteSettings 75 | // does not add enclosing parens like dotc does 76 | // .settings(scalafixRewrite := true) 77 | 78 | /* 79 | Type inference incompatibilities 80 | */ 81 | lazy val typeInferIncompats = Seq[ProjectReference]( 82 | typeInfer3, 83 | typeInfer4, 84 | typeInfer5, 85 | typeInfer9, 86 | typeInfer10, 87 | ) 88 | 89 | 90 | lazy val typeInfer3 = project.in(file("incompat-3/type-infer-3")).incompat3Settings 91 | lazy val typeInfer4 = project.in(file("incompat-3/type-infer-4")).incompat3Settings 92 | lazy val typeInfer5 = project.in(file("incompat-3/type-infer-5")).incompat3Settings 93 | lazy val typeInfer9 = project.in(file("incompat-3/type-infer-9")).incompat3Settings 94 | lazy val typeInfer10 = project.in(file("incompat-3/type-infer-10")).incompat3Settings 95 | 96 | /* 97 | Other incompatibilities 98 | They all are compile time incompatibilities, except `implicitView` 99 | */ 100 | lazy val otherIncompats = Seq[ProjectReference]( 101 | anonymousTypeParam, 102 | indentation1, 103 | restrictedOperator, 104 | typeParamIdentifier, 105 | abstractOverride, 106 | any2stringaddConversion, 107 | byNameParamTypeInfer, 108 | variance, 109 | earlyInitializer, 110 | existentialType, 111 | wildcardArgument, 112 | explicitCallToUnapply, 113 | reflectiveCall, 114 | ambiguousConversion, 115 | implicitView, 116 | typeOfImplicitDef, 117 | viewBound, 118 | caseClassCompanion, 119 | patternMatch, 120 | `bean-property`, 121 | `infer-return-type` 122 | ) 123 | 124 | // Syntactic incompatibilities 125 | lazy val anonymousTypeParam = project.in(file("incompat-3/anonymous-type-param")).incompat3Settings 126 | lazy val indentation1 = project.in(file("incompat-3/indentation/indentation-1")).incompat3Settings 127 | lazy val restrictedOperator = project.in(file("incompat-3/restricted-operator")).incompat3Settings 128 | lazy val typeParamIdentifier = project.in(file("incompat-3/type-param-identifier")).incompat3Settings 129 | 130 | // Changed or dropped features 131 | lazy val abstractOverride = project.in(file("incompat-3/abstract-override")).incompat3Settings 132 | lazy val any2stringaddConversion = project.in(file("incompat-3/any2stringadd-conversion")).incompat3Settings 133 | lazy val byNameParamTypeInfer = project.in(file("incompat-3/by-name-param-type-infer")).incompat3Settings 134 | lazy val variance = project.in(file("incompat-3/variance")).incompat3Settings 135 | lazy val earlyInitializer = project.in(file("incompat-3/early-initializer")).incompat3Settings 136 | lazy val existentialType = project.in(file("incompat-3/existential-type")).incompat3Settings 137 | lazy val wildcardArgument = project.in(file("incompat-3/wildcard-argument")).incompat3Settings 138 | lazy val explicitCallToUnapply = project.in(file("incompat-3/explicit-call-to-unapply")).incompat3Settings 139 | lazy val reflectiveCall = project.in(file("incompat-3/reflective-call")).incompat3Settings 140 | lazy val caseClassCompanion = project.in(file("incompat-3/case-class-companion")).incompat3Settings 141 | lazy val patternMatch = project.in(file("incompat-3/pattern-match")).incompat3Settings 142 | lazy val `bean-property` = project.in(file("incompat-3/bean-property")).incompat3Settings 143 | lazy val `infer-return-type` = project.in(file("incompat-3/infer-return-type")).incompat3Settings 144 | 145 | // Contextual abstraction incompatibilities 146 | lazy val ambiguousConversion = 147 | project.in(file("incompat-3/ambiguous-conversion")) 148 | .incompat3Settings 149 | .settings(scalacOptions += "-language:implicitConversions") 150 | lazy val typeOfImplicitDef = 151 | project.in(file("incompat-3/type-of-implicit-def")) 152 | .incompat3Settings 153 | .settings(scalafixRewrite := true) 154 | lazy val accessModifier = project.in(file("incompat-3/access-modifier")).incompat3Settings 155 | lazy val viewBound = project.in(file("incompat-3/view-bound")) 156 | .incompat3Settings 157 | .settings(scalacOptions += "-deprecation") 158 | 159 | // This one is a runtime incompatibility 160 | // It compiles but the runtime behavior is different 161 | // In this case Scala 3 throws an `AssertionError` 162 | lazy val implicitView = 163 | project.in(file("incompat-3/implicit-view")) 164 | .runtimeIncompat3Settings 165 | .settings(scalacOptions += "-language:implicitConversions") 166 | 167 | /* 168 | Dotty migration rewrites between 3.0 and 3.1 169 | `dotc -source:future-migration -rewrite` 170 | */ 171 | lazy val dotty3FutureMigrationRewrites = Seq[ProjectReference]( 172 | alphanumericInfix, 173 | contextBoundArg, 174 | etaExpansion, 175 | implicitLambdaParam, 176 | patternBinding, 177 | wildcard 178 | ) 179 | 180 | // This one is not a migration rewrite but a 3.1 deprecation rewrite 181 | // `dotc -source:future -deprecation -rewrite` 182 | lazy val alphanumericInfix = 183 | project.in(file("incompat-3-future/alphanumeric-infix")) 184 | .dotty3FutureMigrationRewriteSettings 185 | .settings( 186 | scalacOptions -= "-source:future-migration", 187 | scalacOptions ++= Seq("-source:future", "-deprecation") 188 | ) 189 | 190 | lazy val contextBoundArg = project.in(file("incompat-3-future/context-bound-arg")).dotty3FutureMigrationRewriteSettings 191 | lazy val etaExpansion = project.in(file("incompat-3-future/eta-expansion")).dotty3FutureMigrationRewriteSettings 192 | lazy val implicitLambdaParam = project.in(file("incompat-3-future/implicit-lambda-param")).dotty3FutureMigrationRewriteSettings 193 | lazy val patternBinding = project.in(file("incompat-3-future/pattern-binding")).dotty3FutureMigrationRewriteSettings 194 | lazy val wildcard = new IncompatSettings(project.in(file("incompat-3-future/wildcard"))).dotty3FutureMigrationRewriteSettings 195 | -------------------------------------------------------------------------------- /mdoc/src/main/scala/docs/FileModifier.scala: -------------------------------------------------------------------------------- 1 | package docs 2 | 3 | import java.nio.charset.StandardCharsets 4 | 5 | import mdoc.{Reporter, StringModifier} 6 | 7 | import scala.meta.inputs.{Input, Position} 8 | import scala.meta.internal.io.FileIO 9 | import scala.meta.io.AbsolutePath 10 | import scala.util.Try 11 | 12 | class FileModifier extends StringModifier { 13 | /* 14 | Usage is mdoc:file:docs/upgrade.md:skip-first-line // will skip the first line when importing the file 15 | mdoc:file:docs/upgrade.md // will import the entire file 16 | */ 17 | override val name: String = "file" 18 | 19 | override def process(info: String, 20 | code: Input, 21 | reporter: Reporter): String = { 22 | val args = info.split(':').toSeq 23 | val file = AbsolutePath(args.headOption.getOrElse("")) 24 | val skipFirstLine = Try(args(1)).toOption match { 25 | case Some("skip-first-line") => true 26 | case _ => false 27 | } 28 | if (file.isFile) { 29 | val text = FileIO.slurp(file, StandardCharsets.UTF_8).trim 30 | if (skipFirstLine) text.linesIterator.drop(1).toList.mkString("\n") else text 31 | } else { 32 | val pos = Position.Range(code, 0 - info.length - 1, 0 - 1) 33 | reporter.error(pos, s"no such file: $file") 34 | "" 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /mdoc/src/main/scala/docs/Main.scala: -------------------------------------------------------------------------------- 1 | package docs 2 | 3 | import java.nio.file.Paths 4 | 5 | object Main { 6 | def main(args: Array[String]): Unit = { 7 | val out = Paths.get("website", "target", "docs") 8 | val base = mdoc.MainSettings() 9 | val settings = base 10 | .withOut(out) 11 | .withCleanTarget(false) 12 | .withReportRelativePaths(true) 13 | .withArgs(args.toList) 14 | .withStringModifiers( 15 | List(new FileModifier) 16 | ) 17 | val exit = mdoc.Main.process(settings) 18 | if (exit != 0) sys.exit(exit) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /project/Assert.scala: -------------------------------------------------------------------------------- 1 | import sbt._ 2 | import xsbti.compile.CompileAnalysis 3 | 4 | object Assert { 5 | def dottyRewrite( 6 | name: String, 7 | scalaVersion: String, 8 | compileResult: Result[CompileAnalysis], 9 | rewriteDir: File, 10 | dottySourceDir: File, 11 | logger: Logger 12 | ): Unit = { 13 | compileResult match { 14 | case Inc(_) => 15 | throw new MessageOnlyException(s"$name does not compile with Dotty version $scalaVersion in migration mode.") 16 | case Value(_) => 17 | FileChecker(logger).check(rewriteDir, dottySourceDir) 18 | logger.info(s"$name is rewritten successfully by Dotty") 19 | } 20 | } 21 | 22 | def scalafixRewrite( 23 | name: String, 24 | scalaVersion: String, 25 | compileResult: Result[CompileAnalysis], 26 | rewriteDir: File, 27 | dottySourceDir: File, 28 | logger: Logger 29 | ): Unit = { 30 | compileResult match { 31 | case Inc(_) => 32 | throw new MessageOnlyException(s"$name does not compile with Scala version $scalaVersion.") 33 | case Value(_) => 34 | FileChecker(logger).check(rewriteDir, dottySourceDir) 35 | logger.info(s"$name is rewritten successfully by Scalafix") 36 | } 37 | } 38 | 39 | def incompatibility( 40 | name: String, 41 | scalaVersion: String, 42 | compileResult: Result[CompileAnalysis], 43 | logger: Logger 44 | ): Unit = { 45 | compileResult match { 46 | case Value(_) => 47 | throw new MessageOnlyException( 48 | "Compilation has succeeded but failure was expected. " + 49 | s"The '$name' incompatibility is probably fixed, in version $scalaVersion." 50 | ) 51 | case Inc(_) => 52 | logger.info(s"$name is incompatible with $scalaVersion") 53 | } 54 | } 55 | 56 | def compilation( 57 | name: String, 58 | scalaVersion: String, 59 | compileResult: Result[CompileAnalysis], 60 | logger: Logger 61 | ): Unit = { 62 | compileResult match { 63 | case Value(_) => () 64 | case Inc(_) => 65 | throw new MessageOnlyException(s"$name does not compile with version $scalaVersion anymore.") 66 | } 67 | } 68 | 69 | def runtimeIncompatibility( 70 | name: String, 71 | scalaVersion: String, 72 | runResult: Result[Unit], 73 | logger: Logger 74 | ): Unit = { 75 | runResult match { 76 | case Value(_) => 77 | throw new MessageOnlyException( 78 | "Run has succeeded but failure was expected. " + 79 | s"The '$name' incompatibility is probably fixed, in version $scalaVersion." 80 | ) 81 | case Inc(_) => 82 | logger.info(s"$name is runtime incompatible with $scalaVersion") 83 | } 84 | } 85 | 86 | def run( 87 | name: String, 88 | scalaVersion:String, 89 | runResult: Result[Unit], 90 | logger: Logger 91 | ): Unit = { 92 | runResult match { 93 | case Value(_) => () 94 | case Inc(_) => 95 | throw new MessageOnlyException(s"$name does not run successfully with version $scalaVersion anymore.") 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /project/FileChecker.scala: -------------------------------------------------------------------------------- 1 | import java.io.File 2 | import scala.io.Source 3 | import scala.collection.JavaConverters._ 4 | import sbt.util.Logger 5 | import com.github.difflib.text._ 6 | import sbt.internal.util.MessageOnlyException 7 | 8 | class FileChecker(logger: Logger) { 9 | private val diffGen = DiffRowGenerator.create() 10 | .showInlineDiffs(true) 11 | .inlineDiffByWord(true) 12 | .oldTag(f => "**") 13 | .build() 14 | 15 | def check(inputDir: File, checkDir: File): Unit = { 16 | val inputFiles = inputDir.listFiles 17 | .filter(_.isFile) 18 | .map(f => f.getName() -> f) 19 | .toMap 20 | 21 | val checkFiles = checkDir.listFiles().filter(_.isFile()) 22 | 23 | val initialReport = Report(0, 0) 24 | 25 | val finalReport = checkFiles.foldLeft(initialReport) { 26 | (report, checkFile) => 27 | val fileName = checkFile.getName 28 | inputFiles.get(fileName) match { 29 | case None => report.missingFile(fileName) 30 | case Some(inputFile) => 31 | val diff = compare(inputFile, checkFile) 32 | if (diff.isEmpty) report.success(fileName) 33 | else report.fileDiff(fileName, diff) 34 | } 35 | } 36 | 37 | if (finalReport.failed > 0) 38 | throw new MessageOnlyException(s"${finalReport.failed} file checks failed") 39 | } 40 | 41 | private def compare(inputFile: File, checkFile: File): Seq[String] = { 42 | val diff = diffGen.generateDiffRows( 43 | Source.fromFile(inputFile).getLines().toList.asJava, 44 | Source.fromFile(checkFile).getLines().toList.asJava 45 | ) 46 | diff.asScala.toSeq 47 | .zipWithIndex 48 | .filter { case (delta, _) => delta.getTag() != DiffRow.Tag.EQUAL } 49 | .map { case (delta, line) => s"line ${line}:" + delta.getOldLine } 50 | } 51 | 52 | private case class Report(succeeded: Int, failed: Int) { 53 | def missingFile(name: String): Report = { 54 | logger.error(s"missing input file $name") 55 | Report(succeeded, failed + 1) 56 | } 57 | 58 | def fileDiff(name: String, diff: Seq[String]): Report = { 59 | logger.error(s"diff in file $name") 60 | diff.foreach(logger.error(_)) 61 | Report(succeeded, failed + 1) 62 | } 63 | 64 | def success(name: String): Report = { 65 | logger.info(s"no diff in $name") 66 | Report(succeeded + 1, failed) 67 | } 68 | } 69 | } 70 | 71 | object FileChecker { 72 | def apply(logger: Logger): FileChecker = new FileChecker(logger) 73 | } 74 | -------------------------------------------------------------------------------- /project/IncompatSettings.scala: -------------------------------------------------------------------------------- 1 | import sbt._ 2 | import sbt.Keys._ 3 | import scalafix.sbt.ScalafixPlugin.autoImport._ 4 | import Versions._ 5 | 6 | object IncompatSettings { 7 | val CompileBackward = Configuration.of("CompileBackward", "compile-bwd") 8 | val scala213SourceDir = settingKey[File]("Directory containing the Scala 2.13 sources") 9 | val scala3SourceDir = settingKey[File]("Directory containing the Scala 3 sources") 10 | val scala3FutureSourceDir = settingKey[File]("Directory containing the Scala 3.1 sources") 11 | val dottyRewrite = settingKey[Boolean]("Does this incompatibility have a Dotty rewrite?") 12 | val scalafixRewrite = settingKey[Boolean]("Does this incompatibility have a Scalafix rewrite?") 13 | val rewriteDir = settingKey[File]("Directory where the sources are rewritten by either Dotty or Scalafix") 14 | val isScala3 = Def.settingKey[Boolean]("") 15 | 16 | implicit def apply(project: Project): IncompatSettings = new IncompatSettings(project) 17 | } 18 | 19 | class IncompatSettings(project: Project) { 20 | import IncompatSettings._ 21 | 22 | def dotty3MigrationRewriteSettings = project.incompat3Settings.settings(dottyRewrite := true) 23 | 24 | def dotty3FutureMigrationRewriteSettings = project.incompat3FutureSettings.settings(dottyRewrite := true) 25 | 26 | def incompat3Settings: Project = project 27 | .configs(CompileBackward) 28 | .settings( 29 | inConfig(CompileBackward)(Defaults.configSettings), 30 | inConfig(CompileBackward)(scalafixConfigSettings(CompileBackward)), 31 | isScala3 := scalaVersion.value.startsWith("3"), 32 | scalaVersion := scala3, 33 | crossScalaVersions := List(scala213, scala3), 34 | 35 | scala213SourceDir := baseDirectory.value / s"src/main/scala-2.13", 36 | scala3SourceDir := baseDirectory.value / s"src/main/scala", 37 | dottyRewrite := false, 38 | scalafixRewrite := false, 39 | rewriteDir := target.value / s"src-managed/main/scala", 40 | 41 | Compile / unmanagedSourceDirectories := Seq(scala3SourceDir.value), 42 | // we copy the scala213 sources into the target folder 43 | // because it might be rewritten by dotc or scalafix 44 | CompileBackward / sourceGenerators += Def.task { 45 | val _ = (CompileBackward / clean).value // clean to force recompilation and rewrite 46 | copySources(scala213SourceDir.value, rewriteDir.value) 47 | }, 48 | CompileBackward / managedClasspath := (Compile / managedClasspath).value, 49 | 50 | CompileBackward / scalacOptions ++= { 51 | if (isScala3.value && dottyRewrite.value) 52 | Seq("-source:3.0-migration", "-rewrite") 53 | else Seq() 54 | }, 55 | 56 | // scalafix configuration 57 | semanticdbVersion := "4.8.8", 58 | semanticdbEnabled := !isScala3.value && scalafixRewrite.value, 59 | CompileBackward / scalafixConfig := Some(baseDirectory.value / ".scalafix.conf"), 60 | CompileBackward / scalafixOnCompile := !isScala3.value && scalafixRewrite.value, 61 | CompileBackward / scalafix / unmanagedSources := (CompileBackward / managedSources).value, // hack to force Scalafix on managedSources 62 | CompileBackward / scalafixCaching := false, 63 | 64 | Test / test := { 65 | val logger = streams.value.log 66 | val _ = (Compile / compile).value 67 | val compileBwd = (CompileBackward / compile).result.value 68 | if (isScala3.value && dottyRewrite.value) 69 | Assert.dottyRewrite( 70 | name.value, 71 | scalaVersion.value, 72 | compileBwd, 73 | rewriteDir.value, 74 | scala3SourceDir.value, 75 | logger 76 | ) 77 | else if (isScala3.value && !dottyRewrite.value) 78 | Assert.incompatibility(name.value, scalaVersion.value, compileBwd, logger) 79 | else if (scalafixRewrite.value) 80 | Assert.scalafixRewrite( 81 | name.value, 82 | scalaVersion.value, 83 | compileBwd, 84 | rewriteDir.value, 85 | scala3SourceDir.value, 86 | logger 87 | ) 88 | else 89 | Assert.compilation(name.value, scalaVersion.value, compileBwd, logger) 90 | } 91 | ) 92 | 93 | def runtimeIncompat3Settings = project.incompat3Settings 94 | .settings( 95 | Test / test := { 96 | val logger = streams.value.log 97 | val _ = (Compile / run).toTask("").value 98 | val runBwd = (CompileBackward / run).toTask("").result.value 99 | 100 | if (isScala3.value) 101 | Assert.runtimeIncompatibility(name.value, scalaVersion.value, runBwd, logger) 102 | else 103 | Assert.run(name.value, scalaVersion.value, runBwd, logger) 104 | } 105 | ) 106 | 107 | def incompat3FutureSettings = project 108 | .configs(CompileBackward) 109 | .settings( 110 | inConfig(CompileBackward)(Defaults.compileSettings), 111 | scalaVersion := scala3, 112 | scala3SourceDir := baseDirectory.value / s"src/main/scala-3.0", 113 | scala3FutureSourceDir := baseDirectory.value / s"src/main/scala", 114 | dottyRewrite := false, 115 | rewriteDir := target.value / s"src-managed/main/scala", 116 | 117 | Compile / unmanagedSourceDirectories := Seq(scala3FutureSourceDir.value), 118 | // we copy the scala3 sources into the target folder 119 | // because they might be rewritten by dotc or scalafix 120 | CompileBackward / sourceGenerators += Def.task { 121 | val _ = (CompileBackward / clean).value // clean to force recompilation and rewrite 122 | copySources(scala3SourceDir.value, rewriteDir.value) 123 | }, 124 | CompileBackward / managedClasspath := (Compile / managedClasspath).value, 125 | CompileBackward / scalacOptions ++= { 126 | if (dottyRewrite.value) Seq(s"-source:future-migration", "-rewrite") 127 | else Seq.empty 128 | }, 129 | Test / test := { 130 | val logger = streams.value.log 131 | val _ = (Compile / compile).value 132 | val compileBwd = (CompileBackward / compile).result.value 133 | if (dottyRewrite.value) 134 | Assert.dottyRewrite( 135 | name.value, 136 | scalaVersion.value, 137 | compileBwd, 138 | rewriteDir.value, 139 | scala3FutureSourceDir.value, 140 | logger 141 | ) 142 | else 143 | Assert.compilation(name.value, scalaVersion.value, compileBwd, logger) 144 | } 145 | ) 146 | 147 | private def copySources(inputDir: File, outputDir: File): Seq[File] = { 148 | if (outputDir.exists) IO.delete(outputDir) 149 | IO.copyDirectory(inputDir, outputDir) 150 | outputDir.listFiles.filter(_.isFile) 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /project/Versions.scala: -------------------------------------------------------------------------------- 1 | object Versions { 2 | val scala213 = "2.13.11" 3 | val scala3 = "3.3.0" 4 | val sbtDotty = "0.5.3" 5 | val osLib = "0.7.7" 6 | val sourcecode = "0.2.7" 7 | val scala3Migrate = "0.5.1" 8 | val munit = "0.7.26" 9 | } 10 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.9.2 2 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.2.23") 2 | addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.26") 3 | 4 | libraryDependencies ++= Seq( 5 | "io.github.java-diff-utils" % "java-diff-utils" % "4.11" 6 | ) 7 | -------------------------------------------------------------------------------- /tutorials.sbt: -------------------------------------------------------------------------------- 1 | import Versions._ 2 | 3 | lazy val `sbt-migration-tutorial` = project 4 | .in(file("tutorials/sbt-migration")) 5 | .settings( 6 | scalaVersion := scala3, 7 | crossScalaVersions := Seq(scala213, scala3), 8 | libraryDependencies ++= Seq( 9 | "org.typelevel" % "cats-core_2.13" % "2.1.1", 10 | "com.lihaoyi" %% "os-lib" % osLib, 11 | "com.lihaoyi" %% "sourcecode" % sourcecode 12 | ), 13 | scalacOptions ++= { 14 | Seq( 15 | "-encoding", 16 | "UTF-8", 17 | "-feature", 18 | "-language:implicitConversions", 19 | // "-Xfatal-warnings" disabled during the migration, 20 | ) ++ 21 | (CrossVersion.partialVersion(scalaVersion.value) match { 22 | case Some((3, _)) => Seq( 23 | "-unchecked", 24 | "-source:3.0-migration" 25 | ) 26 | case _ => Seq( 27 | "-deprecation", 28 | "-Xfatal-warnings", 29 | "-Wunused:imports,privates,locals", 30 | "-Wvalue-discard" 31 | ) 32 | }) 33 | } 34 | ) 35 | 36 | lazy val `macro-cross-building-example` = project 37 | .in(file("tutorials/macro-cross-building/example")) 38 | .settings( 39 | scalaVersion := scala3, 40 | crossScalaVersions := Seq(scala213, scala3), 41 | libraryDependencies ++= { 42 | CrossVersion.partialVersion(scalaVersion.value) match { 43 | case Some((2, 13)) => Seq( 44 | "org.scala-lang" % "scala-reflect" % scalaVersion.value, 45 | ) 46 | case _ => Seq.empty 47 | } 48 | }, 49 | libraryDependencies ++= Seq( 50 | "org.scalameta" %% "munit" % Versions.munit % Test 51 | ) 52 | ) 53 | 54 | lazy val `macro-mixing-example` = project 55 | .in(file("tutorials/macro-mixing/example")) 56 | .settings( 57 | scalaVersion := scala3 58 | ) 59 | .dependsOn(`macro-mixing-example-compat`) 60 | 61 | lazy val `macro-mixing-example-compat` = project 62 | .in(file("tutorials/macro-mixing/example-compat")) 63 | .settings( 64 | scalaVersion := scala213, 65 | libraryDependencies ++= Seq( 66 | "org.scala-lang" % "scala-reflect" % scalaVersion.value 67 | ) 68 | ) 69 | 70 | lazy val `macro-mixing-example-test` = project 71 | .in(file("tutorials/macro-mixing/example-test")) 72 | .settings( 73 | scalaVersion := scala3, 74 | crossScalaVersions := Seq(scala3, scala213), 75 | scalacOptions ++= { 76 | CrossVersion.partialVersion(scalaVersion.value) match { 77 | case Some((2, 13)) => Seq("-Ytasty-reader") 78 | case _ => Seq.empty 79 | } 80 | }, 81 | libraryDependencies += "org.scalameta" %% "munit" % munit % Test 82 | ) 83 | .dependsOn(`macro-mixing-example`) 84 | -------------------------------------------------------------------------------- /tutorials/macro-cross-building/example/src/main/scala-2/location/Macros.scala: -------------------------------------------------------------------------------- 1 | package location 2 | 3 | import scala.reflect.macros.blackbox.Context 4 | import scala.language.experimental.macros 5 | 6 | object Macros { 7 | def location: Location = macro locationImpl 8 | 9 | def locationImpl(c: Context): c.Tree = { 10 | import c.universe._ 11 | val location = typeOf[Location] 12 | val line = Literal(Constant(c.enclosingPosition.line)) 13 | val path = Literal(Constant(c.enclosingPosition.source.path)) 14 | q"new $location($path, $line)" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tutorials/macro-cross-building/example/src/main/scala-3/location/Macros.scala: -------------------------------------------------------------------------------- 1 | package location 2 | 3 | import scala.quoted.{Quotes, Expr} 4 | 5 | object Macros: 6 | inline def location: Location = ${locationImpl} 7 | 8 | private def locationImpl(using quotes: Quotes): Expr[Location] = 9 | import quotes.reflect.Position 10 | val pos = Position.ofMacroExpansion 11 | val file = Expr(pos.sourceFile.jpath.toString) 12 | val line = Expr(pos.startLine + 1) 13 | '{new Location($file, $line)} 14 | -------------------------------------------------------------------------------- /tutorials/macro-cross-building/example/src/main/scala/location/Location.scala: -------------------------------------------------------------------------------- 1 | package location 2 | case class Location(path: String, line: Int) { 3 | override def toString(): String = s"Line $line in $path" 4 | } 5 | -------------------------------------------------------------------------------- /tutorials/macro-cross-building/example/src/test/scala/location/MacrosSpec.scala: -------------------------------------------------------------------------------- 1 | package location 2 | 3 | class MacrosSpec extends munit.FunSuite { 4 | test("location") { 5 | assertEquals(Macros.location.line, 5) 6 | } 7 | } -------------------------------------------------------------------------------- /tutorials/macro-mixing/example-compat/src/main/scala/location/Location.scala: -------------------------------------------------------------------------------- 1 | package location 2 | 3 | import scala.reflect.macros.blackbox.Context 4 | 5 | case class Location(path: String, line: Int) { 6 | override def toString(): String = s"Line $line in $path" 7 | } 8 | 9 | object Scala2Macros { 10 | def locationImpl(c: Context): c.Tree = { 11 | import c.universe._ 12 | val location = typeOf[Location] 13 | val line = Literal(Constant(c.enclosingPosition.line)) 14 | val path = Literal(Constant(c.enclosingPosition.source.path)) 15 | q"new $location($path, $line)" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tutorials/macro-mixing/example-test/src/test/scala/location/MacrosSpec.scala: -------------------------------------------------------------------------------- 1 | package location 2 | 3 | class MacrosSpec extends munit.FunSuite { 4 | test("location") { 5 | assertEquals(Macros.location.line, 5) 6 | } 7 | } -------------------------------------------------------------------------------- /tutorials/macro-mixing/example/src/main/scala/location/Macros.scala: -------------------------------------------------------------------------------- 1 | package location 2 | 3 | import scala.language.experimental.macros 4 | import scala.quoted.{Quotes, Expr} 5 | 6 | object Macros: 7 | def location: Location = macro Scala2Macros.locationImpl 8 | inline def location: Location = ${locationImpl} 9 | 10 | def locationImpl(using quotes: Quotes): Expr[Location] = 11 | import quotes.reflect.Position 12 | val file = Expr(Position.ofMacroExpansion.sourceFile.jpath.toString) 13 | val line = Expr(Position.ofMacroExpansion.startLine + 1) 14 | '{new Location($file, $line)} 15 | -------------------------------------------------------------------------------- /tutorials/sbt-migration/src/main/scala/app/Main.scala: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import cats.data._ 4 | import sourcecode._ 5 | import os.Path 6 | 7 | object Main extends App { 8 | def debug[V](value: Text[V])(implicit file: File) = { 9 | assert(os.exists(Path(file.value))) 10 | println(s"${value.source}: ${value.value}") 11 | } 12 | 13 | debug(Chain.fromSeq(List(1, 2))) 14 | } 15 | -------------------------------------------------------------------------------- /website/core/Footer.js: -------------------------------------------------------------------------------- 1 | const React = require("react"); 2 | 3 | const siteConfig = require(process.cwd() + "/siteConfig.js"); 4 | 5 | class Footer extends React.Component { 6 | render() { 7 | const currentYear = new Date().getFullYear(); 8 | const { 9 | copyright, 10 | colors: { secondaryColor } 11 | } = this.props.config; 12 | return ( 13 | 64 | ); 65 | } 66 | } 67 | 68 | module.exports = Footer; -------------------------------------------------------------------------------- /website/i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "This file is auto-generated by write-translations.js", 3 | "localized-strings": { 4 | "next": "Next", 5 | "previous": "Previous", 6 | "tagline": "An evolving guide to support the migration to Scala 3", 7 | "docs": { 8 | "compatibility/classpath": { 9 | "title": "Classpath Level" 10 | }, 11 | "compatibility/metaprogramming": { 12 | "title": "Metaprogramming" 13 | }, 14 | "compatibility/runtime": { 15 | "title": "Runtime" 16 | }, 17 | "compatibility/source": { 18 | "title": "Source Level" 19 | }, 20 | "compiler-options/compiler-options-table": { 21 | "title": "Compiler Options Table" 22 | }, 23 | "compiler-options/new-compiler-options": { 24 | "title": "New Scala 3 compiler options" 25 | }, 26 | "contributing": { 27 | "title": "Contributing" 28 | }, 29 | "external-resources/moving-from-scala-2-to-scala-3": { 30 | "title": "Moving from Scala 2 to Scala 3" 31 | }, 32 | "get-started": { 33 | "title": "Introduction" 34 | }, 35 | "incompat-31": { 36 | "title": "Dotty future-migration Mode" 37 | }, 38 | "incompatibilities/contextual-abstractions": { 39 | "title": "Contextual Abstractions" 40 | }, 41 | "incompatibilities/dropped-features": { 42 | "title": "Dropped Features" 43 | }, 44 | "incompatibilities/incompatibility-table": { 45 | "title": "Incompatibility Table" 46 | }, 47 | "incompatibilities/other-changed-features": { 48 | "title": "Other Changed Features" 49 | }, 50 | "incompatibilities/syntactic-changes": { 51 | "title": "Syntactic Changes" 52 | }, 53 | "incompatibilities/type-checker": { 54 | "title": "Type Checker" 55 | }, 56 | "incompatibilities/type-inference": { 57 | "title": "Type Inference" 58 | }, 59 | "macros/macro-libraries": { 60 | "title": "Scala Macro Libraries" 61 | }, 62 | "tooling/migration-tools": { 63 | "title": "Tour of the Migration Tools" 64 | }, 65 | "tooling/scala-3-migrate-plugin": { 66 | "title": "Scala 3 Migrate Plugin" 67 | }, 68 | "tooling/scala-3-migration-mode": { 69 | "title": "Scala 3 Migration Mode" 70 | }, 71 | "tooling/scala-3-syntax-rewrites": { 72 | "title": "Scala 3 Syntax Rewriting" 73 | }, 74 | "tutorials/kind-projector": { 75 | "title": "kind-projector Migration Tutorial" 76 | }, 77 | "tutorials/macro-cross-building": { 78 | "title": "Cross-Building a Macro Library" 79 | }, 80 | "tutorials/macro-mixing": { 81 | "title": "Mixing Scala 2.13 and Scala 3 Macros" 82 | }, 83 | "tutorials/prerequisites": { 84 | "title": "Project Prerequisites" 85 | }, 86 | "tutorials/sbt-migration": { 87 | "title": "sbt Migration Tutorial" 88 | } 89 | }, 90 | "links": { 91 | "User Guide": "User Guide", 92 | "Contribute": "Contribute", 93 | "GitHub": "GitHub" 94 | }, 95 | "categories": { 96 | "Compatibility Reference": "Compatibility Reference", 97 | "Tooling": "Tooling", 98 | "Resources": "Resources" 99 | } 100 | }, 101 | "pages-strings": { 102 | "Help Translate|recruit community translators for your project": "Help Translate", 103 | "Edit this Doc|recruitment message asking to edit the doc source": "Edit", 104 | "Translate this Doc|recruitment message asking to translate the docs": "Translate" 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "examples": "docusaurus-examples", 4 | "start": "docusaurus-start", 5 | "build": "docusaurus-build", 6 | "publish-gh-pages": "docusaurus-publish", 7 | "write-translations": "docusaurus-write-translations", 8 | "version": "docusaurus-version", 9 | "rename-version": "docusaurus-rename-version" 10 | }, 11 | "devDependencies": { 12 | "docusaurus": "^1.14.6" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /website/pages/en/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | const React = require("react"); 9 | 10 | const CompLibrary = require("../../core/CompLibrary.js"); 11 | 12 | const highlightBlock = require("highlight.js"); 13 | 14 | const MarkdownBlock = CompLibrary.MarkdownBlock; /* Used to read markdown */ 15 | const Container = CompLibrary.Container; 16 | const GridBlock = CompLibrary.GridBlock; 17 | 18 | const siteConfig = require(process.cwd() + "/siteConfig.js"); 19 | 20 | function imgUrl(img) { 21 | return siteConfig.baseUrl + "img/" + img; 22 | } 23 | 24 | function docUrl(doc, language) { 25 | return siteConfig.baseUrl + "docs/" + (language ? language + "/" : "") + doc; 26 | } 27 | 28 | function pageUrl(page, language) { 29 | return siteConfig.baseUrl + (language ? language + "/" : "") + page; 30 | } 31 | 32 | class Button extends React.Component { 33 | render() { 34 | return ( 35 | 36 | 37 | {this.props.children} 38 | 39 | 40 | ); 41 | } 42 | } 43 | 44 | Button.defaultProps = { 45 | target: "_self" 46 | }; 47 | 48 | const SplashContainer = props => ( 49 | 50 | 51 | {props.children} 52 | 53 | 54 | ); 55 | 56 | const Logo = (props) => ( 57 | 58 | 59 | 60 | ); 61 | 62 | const ProjectTitle = props => ( 63 | 64 | {siteConfig.title} 65 | {siteConfig.tagline} 66 | 67 | ); 68 | 69 | const PromoSection = props => ( 70 | 71 | 72 | {props.children} 73 | 74 | 75 | ); 76 | 77 | class HomeSplash extends React.Component { 78 | render() { 79 | let language = this.props.language || ""; 80 | return ( 81 | 82 | 83 | 84 | 85 | 86 | 87 | Go to docs.scala-lang.org 88 | 89 | 90 | 91 | 92 | ); 93 | } 94 | } 95 | 96 | const Deprecation = () => ( 97 | 98 | {[ 99 | { 100 | content: 101 | 'The Scala 3 migration guide has moved to [docs.scala-lang.org](https://docs.scala-lang.org/scala3/guides/migration/compatibility-intro.html). This website is deprecated.', 102 | title: 'Deprecation' 103 | } 104 | ]} 105 | 106 | ) 107 | 108 | const Block = props => ( 109 | 114 | 115 | 116 | ); 117 | 118 | class Index extends React.Component { 119 | render() { 120 | let language = this.props.language || ""; 121 | return ( 122 | 123 | 124 | 125 | 126 | 127 | 128 | ); 129 | } 130 | } 131 | 132 | module.exports = Index; 133 | -------------------------------------------------------------------------------- /website/sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "docs": { 3 | "Compatibility Reference": [ 4 | "get-started" 5 | ], 6 | "Tooling": [ 7 | "tooling/scala-3-migrate-plugin" 8 | ], 9 | "Resources": [ 10 | "macros/macro-libraries", 11 | "external-resources/moving-from-scala-2-to-scala-3" 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /website/siteConfig.js: -------------------------------------------------------------------------------- 1 | // See https://docusaurus.io/docs/site-config for all the possible 2 | // site configuration options. 3 | 4 | const repoUrl = "https://github.com/scalacenter/scala-3-migration-guide"; 5 | 6 | const siteConfig = { 7 | title: "Scala 3 Migration guide", 8 | tagline: "An evolving guide to support the migration to Scala 3", 9 | 10 | url: "https://scalacenter.github.io/", 11 | baseUrl: "/scala-3-migration-guide/", 12 | 13 | // Used for publishing and more 14 | projectName: "scala-3-migration-guide", 15 | organizationName: "scalacenter", 16 | 17 | customDocsPath: 'website/target/docs', 18 | 19 | algolia: { 20 | apiKey: "f77e0c381ea8939fc6c34dc0e17ea492", 21 | indexName: "scala-3-migration-guide" 22 | }, 23 | 24 | // For no header links in the top nav bar -> headerLinks: [], 25 | headerLinks: [ 26 | {doc: 'get-started', label: 'User Guide'}, 27 | {doc: 'contributing', label: 'Contribute'}, 28 | { href: repoUrl, label: "GitHub", external: true } 29 | ], 30 | 31 | /* path to images for header/footer */ 32 | headerIcon: 'img/dotty-logo-white.svg', 33 | footerIcon: 'img/dotty-logo-white.svg', 34 | favicon: 'img/dotty-logo.svg', 35 | 36 | /* Colors for website */ 37 | colors: { 38 | primaryColor: '#ca445e', 39 | secondaryColor: '#224951', 40 | }, 41 | 42 | /* Custom fonts for website */ 43 | /* 44 | fonts: { 45 | myFont: [ 46 | "Lato", 47 | "Serif" 48 | ], 49 | myOtherFont: [ 50 | "-apple-system", 51 | "system-ui" 52 | ] 53 | }, 54 | */ 55 | 56 | stylesheets: [ 57 | 'https://use.fontawesome.com/releases/v5.14.0/css/all.css', 58 | 'https://fonts.googleapis.com/css?family=Lobster&display=swap', 59 | 'https://fonts.googleapis.com/css?family=Lato:400,700|Fira+Code:400,700&display=fallback' 60 | ], 61 | 62 | // This copyright info is used in /core/Footer.js and blog rss/atom feeds. 63 | copyright: `Copyright © ${new Date().getFullYear()} Scala Center`, 64 | 65 | highlight: { 66 | // Highlight.js theme to use for syntax highlighting in code blocks 67 | theme: "github" 68 | }, 69 | 70 | // Add custom scripts here that would be placed in
inline def bar: Bar = ${ barImpl }
def bar: Bar = macro Scala2Macros.barImpl