From caf30e3d1186ed306ba5c8ef93b148ad7db6dc54 Mon Sep 17 00:00:00 2001 From: i10416 Date: Sun, 22 Oct 2023 15:15:43 +0900 Subject: [PATCH 001/220] fix(#18265): crash on extension method without body This commit fixes a bug that causes Scala compiler to crash due to position error when an extension method followed by a newline has neither type annotation nor `= `. This commit is based on https://github.com/lampepfl/dotty/pull/18445. Co-Authored-By: @hamzaremmal --- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 2 ++ tests/neg/i18265.check | 6 ++++++ tests/neg/i18265.scala | 5 +++++ 3 files changed, 13 insertions(+) create mode 100644 tests/neg/i18265.check create mode 100644 tests/neg/i18265.scala diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 363c95f6c357..47255114b2d1 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -2577,6 +2577,8 @@ object Parsers { parents match { case parent :: Nil if !in.isNestedStart => reposition(if (parent.isType) ensureApplied(wrapNew(parent)) else parent) + case tkn if in.token == INDENT => + New(templateBodyOpt(emptyConstructor, parents, Nil)) case _ => New(reposition(templateBodyOpt(emptyConstructor, parents, Nil))) } diff --git a/tests/neg/i18265.check b/tests/neg/i18265.check new file mode 100644 index 000000000000..fc9f044f4e83 --- /dev/null +++ b/tests/neg/i18265.check @@ -0,0 +1,6 @@ +-- [E019] Syntax Error: tests/neg/i18265.scala:5:13 -------------------------------------------------------------------- +5 | def twice // error + | ^ + | Missing return type + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg/i18265.scala b/tests/neg/i18265.scala new file mode 100644 index 000000000000..5cc67b7bd182 --- /dev/null +++ b/tests/neg/i18265.scala @@ -0,0 +1,5 @@ +trait Foo + +val foo = new Foo: + extension (s: String) + def twice // error From 07761aec094af62c4ed7621a0362167cbe66eb1b Mon Sep 17 00:00:00 2001 From: i10416 Date: Sun, 22 Oct 2023 17:03:07 +0900 Subject: [PATCH 002/220] maybefix: update semanticdb expected output --- tests/semanticdb/expect/StructuralTypes.expect.scala | 4 ++-- tests/semanticdb/metac.expect | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/semanticdb/expect/StructuralTypes.expect.scala b/tests/semanticdb/expect/StructuralTypes.expect.scala index 96c7181d6f10..98aaca95f880 100644 --- a/tests/semanticdb/expect/StructuralTypes.expect.scala +++ b/tests/semanticdb/expect/StructuralTypes.expect.scala @@ -16,7 +16,7 @@ object StructuralTypes/*<-example::StructuralTypes.*/: val V/*<-example::StructuralTypes.V.*/: Object/*->java::lang::Object#*/ { def scalameta/*<-local4*/: String/*->scala::Predef.String#*/ - } = /*<-local6*/new: - def scalameta/*<-local5*/ = "4.0" + } = new: + /*<-local6*/def scalameta/*<-local5*/ = "4.0" V/*->example::StructuralTypes.V.*/.scalameta/*->scala::reflect::Selectable#selectDynamic().*/ end StructuralTypes/*->example::StructuralTypes.*/ \ No newline at end of file diff --git a/tests/semanticdb/metac.expect b/tests/semanticdb/metac.expect index e05a645c0141..00aa8673f015 100644 --- a/tests/semanticdb/metac.expect +++ b/tests/semanticdb/metac.expect @@ -3472,7 +3472,7 @@ Occurrences: [16:9..16:15): Object -> java/lang/Object# [17:8..17:17): scalameta <- local4 [17:19..17:25): String -> scala/Predef.String# -[18:6..18:6): <- local6 +[19:4..19:4): <- local6 [19:8..19:17): scalameta <- local5 [20:2..20:3): V -> example/StructuralTypes.V. [20:4..20:13): scalameta -> scala/reflect/Selectable#selectDynamic(). From 070b877d80f90539dee689fd3eff7d344fef232c Mon Sep 17 00:00:00 2001 From: odersky Date: Fri, 17 Nov 2023 10:43:54 +0100 Subject: [PATCH 003/220] Description of capture set constraint handling --- .../internals/cc/handling-invariant-vars.md | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 docs/_docs/internals/cc/handling-invariant-vars.md diff --git a/docs/_docs/internals/cc/handling-invariant-vars.md b/docs/_docs/internals/cc/handling-invariant-vars.md new file mode 100644 index 000000000000..e9f0dc85317c --- /dev/null +++ b/docs/_docs/internals/cc/handling-invariant-vars.md @@ -0,0 +1,125 @@ +Handling invariant capture set variables +======================================== + +This note gives a high-level overview of constraints and constraint solving in Scala's capture checker. It then describes a proposal to improve a current problem area: the handling of invariantly mapped capture set variables. + +A capture checking constraint consists of subcapturing constraints between +capture sets. Capture sets can be variable or constant. A capture set variable is either defined by itself, +or is the result of a mapping of a type map. +Depending on what part of an original type created a map result, the set `v` is classified as invariant, covariant, or contravariant. + +We can describe the syntax of capture set constraints like this: +``` +Capture set a, b, c = ac // constant, aliases bv, cc + | av // variable, aliases bv, cv + +Typemap tm = B // bijective on capabilities + | F // arbitrary + +Constraint C = a <: b // simple constraint + | a = B(b) // bimap constraint + | a >: F(b) // covariant map constraint + | a <: F(b) // contravariant map constraint + | a = F(b) // invariant map constraint +``` +Variables appearing in the left hand side of a map constraint are called +map results. In a constraint set, each map result variable appears on the left hand side of only one map constraint, the one which defines it. +We distinguish two kinds of type maps, bijective maps `B` and general maps `F`. General maps are capture-monotonic: if `A <: B` +then the capture set of `F(A)` subcaptures the capture set of `F(B)`. All considered type maps map `cap` to `cap`. + +Examples of bijective maps are substitutions of parameters of one method type +for another, or mapping local method parameter symbols to method parameters. +Examples of monotonic maps are substitutions of argument types for parameters, +avoidance, or as-seen-from. + +Bijective map constraints define variables exactly. General map constraints come in three different forms. In the form `a >: F(b)`, `a` is bounded from +below by the map's result. Such constraints are created when a part +of a type appearing in covariant position is mapped. Consequently, variables +bound that way are called _covariant_. _Contravariant_ variables are defined +by constraints of the `a <: F(b)`. Such constraints are created when a part +of a type appearing in contravariant position is mapped. Finally, _invariant_ variables are defined by constraints of the `a = F(b)`, which are created when a part of a type appearing in invariant position is mapped. + +A solution to a subcapturing constraint set consists of an assignment of capture set constants to capture set variables, so that the resulting constraint set is true. The capture checker uses an incremental propagation-based +solver where capture set variables record which references they are known to contain. When new elements +are added to a set or a new relationship between capture sets is added, elements are propagated until +a new partial solution is found, or a contradiction is detected. A contradiction arises when an attempt +is made to add an element to a constant set that is not accounted for by the set. + +The propagation actions depend on the kind of constraint and whether a new capture set `c` is propagated +to the left part `a` or the right part `b` of the constraint. In the cases where the constraint +involves a general mapping `F`, the mapping `F(r)` of a capability `r` is in general a type, not +a capability or capture set. In this case we use `F(r).CS` for the capture set of the type +`F(r)`. Likewise, if `c` is a capture set, then `F(c)` might be a capture set `c'` if `F` maps all +capabilities in `c` to capabilities. But in general it will be a set of types, and `F(c).CS` +denotes the set of capture sets of these types. Furthermore, we use `c.super` for the capture set +of the definition of the reference `c` (as it shows up in rule (sc-var)). + +The propagation rules are summarized as follows: + +``` +Constraint new relation propagation remark +--------------------------------------------------------------- + a <: b c <: a c <: b + c <: b none + + a = B(b) c <: a B^-1(c) <: b + c <: b B(c) <: a + + a >: F(b) c <: a none + c <: b F(c).CS <: a + + a <: F(b) c <: a c <: b if F(c) = c (1) + c.super <: a otherwise + c <: b none + + a = F(b) c <: a c <: b if F(c) = c (1) + c.super <: a otherwise + c <: b c' <: a if F(c) = c' + F(c).CS? <: a otherwise (2) +``` +Remarks: + +(1) If `F(c) = c`, we solve by adding `c` also to `b`. Otherwise + we try again with `c.super <: a` instead of `c <: a`. At some point + this will succeed since we assume that for all maps `F`, `F(cap) = cap`. + This is clearly sound, but loses completeness since there might be + other, smaller solutions for the constraint. But with `F` not being + bijective, we'd have to try all possible capture sets to find + a suitable set that we could add to `b` so that `c` subcaptures the mapped set. + +(2) is the hard case. If the target set `a` appears invariantly, and `F(x)` is a type, we can use neither the lower bound set `{}` nor the upper bound set `F(x).CS`. Previously, we addressed this problem by making sure case (2) could not arise using the _range_ mechanism, which is also employed for regular type inference. To explain, let's say we try to map some type `t` where `F` is not defined on `t` but we know lower and upper approximations `tl` and `tu`. If `t` appears in +co- or contravariant positions, we can return `tu` or `tl`, respectively. But if `t` +appears in invariant position, we return `Range(tl, tu)`. This is not a type, but a type interval +which will be mapped itself, and will be resolved to one of its bounds at the first +point further out where the variance is positive or negative. There's also the case +where a Range appears in argument position of a parameterized class type, where we can +map it to the wildcard type `? >: tl <: tu`. We used the same mechanism for capture +set inference, by converting invariant occurrences of mapped type arguments `t^v` to wildcard types `? >: t^v1 <: t^v2` proactively, splitting the variable `v` to `v1` and `v2`, so that all capture set constraints occurred at co- or contravariant positions. + +Unfortunately this splitting has bad consequences for type inference, since a wildcard +is usually not compatible with a single expected type. So we would like to find another +technique for solving this issue. + +The idea is to use a technique similar to ranges directly on the capture sets. This means +that we now have a new class of elements of capture sets standing for references that might or might not be in the set. We use `{x?, ...}` as notation for a reference `x` that might or might not be an element of the enclosing capture set. Like `Range`, the notation is purely internal, we +never write it in a source program. + +We now describe how to handle the missing case (2) above. Assume `F(x)` is not a tracked reference, its image `a` is invariant and its capture set `cfr` is `{x_1,...,x_n}` where `n > 0`. In this case we add to `a` the _maybe references_ `x_1?, ..., x_n?`. Generalized to sets, `c <: b` where +`F(c) != c` leads to `F(c).CS?` to be added to `a`. Here, `CS?` is the set consisting of all references `x` in `cs` converted to maybe references `x?`. + +These references behave as follows: + + - For unions, `x` subsumes `x?`, so adding both `x` and `x?` to a set means + only `x` needs to be addded. + + - For further propagation of elements up the chain in e.g. `a <: b`, a maybe reference `x?` behaves like `x`. That is, since the reference could be in the set we have to propagate it upwards to be sound. + + - For propagations from lower sets, a maybe reference is treated as if it was missing. For instance, if we have `a <: b`, `b` contains `x?` and we propagate `x` from `a` to `b`, we need to add `x` as usual to `b`, which might imply back-proagation in the case `b` is an image of a type map `F`. + + - For mappings, maybe references are handled depending on the variance of the + image set. Assume we add `x?` to `b`. If `a >: F(b)` this amounts + to adding `F(x).CS` to `a`. If `a` is contravariant, this amounts to doing nothing. If `a` is invariant, we add `F(x).CS?` to `a`. If + `CS` is a capture set variable, it's "maybe" status has to be recorded and all elements this set acquires in the future also have to be converted to maybe references. + + + From 4e84ac455bb9508af59c6b037838a28c176eaac8 Mon Sep 17 00:00:00 2001 From: odersky Date: Fri, 17 Nov 2023 15:09:16 +0100 Subject: [PATCH 004/220] Align handling of covariant capturesets with description Still missing: - going to .super for other variables - maybe capabilities --- .../src/dotty/tools/dotc/cc/CaptureSet.scala | 23 +++++++------------ .../captures/usingLogFile.check | 4 ---- .../captures/usingLogFile.scala | 2 +- 3 files changed, 9 insertions(+), 20 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/cc/CaptureSet.scala b/compiler/src/dotty/tools/dotc/cc/CaptureSet.scala index fb086ca0399b..673c85479218 100644 --- a/compiler/src/dotty/tools/dotc/cc/CaptureSet.scala +++ b/compiler/src/dotty/tools/dotc/cc/CaptureSet.scala @@ -701,24 +701,17 @@ object CaptureSet: if mapped.isConst then CompareResult.OK else if mapped.asVar.recordDepsState() then { addAsDependentTo(mapped); CompareResult.OK } else CompareResult.Fail(this :: Nil) - else if !isFixpoint then - // We did not yet observe the !isFixpoint condition in our tests, but it's a - // theoretical possibility. In that case, it would be inconsistent to both - // add `elem` to the set and back-propagate it. But if `{elem} <:< tm(elem)` - // and the variance of the set is positive, we can soundly add `tm(ref)` to - // the set while back-propagating `ref` as before. Otherwise there's nothing - // obvious left to do except fail (which is always sound). - if variance > 0 - && elem.singletonCaptureSet.subCaptures(mapped, frozen = true).isOK then - // widen to fixpoint. mapped is known to be a fixpoint since tm is idempotent. - // The widening is sound, but loses completeness. - addMapped - else - failNoFixpoint else if accountsFor(elem) then CompareResult.OK - else + else if variance > 0 then + // we can soundly add nothing to source and `x` to this set + addNewElem(elem) + else if isFixpoint then + // We can soundly add `x` to both this set and source since `f(x) = x` addNewElem(elem).andAlso(propagate) + else + // we are out of options; fail (which is always sound). + failNoFixpoint end tryInclude override def computeApprox(origin: CaptureSet)(using Context): CaptureSet = diff --git a/tests/neg-custom-args/captures/usingLogFile.check b/tests/neg-custom-args/captures/usingLogFile.check index 476bf99ef0ef..ef0c5d1e77c9 100644 --- a/tests/neg-custom-args/captures/usingLogFile.check +++ b/tests/neg-custom-args/captures/usingLogFile.check @@ -10,7 +10,3 @@ 44 | val later = usingFile("out", f => (y: Int) => xs.foreach(x => f.write(x + y))) // error | ^^^^^^^^^ | local reference f leaks into outer capture set of type parameter T of method usingFile --- Error: tests/neg-custom-args/captures/usingLogFile.scala:52:16 ------------------------------------------------------ -52 | val later = usingFile("logfile", // error !!! but should be ok, since we can widen `l` to `file` instead of to `cap` - | ^^^^^^^^^ - | local reference l leaks into outer capture set of type parameter T of method usingFile diff --git a/tests/neg-custom-args/captures/usingLogFile.scala b/tests/neg-custom-args/captures/usingLogFile.scala index e5dc271975b0..67e6f841e7ce 100644 --- a/tests/neg-custom-args/captures/usingLogFile.scala +++ b/tests/neg-custom-args/captures/usingLogFile.scala @@ -49,6 +49,6 @@ object Test3: op(logger) def test = - val later = usingFile("logfile", // error !!! but should be ok, since we can widen `l` to `file` instead of to `cap` + val later = usingFile("logfile", // now ok usingLogger(_, l => () => l.log("test"))) later() From f4ddeaf78c5acf8a3fcdaefab7edcdd6e53a0e66 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 4 Dec 2023 14:14:34 +0100 Subject: [PATCH 005/220] Add regression test for #18260 Closes #18260 --- tests/pos/i18260.scala | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tests/pos/i18260.scala diff --git a/tests/pos/i18260.scala b/tests/pos/i18260.scala new file mode 100644 index 000000000000..4cda6d48f05a --- /dev/null +++ b/tests/pos/i18260.scala @@ -0,0 +1,11 @@ +import scala.deriving.Mirror + +type Id[A] = A +object Id: + def apply[A](a: A): Id[A] = a + +def test[P <: Product](using mirror: Mirror.ProductOf[P])(tuples: Tuple.Map[mirror.MirroredElemTypes, Id]): Tuple.Map[mirror.MirroredElemTypes, Id] = tuples + +def main() = + case class Test(p1: 1, p2: 2, p3: 3, p4: 4, p5: 5, p6: 6, p7: 7, p8: 8, p9: 9, p10: 10, p11: 11, p12: 12, p13: 13, p14: 14, p15: 15, p16: 16, p17: 17, p18: 18, p19: 19, p20: 20, p21: 21, p22: 22, p23: 23) + test[Test](Id[1](1), Id[2](2), Id[3](3), Id[4](4), Id[5](5), Id[6](6), Id[7](7), Id[8](8), Id[9](9), Id[10](10), Id[11](11), Id[12](12), Id[13](13), Id[14](14), Id[15](15), Id[16](16), Id[17](17), Id[18](18), Id[19](19), Id[20](20), Id[21](21), Id[22](22), Id[23](23)) From 290094db16d6122ee2c94861f65fa90028fd2430 Mon Sep 17 00:00:00 2001 From: Hamza Remmal <56235032+hamzaremmal@users.noreply.github.com> Date: Sun, 26 Nov 2023 01:28:46 +0100 Subject: [PATCH 006/220] Add support for @deprecatedInheritance --- .../dotty/tools/dotc/core/Definitions.scala | 1 + .../dotc/interactive/InteractiveDriver.scala | 8 +-- .../dotty/tools/dotc/reporting/Message.scala | 3 +- .../dotty/tools/dotc/rewrites/Rewrites.scala | 2 +- .../semanticdb/SemanticSymbolBuilder.scala | 3 +- .../dotc/transform/CountOuterAccesses.scala | 4 +- .../tools/dotc/transform/PatternMatcher.scala | 4 +- .../src/dotty/tools/dotc/typer/Checking.scala | 4 +- .../tools/dotc/typer/CrossVersionChecks.scala | 58 ++++++++++++------- .../src/dotty/tools/dotc/util/Stats.scala | 4 +- tests/init/pos/patternMatcher.scala | 4 +- tests/warn/i19002.check | 36 ++++++++++++ tests/warn/i19002.scala | 23 ++++++++ 13 files changed, 108 insertions(+), 46 deletions(-) create mode 100644 tests/warn/i19002.check create mode 100644 tests/warn/i19002.scala diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index c500953f49bf..cc013c6952dc 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -1006,6 +1006,7 @@ class Definitions { @tu lazy val ProvisionalSuperClassAnnot: ClassSymbol = requiredClass("scala.annotation.internal.ProvisionalSuperClass") @tu lazy val DeprecatedAnnot: ClassSymbol = requiredClass("scala.deprecated") @tu lazy val DeprecatedOverridingAnnot: ClassSymbol = requiredClass("scala.deprecatedOverriding") + @tu lazy val DeprecatedInheritanceAnnot: ClassSymbol = requiredClass("scala.deprecatedInheritance") @tu lazy val ImplicitAmbiguousAnnot: ClassSymbol = requiredClass("scala.annotation.implicitAmbiguous") @tu lazy val ImplicitNotFoundAnnot: ClassSymbol = requiredClass("scala.annotation.implicitNotFound") @tu lazy val InlineParamAnnot: ClassSymbol = requiredClass("scala.annotation.internal.InlineParam") diff --git a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala index b00cd1036018..c99b332fe949 100644 --- a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala +++ b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala @@ -47,14 +47,10 @@ class InteractiveDriver(val settings: List[String]) extends Driver { private val compiler: Compiler = new InteractiveCompiler - private val myOpenedFiles = new mutable.LinkedHashMap[URI, SourceFile] { - override def default(key: URI) = NoSource - } + private val myOpenedFiles = new mutable.LinkedHashMap[URI, SourceFile].withDefaultValue(NoSource) def openedFiles: Map[URI, SourceFile] = myOpenedFiles - private val myOpenedTrees = new mutable.LinkedHashMap[URI, List[SourceTree]] { - override def default(key: URI) = Nil - } + private val myOpenedTrees = new mutable.LinkedHashMap[URI, List[SourceTree]].withDefaultValue(Nil) def openedTrees: Map[URI, List[SourceTree]] = myOpenedTrees private val myCompilationUnits = new mutable.LinkedHashMap[URI, CompilationUnit] diff --git a/compiler/src/dotty/tools/dotc/reporting/Message.scala b/compiler/src/dotty/tools/dotc/reporting/Message.scala index 11d86386d630..98fd34adbedc 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Message.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Message.scala @@ -57,8 +57,7 @@ object Message: def openLambda(tp: LambdaType): Unit = openedLambdas += tp - val seen = new collection.mutable.HashMap[SeenKey, List[Recorded]]: - override def default(key: SeenKey) = Nil + val seen = new collection.mutable.HashMap[SeenKey, List[Recorded]].withDefaultValue(Nil) var nonSensical = false diff --git a/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala b/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala index 2586ad8604c3..305f61dfa177 100644 --- a/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala +++ b/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala @@ -15,7 +15,7 @@ import dotty.tools.dotc.reporting.CodeAction /** Handles rewriting of Scala2 files to Dotty */ object Rewrites { - private class PatchedFiles extends mutable.HashMap[SourceFile, Patches] + private type PatchedFiles = mutable.HashMap[SourceFile, Patches] private case class Patch(span: Span, replacement: String) { def delta = replacement.length - (span.end - span.start) diff --git a/compiler/src/dotty/tools/dotc/semanticdb/SemanticSymbolBuilder.scala b/compiler/src/dotty/tools/dotc/semanticdb/SemanticSymbolBuilder.scala index 6376fb86d6c5..50ea6ec48510 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/SemanticSymbolBuilder.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/SemanticSymbolBuilder.scala @@ -20,8 +20,7 @@ class SemanticSymbolBuilder: private val locals = mutable.HashMap[Symbol, Int]() /** The local symbol(s) starting at given offset */ - private val symsAtOffset = new mutable.HashMap[Int, Set[Symbol]](): - override def default(key: Int) = Set[Symbol]() + private val symsAtOffset = new mutable.HashMap[Int, Set[Symbol]]().withDefault(_ => Set[Symbol]()) def symbolName(sym: Symbol)(using Context): String = diff --git a/compiler/src/dotty/tools/dotc/transform/CountOuterAccesses.scala b/compiler/src/dotty/tools/dotc/transform/CountOuterAccesses.scala index b5c02347d5d2..e55c3d953ac2 100644 --- a/compiler/src/dotty/tools/dotc/transform/CountOuterAccesses.scala +++ b/compiler/src/dotty/tools/dotc/transform/CountOuterAccesses.scala @@ -43,9 +43,7 @@ class CountOuterAccesses extends MiniPhase: // LambdaLift can create outer paths. These need to be known in this phase. /** The number of times an outer accessor that might be dropped is accessed */ - val outerAccessCount = new mutable.HashMap[Symbol, Int] { - override def default(s: Symbol): Int = 0 - } + val outerAccessCount = new mutable.HashMap[Symbol, Int].withDefaultValue(0) private def markAccessed(tree: RefTree)(using Context): Tree = val sym = tree.symbol diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index f6d15b65b9f6..2e1dfe4c42cc 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -504,9 +504,7 @@ object PatternMatcher { } private class RefCounter extends PlanTransform { - val count = new mutable.HashMap[Symbol, Int] { - override def default(key: Symbol) = 0 - } + val count = new mutable.HashMap[Symbol, Int].withDefaultValue(0) } /** Reference counts for all labels */ diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 3b57ada3fc77..2c81a91a98c5 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -1150,9 +1150,7 @@ trait Checking { /** Check that class does not declare same symbol twice */ def checkNoDoubleDeclaration(cls: Symbol)(using Context): Unit = { - val seen = new mutable.HashMap[Name, List[Symbol]] { - override def default(key: Name) = Nil - } + val seen = new mutable.HashMap[Name, List[Symbol]].withDefaultValue(Nil) typr.println(i"check no double declarations $cls") def checkDecl(decl: Symbol): Unit = { diff --git a/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala b/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala index 91303b00618c..29c5ca96049c 100644 --- a/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala @@ -32,10 +32,16 @@ class CrossVersionChecks extends MiniPhase: checkMigration(sym, pos, xMigrationValue) end checkUndesiredProperties - /** If @deprecated is present, and the point of reference is not enclosed - * in either a deprecated member or a scala bridge method, issue a warning. - */ - private def checkDeprecated(sym: Symbol, pos: SrcPos)(using Context): Unit = + /**Skip warnings for synthetic members of case classes during declaration and + * scan the chain of outer declaring scopes from the current context + * a deprecation warning will be skipped if one the following holds + * for a given declaring scope: + * - the symbol associated with the scope is also deprecated. + * - if and only if `sym` is an enum case, the scope is either + * a module that declares `sym`, or the companion class of the + * module that declares `sym`. + */ + def skipWarning(sym: Symbol)(using Context): Boolean = /** is the owner an enum or its companion and also the owner of sym */ def isEnumOwner(owner: Symbol)(using Context) = @@ -46,26 +52,22 @@ class CrossVersionChecks extends MiniPhase: def isDeprecatedOrEnum(owner: Symbol)(using Context) = // pre: sym is an enumcase - owner.isDeprecated - || isEnumOwner(owner) - - /**Skip warnings for synthetic members of case classes during declaration and - * scan the chain of outer declaring scopes from the current context - * a deprecation warning will be skipped if one the following holds - * for a given declaring scope: - * - the symbol associated with the scope is also deprecated. - * - if and only if `sym` is an enum case, the scope is either - * a module that declares `sym`, or the companion class of the - * module that declares `sym`. - */ - def skipWarning(using Context): Boolean = - (ctx.owner.is(Synthetic) && sym.is(CaseClass)) - || ctx.owner.ownersIterator.exists(if sym.isEnumCase then isDeprecatedOrEnum else _.isDeprecated) + owner.isDeprecated || isEnumOwner(owner) + + (ctx.owner.is(Synthetic) && sym.is(CaseClass)) + || ctx.owner.ownersIterator.exists(if sym.isEnumCase then isDeprecatedOrEnum else _.isDeprecated) + end skipWarning + + + /** If @deprecated is present, and the point of reference is not enclosed + * in either a deprecated member or a scala bridge method, issue a warning. + */ + private def checkDeprecated(sym: Symbol, pos: SrcPos)(using Context): Unit = // Also check for deprecation of the companion class for synthetic methods val toCheck = sym :: (if sym.isAllOf(SyntheticMethod) then sym.owner.companionClass :: Nil else Nil) for sym <- toCheck; annot <- sym.getAnnotation(defn.DeprecatedAnnot) do - if !skipWarning then + if !skipWarning(sym) then val msg = annot.argumentConstant(0).map(": " + _.stringValue).getOrElse("") val since = annot.argumentConstant(1).map(" since " + _.stringValue).getOrElse("") report.deprecationWarning(em"${sym.showLocated} is deprecated${since}${msg}", pos) @@ -107,6 +109,18 @@ class CrossVersionChecks extends MiniPhase: } } + /** ??? */ + def checkDeprecatedInheritance(parents: List[Tree])(using Context): Unit = { + for parent <- parents + psym = parent.tpe.classSymbol + annot <- psym.getAnnotation(defn.DeprecatedInheritanceAnnot) + if !skipWarning(psym) + do + val msg = annot.argumentConstantString(0).map(msg => s": $msg").getOrElse("") + val since = annot.argumentConstantString(1).map(version => s" (since: $version)").getOrElse("") + report.deprecationWarning(em"inheritance from $psym is deprecated$since$msg", parent.srcPos) + } + override def transformValDef(tree: ValDef)(using Context): ValDef = checkDeprecatedOvers(tree) checkExperimentalAnnots(tree.symbol) @@ -122,6 +136,10 @@ class CrossVersionChecks extends MiniPhase: checkExperimentalAnnots(tree.symbol) tree + override def transformTemplate(tree: tpd.Template)(using Context): tpd.Tree = + checkDeprecatedInheritance(tree.parents) + tree + override def transformIdent(tree: Ident)(using Context): Ident = { checkUndesiredProperties(tree.symbol, tree.srcPos) tree diff --git a/compiler/src/dotty/tools/dotc/util/Stats.scala b/compiler/src/dotty/tools/dotc/util/Stats.scala index 750a799a9f0a..2f4e3bd9cb4f 100644 --- a/compiler/src/dotty/tools/dotc/util/Stats.scala +++ b/compiler/src/dotty/tools/dotc/util/Stats.scala @@ -19,9 +19,7 @@ import collection.mutable @volatile private var stack: List[String] = Nil - val hits: mutable.HashMap[String, Int] = new mutable.HashMap[String, Int] { - override def default(key: String): Int = 0 - } + val hits: mutable.Map[String, Int] = new mutable.HashMap[String, Int].withDefaultValue(0) inline def record(inline fn: String, inline n: Int = 1, inline skip: Boolean = timerOnly): Unit = if (enabled && !skip) doRecord(fn, n) diff --git a/tests/init/pos/patternMatcher.scala b/tests/init/pos/patternMatcher.scala index 425c48b71260..99b2acb16df5 100644 --- a/tests/init/pos/patternMatcher.scala +++ b/tests/init/pos/patternMatcher.scala @@ -1,8 +1,6 @@ import scala.collection.mutable class Translater: - val count = new mutable.HashMap[Int, Int] { - override def default(key: Int) = 0 - } + val count = new mutable.HashMap[Int, Int].withDefaultValue(0) count.get(10) val n = 10 diff --git a/tests/warn/i19002.check b/tests/warn/i19002.check new file mode 100644 index 000000000000..be26ff5e32f4 --- /dev/null +++ b/tests/warn/i19002.check @@ -0,0 +1,36 @@ +-- Deprecation Warning: tests/warn/i19002.scala:5:20 ------------------------------------------------------------------- +5 |class TBar1 extends TFoo // warn + | ^^^^ + | inheritance from trait TFoo is deprecated (since: FooLib 12.0): this class will be made final +-- Deprecation Warning: tests/warn/i19002.scala:6:20 ------------------------------------------------------------------- +6 |trait TBar2 extends TFoo // warn + | ^^^^ + | inheritance from trait TFoo is deprecated (since: FooLib 12.0): this class will be made final +-- Deprecation Warning: tests/warn/i19002.scala:11:20 ------------------------------------------------------------------ +11 |class CBar1 extends CFoo // warn + | ^^^^ + | inheritance from class CFoo is deprecated (since: FooLib 11.0) +-- Deprecation Warning: tests/warn/i19002.scala:12:20 ------------------------------------------------------------------ +12 |trait CBar2 extends CFoo // warn + | ^^^^ + | inheritance from class CFoo is deprecated (since: FooLib 11.0) +-- Deprecation Warning: tests/warn/i19002.scala:17:20 ------------------------------------------------------------------ +17 |class ABar1 extends AFoo // warn + | ^^^^ + | inheritance from class AFoo is deprecated: this class will be made final +-- Deprecation Warning: tests/warn/i19002.scala:18:20 ------------------------------------------------------------------ +18 |trait ABar2 extends AFoo // warn + | ^^^^ + | inheritance from class AFoo is deprecated: this class will be made final +-- Deprecation Warning: tests/warn/i19002.scala:7:16 ------------------------------------------------------------------- +7 |def TBar3 = new TFoo {} // warn + | ^^^^ + | inheritance from trait TFoo is deprecated (since: FooLib 12.0): this class will be made final +-- Deprecation Warning: tests/warn/i19002.scala:13:16 ------------------------------------------------------------------ +13 |def CBar3 = new CFoo {} // warn + | ^^^^ + | inheritance from class CFoo is deprecated (since: FooLib 11.0) +-- Deprecation Warning: tests/warn/i19002.scala:19:16 ------------------------------------------------------------------ +19 |def ABar3 = new AFoo {} // warn + | ^^^^ + | inheritance from class AFoo is deprecated: this class will be made final diff --git a/tests/warn/i19002.scala b/tests/warn/i19002.scala new file mode 100644 index 000000000000..5242c1bfb49e --- /dev/null +++ b/tests/warn/i19002.scala @@ -0,0 +1,23 @@ +//> using options -deprecation + +@deprecatedInheritance("this class will be made final", "FooLib 12.0") +trait TFoo +class TBar1 extends TFoo // warn +trait TBar2 extends TFoo // warn +def TBar3 = new TFoo {} // warn + +@deprecatedInheritance(since = "FooLib 11.0") +class CFoo +class CBar1 extends CFoo // warn +trait CBar2 extends CFoo // warn +def CBar3 = new CFoo {} // warn + +@deprecatedInheritance(message = "this class will be made final") +abstract class AFoo +class ABar1 extends AFoo // warn +trait ABar2 extends AFoo // warn +def ABar3 = new AFoo {} // warn + +@deprecated +class DeprecatedFoo: + class Foo extends AFoo // it shoudln't warn here (in deprecated context) From 19b73867f48957b13209fbaa73c52750ab6992f7 Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Fri, 15 Dec 2023 16:27:02 +0100 Subject: [PATCH 007/220] Warn nopos & tests/init refactor for warn tests --- .../test/dotty/tools/dotc/CompilationTests.scala | 1 + .../test/dotty/tools/vulpix/ParallelTesting.scala | 11 +++++++---- tests/init/neg/early-promote2.scala | 6 ------ tests/init/neg/simple1.scala | 4 ---- tests/init/neg/soundness4.scala | 3 --- tests/init/{neg => warn}/AbstractFile.scala | 2 +- tests/init/{neg => warn}/alias.scala | 2 +- tests/init/{neg => warn}/apply.scala | 6 +++--- tests/init/{neg => warn}/apply2.scala | 2 +- .../as-instance-of-cold-field-access.scala | 2 +- tests/init/{neg => warn}/by-name-error.scala | 2 +- tests/init/{neg => warn}/closureLeak.scala | 2 +- tests/init/{neg => warn}/cold-insert-hot-array.scala | 2 +- tests/init/{neg => warn}/cycle-structure.scala | 4 ++-- tests/init/{neg => warn}/cycle.scala | 4 ++-- tests/init/{neg => warn}/default-this.scala | 2 +- tests/init/{neg => warn}/early-promote.scala | 2 +- tests/init/warn/early-promote2.scala | 6 ++++++ tests/init/{neg => warn}/early-promote3.scala | 2 +- tests/init/{neg => warn}/early-promote4.scala | 2 +- tests/init/{neg => warn}/early-promote5.scala | 4 ++-- tests/init/{neg => warn}/escape1.scala | 2 +- tests/init/{neg => warn}/features-high-order.scala | 2 +- .../init/{neg => warn}/features-linearization.scala | 2 +- tests/init/{neg => warn}/features-trees.scala | 2 +- tests/init/{neg => warn}/final-fields.scala | 8 ++++---- tests/init/{neg => warn}/flow2.scala | 2 +- tests/init/{neg => warn}/function-loop.scala | 2 +- tests/init/{neg => warn}/function1.scala | 4 ++-- tests/init/{neg => warn}/function10.scala | 2 +- tests/init/{neg => warn}/function11.scala | 2 +- tests/init/{neg => warn}/function2.scala | 2 +- tests/init/{neg => warn}/hybrid1.scala | 2 +- tests/init/{neg => warn}/hybrid2.scala | 2 +- tests/init/{neg => warn}/hybrid4.scala | 2 +- tests/init/{neg => warn}/hybrid5.scala | 2 +- tests/init/{neg => warn}/hybrid6.scala | 2 +- tests/init/{neg => warn}/i10549b.scala | 2 +- tests/init/{neg => warn}/i11572.scala | 2 +- tests/init/{neg => warn}/i12544.scala | 2 +- tests/init/{neg => warn}/i15363.scala | 2 +- tests/init/{neg => warn}/i15459.scala | 2 +- tests/init/{neg => warn}/i4031.scala | 2 +- tests/init/{neg => warn}/i4042.scala | 2 +- tests/init/{neg => warn}/i50.scala | 2 +- tests/init/{neg => warn}/i5854.scala | 2 +- tests/init/{neg => warn}/inherit-non-hot.scala | 2 +- tests/init/{neg => warn}/inlined-method.scala | 2 +- tests/init/{neg => warn}/inner-case.scala | 2 +- tests/init/{neg => warn}/inner-first.scala | 2 +- tests/init/{neg => warn}/inner-loop.scala | 4 ++-- tests/init/{neg => warn}/inner-new.scala | 2 +- tests/init/{neg => warn}/inner-pat_iuli.scala | 2 +- tests/init/{neg => warn}/inner1.scala | 2 +- tests/init/{neg => warn}/inner11.scala | 2 +- tests/init/{neg => warn}/inner15.scala | 2 +- tests/init/{neg => warn}/inner16.scala | 2 +- tests/init/{neg => warn}/inner17.scala | 2 +- tests/init/{neg => warn}/inner19.scala | 2 +- tests/init/{neg => warn}/inner20.scala | 2 +- tests/init/{neg => warn}/inner21.scala | 4 ++-- tests/init/{neg => warn}/inner22.scala | 2 +- tests/init/{neg => warn}/inner23.scala | 2 +- tests/init/{neg => warn}/inner24.scala | 2 +- tests/init/{neg => warn}/inner25.scala | 2 +- tests/init/{neg => warn}/inner29.scala | 2 +- tests/init/{neg => warn}/inner30.scala | 2 +- tests/init/{neg => warn}/inner4.scala | 2 +- tests/init/{neg => warn}/inner5.scala | 2 +- tests/init/{neg => warn}/inner6.scala | 2 +- tests/init/{neg => warn}/inner7.scala | 2 +- tests/init/{neg => warn}/inner9.scala | 4 ++-- .../{neg => warn}/insert-cold-subtype-to-array.scala | 2 +- tests/init/{neg => warn}/java1.scala | 2 +- tests/init/{neg => warn}/lazy.scala | 4 ++-- tests/init/{neg => warn}/lazylist2.scala | 4 ++-- tests/init/{neg => warn}/leak-warm.scala | 2 +- tests/init/{neg => warn}/local-class.scala | 2 +- tests/init/{neg => warn}/override1.scala | 2 +- tests/init/{neg => warn}/override10.scala | 2 +- tests/init/{neg => warn}/override14.scala | 2 +- tests/init/{neg => warn}/override15.scala | 2 +- tests/init/{neg => warn}/override17.scala | 2 +- tests/init/{neg => warn}/override18.scala | 2 +- tests/init/{neg => warn}/override19.scala | 2 +- tests/init/{neg => warn}/override2.scala | 2 +- tests/init/{neg => warn}/override20.scala | 2 +- tests/init/{neg => warn}/override21.scala | 2 +- tests/init/{neg => warn}/override22.scala | 2 +- tests/init/{neg => warn}/override23.scala | 2 +- tests/init/{neg => warn}/override24.scala | 2 +- tests/init/{neg => warn}/override25.scala | 2 +- tests/init/{neg => warn}/override26.scala | 2 +- tests/init/{neg => warn}/override27.scala | 4 ++-- tests/init/{neg => warn}/override28.scala | 2 +- tests/init/{neg => warn}/override29.scala | 2 +- tests/init/{neg => warn}/override3.scala | 2 +- tests/init/{neg => warn}/override30.scala | 2 +- tests/init/{neg => warn}/override31.scala | 2 +- tests/init/{neg => warn}/override32.scala | 2 +- tests/init/{neg => warn}/override33.scala | 2 +- tests/init/{neg => warn}/override34.scala | 2 +- tests/init/{neg => warn}/override35.scala | 2 +- tests/init/{neg => warn}/override36.scala | 2 +- tests/init/{neg => warn}/override38.scala | 2 +- tests/init/{neg => warn}/override39.scala | 2 +- tests/init/{neg => warn}/override4.scala | 2 +- tests/init/{neg => warn}/override40.scala | 2 +- tests/init/{neg => warn}/override41.scala | 2 +- tests/init/{neg => warn}/override42.scala | 2 +- tests/init/{neg => warn}/override43.scala | 2 +- tests/init/{neg => warn}/override44.scala | 2 +- tests/init/{neg => warn}/override45.scala | 2 +- tests/init/{neg => warn}/override46.scala | 2 +- tests/init/{neg => warn}/override5.scala | 4 ++-- tests/init/{neg => warn}/override6.scala | 2 +- tests/init/{neg => warn}/override7.scala | 2 +- tests/init/{neg => warn}/override8.scala | 2 +- tests/init/{neg => warn}/override9.scala | 2 +- tests/init/{neg => warn}/polyfun.scala | 2 +- tests/init/{neg => warn}/private.scala | 2 +- tests/init/{neg => warn}/promote-warm.scala | 2 +- tests/init/{neg => warn}/promote.scala | 2 +- tests/init/{neg => warn}/promotion-loop.scala | 2 +- tests/init/{neg => warn}/promotion-segment.scala | 2 +- tests/init/{neg => warn}/promotion-segment2.scala | 2 +- tests/init/{neg => warn}/promotion-segment3.scala | 2 +- tests/init/{neg => warn}/secondary-ctor.scala | 2 +- tests/init/{neg => warn}/secondary-ctor2.scala | 2 +- tests/init/{neg => warn}/secondary-ctor3.scala | 2 +- tests/init/{neg => warn}/secondary-ctor4.check | 12 ++++++------ tests/init/{neg => warn}/secondary-ctor4.scala | 6 +++--- tests/init/warn/simple1.scala | 4 ++++ tests/init/{neg => warn}/simple2.scala | 2 +- tests/init/{neg => warn}/simple3.scala | 2 +- tests/init/{neg => warn}/simple5.scala | 4 ++-- tests/init/{neg => warn}/soundness1.scala | 4 ++-- tests/init/{neg => warn}/soundness2.scala | 2 +- tests/init/warn/soundness4.scala | 3 +++ tests/init/{neg => warn}/soundness6.scala | 2 +- tests/init/{neg => warn}/structural.scala | 2 +- tests/init/{neg => warn}/super-resolution.scala | 6 +++--- tests/init/{neg => warn}/super-resolution2.scala | 4 ++-- tests/init/{neg => warn}/super-resolution3.scala | 8 ++++---- tests/init/{neg => warn}/super.scala | 4 ++-- tests/init/{neg => warn}/t3273.scala | 4 ++-- tests/init/{neg => warn}/trait1.scala | 2 +- tests/init/{neg => warn}/trait2.scala | 2 +- tests/init/{neg => warn}/trees.scala | 2 +- tests/init/{neg => warn}/unsound1.scala | 2 +- tests/init/{neg => warn}/unsound2.scala | 2 +- tests/init/{neg => warn}/unsound3.scala | 2 +- tests/init/{neg => warn}/unsound4.scala | 2 +- 153 files changed, 199 insertions(+), 195 deletions(-) delete mode 100644 tests/init/neg/early-promote2.scala delete mode 100644 tests/init/neg/simple1.scala delete mode 100644 tests/init/neg/soundness4.scala rename tests/init/{neg => warn}/AbstractFile.scala (64%) rename tests/init/{neg => warn}/alias.scala (63%) rename tests/init/{neg => warn}/apply.scala (85%) rename tests/init/{neg => warn}/apply2.scala (75%) mode change 100755 => 100644 rename tests/init/{neg => warn}/as-instance-of-cold-field-access.scala (78%) rename tests/init/{neg => warn}/by-name-error.scala (79%) rename tests/init/{neg => warn}/closureLeak.scala (83%) rename tests/init/{neg => warn}/cold-insert-hot-array.scala (84%) rename tests/init/{neg => warn}/cycle-structure.scala (64%) rename tests/init/{neg => warn}/cycle.scala (59%) rename tests/init/{neg => warn}/default-this.scala (89%) rename tests/init/{neg => warn}/early-promote.scala (84%) create mode 100644 tests/init/warn/early-promote2.scala rename tests/init/{neg => warn}/early-promote3.scala (77%) rename tests/init/{neg => warn}/early-promote4.scala (87%) rename tests/init/{neg => warn}/early-promote5.scala (80%) rename tests/init/{neg => warn}/escape1.scala (71%) rename tests/init/{neg => warn}/features-high-order.scala (81%) rename tests/init/{neg => warn}/features-linearization.scala (82%) rename tests/init/{neg => warn}/features-trees.scala (76%) rename tests/init/{neg => warn}/final-fields.scala (72%) rename tests/init/{neg => warn}/flow2.scala (73%) rename tests/init/{neg => warn}/function-loop.scala (78%) rename tests/init/{neg => warn}/function1.scala (60%) rename tests/init/{neg => warn}/function10.scala (53%) rename tests/init/{neg => warn}/function11.scala (89%) rename tests/init/{neg => warn}/function2.scala (70%) rename tests/init/{neg => warn}/hybrid1.scala (87%) rename tests/init/{neg => warn}/hybrid2.scala (84%) rename tests/init/{neg => warn}/hybrid4.scala (75%) rename tests/init/{neg => warn}/hybrid5.scala (86%) rename tests/init/{neg => warn}/hybrid6.scala (81%) rename tests/init/{neg => warn}/i10549b.scala (81%) rename tests/init/{neg => warn}/i11572.scala (90%) rename tests/init/{neg => warn}/i12544.scala (93%) rename tests/init/{neg => warn}/i15363.scala (78%) rename tests/init/{neg => warn}/i15459.scala (81%) rename tests/init/{neg => warn}/i4031.scala (78%) rename tests/init/{neg => warn}/i4042.scala (87%) rename tests/init/{neg => warn}/i50.scala (64%) rename tests/init/{neg => warn}/i5854.scala (63%) rename tests/init/{neg => warn}/inherit-non-hot.scala (86%) rename tests/init/{neg => warn}/inlined-method.scala (70%) rename tests/init/{neg => warn}/inner-case.scala (82%) rename tests/init/{neg => warn}/inner-first.scala (69%) rename tests/init/{neg => warn}/inner-loop.scala (88%) rename tests/init/{neg => warn}/inner-new.scala (80%) rename tests/init/{neg => warn}/inner-pat_iuli.scala (92%) rename tests/init/{neg => warn}/inner1.scala (80%) rename tests/init/{neg => warn}/inner11.scala (93%) rename tests/init/{neg => warn}/inner15.scala (84%) rename tests/init/{neg => warn}/inner16.scala (87%) rename tests/init/{neg => warn}/inner17.scala (78%) rename tests/init/{neg => warn}/inner19.scala (79%) rename tests/init/{neg => warn}/inner20.scala (84%) rename tests/init/{neg => warn}/inner21.scala (71%) rename tests/init/{neg => warn}/inner22.scala (92%) rename tests/init/{neg => warn}/inner23.scala (77%) rename tests/init/{neg => warn}/inner24.scala (84%) rename tests/init/{neg => warn}/inner25.scala (91%) rename tests/init/{neg => warn}/inner29.scala (83%) rename tests/init/{neg => warn}/inner30.scala (92%) rename tests/init/{neg => warn}/inner4.scala (77%) rename tests/init/{neg => warn}/inner5.scala (76%) rename tests/init/{neg => warn}/inner6.scala (91%) rename tests/init/{neg => warn}/inner7.scala (81%) rename tests/init/{neg => warn}/inner9.scala (79%) rename tests/init/{neg => warn}/insert-cold-subtype-to-array.scala (84%) rename tests/init/{neg => warn}/java1.scala (91%) rename tests/init/{neg => warn}/lazy.scala (69%) rename tests/init/{neg => warn}/lazylist2.scala (89%) rename tests/init/{neg => warn}/leak-warm.scala (91%) rename tests/init/{neg => warn}/local-class.scala (84%) rename tests/init/{neg => warn}/override1.scala (84%) rename tests/init/{neg => warn}/override10.scala (75%) rename tests/init/{neg => warn}/override14.scala (76%) rename tests/init/{neg => warn}/override15.scala (81%) rename tests/init/{neg => warn}/override17.scala (76%) rename tests/init/{neg => warn}/override18.scala (88%) rename tests/init/{neg => warn}/override19.scala (79%) rename tests/init/{neg => warn}/override2.scala (89%) rename tests/init/{neg => warn}/override20.scala (75%) rename tests/init/{neg => warn}/override21.scala (86%) rename tests/init/{neg => warn}/override22.scala (87%) rename tests/init/{neg => warn}/override23.scala (87%) rename tests/init/{neg => warn}/override24.scala (91%) rename tests/init/{neg => warn}/override25.scala (85%) rename tests/init/{neg => warn}/override26.scala (85%) rename tests/init/{neg => warn}/override27.scala (73%) rename tests/init/{neg => warn}/override28.scala (72%) rename tests/init/{neg => warn}/override29.scala (78%) rename tests/init/{neg => warn}/override3.scala (91%) rename tests/init/{neg => warn}/override30.scala (79%) rename tests/init/{neg => warn}/override31.scala (84%) rename tests/init/{neg => warn}/override32.scala (80%) rename tests/init/{neg => warn}/override33.scala (85%) rename tests/init/{neg => warn}/override34.scala (79%) rename tests/init/{neg => warn}/override35.scala (77%) rename tests/init/{neg => warn}/override36.scala (87%) rename tests/init/{neg => warn}/override38.scala (77%) rename tests/init/{neg => warn}/override39.scala (82%) rename tests/init/{neg => warn}/override4.scala (82%) rename tests/init/{neg => warn}/override40.scala (80%) rename tests/init/{neg => warn}/override41.scala (82%) rename tests/init/{neg => warn}/override42.scala (81%) rename tests/init/{neg => warn}/override43.scala (83%) rename tests/init/{neg => warn}/override44.scala (83%) rename tests/init/{neg => warn}/override45.scala (81%) rename tests/init/{neg => warn}/override46.scala (75%) rename tests/init/{neg => warn}/override5.scala (78%) rename tests/init/{neg => warn}/override6.scala (70%) rename tests/init/{neg => warn}/override7.scala (87%) rename tests/init/{neg => warn}/override8.scala (93%) rename tests/init/{neg => warn}/override9.scala (64%) rename tests/init/{neg => warn}/polyfun.scala (72%) rename tests/init/{neg => warn}/private.scala (84%) rename tests/init/{neg => warn}/promote-warm.scala (84%) rename tests/init/{neg => warn}/promote.scala (82%) rename tests/init/{neg => warn}/promotion-loop.scala (86%) rename tests/init/{neg => warn}/promotion-segment.scala (85%) rename tests/init/{neg => warn}/promotion-segment2.scala (87%) rename tests/init/{neg => warn}/promotion-segment3.scala (82%) rename tests/init/{neg => warn}/secondary-ctor.scala (87%) rename tests/init/{neg => warn}/secondary-ctor2.scala (91%) rename tests/init/{neg => warn}/secondary-ctor3.scala (94%) rename tests/init/{neg => warn}/secondary-ctor4.check (84%) rename tests/init/{neg => warn}/secondary-ctor4.scala (90%) create mode 100644 tests/init/warn/simple1.scala rename tests/init/{neg => warn}/simple2.scala (86%) rename tests/init/{neg => warn}/simple3.scala (64%) rename tests/init/{neg => warn}/simple5.scala (68%) rename tests/init/{neg => warn}/soundness1.scala (81%) rename tests/init/{neg => warn}/soundness2.scala (50%) create mode 100644 tests/init/warn/soundness4.scala rename tests/init/{neg => warn}/soundness6.scala (58%) rename tests/init/{neg => warn}/structural.scala (86%) rename tests/init/{neg => warn}/super-resolution.scala (82%) rename tests/init/{neg => warn}/super-resolution2.scala (84%) rename tests/init/{neg => warn}/super-resolution3.scala (81%) rename tests/init/{neg => warn}/super.scala (87%) rename tests/init/{neg => warn}/t3273.scala (90%) rename tests/init/{neg => warn}/trait1.scala (79%) rename tests/init/{neg => warn}/trait2.scala (83%) rename tests/init/{neg => warn}/trees.scala (78%) rename tests/init/{neg => warn}/unsound1.scala (80%) rename tests/init/{neg => warn}/unsound2.scala (88%) rename tests/init/{neg => warn}/unsound3.scala (72%) rename tests/init/{neg => warn}/unsound4.scala (70%) diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 41b8de0d6138..4f1a64bbc6fa 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -225,6 +225,7 @@ class CompilationTests { implicit val testGroup: TestGroup = TestGroup("checkInit") val options = defaultOptions.and("-Ysafe-init", "-Xfatal-warnings") compileFilesInDir("tests/init/neg", options).checkExpectedErrors() + compileFilesInDir("tests/init/warn", defaultOptions.and("-Ysafe-init")).checkWarnings() compileFilesInDir("tests/init/pos", options).checkCompile() compileFilesInDir("tests/init/crash", options.without("-Xfatal-warnings")).checkCompile() // The regression test for i12128 has some atypical classpath requirements. diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala index e93a0435987b..174fbb60ef34 100644 --- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala +++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala @@ -776,7 +776,7 @@ trait ParallelTesting extends RunnerOrchestration { self => end maybeFailureMessage def getWarnMapAndExpectedCount(files: Seq[JFile]): (HashMap[String, Integer], Int) = - val comment = raw"//( *)warn".r + val comment = raw"//( *)(nopos-)?warn".r val map = new HashMap[String, Integer]() var count = 0 def bump(key: String): Unit = @@ -787,8 +787,11 @@ trait ParallelTesting extends RunnerOrchestration { self => files.filter(isSourceFile).foreach { file => Using(Source.fromFile(file, StandardCharsets.UTF_8.name)) { source => source.getLines.zipWithIndex.foreach { case (line, lineNbr) => - comment.findAllMatchIn(line).foreach { _ => - bump(s"${file.getPath}:${lineNbr+1}") + comment.findAllMatchIn(line).foreach { m => + m.group(2) match + case "nopos-" => + bump("nopos") + case _ => bump(s"${file.getPath}:${lineNbr+1}") } } }.get @@ -809,7 +812,7 @@ trait ParallelTesting extends RunnerOrchestration { self => val key = s"${relativize(srcpos.source.file.toString())}:${srcpos.line + 1}" if !seenAt(key) then unexpected += key else - unpositioned += relativize(srcpos.source.file.toString()) + if(!seenAt("nopos")) unpositioned += relativize(srcpos.source.file.toString()) reporterWarnings.foreach(sawDiagnostic) diff --git a/tests/init/neg/early-promote2.scala b/tests/init/neg/early-promote2.scala deleted file mode 100644 index 514aed36a8ed..000000000000 --- a/tests/init/neg/early-promote2.scala +++ /dev/null @@ -1,6 +0,0 @@ -class M { - println(this) // error - foo() - private val a = 5 // error - def foo() = a -} diff --git a/tests/init/neg/simple1.scala b/tests/init/neg/simple1.scala deleted file mode 100644 index 93fba24008b9..000000000000 --- a/tests/init/neg/simple1.scala +++ /dev/null @@ -1,4 +0,0 @@ -class Foo { - val len = name.size - val name: String = "Jack" // error -} \ No newline at end of file diff --git a/tests/init/neg/soundness4.scala b/tests/init/neg/soundness4.scala deleted file mode 100644 index 308856b5e870..000000000000 --- a/tests/init/neg/soundness4.scala +++ /dev/null @@ -1,3 +0,0 @@ -class Foo { - val a : Foo = this.a.a // error -} \ No newline at end of file diff --git a/tests/init/neg/AbstractFile.scala b/tests/init/warn/AbstractFile.scala similarity index 64% rename from tests/init/neg/AbstractFile.scala rename to tests/init/warn/AbstractFile.scala index f4f38982608a..bb8abc6e8322 100644 --- a/tests/init/neg/AbstractFile.scala +++ b/tests/init/warn/AbstractFile.scala @@ -4,6 +4,6 @@ abstract class AbstractFile { } class RemoteFile(url: String) extends AbstractFile { - val localFile: String = s"${url.##}.tmp" // error: usage of `localFile` before it's initialized + val localFile: String = s"${url.##}.tmp" // warn: usage of `localFile` before it's initialized def name: String = localFile } diff --git a/tests/init/neg/alias.scala b/tests/init/warn/alias.scala similarity index 63% rename from tests/init/neg/alias.scala rename to tests/init/warn/alias.scala index 79367b36d0c5..8e9cb56b75c0 100644 --- a/tests/init/neg/alias.scala +++ b/tests/init/warn/alias.scala @@ -1,5 +1,5 @@ class Foo { val self = this val x = self.n - val n = 10 // error + val n = 10 // warn } \ No newline at end of file diff --git a/tests/init/neg/apply.scala b/tests/init/warn/apply.scala similarity index 85% rename from tests/init/neg/apply.scala rename to tests/init/warn/apply.scala index 2847115cc73c..fffa4c59968f 100644 --- a/tests/init/neg/apply.scala +++ b/tests/init/warn/apply.scala @@ -6,7 +6,7 @@ object A: class B: val a = A(this) - val a2 = A.foo(this) // error + val a2 = A.foo(this) // warn val a3 = A.bar(this) // test receiver is ThisRef @@ -20,7 +20,7 @@ object O: class B: val a = A(this) - val a2 = A.foo(this) // error + val a2 = A.foo(this) // warn val a3 = A.bar(this) val b = new B @@ -38,7 +38,7 @@ class M(n: N): class B: val a = A(this) - val a2 = A.foo(this) // error + val a2 = A.foo(this) // warn val a3 = A.bar(this) end M diff --git a/tests/init/neg/apply2.scala b/tests/init/warn/apply2.scala old mode 100755 new mode 100644 similarity index 75% rename from tests/init/neg/apply2.scala rename to tests/init/warn/apply2.scala index ea312ac6e8c7..efb083cfc863 --- a/tests/init/neg/apply2.scala +++ b/tests/init/warn/apply2.scala @@ -3,7 +3,7 @@ class O: println(n) class B: - val a = A(this) // error + val a = A(this) // warn val b = new B val n = 10 diff --git a/tests/init/neg/as-instance-of-cold-field-access.scala b/tests/init/warn/as-instance-of-cold-field-access.scala similarity index 78% rename from tests/init/neg/as-instance-of-cold-field-access.scala rename to tests/init/warn/as-instance-of-cold-field-access.scala index c8de99e96d0e..caef6f42f623 100644 --- a/tests/init/neg/as-instance-of-cold-field-access.scala +++ b/tests/init/warn/as-instance-of-cold-field-access.scala @@ -1,7 +1,7 @@ final class MyAsInstanceOfClass(o: MyAsInstanceOfClass) { val other: MyAsInstanceOfClass = { if (o.asInstanceOf[MyAsInstanceOfClass].oRef ne null) o - else new MyAsInstanceOfClass(this) // error + else new MyAsInstanceOfClass(this) // warn } val oRef = o } diff --git a/tests/init/neg/by-name-error.scala b/tests/init/warn/by-name-error.scala similarity index 79% rename from tests/init/neg/by-name-error.scala rename to tests/init/warn/by-name-error.scala index 960bbe9bf7e9..8d3a690c7cfd 100644 --- a/tests/init/neg/by-name-error.scala +++ b/tests/init/warn/by-name-error.scala @@ -8,6 +8,6 @@ object Foo { } class A { - val foo = implicitly[Foo] // error + val foo = implicitly[Foo] // warn assert(foo eq foo.next) } \ No newline at end of file diff --git a/tests/init/neg/closureLeak.scala b/tests/init/warn/closureLeak.scala similarity index 83% rename from tests/init/neg/closureLeak.scala rename to tests/init/warn/closureLeak.scala index ae7db5124028..3e4e1f88102b 100644 --- a/tests/init/neg/closureLeak.scala +++ b/tests/init/warn/closureLeak.scala @@ -8,6 +8,6 @@ class Outer { } val l: List[A] = List(new A(5), new A(10)) - l.foreach(a => a.addX(this)) // error + l.foreach(a => a.addX(this)) // warn val p = 10 } diff --git a/tests/init/neg/cold-insert-hot-array.scala b/tests/init/warn/cold-insert-hot-array.scala similarity index 84% rename from tests/init/neg/cold-insert-hot-array.scala rename to tests/init/warn/cold-insert-hot-array.scala index a11d92b2a265..a6c4b4aaebfd 100644 --- a/tests/init/neg/cold-insert-hot-array.scala +++ b/tests/init/warn/cold-insert-hot-array.scala @@ -3,7 +3,7 @@ object A: class B { var a = new Array[B](2) - A.foo(this, a) // error + A.foo(this, a) // warn println(a(0).i) val i = 99 } diff --git a/tests/init/neg/cycle-structure.scala b/tests/init/warn/cycle-structure.scala similarity index 64% rename from tests/init/neg/cycle-structure.scala rename to tests/init/warn/cycle-structure.scala index 1a02a31188b1..f3eb7560f414 100644 --- a/tests/init/neg/cycle-structure.scala +++ b/tests/init/warn/cycle-structure.scala @@ -1,11 +1,11 @@ case class A(b: B) { val x1 = b.x - val x = B(this) // error + val x = B(this) // warn val y = x.a } case class B(a: A) { val x1 = a.x - val x = A(this) // error + val x = A(this) // warn val h = x.b } diff --git a/tests/init/neg/cycle.scala b/tests/init/warn/cycle.scala similarity index 59% rename from tests/init/neg/cycle.scala rename to tests/init/warn/cycle.scala index 7d871795f0a2..f3733df03da4 100644 --- a/tests/init/neg/cycle.scala +++ b/tests/init/warn/cycle.scala @@ -1,11 +1,11 @@ class A(x: B) { println(x.b) - val a = new B(this) // error + val a = new B(this) // warn val d = a.b } class B(x: A) { println(x.a) - val b = new A(this) // error + val b = new A(this) // warn val d = b.a } \ No newline at end of file diff --git a/tests/init/neg/default-this.scala b/tests/init/warn/default-this.scala similarity index 89% rename from tests/init/neg/default-this.scala rename to tests/init/warn/default-this.scala index 1b0173fc134f..26b669bcbd40 100644 --- a/tests/init/neg/default-this.scala +++ b/tests/init/warn/default-this.scala @@ -6,7 +6,7 @@ class A { class B extends A { def updateThenCompare(c: Int): Boolean = { x = c - compare() // error + compare() // warn } val result = updateThenCompare(5) } diff --git a/tests/init/neg/early-promote.scala b/tests/init/warn/early-promote.scala similarity index 84% rename from tests/init/neg/early-promote.scala rename to tests/init/warn/early-promote.scala index fd226df347fb..1cd608d3f63b 100644 --- a/tests/init/neg/early-promote.scala +++ b/tests/init/warn/early-promote.scala @@ -24,7 +24,7 @@ class A { // checking A def c = new C } val b = new B() - println(b) // error: the checker simply issue warnings for objects that contain inner classes + println(b) // warn: the checker simply issue warnings for objects that contain inner classes val af = 42 } diff --git a/tests/init/warn/early-promote2.scala b/tests/init/warn/early-promote2.scala new file mode 100644 index 000000000000..8326aa851e21 --- /dev/null +++ b/tests/init/warn/early-promote2.scala @@ -0,0 +1,6 @@ +class M { + println(this) // warn + foo() + private val a = 5 // warn + def foo() = a +} diff --git a/tests/init/neg/early-promote3.scala b/tests/init/warn/early-promote3.scala similarity index 77% rename from tests/init/neg/early-promote3.scala rename to tests/init/warn/early-promote3.scala index ecb5bbedca69..a81b261d78ba 100644 --- a/tests/init/neg/early-promote3.scala +++ b/tests/init/warn/early-promote3.scala @@ -6,6 +6,6 @@ abstract class A { } class M extends A { - def bar() = promote(this) // error + def bar() = promote(this) // warn def promote(m: M) = m.foo() } diff --git a/tests/init/neg/early-promote4.scala b/tests/init/warn/early-promote4.scala similarity index 87% rename from tests/init/neg/early-promote4.scala rename to tests/init/warn/early-promote4.scala index 487a75c5516f..9d215b308200 100644 --- a/tests/init/neg/early-promote4.scala +++ b/tests/init/warn/early-promote4.scala @@ -16,5 +16,5 @@ class Outer { class Dummy { val m: Int = n + 4 - val n: Int = 10 // error + val n: Int = 10 // warn } diff --git a/tests/init/neg/early-promote5.scala b/tests/init/warn/early-promote5.scala similarity index 80% rename from tests/init/neg/early-promote5.scala rename to tests/init/warn/early-promote5.scala index 3f850b623ea3..bbcc63527fdf 100644 --- a/tests/init/neg/early-promote5.scala +++ b/tests/init/warn/early-promote5.scala @@ -14,11 +14,11 @@ class Outer { class Container { val o = new Outer - val m = new o.M(this) // error + val m = new o.M(this) // warn val s = "hello" } class Dummy { val m: Int = n + 4 - val n: Int = 10 // error + val n: Int = 10 // warn } diff --git a/tests/init/neg/escape1.scala b/tests/init/warn/escape1.scala similarity index 71% rename from tests/init/neg/escape1.scala rename to tests/init/warn/escape1.scala index 588f0933cfc3..ff0cb4ea3816 100644 --- a/tests/init/neg/escape1.scala +++ b/tests/init/warn/escape1.scala @@ -1,5 +1,5 @@ class Foo { - val a = Foo.bar(this) // error + val a = Foo.bar(this) // warn val b = "hello" } diff --git a/tests/init/neg/features-high-order.scala b/tests/init/warn/features-high-order.scala similarity index 81% rename from tests/init/neg/features-high-order.scala rename to tests/init/warn/features-high-order.scala index 60c15545cc14..6f758aeb6785 100644 --- a/tests/init/neg/features-high-order.scala +++ b/tests/init/warn/features-high-order.scala @@ -4,6 +4,6 @@ abstract class Parent { } class Child extends Parent { val a = f() - val b = "hello" // error + val b = "hello" // warn def message: String = b } diff --git a/tests/init/neg/features-linearization.scala b/tests/init/warn/features-linearization.scala similarity index 82% rename from tests/init/neg/features-linearization.scala rename to tests/init/warn/features-linearization.scala index 77d6a231d79a..d3c7b7b0db47 100644 --- a/tests/init/neg/features-linearization.scala +++ b/tests/init/warn/features-linearization.scala @@ -1,5 +1,5 @@ trait TA { - val x = "world" // error + val x = "world" // warn } trait TB { diff --git a/tests/init/neg/features-trees.scala b/tests/init/warn/features-trees.scala similarity index 76% rename from tests/init/neg/features-trees.scala rename to tests/init/warn/features-trees.scala index 867e6636bb12..32026785b3e5 100644 --- a/tests/init/neg/features-trees.scala +++ b/tests/init/warn/features-trees.scala @@ -2,5 +2,5 @@ class Trees { class ValDef { counter += 1 } class EmptyValDef extends ValDef val theEmptyValDef = new EmptyValDef - private var counter = 0 // error + private var counter = 0 // warn } diff --git a/tests/init/neg/final-fields.scala b/tests/init/warn/final-fields.scala similarity index 72% rename from tests/init/neg/final-fields.scala rename to tests/init/warn/final-fields.scala index 7154673058b7..878a1c44c49f 100644 --- a/tests/init/neg/final-fields.scala +++ b/tests/init/warn/final-fields.scala @@ -29,10 +29,10 @@ class Test1 extends U { } class Test extends T { - override final val f1 = /*super.f1*/ 1 + f2 // error - override final val f2 = 2 // error - override final val f3 = {println(3); 3} // error - override val f4 = f3 + 1 // error + override final val f1 = /*super.f1*/ 1 + f2 // warn + override final val f2 = 2 // warn + override final val f3 = {println(3); 3} // warn + override val f4 = f3 + 1 // warn def g: 3 = { println("g"); 3 } final val x = g + 1 diff --git a/tests/init/neg/flow2.scala b/tests/init/warn/flow2.scala similarity index 73% rename from tests/init/neg/flow2.scala rename to tests/init/warn/flow2.scala index a0c5f89601ee..3bb4fa110e50 100644 --- a/tests/init/neg/flow2.scala +++ b/tests/init/warn/flow2.scala @@ -1,6 +1,6 @@ class Foo { val len = list.size - val list = List(4, 6) // error + val list = List(4, 6) // warn lazy val len2 = list2.size // ok val list2 = List(4, 6) diff --git a/tests/init/neg/function-loop.scala b/tests/init/warn/function-loop.scala similarity index 78% rename from tests/init/neg/function-loop.scala rename to tests/init/warn/function-loop.scala index 12048860c3a6..981e8f8215c5 100644 --- a/tests/init/neg/function-loop.scala +++ b/tests/init/warn/function-loop.scala @@ -2,5 +2,5 @@ class Foo { val f: Int => Foo = (x: Int) => if x > 0 then f(x) else this f(10).n - val n = 10 // error + val n = 10 // warn } \ No newline at end of file diff --git a/tests/init/neg/function1.scala b/tests/init/warn/function1.scala similarity index 60% rename from tests/init/neg/function1.scala rename to tests/init/warn/function1.scala index 15427f3de750..29a139b39bd2 100644 --- a/tests/init/neg/function1.scala +++ b/tests/init/warn/function1.scala @@ -4,9 +4,9 @@ class Foo { val fun2: Int => Int = n => 1 + n + list.size fun2(5) - List(5, 9).map(n => 2 + n + list.size) // error + List(5, 9).map(n => 2 + n + list.size) // warn - final val list = List(1, 2, 3) // error + final val list = List(1, 2, 3) // warn List(5, 9).map(n => 3 + n + list.size) } \ No newline at end of file diff --git a/tests/init/neg/function10.scala b/tests/init/warn/function10.scala similarity index 53% rename from tests/init/neg/function10.scala rename to tests/init/warn/function10.scala index 3d8a72aaa1ea..22260bb5d622 100644 --- a/tests/init/neg/function10.scala +++ b/tests/init/warn/function10.scala @@ -1,5 +1,5 @@ class Base { self => - (0 to 10).foreach { i => // error + (0 to 10).foreach { i => // warn println(a) } diff --git a/tests/init/neg/function11.scala b/tests/init/warn/function11.scala similarity index 89% rename from tests/init/neg/function11.scala rename to tests/init/warn/function11.scala index 278192d003aa..a50f7937b562 100644 --- a/tests/init/neg/function11.scala +++ b/tests/init/warn/function11.scala @@ -1,7 +1,7 @@ final class Capture { private var m: Boolean = false - (0 to 10).foreach { i => // error + (0 to 10).foreach { i => // warn f() } diff --git a/tests/init/neg/function2.scala b/tests/init/warn/function2.scala similarity index 70% rename from tests/init/neg/function2.scala rename to tests/init/warn/function2.scala index 0a0f44e2744e..045eb8f4289e 100644 --- a/tests/init/neg/function2.scala +++ b/tests/init/warn/function2.scala @@ -2,5 +2,5 @@ final class Foo { def fun: Int => Int = n => n + x.size fun(5) - val x = "hello" // error + val x = "hello" // warn } \ No newline at end of file diff --git a/tests/init/neg/hybrid1.scala b/tests/init/warn/hybrid1.scala similarity index 87% rename from tests/init/neg/hybrid1.scala rename to tests/init/warn/hybrid1.scala index 94c7a43bfbcd..f1a4665954c9 100644 --- a/tests/init/neg/hybrid1.scala +++ b/tests/init/warn/hybrid1.scala @@ -17,5 +17,5 @@ class Y { new C - val n = 10 // error + val n = 10 // warn } diff --git a/tests/init/neg/hybrid2.scala b/tests/init/warn/hybrid2.scala similarity index 84% rename from tests/init/neg/hybrid2.scala rename to tests/init/warn/hybrid2.scala index a9f8246fd58d..6d901d810a64 100644 --- a/tests/init/neg/hybrid2.scala +++ b/tests/init/warn/hybrid2.scala @@ -15,5 +15,5 @@ class Y { val x = new X x.b.g - val n = 10 // error + val n = 10 // warn } diff --git a/tests/init/neg/hybrid4.scala b/tests/init/warn/hybrid4.scala similarity index 75% rename from tests/init/neg/hybrid4.scala rename to tests/init/warn/hybrid4.scala index 6243fbf2d5f4..8237d0e8244a 100644 --- a/tests/init/neg/hybrid4.scala +++ b/tests/init/warn/hybrid4.scala @@ -8,5 +8,5 @@ class Foo { } val bar: Bar = new Bar - val list = List(1, 2, 3) // error + val list = List(1, 2, 3) // warn } diff --git a/tests/init/neg/hybrid5.scala b/tests/init/warn/hybrid5.scala similarity index 86% rename from tests/init/neg/hybrid5.scala rename to tests/init/warn/hybrid5.scala index 54c781b8835d..4f7f5baad771 100644 --- a/tests/init/neg/hybrid5.scala +++ b/tests/init/warn/hybrid5.scala @@ -15,5 +15,5 @@ class Foo { def g = new Foo.this.Inner } - val list = List(1, 2, 3) // error + val list = List(1, 2, 3) // warn } diff --git a/tests/init/neg/hybrid6.scala b/tests/init/warn/hybrid6.scala similarity index 81% rename from tests/init/neg/hybrid6.scala rename to tests/init/warn/hybrid6.scala index bbecc16942e5..58cbaa76979f 100644 --- a/tests/init/neg/hybrid6.scala +++ b/tests/init/warn/hybrid6.scala @@ -11,5 +11,5 @@ class Foo { def g = list } - val list = List(1, 2, 3) // error + val list = List(1, 2, 3) // warn } diff --git a/tests/init/neg/i10549b.scala b/tests/init/warn/i10549b.scala similarity index 81% rename from tests/init/neg/i10549b.scala rename to tests/init/warn/i10549b.scala index 7353844b3927..b0dd305c7e27 100644 --- a/tests/init/neg/i10549b.scala +++ b/tests/init/warn/i10549b.scala @@ -4,6 +4,6 @@ class Wrap { abstract class E[+T] { def foo: T } object E { final val A: E[Nothing] = new E { def foo = ref } - val ref = qux(A) // error + val ref = qux(A) // warn } } diff --git a/tests/init/neg/i11572.scala b/tests/init/warn/i11572.scala similarity index 90% rename from tests/init/neg/i11572.scala rename to tests/init/warn/i11572.scala index 59fa3c1fbc43..2a32a8bdd540 100644 --- a/tests/init/neg/i11572.scala +++ b/tests/init/warn/i11572.scala @@ -5,7 +5,7 @@ class A { trait Bounded { type T >: Cov[Int] <: Cov[String] } - val t: Bounded = new Bounded { // error + val t: Bounded = new Bounded { // warn // Note: using this instead of t produces an error (as expected) override type T >: t.T <: t.T } diff --git a/tests/init/neg/i12544.scala b/tests/init/warn/i12544.scala similarity index 93% rename from tests/init/neg/i12544.scala rename to tests/init/warn/i12544.scala index 695e57e1d42a..283e0d62203b 100644 --- a/tests/init/neg/i12544.scala +++ b/tests/init/warn/i12544.scala @@ -15,7 +15,7 @@ class Outer: class B() { def foo() = n + 1 } def g(b: B): Int = b.foo() - g(new B()) // error + g(new B()) // warn val n: Int = 10 @main def main(): Unit = { diff --git a/tests/init/neg/i15363.scala b/tests/init/warn/i15363.scala similarity index 78% rename from tests/init/neg/i15363.scala rename to tests/init/warn/i15363.scala index 01a2bdfcf530..87ca08ea916e 100644 --- a/tests/init/neg/i15363.scala +++ b/tests/init/warn/i15363.scala @@ -1,6 +1,6 @@ class A: // should report one error here - val b = new B(this) // error + val b = new B(this) // warn val m = 10 val n = 20 diff --git a/tests/init/neg/i15459.scala b/tests/init/warn/i15459.scala similarity index 81% rename from tests/init/neg/i15459.scala rename to tests/init/warn/i15459.scala index 4d54f31f7af8..72779ef0c7c1 100644 --- a/tests/init/neg/i15459.scala +++ b/tests/init/warn/i15459.scala @@ -1,6 +1,6 @@ class Sup: val a = 10 - println(this) // error + println(this) // warn class Sub extends Sup: val b = 20 diff --git a/tests/init/neg/i4031.scala b/tests/init/warn/i4031.scala similarity index 78% rename from tests/init/neg/i4031.scala rename to tests/init/warn/i4031.scala index ed3f18ac931a..6cb49fcfd93c 100644 --- a/tests/init/neg/i4031.scala +++ b/tests/init/warn/i4031.scala @@ -1,7 +1,7 @@ class App { trait A { type L >: Any} def upcast(a: A, x: Any): a.L = x - val p: A { type L <: Nothing } = p // error + val p: A { type L <: Nothing } = p // warn def coerce(x: Any): Int = upcast(p, x) def main(args: Array[String]): Unit = { diff --git a/tests/init/neg/i4042.scala b/tests/init/warn/i4042.scala similarity index 87% rename from tests/init/neg/i4042.scala rename to tests/init/warn/i4042.scala index 58c884a5690d..284f97a352c9 100644 --- a/tests/init/neg/i4042.scala +++ b/tests/init/warn/i4042.scala @@ -5,7 +5,7 @@ object App { class T[A <: X](val a: A)(val value: a.R) - object O { val x : Y & X = x } // error + object O { val x : Y & X = x } // warn val a = new T[Y & X](O.x)(u) a.value diff --git a/tests/init/neg/i50.scala b/tests/init/warn/i50.scala similarity index 64% rename from tests/init/neg/i50.scala rename to tests/init/warn/i50.scala index 9131fb263f48..7c860bc007fa 100644 --- a/tests/init/neg/i50.scala +++ b/tests/init/warn/i50.scala @@ -1,5 +1,5 @@ class C[T] { val a: T = method def method = b - val b: T = a // error + val b: T = a // warn } \ No newline at end of file diff --git a/tests/init/neg/i5854.scala b/tests/init/warn/i5854.scala similarity index 63% rename from tests/init/neg/i5854.scala rename to tests/init/warn/i5854.scala index 05fa1033dd2c..60060394bdcd 100644 --- a/tests/init/neg/i5854.scala +++ b/tests/init/warn/i5854.scala @@ -1,5 +1,5 @@ class B { val a: String = (((1: Any): b.A): Nothing): String - val b: { type A >: Any <: Nothing } = loop() // error + val b: { type A >: Any <: Nothing } = loop() // warn def loop(): Nothing = loop() } diff --git a/tests/init/neg/inherit-non-hot.scala b/tests/init/warn/inherit-non-hot.scala similarity index 86% rename from tests/init/neg/inherit-non-hot.scala rename to tests/init/warn/inherit-non-hot.scala index 44be67351630..28520ea9c621 100644 --- a/tests/init/neg/inherit-non-hot.scala +++ b/tests/init/warn/inherit-non-hot.scala @@ -3,7 +3,7 @@ object Foo { abstract class A { var b: B = null def toB: B = - if b == null then b = new B(this) // error + if b == null then b = new B(this) // warn b } diff --git a/tests/init/neg/inlined-method.scala b/tests/init/warn/inlined-method.scala similarity index 70% rename from tests/init/neg/inlined-method.scala rename to tests/init/warn/inlined-method.scala index 4af473837f0f..e6ea86ba33c9 100644 --- a/tests/init/neg/inlined-method.scala +++ b/tests/init/warn/inlined-method.scala @@ -5,4 +5,4 @@ class InlineError { object Assertion: transparent inline def failAssert(inline message: => Any): Unit = - scala.runtime.Scala3RunTime.assertFailed(message) // error \ No newline at end of file + scala.runtime.Scala3RunTime.assertFailed(message) // warn \ No newline at end of file diff --git a/tests/init/neg/inner-case.scala b/tests/init/warn/inner-case.scala similarity index 82% rename from tests/init/neg/inner-case.scala rename to tests/init/warn/inner-case.scala index 20a9b1d2684f..317d77376aa9 100644 --- a/tests/init/neg/inner-case.scala +++ b/tests/init/warn/inner-case.scala @@ -4,7 +4,7 @@ class Foo { } val a = Inner(5) // ok - println(a) // error + println(a) // warn var count = 0 println(a) // ok diff --git a/tests/init/neg/inner-first.scala b/tests/init/warn/inner-first.scala similarity index 69% rename from tests/init/neg/inner-first.scala rename to tests/init/warn/inner-first.scala index cd7b28a30b62..be3c7d824dc5 100644 --- a/tests/init/neg/inner-first.scala +++ b/tests/init/warn/inner-first.scala @@ -1,6 +1,6 @@ class A: class B: - println(this) // error + println(this) // warn val n = 10 def foo() = println(m) new B diff --git a/tests/init/neg/inner-loop.scala b/tests/init/warn/inner-loop.scala similarity index 88% rename from tests/init/neg/inner-loop.scala rename to tests/init/warn/inner-loop.scala index c6d5c615580c..8b63eb9507dc 100644 --- a/tests/init/neg/inner-loop.scala +++ b/tests/init/warn/inner-loop.scala @@ -3,7 +3,7 @@ class Outer { outer => val x = 5 + outer.n } val inner = new Inner - val n = 6 // error + val n = 6 // warn } class Outer2 { outer => @@ -28,7 +28,7 @@ class Test { // If we change policy to check more eagerly, // the check has to avoid loop here. - println(outer) // error + println(outer) // warn val m = 10 } \ No newline at end of file diff --git a/tests/init/neg/inner-new.scala b/tests/init/warn/inner-new.scala similarity index 80% rename from tests/init/neg/inner-new.scala rename to tests/init/warn/inner-new.scala index d09dc5193dbf..2ecaf5e544e1 100644 --- a/tests/init/neg/inner-new.scala +++ b/tests/init/warn/inner-new.scala @@ -4,7 +4,7 @@ class Foo { } val a = new Inner // ok - println(a) // error + println(a) // warn var count = 0 println(a) // ok diff --git a/tests/init/neg/inner-pat_iuli.scala b/tests/init/warn/inner-pat_iuli.scala similarity index 92% rename from tests/init/neg/inner-pat_iuli.scala rename to tests/init/warn/inner-pat_iuli.scala index e5010cca98ec..bd84fee43d97 100644 --- a/tests/init/neg/inner-pat_iuli.scala +++ b/tests/init/warn/inner-pat_iuli.scala @@ -20,5 +20,5 @@ trait Blox { self: MyCodes => class MyCodes extends AnyRef with Ops with Blox { val a = b - val b: Int = 10 // error + val b: Int = 10 // warn } diff --git a/tests/init/neg/inner1.scala b/tests/init/warn/inner1.scala similarity index 80% rename from tests/init/neg/inner1.scala rename to tests/init/warn/inner1.scala index d39c3ba2ac77..9220eda882cf 100644 --- a/tests/init/neg/inner1.scala +++ b/tests/init/warn/inner1.scala @@ -1,7 +1,7 @@ class Foo { new this.Inner - val list = List(1, 2, 3) // error, as Inner access `this.list` + val list = List(1, 2, 3) // warn, as Inner access `this.list` val inner: Inner = new this.Inner // ok, `list` is instantiated lib.escape(inner) // ok, can promote inner early diff --git a/tests/init/neg/inner11.scala b/tests/init/warn/inner11.scala similarity index 93% rename from tests/init/neg/inner11.scala rename to tests/init/warn/inner11.scala index 04098be8a3fd..2ea6d25f5d6f 100644 --- a/tests/init/neg/inner11.scala +++ b/tests/init/warn/inner11.scala @@ -12,7 +12,7 @@ object NameKinds { class ClassifiedNameKind(tag: Int, val infoString: String) extends NameKind(tag) { type ThisInfo = Info val info: Info = new Info - println(info.kind) // error + println(info.kind) // warn val n = 10 } } diff --git a/tests/init/neg/inner15.scala b/tests/init/warn/inner15.scala similarity index 84% rename from tests/init/neg/inner15.scala rename to tests/init/warn/inner15.scala index 59d1daac404f..7c01cd8275d7 100644 --- a/tests/init/neg/inner15.scala +++ b/tests/init/warn/inner15.scala @@ -15,5 +15,5 @@ class B extends A { new Inner1 new Inner2 - override val x = "world" // error + override val x = "world" // warn } \ No newline at end of file diff --git a/tests/init/neg/inner16.scala b/tests/init/warn/inner16.scala similarity index 87% rename from tests/init/neg/inner16.scala rename to tests/init/warn/inner16.scala index 61271396a074..c49cba8a88be 100644 --- a/tests/init/neg/inner16.scala +++ b/tests/init/warn/inner16.scala @@ -13,5 +13,5 @@ class A { val inner = new Inner val b = new O.B - val y = 10 // error + val y = 10 // warn } \ No newline at end of file diff --git a/tests/init/neg/inner17.scala b/tests/init/warn/inner17.scala similarity index 78% rename from tests/init/neg/inner17.scala rename to tests/init/warn/inner17.scala index 756278cd5130..4daad38ea36b 100644 --- a/tests/init/neg/inner17.scala +++ b/tests/init/warn/inner17.scala @@ -9,5 +9,5 @@ class A { } class C extends A { - override val f: Int = 20 // error + override val f: Int = 20 // warn } \ No newline at end of file diff --git a/tests/init/neg/inner19.scala b/tests/init/warn/inner19.scala similarity index 79% rename from tests/init/neg/inner19.scala rename to tests/init/warn/inner19.scala index 2e502eddc24c..91cf406dbc6a 100644 --- a/tests/init/neg/inner19.scala +++ b/tests/init/warn/inner19.scala @@ -15,5 +15,5 @@ class A { class B extends A { println((new O.B).f) O.C(4) - override val n = 50 // error because line 16 + override val n = 50 // warn because line 16 } \ No newline at end of file diff --git a/tests/init/neg/inner20.scala b/tests/init/warn/inner20.scala similarity index 84% rename from tests/init/neg/inner20.scala rename to tests/init/warn/inner20.scala index 1553e09eeeb0..2a868f8b88f5 100644 --- a/tests/init/neg/inner20.scala +++ b/tests/init/warn/inner20.scala @@ -14,5 +14,5 @@ class A { class B extends A { val o = new O println((new o.B).f) - override val n = 50 // error + override val n = 50 // warn } \ No newline at end of file diff --git a/tests/init/neg/inner21.scala b/tests/init/warn/inner21.scala similarity index 71% rename from tests/init/neg/inner21.scala rename to tests/init/warn/inner21.scala index c2277163acc3..232de8fbd0cc 100644 --- a/tests/init/neg/inner21.scala +++ b/tests/init/warn/inner21.scala @@ -8,7 +8,7 @@ class X { A.foo A.bar - val name = "jack" // error + val name = "jack" // warn } @@ -22,5 +22,5 @@ class Y { (new A).foo (new A).bar - val name = "jack" // error + val name = "jack" // warn } \ No newline at end of file diff --git a/tests/init/neg/inner22.scala b/tests/init/warn/inner22.scala similarity index 92% rename from tests/init/neg/inner22.scala rename to tests/init/warn/inner22.scala index aa5a381f2d49..055a9d9bed7d 100644 --- a/tests/init/neg/inner22.scala +++ b/tests/init/warn/inner22.scala @@ -28,5 +28,5 @@ class D { new C - val x = 10 // error + val x = 10 // warn } \ No newline at end of file diff --git a/tests/init/neg/inner23.scala b/tests/init/warn/inner23.scala similarity index 77% rename from tests/init/neg/inner23.scala rename to tests/init/warn/inner23.scala index 5d373c649ce2..a5985a8d805c 100644 --- a/tests/init/neg/inner23.scala +++ b/tests/init/warn/inner23.scala @@ -9,5 +9,5 @@ class Trees { } val theEmptyValDef = new EmptyValDef - val name = "hello" // error + val name = "hello" // warn } diff --git a/tests/init/neg/inner24.scala b/tests/init/warn/inner24.scala similarity index 84% rename from tests/init/neg/inner24.scala rename to tests/init/warn/inner24.scala index f8a60c1bb311..3c28546b10cc 100644 --- a/tests/init/neg/inner24.scala +++ b/tests/init/warn/inner24.scala @@ -14,5 +14,5 @@ class Bar extends Foo { val b = new B override def foo(x: Int) = x + id - val id = 100 // error + val id = 100 // warn } \ No newline at end of file diff --git a/tests/init/neg/inner25.scala b/tests/init/warn/inner25.scala similarity index 91% rename from tests/init/neg/inner25.scala rename to tests/init/warn/inner25.scala index 8cf99539b849..a9538dee6462 100644 --- a/tests/init/neg/inner25.scala +++ b/tests/init/warn/inner25.scala @@ -8,7 +8,7 @@ class A[K, V] { self => } } - println(new O) // error + println(new O) // warn val a = 10 } \ No newline at end of file diff --git a/tests/init/neg/inner29.scala b/tests/init/warn/inner29.scala similarity index 83% rename from tests/init/neg/inner29.scala rename to tests/init/warn/inner29.scala index 740352db1e4e..03350a5266b8 100644 --- a/tests/init/neg/inner29.scala +++ b/tests/init/warn/inner29.scala @@ -15,7 +15,7 @@ class C extends B(5) { override def f: Int = x } - val a = new E // error: init too late + val a = new E // warn: init too late val x = 10 } \ No newline at end of file diff --git a/tests/init/neg/inner30.scala b/tests/init/warn/inner30.scala similarity index 92% rename from tests/init/neg/inner30.scala rename to tests/init/warn/inner30.scala index 87d8888437da..d9b1eec3d6b1 100644 --- a/tests/init/neg/inner30.scala +++ b/tests/init/warn/inner30.scala @@ -17,5 +17,5 @@ class Scanners { } val m: Int = n * 2 - val n = 10 // error + val n = 10 // warn } \ No newline at end of file diff --git a/tests/init/neg/inner4.scala b/tests/init/warn/inner4.scala similarity index 77% rename from tests/init/neg/inner4.scala rename to tests/init/warn/inner4.scala index 5fc4d2b9e053..66a39da03909 100644 --- a/tests/init/neg/inner4.scala +++ b/tests/init/warn/inner4.scala @@ -6,5 +6,5 @@ class Foo(val foo1: Foo) { new this.Inner new foo1.Inner - val name = "hello" // error + val name = "hello" // warn } diff --git a/tests/init/neg/inner5.scala b/tests/init/warn/inner5.scala similarity index 76% rename from tests/init/neg/inner5.scala rename to tests/init/warn/inner5.scala index 20f4aa1bdaeb..f91573e98cb6 100644 --- a/tests/init/neg/inner5.scala +++ b/tests/init/warn/inner5.scala @@ -4,7 +4,7 @@ class Foo { } new B - val a = 3 // error + val a = 3 // warn def foo(x: Int) = a + x } \ No newline at end of file diff --git a/tests/init/neg/inner6.scala b/tests/init/warn/inner6.scala similarity index 91% rename from tests/init/neg/inner6.scala rename to tests/init/warn/inner6.scala index 42b68fe2d8ea..7f0436dc6924 100644 --- a/tests/init/neg/inner6.scala +++ b/tests/init/warn/inner6.scala @@ -18,6 +18,6 @@ class Child extends Parent { new InnerA new InnerB - val x = 10 // error + val x = 10 // warn override def foo: Int = x * x } diff --git a/tests/init/neg/inner7.scala b/tests/init/warn/inner7.scala similarity index 81% rename from tests/init/neg/inner7.scala rename to tests/init/warn/inner7.scala index bdac38cc31d8..5e0df53f0888 100644 --- a/tests/init/neg/inner7.scala +++ b/tests/init/warn/inner7.scala @@ -11,6 +11,6 @@ class Child extends Parent { class InnerA extends Inner1 new InnerA - override val list = List(4, 5) // error + override val list = List(4, 5) // warn override def foo: Int = list.size } diff --git a/tests/init/neg/inner9.scala b/tests/init/warn/inner9.scala similarity index 79% rename from tests/init/neg/inner9.scala rename to tests/init/warn/inner9.scala index b572c8cb49d3..64e83ead0b07 100644 --- a/tests/init/neg/inner9.scala +++ b/tests/init/warn/inner9.scala @@ -1,5 +1,5 @@ class Outer: - val flags = new Flags // error + val flags = new Flags // warn class Flags { class Inner { @@ -9,7 +9,7 @@ class Outer: new flags.Inner val a = this.b + 3 - val b = 5 // error + val b = 5 // warn } class Flags2 { diff --git a/tests/init/neg/insert-cold-subtype-to-array.scala b/tests/init/warn/insert-cold-subtype-to-array.scala similarity index 84% rename from tests/init/neg/insert-cold-subtype-to-array.scala rename to tests/init/warn/insert-cold-subtype-to-array.scala index 82eee1935a95..6f4bf9bca73e 100644 --- a/tests/init/neg/insert-cold-subtype-to-array.scala +++ b/tests/init/warn/insert-cold-subtype-to-array.scala @@ -3,6 +3,6 @@ object A: class B: var a = new Array[B](2) - A.foo(this, a) // error + A.foo(this, a) // warn println(a(0).i) val i = 99 \ No newline at end of file diff --git a/tests/init/neg/java1.scala b/tests/init/warn/java1.scala similarity index 91% rename from tests/init/neg/java1.scala rename to tests/init/warn/java1.scala index 1eff09cb6ff1..36044413d2ea 100644 --- a/tests/init/neg/java1.scala +++ b/tests/init/warn/java1.scala @@ -8,4 +8,4 @@ class A extends Spliterator.OfDouble: def tryAdvance(x$0: java.util.function.DoubleConsumer): Boolean = false val m = n + 1 - val n = 10 // error + val n = 10 // warn diff --git a/tests/init/neg/lazy.scala b/tests/init/warn/lazy.scala similarity index 69% rename from tests/init/neg/lazy.scala rename to tests/init/warn/lazy.scala index 0f3047bc0d1b..a895714b0f9a 100644 --- a/tests/init/neg/lazy.scala +++ b/tests/init/warn/lazy.scala @@ -1,11 +1,11 @@ class Foo { val len = list.size - val list = List(4, 6) // error + val list = List(4, 6) // warn lazy val len2 = list2.size // ok val list2 = List(4, 6) lazy val len3 = name.size val len4 = len3 + 4 - val name = "hello" // error + val name = "hello" // warn } diff --git a/tests/init/neg/lazylist2.scala b/tests/init/warn/lazylist2.scala similarity index 89% rename from tests/init/neg/lazylist2.scala rename to tests/init/warn/lazylist2.scala index 18072676fa4c..618364f49a98 100644 --- a/tests/init/neg/lazylist2.scala +++ b/tests/init/warn/lazylist2.scala @@ -26,7 +26,7 @@ final class Test1 { a.head // ok b.head // ok - val x: LazyList[Int] = 5 #:: y // error + val x: LazyList[Int] = 5 #:: y // warn val y: LazyList[Int] = 10 #:: x } @@ -37,7 +37,7 @@ final class Test2 { } final class Test3 { - val a: LazyList[Int] = n #:: (a: @unchecked) // error + val a: LazyList[Int] = n #:: (a: @unchecked) // warn a.head val n: Int = 20 } \ No newline at end of file diff --git a/tests/init/neg/leak-warm.scala b/tests/init/warn/leak-warm.scala similarity index 91% rename from tests/init/neg/leak-warm.scala rename to tests/init/warn/leak-warm.scala index 9bfbe2e4f285..5278b67e7eac 100644 --- a/tests/init/neg/leak-warm.scala +++ b/tests/init/warn/leak-warm.scala @@ -16,5 +16,5 @@ class leakWarm { val c = new C(1, 2) val d = new D(3, 4) val l: List[A] = List(c, d) - val l2 = l.map(_.m()) // error + val l2 = l.map(_.m()) // warn } diff --git a/tests/init/neg/local-class.scala b/tests/init/warn/local-class.scala similarity index 84% rename from tests/init/neg/local-class.scala rename to tests/init/warn/local-class.scala index 20e77912dce8..14f203a738c3 100644 --- a/tests/init/neg/local-class.scala +++ b/tests/init/warn/local-class.scala @@ -12,5 +12,5 @@ class Outer { foo - val n = 10 // error + val n = 10 // warn } diff --git a/tests/init/neg/override1.scala b/tests/init/warn/override1.scala similarity index 84% rename from tests/init/neg/override1.scala rename to tests/init/warn/override1.scala index c9c9fed3ecd8..b247470c19d5 100644 --- a/tests/init/neg/override1.scala +++ b/tests/init/warn/override1.scala @@ -15,6 +15,6 @@ class Qux(x: Int) extends Bar { } class Yun extends Bar { - override val x: Int = 10 // error + override val x: Int = 10 // warn def foo(n: Int) = x + n } diff --git a/tests/init/neg/override10.scala b/tests/init/warn/override10.scala similarity index 75% rename from tests/init/neg/override10.scala rename to tests/init/warn/override10.scala index 6b8b0e7101db..0c49d7c63113 100644 --- a/tests/init/neg/override10.scala +++ b/tests/init/warn/override10.scala @@ -5,5 +5,5 @@ trait Foo { class Bar extends Foo { f() - val message = "hello" // error + val message = "hello" // warn } \ No newline at end of file diff --git a/tests/init/neg/override14.scala b/tests/init/warn/override14.scala similarity index 76% rename from tests/init/neg/override14.scala rename to tests/init/warn/override14.scala index 451a12087103..0d773e61f9b2 100644 --- a/tests/init/neg/override14.scala +++ b/tests/init/warn/override14.scala @@ -1,5 +1,5 @@ abstract class A { - val x = f(this) // error + val x = f(this) // warn val y = 10 def f(a: A): Int diff --git a/tests/init/neg/override15.scala b/tests/init/warn/override15.scala similarity index 81% rename from tests/init/neg/override15.scala rename to tests/init/warn/override15.scala index 0f22430cf6a6..ca3e32abb35e 100644 --- a/tests/init/neg/override15.scala +++ b/tests/init/warn/override15.scala @@ -1,6 +1,6 @@ abstract class A { val g = (n: Int) => n + y - val x: Int = f(g) // error + val x: Int = f(g) // warn val y: Int = 10 def f(m: Int => Int): Int diff --git a/tests/init/neg/override17.scala b/tests/init/warn/override17.scala similarity index 76% rename from tests/init/neg/override17.scala rename to tests/init/warn/override17.scala index 72bd8db9a246..cbeaaed37bea 100644 --- a/tests/init/neg/override17.scala +++ b/tests/init/warn/override17.scala @@ -3,7 +3,7 @@ class A { self : B => } trait B { - val x = 10 // error + val x = 10 // warn } class C extends A with B diff --git a/tests/init/neg/override18.scala b/tests/init/warn/override18.scala similarity index 88% rename from tests/init/neg/override18.scala rename to tests/init/warn/override18.scala index 61edaf6d8c8f..3c2ca3e7af5d 100644 --- a/tests/init/neg/override18.scala +++ b/tests/init/warn/override18.scala @@ -10,7 +10,7 @@ class B extends A { class C extends A { val x = f - val y = x // error + val y = x // warn def f: Int = y } diff --git a/tests/init/neg/override19.scala b/tests/init/warn/override19.scala similarity index 79% rename from tests/init/neg/override19.scala rename to tests/init/warn/override19.scala index 8e1f6a832323..61d17bb93597 100644 --- a/tests/init/neg/override19.scala +++ b/tests/init/warn/override19.scala @@ -5,6 +5,6 @@ abstract class A extends Product { case class B(x: Int, y: String) extends A case class C(x: Int) extends A { - val y = 10 // error + val y = 10 // warn def productArity: Int = y } \ No newline at end of file diff --git a/tests/init/neg/override2.scala b/tests/init/warn/override2.scala similarity index 89% rename from tests/init/neg/override2.scala rename to tests/init/warn/override2.scala index f9964f60ad29..3adae93c23c9 100644 --- a/tests/init/neg/override2.scala +++ b/tests/init/warn/override2.scala @@ -8,7 +8,7 @@ trait Foo { } class Bar extends Foo { - val y = "hello" // error + val y = "hello" // warn foo(5) bar(10) diff --git a/tests/init/neg/override20.scala b/tests/init/warn/override20.scala similarity index 75% rename from tests/init/neg/override20.scala rename to tests/init/warn/override20.scala index 65ece64c6020..4f1f7b452f75 100644 --- a/tests/init/neg/override20.scala +++ b/tests/init/warn/override20.scala @@ -2,7 +2,7 @@ class A { self : B => val y = f } -trait B(x: Int) { // error +trait B(x: Int) { // warn def f: Int = x } diff --git a/tests/init/neg/override21.scala b/tests/init/warn/override21.scala similarity index 86% rename from tests/init/neg/override21.scala rename to tests/init/warn/override21.scala index 332ce702a9fc..84c319949cb7 100644 --- a/tests/init/neg/override21.scala +++ b/tests/init/warn/override21.scala @@ -10,7 +10,7 @@ class Child extends Parent { this.z val m = this.x - val y = "hello" // error + val y = "hello" // warn def bar = y.size } \ No newline at end of file diff --git a/tests/init/neg/override22.scala b/tests/init/warn/override22.scala similarity index 87% rename from tests/init/neg/override22.scala rename to tests/init/warn/override22.scala index 7de6f03aa837..f7fc1b312e4e 100644 --- a/tests/init/neg/override22.scala +++ b/tests/init/warn/override22.scala @@ -9,7 +9,7 @@ class Child extends Parent { val y = "hello" this.foo - val m = this.x // error + val m = this.x // warn this.z def bar = m.size + 6 diff --git a/tests/init/neg/override23.scala b/tests/init/warn/override23.scala similarity index 87% rename from tests/init/neg/override23.scala rename to tests/init/warn/override23.scala index 3ada767bfafc..2af45c953ae5 100644 --- a/tests/init/neg/override23.scala +++ b/tests/init/warn/override23.scala @@ -10,7 +10,7 @@ class Child(o: String) extends Parent(o) { this.foo this.z - val y = "hello" // error + val y = "hello" // warn def bar = y.size } \ No newline at end of file diff --git a/tests/init/neg/override24.scala b/tests/init/warn/override24.scala similarity index 91% rename from tests/init/neg/override24.scala rename to tests/init/warn/override24.scala index 9adfac27bb02..feaa07396755 100644 --- a/tests/init/neg/override24.scala +++ b/tests/init/warn/override24.scala @@ -15,7 +15,7 @@ class Bar extends Foo { foo(4) - val name = "bar" // error + val name = "bar" // warn foo(4) } \ No newline at end of file diff --git a/tests/init/neg/override25.scala b/tests/init/warn/override25.scala similarity index 85% rename from tests/init/neg/override25.scala rename to tests/init/warn/override25.scala index 9554b4296a9f..e5d5d7f8e34f 100644 --- a/tests/init/neg/override25.scala +++ b/tests/init/warn/override25.scala @@ -1,4 +1,4 @@ -trait Foo(x: Int) { // error +trait Foo(x: Int) { // warn def name: String = "hello" def f: Int = x diff --git a/tests/init/neg/override26.scala b/tests/init/warn/override26.scala similarity index 85% rename from tests/init/neg/override26.scala rename to tests/init/warn/override26.scala index 37e83898bfcc..98a30477ee74 100644 --- a/tests/init/neg/override26.scala +++ b/tests/init/warn/override26.scala @@ -11,6 +11,6 @@ trait Bar { this: Foo => } class Qux extends Foo with Bar { - val x = "hello" // error + val x = "hello" // warn def title = x } diff --git a/tests/init/neg/override27.scala b/tests/init/warn/override27.scala similarity index 73% rename from tests/init/neg/override27.scala rename to tests/init/warn/override27.scala index 4b3a79ac233b..ae9ffe6ad63f 100644 --- a/tests/init/neg/override27.scala +++ b/tests/init/warn/override27.scala @@ -1,6 +1,6 @@ abstract class Base { def f: Int - val a = f // error + val a = f // warn } class Derived extends Base { @@ -10,7 +10,7 @@ class Derived extends Base { } class Derived2 extends Base { - val b = 30 // error + val b = 30 // warn def f = g def g: Int = b + a diff --git a/tests/init/neg/override28.scala b/tests/init/warn/override28.scala similarity index 72% rename from tests/init/neg/override28.scala rename to tests/init/warn/override28.scala index 8e77f8acb3ba..60ba0bff6c76 100644 --- a/tests/init/neg/override28.scala +++ b/tests/init/warn/override28.scala @@ -6,5 +6,5 @@ abstract class Base(val x: Int) { class C(x: Int) extends Base(x) { - val d = f // error + val d = f // warn } \ No newline at end of file diff --git a/tests/init/neg/override29.scala b/tests/init/warn/override29.scala similarity index 78% rename from tests/init/neg/override29.scala rename to tests/init/warn/override29.scala index e0070eb10218..5c640e2fcc0e 100644 --- a/tests/init/neg/override29.scala +++ b/tests/init/warn/override29.scala @@ -1,5 +1,5 @@ trait A { - var a = 20 // error + var a = 20 // warn def f: Int = a } diff --git a/tests/init/neg/override3.scala b/tests/init/warn/override3.scala similarity index 91% rename from tests/init/neg/override3.scala rename to tests/init/warn/override3.scala index 51759320e1b5..74fae84a547a 100644 --- a/tests/init/neg/override3.scala +++ b/tests/init/warn/override3.scala @@ -13,7 +13,7 @@ class Bar1 extends Foo { } class Qux extends Bar1 { - val u = "hello" // error + val u = "hello" // warn override def foo(n: Int) = u + "world" } diff --git a/tests/init/neg/override30.scala b/tests/init/warn/override30.scala similarity index 79% rename from tests/init/neg/override30.scala rename to tests/init/warn/override30.scala index adb4c2e00d2b..1677574130d4 100644 --- a/tests/init/neg/override30.scala +++ b/tests/init/warn/override30.scala @@ -10,6 +10,6 @@ class Bar extends Foo { } class Qux extends Bar { - val a = 30 // error + val a = 30 // warn override def f = a } \ No newline at end of file diff --git a/tests/init/neg/override31.scala b/tests/init/warn/override31.scala similarity index 84% rename from tests/init/neg/override31.scala rename to tests/init/warn/override31.scala index d902f4a6dc54..baffab3ad08e 100644 --- a/tests/init/neg/override31.scala +++ b/tests/init/warn/override31.scala @@ -11,5 +11,5 @@ class Bar extends Foo { class Qux extends Bar { init override def f = a - private val a = 30 // error + private val a = 30 // warn } \ No newline at end of file diff --git a/tests/init/neg/override32.scala b/tests/init/warn/override32.scala similarity index 80% rename from tests/init/neg/override32.scala rename to tests/init/warn/override32.scala index 09970a9bd392..b9a4e7eae178 100644 --- a/tests/init/neg/override32.scala +++ b/tests/init/warn/override32.scala @@ -6,7 +6,7 @@ trait Foo { } trait Bar { - final val m: String = "hello" // error + final val m: String = "hello" // warn def foo(n: Int) = m } diff --git a/tests/init/neg/override33.scala b/tests/init/warn/override33.scala similarity index 85% rename from tests/init/neg/override33.scala rename to tests/init/warn/override33.scala index b093dc570f04..04d27be6777c 100644 --- a/tests/init/neg/override33.scala +++ b/tests/init/warn/override33.scala @@ -8,7 +8,7 @@ abstract class Foo { } trait Bar { - val name: String = "Foo" // error + val name: String = "Foo" // warn def title: String = name } diff --git a/tests/init/neg/override34.scala b/tests/init/warn/override34.scala similarity index 79% rename from tests/init/neg/override34.scala rename to tests/init/warn/override34.scala index 6cf3e3cf4b4d..e4a21e861eb2 100644 --- a/tests/init/neg/override34.scala +++ b/tests/init/warn/override34.scala @@ -5,7 +5,7 @@ abstract class Foo { } trait Bar { - val name: String = "Foo" // error + val name: String = "Foo" // warn } class Qux extends Foo with Bar { diff --git a/tests/init/neg/override35.scala b/tests/init/warn/override35.scala similarity index 77% rename from tests/init/neg/override35.scala rename to tests/init/warn/override35.scala index 958ed1ff9d2f..1769f7b3a361 100644 --- a/tests/init/neg/override35.scala +++ b/tests/init/warn/override35.scala @@ -10,6 +10,6 @@ trait Bar { } class Qux extends Foo with Bar { - private val x = 30 // error + private val x = 30 // warn override def f = x } \ No newline at end of file diff --git a/tests/init/neg/override36.scala b/tests/init/warn/override36.scala similarity index 87% rename from tests/init/neg/override36.scala rename to tests/init/warn/override36.scala index 6df0891d5b27..2fedf7ff6bcb 100644 --- a/tests/init/neg/override36.scala +++ b/tests/init/warn/override36.scala @@ -14,5 +14,5 @@ class Bar extends Foo { class Qux extends Bar { init override def h = a - private val a = 30 // error + private val a = 30 // warn } \ No newline at end of file diff --git a/tests/init/neg/override38.scala b/tests/init/warn/override38.scala similarity index 77% rename from tests/init/neg/override38.scala rename to tests/init/warn/override38.scala index dd47b0438980..feb962cd5029 100644 --- a/tests/init/neg/override38.scala +++ b/tests/init/warn/override38.scala @@ -1,7 +1,7 @@ abstract class A { def f: Int - (1 to 10).foreach { i => // error + (1 to 10).foreach { i => // warn f } diff --git a/tests/init/neg/override39.scala b/tests/init/warn/override39.scala similarity index 82% rename from tests/init/neg/override39.scala rename to tests/init/warn/override39.scala index 723e71554da2..34f25cee2022 100644 --- a/tests/init/neg/override39.scala +++ b/tests/init/warn/override39.scala @@ -6,6 +6,6 @@ abstract class Parent extends Product { } case class Child(x: Int) extends Parent { - val m = 10 // error + val m = 10 // warn def productArity: Int = m } \ No newline at end of file diff --git a/tests/init/neg/override4.scala b/tests/init/warn/override4.scala similarity index 82% rename from tests/init/neg/override4.scala rename to tests/init/warn/override4.scala index 1489e1c2508b..1a63d2b3b59b 100644 --- a/tests/init/neg/override4.scala +++ b/tests/init/warn/override4.scala @@ -12,7 +12,7 @@ class Bar extends Foo { } class Bar2 extends Bar { - val mymap: mutable.Map[Int, String] = mutable.Map.empty // error + val mymap: mutable.Map[Int, String] = mutable.Map.empty // warn override def enter(k: Int, v: String) = { mymap(k) = v diff --git a/tests/init/neg/override40.scala b/tests/init/warn/override40.scala similarity index 80% rename from tests/init/neg/override40.scala rename to tests/init/warn/override40.scala index 2f081a9de30b..305210158d54 100644 --- a/tests/init/neg/override40.scala +++ b/tests/init/warn/override40.scala @@ -6,5 +6,5 @@ abstract class A { class B extends A { this.getClass f - val a = 20 // error + val a = 20 // warn } \ No newline at end of file diff --git a/tests/init/neg/override41.scala b/tests/init/warn/override41.scala similarity index 82% rename from tests/init/neg/override41.scala rename to tests/init/warn/override41.scala index bfd5bc18f3d6..6cb58ae326aa 100644 --- a/tests/init/neg/override41.scala +++ b/tests/init/warn/override41.scala @@ -11,5 +11,5 @@ class Child extends Parent { def show = println(name) - val name = "child" // error + val name = "child" // warn } \ No newline at end of file diff --git a/tests/init/neg/override42.scala b/tests/init/warn/override42.scala similarity index 81% rename from tests/init/neg/override42.scala rename to tests/init/warn/override42.scala index b4a53b977852..39a4d5097215 100644 --- a/tests/init/neg/override42.scala +++ b/tests/init/warn/override42.scala @@ -12,5 +12,5 @@ class Bar { def show = println(name) - val name = "child" // error + val name = "child" // warn } diff --git a/tests/init/neg/override43.scala b/tests/init/warn/override43.scala similarity index 83% rename from tests/init/neg/override43.scala rename to tests/init/warn/override43.scala index 2d55742c3ecd..ab8ec95133d6 100644 --- a/tests/init/neg/override43.scala +++ b/tests/init/warn/override43.scala @@ -8,6 +8,6 @@ final class Child extends Parent { def g() = foo() g() + b - val b = 10 // error + val b = 10 // warn g() } \ No newline at end of file diff --git a/tests/init/neg/override44.scala b/tests/init/warn/override44.scala similarity index 83% rename from tests/init/neg/override44.scala rename to tests/init/warn/override44.scala index ed7a0ae30b7a..50e7691d6fee 100644 --- a/tests/init/neg/override44.scala +++ b/tests/init/warn/override44.scala @@ -8,6 +8,6 @@ class Child extends Parent { def g() = foo() g() + b - val b = 10 // error + val b = 10 // warn g() } \ No newline at end of file diff --git a/tests/init/neg/override45.scala b/tests/init/warn/override45.scala similarity index 81% rename from tests/init/neg/override45.scala rename to tests/init/warn/override45.scala index dbf767239e6b..7eb0ba2f8cca 100644 --- a/tests/init/neg/override45.scala +++ b/tests/init/warn/override45.scala @@ -8,5 +8,5 @@ class Child extends Parent { val x = a val y = b override def f: Int = z - val z = 30 // error + val z = 30 // warn } \ No newline at end of file diff --git a/tests/init/neg/override46.scala b/tests/init/warn/override46.scala similarity index 75% rename from tests/init/neg/override46.scala rename to tests/init/warn/override46.scala index 397ec85a6984..f10d4516439c 100644 --- a/tests/init/neg/override46.scala +++ b/tests/init/warn/override46.scala @@ -1,5 +1,5 @@ trait TA { - val x = "world" // error + val x = "world" // warn } trait TB { this: TA => diff --git a/tests/init/neg/override5.scala b/tests/init/warn/override5.scala similarity index 78% rename from tests/init/neg/override5.scala rename to tests/init/warn/override5.scala index 061a41dc3fc2..fe9e3bfbde70 100644 --- a/tests/init/neg/override5.scala +++ b/tests/init/warn/override5.scala @@ -5,7 +5,7 @@ trait Foo { } class Bar extends Foo { - val name = "Jack" // error + val name = "Jack" // warn } @@ -16,7 +16,7 @@ trait Zen { } class Tao extends Zen { - val name = "Jack" // error + val name = "Jack" // warn } diff --git a/tests/init/neg/override6.scala b/tests/init/warn/override6.scala similarity index 70% rename from tests/init/neg/override6.scala rename to tests/init/warn/override6.scala index 0c04ea91300d..e8103d999151 100644 --- a/tests/init/neg/override6.scala +++ b/tests/init/warn/override6.scala @@ -4,5 +4,5 @@ trait Foo { } class Bar extends Foo { - val name = "Jack" // error + val name = "Jack" // warn } \ No newline at end of file diff --git a/tests/init/neg/override7.scala b/tests/init/warn/override7.scala similarity index 87% rename from tests/init/neg/override7.scala rename to tests/init/warn/override7.scala index 0a36f02b2790..41fbcd00be69 100644 --- a/tests/init/neg/override7.scala +++ b/tests/init/warn/override7.scala @@ -7,7 +7,7 @@ trait Foo { } class Bar(val name: String) extends Foo { - val title = "Mr." // error + val title = "Mr." // warn def getName = name // ok: name is a Param field diff --git a/tests/init/neg/override8.scala b/tests/init/warn/override8.scala similarity index 93% rename from tests/init/neg/override8.scala rename to tests/init/warn/override8.scala index 526fd5a7f3a3..272143011efc 100644 --- a/tests/init/neg/override8.scala +++ b/tests/init/warn/override8.scala @@ -6,7 +6,7 @@ trait Foo { } trait Bar { - val m = "hello" // error + val m = "hello" // warn def foo(n: Int) = m diff --git a/tests/init/neg/override9.scala b/tests/init/warn/override9.scala similarity index 64% rename from tests/init/neg/override9.scala rename to tests/init/warn/override9.scala index 1b4d32b3e5a3..12dbfde19ec3 100644 --- a/tests/init/neg/override9.scala +++ b/tests/init/warn/override9.scala @@ -1,6 +1,6 @@ trait Foo { def name: String - val message = "hello, " + name // error + val message = "hello, " + name // warn } class Bar extends Foo { diff --git a/tests/init/neg/polyfun.scala b/tests/init/warn/polyfun.scala similarity index 72% rename from tests/init/neg/polyfun.scala rename to tests/init/warn/polyfun.scala index a3a3ecc76814..5ac11721c061 100644 --- a/tests/init/neg/polyfun.scala +++ b/tests/init/warn/polyfun.scala @@ -4,5 +4,5 @@ class Test { println(n) arg } - val n = m.apply(arg = 23) // error + val n = m.apply(arg = 23) // warn } diff --git a/tests/init/neg/private.scala b/tests/init/warn/private.scala similarity index 84% rename from tests/init/neg/private.scala rename to tests/init/warn/private.scala index 658860ab577c..215f0db3deee 100644 --- a/tests/init/neg/private.scala +++ b/tests/init/warn/private.scala @@ -6,7 +6,7 @@ class A(a: Int) { class B extends A(3) { foo() println(a) - val a = 3 // error + val a = 3 // warn } class C extends A(3) { diff --git a/tests/init/neg/promote-warm.scala b/tests/init/warn/promote-warm.scala similarity index 84% rename from tests/init/neg/promote-warm.scala rename to tests/init/warn/promote-warm.scala index c9f9268f1fbd..c776d37a924e 100644 --- a/tests/init/neg/promote-warm.scala +++ b/tests/init/warn/promote-warm.scala @@ -6,7 +6,7 @@ class PromoteWarm: a.foo() val a = new A - val b = new B(a) // error + val b = new B(a) // warn val n = 10 def foo() = println(n) diff --git a/tests/init/neg/promote.scala b/tests/init/warn/promote.scala similarity index 82% rename from tests/init/neg/promote.scala rename to tests/init/warn/promote.scala index 70e951d78f6f..a97122d57a62 100644 --- a/tests/init/neg/promote.scala +++ b/tests/init/warn/promote.scala @@ -4,6 +4,6 @@ class Wrap { abstract class E[+T] { def foo: T } object E { final val A: E[Nothing] = new E { def foo = ref } - val ref = qux(A) // error + val ref = qux(A) // warn } } \ No newline at end of file diff --git a/tests/init/neg/promotion-loop.scala b/tests/init/warn/promotion-loop.scala similarity index 86% rename from tests/init/neg/promotion-loop.scala rename to tests/init/warn/promotion-loop.scala index 7f6856c34cae..c94422daca76 100644 --- a/tests/init/neg/promotion-loop.scala +++ b/tests/init/warn/promotion-loop.scala @@ -13,7 +13,7 @@ class Test { test => } val b = new B - println(b) // error + println(b) // warn val n = 10 } \ No newline at end of file diff --git a/tests/init/neg/promotion-segment.scala b/tests/init/warn/promotion-segment.scala similarity index 85% rename from tests/init/neg/promotion-segment.scala rename to tests/init/warn/promotion-segment.scala index 56968ce79c56..542ee23623f1 100644 --- a/tests/init/neg/promotion-segment.scala +++ b/tests/init/warn/promotion-segment.scala @@ -8,5 +8,5 @@ class Outer: def bar(c: C) = c.foo() - bar(new C) // error + bar(new C) // warn val m = 10 diff --git a/tests/init/neg/promotion-segment2.scala b/tests/init/warn/promotion-segment2.scala similarity index 87% rename from tests/init/neg/promotion-segment2.scala rename to tests/init/warn/promotion-segment2.scala index d3ba8dedf0ce..39cd7129950f 100644 --- a/tests/init/neg/promotion-segment2.scala +++ b/tests/init/warn/promotion-segment2.scala @@ -8,5 +8,5 @@ class Outer: def bar(c: C) = c.foo() - bar(new C) // error + bar(new C) // warn val m = 10 diff --git a/tests/init/neg/promotion-segment3.scala b/tests/init/warn/promotion-segment3.scala similarity index 82% rename from tests/init/neg/promotion-segment3.scala rename to tests/init/warn/promotion-segment3.scala index 9e62291953d3..5dab2224743b 100644 --- a/tests/init/neg/promotion-segment3.scala +++ b/tests/init/warn/promotion-segment3.scala @@ -6,6 +6,6 @@ class A: def bar(b: B) = new b.C().foo() - bar(new B) // error + bar(new B) // warn val m = 10 diff --git a/tests/init/neg/secondary-ctor.scala b/tests/init/warn/secondary-ctor.scala similarity index 87% rename from tests/init/neg/secondary-ctor.scala rename to tests/init/warn/secondary-ctor.scala index d96e149529d0..92a77b11b57a 100644 --- a/tests/init/neg/secondary-ctor.scala +++ b/tests/init/warn/secondary-ctor.scala @@ -15,5 +15,5 @@ class C(b: B) extends A(b) { class D { val b = new B(this) - val c = new C(b, 5) // error + val c = new C(b, 5) // warn } diff --git a/tests/init/neg/secondary-ctor2.scala b/tests/init/warn/secondary-ctor2.scala similarity index 91% rename from tests/init/neg/secondary-ctor2.scala rename to tests/init/warn/secondary-ctor2.scala index 462ff2dbcfaa..5518bbf974e7 100644 --- a/tests/init/neg/secondary-ctor2.scala +++ b/tests/init/warn/secondary-ctor2.scala @@ -21,5 +21,5 @@ class C(b: B) extends A(b) { class D { val b = new B(this) - val c = new C(b, 5) // error + val c = new C(b, 5) // warn } diff --git a/tests/init/neg/secondary-ctor3.scala b/tests/init/warn/secondary-ctor3.scala similarity index 94% rename from tests/init/neg/secondary-ctor3.scala rename to tests/init/warn/secondary-ctor3.scala index 3bbfc413e262..ed01c6fcbe30 100644 --- a/tests/init/neg/secondary-ctor3.scala +++ b/tests/init/warn/secondary-ctor3.scala @@ -35,5 +35,5 @@ def foo() = class D { val b = new B(this) - val c = new C(b, 5) // error + val c = new C(b, 5) // warn } diff --git a/tests/init/neg/secondary-ctor4.check b/tests/init/warn/secondary-ctor4.check similarity index 84% rename from tests/init/neg/secondary-ctor4.check rename to tests/init/warn/secondary-ctor4.check index 2c89cfe9f289..3909af5ac336 100644 --- a/tests/init/neg/secondary-ctor4.check +++ b/tests/init/warn/secondary-ctor4.check @@ -1,10 +1,10 @@ --- Error: tests/init/neg/secondary-ctor4.scala:54:14 ------------------------------------------------------------------- -54 | val c = new C(b, 5) // error +-- Warning: tests/init/warn/secondary-ctor4.scala:54:14 ---------------------------------------------------------------- +54 | val c = new C(b, 5) // warn | ^^^^^^^^^^^ | Problematic object instantiation: arg 1 is not transitively initialized (Hot). Calling trace: | ├── class D { [ secondary-ctor4.scala:52 ] | │ ^ - | └── val c = new C(b, 5) // error [ secondary-ctor4.scala:54 ] + | └── val c = new C(b, 5) // warn [ secondary-ctor4.scala:54 ] | ^^^^^^^^^^^ | | It leads to the following error during object initialization: @@ -21,15 +21,15 @@ | │ ^ | └── println(b.n) [ secondary-ctor4.scala:23 ] | ^^^ --- Error: tests/init/neg/secondary-ctor4.scala:42:4 -------------------------------------------------------------------- -42 | new A(new B(new D)) // error +-- Warning: tests/init/warn/secondary-ctor4.scala:42:4 ----------------------------------------------------------------- +42 | new A(new B(new D)) // warn | ^^^^^^^^^^^^^^^^^^^ |Problematic object instantiation: the outer M.this and arg 1 are not transitively initialized (Hot). Calling trace: |├── class N(d: D) extends M(d) { [ secondary-ctor4.scala:59 ] |│ ^ |├── def this(d: D) = { [ secondary-ctor4.scala:7 ] |│ ^ - |└── new A(new B(new D)) // error [ secondary-ctor4.scala:42 ] + |└── new A(new B(new D)) // warn [ secondary-ctor4.scala:42 ] | ^^^^^^^^^^^^^^^^^^^ | |It leads to the following error during object initialization: diff --git a/tests/init/neg/secondary-ctor4.scala b/tests/init/warn/secondary-ctor4.scala similarity index 90% rename from tests/init/neg/secondary-ctor4.scala rename to tests/init/warn/secondary-ctor4.scala index e80630002638..9c53034ee597 100644 --- a/tests/init/neg/secondary-ctor4.scala +++ b/tests/init/warn/secondary-ctor4.scala @@ -10,7 +10,7 @@ class M(x: Int) { class L1(x: Int) { val n: Int = 5 } class A(b: B, x: Int) { - println(d.n) + println(d.n) class L2(x: Int) { val n: Int = 5 } @@ -39,7 +39,7 @@ class M(x: Int) { val n: Int = 10 } - new A(new B(new D)) // error + new A(new B(new D)) // warn trait T { val m: Int = 10 @@ -51,7 +51,7 @@ class M(x: Int) { class D { val b = new B(this) - val c = new C(b, 5) // error + val c = new C(b, 5) // warn } } } diff --git a/tests/init/warn/simple1.scala b/tests/init/warn/simple1.scala new file mode 100644 index 000000000000..9f8ce2f5c487 --- /dev/null +++ b/tests/init/warn/simple1.scala @@ -0,0 +1,4 @@ +class Foo { + val len = name.size + val name: String = "Jack" // warn +} \ No newline at end of file diff --git a/tests/init/neg/simple2.scala b/tests/init/warn/simple2.scala similarity index 86% rename from tests/init/neg/simple2.scala rename to tests/init/warn/simple2.scala index 70a7f8407c6b..63fa64d5a113 100644 --- a/tests/init/neg/simple2.scala +++ b/tests/init/warn/simple2.scala @@ -4,7 +4,7 @@ class Box(x: Int) { List(3, 4, 5).map(_ * 2) - private var a = "hello" // error + private var a = "hello" // warn def f(m: Int) = m + a.size } diff --git a/tests/init/neg/simple3.scala b/tests/init/warn/simple3.scala similarity index 64% rename from tests/init/neg/simple3.scala rename to tests/init/warn/simple3.scala index 70de74b35bd4..245f982a807b 100644 --- a/tests/init/neg/simple3.scala +++ b/tests/init/warn/simple3.scala @@ -1,5 +1,5 @@ class Foo { val list = List(4, 6) val n = len + 5 - val len = list.size // error + val len = list.size // warn } diff --git a/tests/init/neg/simple5.scala b/tests/init/warn/simple5.scala similarity index 68% rename from tests/init/neg/simple5.scala rename to tests/init/warn/simple5.scala index 9c9d7d053830..bd9506076d26 100644 --- a/tests/init/neg/simple5.scala +++ b/tests/init/warn/simple5.scala @@ -6,7 +6,7 @@ class Foo { b - val name = "Jack" // error + val name = "Jack" // warn } class Bar { @@ -17,5 +17,5 @@ class Bar { b - val name = "Jack" // error + val name = "Jack" // warn } \ No newline at end of file diff --git a/tests/init/neg/soundness1.scala b/tests/init/warn/soundness1.scala similarity index 81% rename from tests/init/neg/soundness1.scala rename to tests/init/warn/soundness1.scala index d528b374f004..4d71c3e52747 100644 --- a/tests/init/neg/soundness1.scala +++ b/tests/init/warn/soundness1.scala @@ -20,10 +20,10 @@ object Test2: object Test3: class A(b: B) { println(b.a2) - val b2 = new B(this) // error + val b2 = new B(this) // warn } class B(a: A) { println(a.b2) - val a2 = new A(this) // error + val a2 = new A(this) // warn } diff --git a/tests/init/neg/soundness2.scala b/tests/init/warn/soundness2.scala similarity index 50% rename from tests/init/neg/soundness2.scala rename to tests/init/warn/soundness2.scala index 3d2821377111..6015ea46c3d7 100644 --- a/tests/init/neg/soundness2.scala +++ b/tests/init/warn/soundness2.scala @@ -1,4 +1,4 @@ class C(c: C) { val d = c.c2 - val c2 = new C(this) // error + val c2 = new C(this) // warn } diff --git a/tests/init/warn/soundness4.scala b/tests/init/warn/soundness4.scala new file mode 100644 index 000000000000..24060f2be083 --- /dev/null +++ b/tests/init/warn/soundness4.scala @@ -0,0 +1,3 @@ +class Foo { + val a : Foo = this.a.a // warn +} \ No newline at end of file diff --git a/tests/init/neg/soundness6.scala b/tests/init/warn/soundness6.scala similarity index 58% rename from tests/init/neg/soundness6.scala rename to tests/init/warn/soundness6.scala index 09d55dba292c..2893c3a4e301 100644 --- a/tests/init/neg/soundness6.scala +++ b/tests/init/warn/soundness6.scala @@ -1,5 +1,5 @@ class C(c: C) { println(c.n) - val c2 = new C(this) // error + val c2 = new C(this) // warn val n = 10 } diff --git a/tests/init/neg/structural.scala b/tests/init/warn/structural.scala similarity index 86% rename from tests/init/neg/structural.scala rename to tests/init/warn/structural.scala index 27b37a04bef7..bf20529a8007 100644 --- a/tests/init/neg/structural.scala +++ b/tests/init/warn/structural.scala @@ -8,5 +8,5 @@ class Test { n + x } - val n = m(23) // error + val n = m(23) // warn } diff --git a/tests/init/neg/super-resolution.scala b/tests/init/warn/super-resolution.scala similarity index 82% rename from tests/init/neg/super-resolution.scala rename to tests/init/warn/super-resolution.scala index d2674bc597e1..6fa295ed5187 100644 --- a/tests/init/neg/super-resolution.scala +++ b/tests/init/warn/super-resolution.scala @@ -16,8 +16,8 @@ trait N extends A with B: class C extends A with M with N: foo() - val a = 10 // error - val b = 20 // error - val m = 30 // error + val a = 10 // warn + val b = 20 // warn + val m = 30 // warn val n = 40 diff --git a/tests/init/neg/super-resolution2.scala b/tests/init/warn/super-resolution2.scala similarity index 84% rename from tests/init/neg/super-resolution2.scala rename to tests/init/warn/super-resolution2.scala index 283fb25a467d..5009e2f3aa64 100644 --- a/tests/init/neg/super-resolution2.scala +++ b/tests/init/warn/super-resolution2.scala @@ -15,6 +15,6 @@ class N extends A with B: new Inner - val m = 30 // error - val n = 40 // error + val m = 30 // warn + val n = 40 // warn val a = 50 diff --git a/tests/init/neg/super-resolution3.scala b/tests/init/warn/super-resolution3.scala similarity index 81% rename from tests/init/neg/super-resolution3.scala rename to tests/init/warn/super-resolution3.scala index 4d510ef22e61..e1b7a2ba3541 100644 --- a/tests/init/neg/super-resolution3.scala +++ b/tests/init/warn/super-resolution3.scala @@ -21,7 +21,7 @@ trait N extends A with B: class C extends A with M with N: new Inner() - val a = 10 // error - val b = 20 // error - val m = 30 // error - val n = 40 // error + val a = 10 // warn + val b = 20 // warn + val m = 30 // warn + val n = 40 // warn diff --git a/tests/init/neg/super.scala b/tests/init/warn/super.scala similarity index 87% rename from tests/init/neg/super.scala rename to tests/init/warn/super.scala index 5a8e72cce65f..9b0b88136f20 100644 --- a/tests/init/neg/super.scala +++ b/tests/init/warn/super.scala @@ -20,11 +20,11 @@ class Bar extends A, B, C: override def foo() = n * n - val n = 10 // error + val n = 10 // warn class Qux extends A, B, C: super.foo() override def foo() = n * n - val n = 10 // error + val n = 10 // warn diff --git a/tests/init/neg/t3273.scala b/tests/init/warn/t3273.scala similarity index 90% rename from tests/init/neg/t3273.scala rename to tests/init/warn/t3273.scala index af1df70c471e..c4b79a4dbfcc 100644 --- a/tests/init/neg/t3273.scala +++ b/tests/init/warn/t3273.scala @@ -1,8 +1,8 @@ import scala.language.implicitConversions class Test { - val num1: LazyList[Int] = 1 #:: num1.map(_ + 1) // error - val num2: LazyList[Int] = 1 #:: num2.iterator.map(_ + 1).to(LazyList) // error + val num1: LazyList[Int] = 1 #:: num1.map(_ + 1) // warn + val num2: LazyList[Int] = 1 #:: num2.iterator.map(_ + 1).to(LazyList) // warn def main(args: Array[String]): Unit = { val x1 = (num1 take 10).toList diff --git a/tests/init/neg/trait1.scala b/tests/init/warn/trait1.scala similarity index 79% rename from tests/init/neg/trait1.scala rename to tests/init/warn/trait1.scala index 48eae248fee7..d5c30569c4ee 100644 --- a/tests/init/neg/trait1.scala +++ b/tests/init/warn/trait1.scala @@ -3,7 +3,7 @@ abstract class A(x: Int) { foo() } -trait B(val y: Int) // error +trait B(val y: Int) // warn class C extends A(10) with B(20) { def foo(): Unit = println(y) diff --git a/tests/init/neg/trait2.scala b/tests/init/warn/trait2.scala similarity index 83% rename from tests/init/neg/trait2.scala rename to tests/init/warn/trait2.scala index 6011c259b73f..1b5bfded5730 100644 --- a/tests/init/neg/trait2.scala +++ b/tests/init/warn/trait2.scala @@ -3,7 +3,7 @@ abstract class A(x: Int) { foo() } -trait B(val y: Int) // error +trait B(val y: Int) // warn class D { class C extends A(10) with B(20) { diff --git a/tests/init/neg/trees.scala b/tests/init/warn/trees.scala similarity index 78% rename from tests/init/neg/trees.scala rename to tests/init/warn/trees.scala index 836f02e9c551..96ae170075c5 100644 --- a/tests/init/neg/trees.scala +++ b/tests/init/warn/trees.scala @@ -3,5 +3,5 @@ class Trees { class ValDef { counter += 1 } class EmptyValDef extends ValDef val theEmptyValDef = new EmptyValDef - private var counter = 0 // error + private var counter = 0 // warn } diff --git a/tests/init/neg/unsound1.scala b/tests/init/warn/unsound1.scala similarity index 80% rename from tests/init/neg/unsound1.scala rename to tests/init/warn/unsound1.scala index 3854504c8478..b017d1cd9f37 100644 --- a/tests/init/neg/unsound1.scala +++ b/tests/init/warn/unsound1.scala @@ -1,5 +1,5 @@ class A(m: Int) { - if (m > 0) println(foo(m - 1).a2.n) // error + if (m > 0) println(foo(m - 1).a2.n) // warn def foo(n: Int): B = if (n % 2 == 0) new B(new A(n - 1), foo(n - 1).a1) diff --git a/tests/init/neg/unsound2.scala b/tests/init/warn/unsound2.scala similarity index 88% rename from tests/init/neg/unsound2.scala rename to tests/init/warn/unsound2.scala index 5ae0c624c32e..d8b017f2c7db 100644 --- a/tests/init/neg/unsound2.scala +++ b/tests/init/warn/unsound2.scala @@ -2,7 +2,7 @@ case class A(x: Int) { def foo(y: Int): B = if (y > 10) then B(bar(y - 1), foo(y - 1).getN) else B(bar(y), 10) def bar(y: Int): A = if (y > 10) then A(y - 1) else this class B(a: A, b: Int) { - def getN: Int = a.n // error + def getN: Int = a.n // warn def getB: Int = b } println(foo(x).getB) diff --git a/tests/init/neg/unsound3.scala b/tests/init/warn/unsound3.scala similarity index 72% rename from tests/init/neg/unsound3.scala rename to tests/init/warn/unsound3.scala index 9ede5c7f97d0..021505cb9931 100644 --- a/tests/init/neg/unsound3.scala +++ b/tests/init/warn/unsound3.scala @@ -7,7 +7,7 @@ class C { def foo(): B = { x += 1 val newB = new B(this) - if (x < 12) then foo().getC().b else newB // error + if (x < 12) then foo().getC().b else newB // warn } val b = foo() } \ No newline at end of file diff --git a/tests/init/neg/unsound4.scala b/tests/init/warn/unsound4.scala similarity index 70% rename from tests/init/neg/unsound4.scala rename to tests/init/warn/unsound4.scala index 8a6e26fe8a6b..2b1a69723342 100644 --- a/tests/init/neg/unsound4.scala +++ b/tests/init/warn/unsound4.scala @@ -1,4 +1,4 @@ class A { def foo(x: Int): A = if (x < 5) then this else foo(x - 1).aAgain - val aAgain = foo(5) // error + val aAgain = foo(5) // warn } \ No newline at end of file From c83ab2752c5363a13b2cea2b9afb0460b3620b18 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 8 Dec 2023 14:51:15 +0100 Subject: [PATCH 008/220] Update comments on TASTy MiMa filters --- project/TastyMiMaFilters.scala | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/project/TastyMiMaFilters.scala b/project/TastyMiMaFilters.scala index 0d2ed387da33..85a9b98b7d87 100644 --- a/project/TastyMiMaFilters.scala +++ b/project/TastyMiMaFilters.scala @@ -20,11 +20,10 @@ object TastyMiMaFilters { ProblemMatcher.make(ProblemKind.MissingTermMember, "scala.math.Big*.underlying"), ProblemMatcher.make(ProblemKind.NewAbstractMember, "scala.math.ScalaNumericConversions.underlying"), - // Problem: super accessors + // Probably OK: super accessors // In Scala 3 these accessors are added in the `postyper` phase. // In Scala 2 these accessors are added in the `superaccessors` phase after typer. - // Are these accessors in the Scala 2 pickles? If so, it implies that TASTy Query/MiMa is ignoring them in Scala 2 but not Scala 3. - // Otherwise, if these are not in the Scala 2 pickles, we might need to remove them when compiling with -Ycompile-scala2-library + // Handle as a special case in `ExtensionMethods`. ProblemMatcher.make(ProblemKind.NewAbstractMember, "scala.collection.immutable.IndexedSeqOps.superscala$collection$immutable$IndexedSeqOps$$slice"), ProblemMatcher.make(ProblemKind.NewAbstractMember, "scala.collection.immutable.StrictOptimizedSeqOps.superscala$collection$immutable$StrictOptimizedSeqOps$$sorted"), ProblemMatcher.make(ProblemKind.NewAbstractMember, "scala.collection.immutable.IndexedSeq.superscala$collection$immutable$IndexedSeq$$*"/* sameElements, canEqual */), @@ -38,7 +37,7 @@ object TastyMiMaFilters { ProblemMatcher.make(ProblemKind.NewAbstractMember, "scala.util.control.NoStackTrace.superscala$util$control$NoStackTrace$$fillInStackTrace"), // TASTy-MiMa bug (probably OK): `private[scala] var` in case class - // This is probably because we can only access the next field from the scala library. + // This member should not have been loaded by TASTy-MiMa. ProblemMatcher.make(ProblemKind.MissingTermMember, "scala.collection.immutable.::.next$access$1"), // Probably OK: Problem Missing setter for `protected var` @@ -60,15 +59,16 @@ object TastyMiMaFilters { ProblemMatcher.make(ProblemKind.MissingTermMember, "scala.Predef.ne"), // The member scala.Predef.ne with signature (java.lang.Object,java.lang.Object):scala.Boolean does not have a correspondant in current version ProblemMatcher.make(ProblemKind.MissingTermMember, "scala.Predef.eq"), // The member scala.Predef.eq with signature (java.lang.Object,java.lang.Object):scala.Boolean does not have a correspondant in current version - // Problem: protected lazy val (processThread, (futureThread, futureValue), destroyer) = { ... } + // Probably OK: protected lazy val (processThread, (futureThread, futureValue), destroyer) = { ... } + // None of these can be accessed from user code. // https://github.com/scala/scala/blob/cff8a9af4da67658d8e1e32f929e1aff03ffa384/src/library/scala/sys/process/ProcessImpl.scala#L99C5-L99C83 ProblemMatcher.make(ProblemKind.IncompatibleKindChange, "scala.sys.process.ProcessImpl.CompoundProcess.destroyer"), // before: lazy val; after: def ProblemMatcher.make(ProblemKind.IncompatibleKindChange, "scala.sys.process.ProcessImpl.CompoundProcess.futureThread"), // before: lazy val; after: def ProblemMatcher.make(ProblemKind.IncompatibleKindChange, "scala.sys.process.ProcessImpl.CompoundProcess.processThread"), // before: lazy val; after: def ProblemMatcher.make(ProblemKind.IncompatibleKindChange, "scala.sys.process.ProcessImpl.CompoundProcess.futureValue"), // before: lazy val; after: def - // Problem? - // https://github.com/scala/scala/blob/2.13.x/src/library/scala/collection/convert/JavaCollectionWrappers.scala#L66-L71 + // Probably Ok: defined within a `private[collection]` object + // https://github.com/scala/scala/blob/2.13.x/src/library/scala/collection/convert/JavaCollectionWrappers.scala#L66-L71 ProblemMatcher.make(ProblemKind.MissingTermMember, "scala.collection.convert.JavaCollectionWrappers.IterableWrapperTrait.iterator"), // The member scala.collection.convert.JavaCollectionWrappers.IterableWrapperTrait.iterator with signature ():scala.collection.convert.JavaCollectionWrappers.IteratorWrapper does not have a correspondant in current version // Problem? From bc36acbf5fae1aaced587ebbad5543a3e37078c6 Mon Sep 17 00:00:00 2001 From: odersky Date: Sun, 17 Dec 2023 13:45:43 +0100 Subject: [PATCH 009/220] Avoid generating given definitions that loop --- .../dotty/tools/dotc/typer/Implicits.scala | 73 ++++++++++++++++--- .../changed-features/implicit-resolution.md | 21 +++++- tests/neg/i15474.check | 6 ++ tests/neg/i15474.scala | 8 +- tests/neg/i6716.check | 6 ++ tests/neg/i6716.scala | 18 +++++ tests/pos/i15474.scala | 20 +++++ tests/pos/i6716.scala | 15 ---- tests/run/i17115.check | 2 + tests/{pos => run}/i17115.scala | 0 tests/run/i6716.check | 2 + tests/run/i6716.scala | 20 +++++ 12 files changed, 161 insertions(+), 30 deletions(-) create mode 100644 tests/neg/i15474.check create mode 100644 tests/neg/i6716.check create mode 100644 tests/neg/i6716.scala create mode 100644 tests/pos/i15474.scala delete mode 100644 tests/pos/i6716.scala create mode 100644 tests/run/i17115.check rename tests/{pos => run}/i17115.scala (100%) create mode 100644 tests/run/i6716.check create mode 100644 tests/run/i6716.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index ff23e8180f1c..bb35306f696c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -26,8 +26,8 @@ import Scopes.newScope import Typer.BindingPrec, BindingPrec.* import Hashable.* import util.{EqHashMap, Stats} -import config.{Config, Feature} -import Feature.migrateTo3 +import config.{Config, Feature, SourceVersion} +import Feature.{migrateTo3, sourceVersion} import config.Printers.{implicits, implicitsDetailed} import collection.mutable import reporting.* @@ -324,7 +324,7 @@ object Implicits: /** Is this the outermost implicits? This is the case if it either the implicits * of NoContext, or the last one before it. */ - private def isOuterMost = { + private def isOutermost = { val finalImplicits = NoContext.implicits (this eq finalImplicits) || (outerImplicits eqn finalImplicits) } @@ -356,7 +356,7 @@ object Implicits: Stats.record("uncached eligible") if monitored then record(s"check uncached eligible refs in irefCtx", refs.length) val ownEligible = filterMatching(tp) - if isOuterMost then ownEligible + if isOutermost then ownEligible else combineEligibles(ownEligible, outerImplicits.nn.uncachedEligible(tp)) /** The implicit references that are eligible for type `tp`. */ @@ -383,7 +383,7 @@ object Implicits: private def computeEligible(tp: Type): List[Candidate] = /*>|>*/ trace(i"computeEligible $tp in $refs%, %", implicitsDetailed) /*<|<*/ { if (monitored) record(s"check eligible refs in irefCtx", refs.length) val ownEligible = filterMatching(tp) - if isOuterMost then ownEligible + if isOutermost then ownEligible else combineEligibles(ownEligible, outerImplicits.nn.eligible(tp)) } @@ -392,7 +392,7 @@ object Implicits: override def toString: String = { val own = i"(implicits: $refs%, %)" - if (isOuterMost) own else own + "\n " + outerImplicits + if (isOutermost) own else own + "\n " + outerImplicits } /** This context, or a copy, ensuring root import from symbol `root` @@ -1550,11 +1550,15 @@ trait Implicits: case _ => tp.isAny || tp.isAnyRef - private def searchImplicit(contextual: Boolean): SearchResult = + /** Search implicit in context `ctxImplicits` or else in implicit scope + * of expected type if `ctxImplicits == null`. + */ + private def searchImplicit(ctxImplicits: ContextualImplicits | Null): SearchResult = if isUnderspecified(wildProto) then SearchFailure(TooUnspecific(pt), span) else - val eligible = + val contextual = ctxImplicits != null + val preEligible = // the eligible candidates, ignoring positions if contextual then if ctx.gadt.isNarrowing then withoutMode(Mode.ImplicitsEnabled) { @@ -1562,6 +1566,43 @@ trait Implicits: } else ctx.implicits.eligible(wildProto) else implicitScope(wildProto).eligible + + /** Does candidate `cand` come too late for it to be considered as an + * eligible candidate? This is the case if `cand` appears in the same + * scope as a given definition enclosing the search point and comes + * later in the source or coincides with that given definition. + */ + def comesTooLate(cand: Candidate): Boolean = + val candSym = cand.ref.symbol + def candSucceedsGiven(sym: Symbol): Boolean = + if sym.owner == candSym.owner then + if sym.is(ModuleClass) then candSucceedsGiven(sym.sourceModule) + else sym.is(Given) && sym.span.exists && sym.span.start <= candSym.span.start + else if sym.is(Package) then false + else candSucceedsGiven(sym.owner) + + ctx.isTyper + && !candSym.isOneOf(TermParamOrAccessor | Synthetic) + && candSym.span.exists + && candSucceedsGiven(ctx.owner) + end comesTooLate + + val eligible = if contextual then preEligible.filterNot(comesTooLate) else preEligible + + def checkResolutionChange(result: SearchResult) = result match + case result: SearchSuccess + if (eligible ne preEligible) && !sourceVersion.isAtLeast(SourceVersion.`future`) => + searchImplicit(preEligible.diff(eligible), contextual) match + case prevResult: SearchSuccess => + report.error( + em"""Warning: result of implicit search for $pt will change. + |current result: ${prevResult.ref.symbol.showLocated} + |result with -source future: ${result.ref.symbol.showLocated}""", + srcPos + ) + case _ => + case _ => + searchImplicit(eligible, contextual) match case result: SearchSuccess => result @@ -1570,14 +1611,24 @@ trait Implicits: case _: AmbiguousImplicits => failure case reason => if contextual then - searchImplicit(contextual = false).recoverWith { + // If we filtered out some candidates for being too late, we should + // do another contextual search further out, since the dropped candidates + // might have shadowed an eligible candidate in an outer level. + // Otherwise, proceed with a search of the implicit scope. + val newCtxImplicits = + if eligible eq preEligible then null + else ctxImplicits.nn.outerImplicits: ContextualImplicits | Null + // !!! Dotty problem: without the ContextualImplicits | Null type ascription + // we get a Ycheck failure after arrayConstructors due to "Types differ" + val result = searchImplicit(newCtxImplicits).recoverWith: failure2 => failure2.reason match case _: AmbiguousImplicits => failure2 case _ => reason match case (_: DivergingImplicit) => failure case _ => List(failure, failure2).maxBy(_.tree.treeSize) - } + checkResolutionChange(result) + result else failure end searchImplicit @@ -1595,7 +1646,7 @@ trait Implicits: case ref: TermRef => SearchSuccess(tpd.ref(ref).withSpan(span.startPos), ref, 0)(ctx.typerState, ctx.gadt) case _ => - searchImplicit(contextual = true) + searchImplicit(ctx.implicits) end bestImplicit def implicitScope(tp: Type): OfTypeImplicits = ctx.run.nn.implicitScope(tp) diff --git a/docs/_docs/reference/changed-features/implicit-resolution.md b/docs/_docs/reference/changed-features/implicit-resolution.md index 6a898690b565..ab8293724a4e 100644 --- a/docs/_docs/reference/changed-features/implicit-resolution.md +++ b/docs/_docs/reference/changed-features/implicit-resolution.md @@ -163,8 +163,27 @@ The new rules are as follows: An implicit `a` defined in `A` is more specific th Condition (*) is new. It is necessary to ensure that the defined relation is transitive. +[//]: # todo: expand with precise rules +**9.** Implicit resolution now tries to avoid recursive givens that can lead to an infinite loop at runtime. Here is an example: +```scala +object Prices { + opaque type Price = BigDecimal + object Price{ + given Ordering[Price] = summon[Ordering[BigDecimal]] // was error, now avoided + } +} +``` + +Previously, implicit resolution would resolve the `summon` to the given in `Price`, leading to an infinite loop (a warning was issued in that case). We now use the underlying given in `BigDecimal` instead. We achieve that by adding the following rule for implicit search: + + - When doing an implicit search while checking the implementation of a `given` definition `G`, discard all search results that lead back to `G` or to a given +with the same owner as `G` that comes later in the source than `G`. + +The new behavior is enabled under `-source future`. In earlier versions, a +warning is issued where that behavior will change. + +Old-style implicit definitions are unaffected by this change. -[//]: # todo: expand with precise rules diff --git a/tests/neg/i15474.check b/tests/neg/i15474.check new file mode 100644 index 000000000000..267a02a80786 --- /dev/null +++ b/tests/neg/i15474.check @@ -0,0 +1,6 @@ +-- Error: tests/neg/i15474.scala:16:56 --------------------------------------------------------------------------------- +16 | given Ordering[Price] = summon[Ordering[BigDecimal]] // error + | ^ + | Warning: result of implicit search for Ordering[BigDecimal] will change. + | current result: given instance given_Ordering_Price in object Price + | result with -source future: object BigDecimal in object Ordering diff --git a/tests/neg/i15474.scala b/tests/neg/i15474.scala index 8edf97a1e55a..c5cf934bdd7a 100644 --- a/tests/neg/i15474.scala +++ b/tests/neg/i15474.scala @@ -4,10 +4,10 @@ import scala.language.implicitConversions object Test1: given c: Conversion[ String, Int ] with - def apply(from: String): Int = from.toInt // error + def apply(from: String): Int = from.toInt // was error, now avoided object Test2: - given c: Conversion[ String, Int ] = _.toInt // loop not detected, could be used as a fallback to avoid the warning. + given c: Conversion[ String, Int ] = _.toInt // now avoided, was loop not detected, could be used as a fallback to avoid the warning. object Prices { opaque type Price = BigDecimal @@ -15,4 +15,6 @@ object Prices { object Price{ given Ordering[Price] = summon[Ordering[BigDecimal]] // error } -} \ No newline at end of file +} + + diff --git a/tests/neg/i6716.check b/tests/neg/i6716.check new file mode 100644 index 000000000000..1e1359442bec --- /dev/null +++ b/tests/neg/i6716.check @@ -0,0 +1,6 @@ +-- Error: tests/neg/i6716.scala:12:39 ---------------------------------------------------------------------------------- +12 | given Monad[Bar] = summon[Monad[Foo]] // error + | ^ + | Warning: result of implicit search for Monad[Foo] will change. + | current result: given instance given_Monad_Bar in object Bar + | result with -source future: object given_Monad_Foo in object Foo diff --git a/tests/neg/i6716.scala b/tests/neg/i6716.scala new file mode 100644 index 000000000000..bbbd9d6d6cd0 --- /dev/null +++ b/tests/neg/i6716.scala @@ -0,0 +1,18 @@ +//> using options -Xfatal-warnings + +trait Monad[T]: + def id: String +class Foo +object Foo { + given Monad[Foo] with { def id = "Foo" } +} + +opaque type Bar = Foo +object Bar { + given Monad[Bar] = summon[Monad[Foo]] // error +} + +object Test extends App { + println(summon[Monad[Foo]].id) + println(summon[Monad[Bar]].id) +} \ No newline at end of file diff --git a/tests/pos/i15474.scala b/tests/pos/i15474.scala new file mode 100644 index 000000000000..e40e11d84581 --- /dev/null +++ b/tests/pos/i15474.scala @@ -0,0 +1,20 @@ +//> using options -Xfatal-warnings +import scala.language.implicitConversions +import language.future + +object Test1: + given c: Conversion[ String, Int ] with + def apply(from: String): Int = from.toInt // was error, now avoided + +object Test2: + given c: Conversion[ String, Int ] = _.toInt // now avoided, was loop not detected, could be used as a fallback to avoid the warning. + +object Prices { + opaque type Price = BigDecimal + + object Price{ + given Ordering[Price] = summon[Ordering[BigDecimal]] // was error, now avoided + } +} + + diff --git a/tests/pos/i6716.scala b/tests/pos/i6716.scala deleted file mode 100644 index 446cd49c9214..000000000000 --- a/tests/pos/i6716.scala +++ /dev/null @@ -1,15 +0,0 @@ -trait Monad[T] -class Foo -object Foo { - given Monad[Foo] with {} -} - -opaque type Bar = Foo -object Bar { - given Monad[Bar] = summon[Monad[Foo]] -} - -object Test { - val mf = summon[Monad[Foo]] - val mb = summon[Monad[Bar]] -} \ No newline at end of file diff --git a/tests/run/i17115.check b/tests/run/i17115.check new file mode 100644 index 000000000000..61c83cba41ce --- /dev/null +++ b/tests/run/i17115.check @@ -0,0 +1,2 @@ +4 +5 diff --git a/tests/pos/i17115.scala b/tests/run/i17115.scala similarity index 100% rename from tests/pos/i17115.scala rename to tests/run/i17115.scala diff --git a/tests/run/i6716.check b/tests/run/i6716.check new file mode 100644 index 000000000000..bb85bd267288 --- /dev/null +++ b/tests/run/i6716.check @@ -0,0 +1,2 @@ +Foo +Foo diff --git a/tests/run/i6716.scala b/tests/run/i6716.scala new file mode 100644 index 000000000000..7c4e7fe394d8 --- /dev/null +++ b/tests/run/i6716.scala @@ -0,0 +1,20 @@ +//> using options -Xfatal-warnings + +import language.future + +trait Monad[T]: + def id: String +class Foo +object Foo { + given Monad[Foo] with { def id = "Foo" } +} + +opaque type Bar = Foo +object Bar { + given Monad[Bar] = summon[Monad[Foo]] // error +} + +object Test extends App { + println(summon[Monad[Foo]].id) + println(summon[Monad[Bar]].id) +} \ No newline at end of file From fab71479ae2fa39483d86e3227a408ef5cf52db9 Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 18 Dec 2023 14:10:56 +0100 Subject: [PATCH 010/220] Use experimental language import to enable the new behavior --- .../src/dotty/tools/dotc/config/Feature.scala | 1 + .../dotty/tools/dotc/semanticdb/Scala3.scala | 3 ++ .../dotty/tools/dotc/typer/Implicits.scala | 47 ++++++++++++++----- .../quoted/runtime/impl/QuotesImpl.scala | 4 ++ .../runtime/stdLibPatches/language.scala | 9 ++++ tests/neg/i15474.check | 12 +++-- tests/neg/i6716.check | 10 +++- tests/neg/i7294-a.check | 23 +++++++++ tests/neg/i7294-a.scala | 2 +- tests/neg/i7294-b.scala | 2 +- tests/pos/i15474.scala | 2 +- tests/run/i6716.scala | 4 +- 12 files changed, 96 insertions(+), 23 deletions(-) create mode 100644 tests/neg/i7294-a.check diff --git a/compiler/src/dotty/tools/dotc/config/Feature.scala b/compiler/src/dotty/tools/dotc/config/Feature.scala index fa262a5880ff..e8ca30ecb243 100644 --- a/compiler/src/dotty/tools/dotc/config/Feature.scala +++ b/compiler/src/dotty/tools/dotc/config/Feature.scala @@ -33,6 +33,7 @@ object Feature: val pureFunctions = experimental("pureFunctions") val captureChecking = experimental("captureChecking") val into = experimental("into") + val avoidLoopingGivens = experimental("avoidLoopingGivens") val globalOnlyImports: Set[TermName] = Set(pureFunctions, captureChecking) diff --git a/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala b/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala index f49b00089712..fdb9251951e5 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala @@ -77,6 +77,9 @@ object Scala3: type SemanticSymbol = Symbol | FakeSymbol given SemanticSymbolOps : AnyRef with + import SymbolOps.* + import StringOps.* + extension (sym: SemanticSymbol) def name(using Context): Name = sym match case s: Symbol => s.name diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index bb35306f696c..7cdc3d4a2508 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -1589,19 +1589,40 @@ trait Implicits: val eligible = if contextual then preEligible.filterNot(comesTooLate) else preEligible - def checkResolutionChange(result: SearchResult) = result match - case result: SearchSuccess - if (eligible ne preEligible) && !sourceVersion.isAtLeast(SourceVersion.`future`) => - searchImplicit(preEligible.diff(eligible), contextual) match - case prevResult: SearchSuccess => - report.error( - em"""Warning: result of implicit search for $pt will change. - |current result: ${prevResult.ref.symbol.showLocated} - |result with -source future: ${result.ref.symbol.showLocated}""", - srcPos - ) - case _ => - case _ => + def checkResolutionChange(result: SearchResult) = + if (eligible ne preEligible) + && !Feature.enabled(Feature.avoidLoopingGivens) + then searchImplicit(preEligible.diff(eligible), contextual) match + case prevResult: SearchSuccess => + def remedy = pt match + case _: SelectionProto => + "conversion,\n - use an import to get extension method into scope" + case _: ViewProto => + "conversion" + case _ => + "argument" + + def showResult(r: SearchResult) = r match + case r: SearchSuccess => ctx.printer.toTextRef(r.ref).show + case r => r.show + + result match + case result: SearchSuccess if prevResult.ref frozen_=:= result.ref => + // OK + case _ => + report.error( + em"""Warning: result of implicit search for $pt will change. + |Current result ${showResult(prevResult)} will be no longer eligible + | because it is not defined before the search position. + |Result with new rules: ${showResult(result)}. + |To opt into the new rules, use the `avoidLoopingGivens` language import, + | + |To fix the problem you could try one of the following: + | - rearrange definitions, + | - use an explicit $remedy.""", + srcPos) + case _ => + end checkResolutionChange searchImplicit(eligible, contextual) match case result: SearchSuccess => diff --git a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala index 51f133c972b4..1203e309c484 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala @@ -1781,6 +1781,8 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler end TypeRepr given TypeReprMethods: TypeReprMethods with + import SymbolMethods.* + extension (self: TypeRepr) def show(using printer: Printer[TypeRepr]): String = printer.show(self) @@ -2608,6 +2610,8 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler end Symbol given SymbolMethods: SymbolMethods with + import FlagsMethods.* + extension (self: Symbol) def owner: Symbol = self.denot.owner def maybeOwner: Symbol = self.denot.maybeOwner diff --git a/library/src/scala/runtime/stdLibPatches/language.scala b/library/src/scala/runtime/stdLibPatches/language.scala index c2a12cec2ecc..9fa8bff120af 100644 --- a/library/src/scala/runtime/stdLibPatches/language.scala +++ b/library/src/scala/runtime/stdLibPatches/language.scala @@ -91,6 +91,15 @@ object language: @compileTimeOnly("`into` can only be used at compile time in import statements") object into + /** Experimental support for new given resolution rules that avoid looping + * givens. By the new rules, a given may not implicitly use itself or givens + * defined after it. + * + * @see [[https://dotty.epfl.ch/docs/reference/experimental/avoid-looping-givens]] + */ + @compileTimeOnly("`avoidLoopingGivens` can only be used at compile time in import statements") + object avoidLoopingGivens + /** Was needed to add support for relaxed imports of extension methods. * The language import is no longer needed as this is now a standard feature since SIP was accepted. * @see [[http://dotty.epfl.ch/docs/reference/contextual/extension-methods]] diff --git a/tests/neg/i15474.check b/tests/neg/i15474.check index 267a02a80786..4bf344dc5a71 100644 --- a/tests/neg/i15474.check +++ b/tests/neg/i15474.check @@ -1,6 +1,12 @@ -- Error: tests/neg/i15474.scala:16:56 --------------------------------------------------------------------------------- 16 | given Ordering[Price] = summon[Ordering[BigDecimal]] // error | ^ - | Warning: result of implicit search for Ordering[BigDecimal] will change. - | current result: given instance given_Ordering_Price in object Price - | result with -source future: object BigDecimal in object Ordering + | Warning: result of implicit search for Ordering[BigDecimal] will change. + | Current result Prices.Price.given_Ordering_Price will be no longer eligible + | because it is not defined before the search position. + | Result with new rules: scala.math.Ordering.BigDecimal. + | To opt into the new rules, use the `avoidLoopingGivens` language import, + | + | To fix the problem you could try one of the following: + | - rearrange definitions, + | - use an explicit argument. diff --git a/tests/neg/i6716.check b/tests/neg/i6716.check index 1e1359442bec..3746eaafad50 100644 --- a/tests/neg/i6716.check +++ b/tests/neg/i6716.check @@ -2,5 +2,11 @@ 12 | given Monad[Bar] = summon[Monad[Foo]] // error | ^ | Warning: result of implicit search for Monad[Foo] will change. - | current result: given instance given_Monad_Bar in object Bar - | result with -source future: object given_Monad_Foo in object Foo + | Current result Bar.given_Monad_Bar will be no longer eligible + | because it is not defined before the search position. + | Result with new rules: Foo.given_Monad_Foo. + | To opt into the new rules, use the `avoidLoopingGivens` language import, + | + | To fix the problem you could try one of the following: + | - rearrange definitions, + | - use an explicit argument. diff --git a/tests/neg/i7294-a.check b/tests/neg/i7294-a.check new file mode 100644 index 000000000000..9541f7979a7a --- /dev/null +++ b/tests/neg/i7294-a.check @@ -0,0 +1,23 @@ +-- Error: tests/neg/i7294-a.scala:6:10 --------------------------------------------------------------------------------- +6 | case x: T => x.g(10) // error // error + | ^ + | Warning: result of implicit search for scala.reflect.TypeTest[Nothing, T] will change. + | Current result foo.i7294-a$package.f will be no longer eligible + | because it is not defined before the search position. + | Result with new rules: No Matching Implicit. + | To opt into the new rules, use the `avoidLoopingGivens` language import, + | + | To fix the problem you could try one of the following: + | - rearrange definitions, + | - use an explicit argument. + | + | where: T is a type in given instance f with bounds <: foo.Foo +-- [E007] Type Mismatch Error: tests/neg/i7294-a.scala:6:15 ------------------------------------------------------------ +6 | case x: T => x.g(10) // error // error + | ^ + | Found: (x : Nothing) + | Required: ?{ g: ? } + | Note that implicit conversions were not tried because the result of an implicit conversion + | must be more specific than ?{ g: [applied to (10) returning T] } + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg/i7294-a.scala b/tests/neg/i7294-a.scala index 13981fa4d375..538dc3159fb8 100644 --- a/tests/neg/i7294-a.scala +++ b/tests/neg/i7294-a.scala @@ -3,7 +3,7 @@ package foo trait Foo { def g(x: Int): Any } inline given f[T <: Foo]: T = ??? match { - case x: T => x.g(10) // error + case x: T => x.g(10) // error // error } @main def Test = f diff --git a/tests/neg/i7294-b.scala b/tests/neg/i7294-b.scala index 423d5037db96..b06d814444e8 100644 --- a/tests/neg/i7294-b.scala +++ b/tests/neg/i7294-b.scala @@ -3,7 +3,7 @@ package foo trait Foo { def g(x: Any): Any } inline given f[T <: Foo]: T = ??? match { - case x: T => x.g(10) // error + case x: T => x.g(10) // error // error } @main def Test = f diff --git a/tests/pos/i15474.scala b/tests/pos/i15474.scala index e40e11d84581..8adc5ad7233d 100644 --- a/tests/pos/i15474.scala +++ b/tests/pos/i15474.scala @@ -1,6 +1,6 @@ //> using options -Xfatal-warnings import scala.language.implicitConversions -import language.future +import scala.language.experimental.avoidLoopingGivens object Test1: given c: Conversion[ String, Int ] with diff --git a/tests/run/i6716.scala b/tests/run/i6716.scala index 7c4e7fe394d8..6208a52190fe 100644 --- a/tests/run/i6716.scala +++ b/tests/run/i6716.scala @@ -1,6 +1,6 @@ //> using options -Xfatal-warnings -import language.future +import scala.language.experimental.avoidLoopingGivens trait Monad[T]: def id: String @@ -11,7 +11,7 @@ object Foo { opaque type Bar = Foo object Bar { - given Monad[Bar] = summon[Monad[Foo]] // error + given Monad[Bar] = summon[Monad[Foo]] // was error fixed by avoidLoopingGivens } object Test extends App { From ed9f427c122471156efb680f97935a3d044c5218 Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 18 Dec 2023 17:52:30 +0100 Subject: [PATCH 011/220] Make the new behavior dependent on source >= 3.4 --- .../dotty/tools/dotc/typer/Implicits.scala | 91 ++++++++++--------- tests/neg/i15474.check | 42 +++++++-- tests/neg/i15474.scala | 4 +- tests/neg/i6716.check | 16 ++-- tests/neg/i7294-a.check | 18 ++-- tests/neg/looping-givens.scala | 9 ++ tests/pos/looping-givens.scala | 11 +++ 7 files changed, 122 insertions(+), 69 deletions(-) create mode 100644 tests/neg/looping-givens.scala create mode 100644 tests/pos/looping-givens.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 7cdc3d4a2508..77328cdbb33d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -1587,46 +1587,54 @@ trait Implicits: && candSucceedsGiven(ctx.owner) end comesTooLate - val eligible = if contextual then preEligible.filterNot(comesTooLate) else preEligible + val eligible = // the eligible candidates that come before the search point + if contextual && sourceVersion.isAtLeast(SourceVersion.`3.4`) + then preEligible.filterNot(comesTooLate) + else preEligible def checkResolutionChange(result: SearchResult) = if (eligible ne preEligible) && !Feature.enabled(Feature.avoidLoopingGivens) - then searchImplicit(preEligible.diff(eligible), contextual) match - case prevResult: SearchSuccess => - def remedy = pt match - case _: SelectionProto => - "conversion,\n - use an import to get extension method into scope" - case _: ViewProto => - "conversion" - case _ => - "argument" - - def showResult(r: SearchResult) = r match - case r: SearchSuccess => ctx.printer.toTextRef(r.ref).show - case r => r.show - - result match - case result: SearchSuccess if prevResult.ref frozen_=:= result.ref => - // OK - case _ => - report.error( - em"""Warning: result of implicit search for $pt will change. - |Current result ${showResult(prevResult)} will be no longer eligible - | because it is not defined before the search position. - |Result with new rules: ${showResult(result)}. - |To opt into the new rules, use the `avoidLoopingGivens` language import, - | - |To fix the problem you could try one of the following: - | - rearrange definitions, - | - use an explicit $remedy.""", - srcPos) - case _ => + then + val prevResult = searchImplicit(preEligible, contextual) + prevResult match + case prevResult: SearchSuccess => + def remedy = pt match + case _: SelectionProto => + "conversion,\n - use an import to get extension method into scope" + case _: ViewProto => + "conversion" + case _ => + "argument" + + def showResult(r: SearchResult) = r match + case r: SearchSuccess => ctx.printer.toTextRef(r.ref).show + case r => r.show + + result match + case result: SearchSuccess if prevResult.ref frozen_=:= result.ref => + // OK + case _ => + report.error( + em"""Warning: result of implicit search for $pt will change. + |Current result ${showResult(prevResult)} will be no longer eligible + | because it is not defined before the search position. + |Result with new rules: ${showResult(result)}. + |To opt into the new rules, use the `experimental.avoidLoopingGivens` language import. + | + |To fix the problem without the language import, you could try one of the following: + | - rearrange definitions so that ${showResult(prevResult)} comes earlier, + | - use an explicit $remedy.""", + srcPos) + case _ => + prevResult + else result end checkResolutionChange - searchImplicit(eligible, contextual) match + val result = searchImplicit(eligible, contextual) + result match case result: SearchSuccess => - result + checkResolutionChange(result) case failure: SearchFailure => failure.reason match case _: AmbiguousImplicits => failure @@ -1641,15 +1649,14 @@ trait Implicits: else ctxImplicits.nn.outerImplicits: ContextualImplicits | Null // !!! Dotty problem: without the ContextualImplicits | Null type ascription // we get a Ycheck failure after arrayConstructors due to "Types differ" - val result = searchImplicit(newCtxImplicits).recoverWith: - failure2 => failure2.reason match - case _: AmbiguousImplicits => failure2 - case _ => - reason match - case (_: DivergingImplicit) => failure - case _ => List(failure, failure2).maxBy(_.tree.treeSize) - checkResolutionChange(result) - result + checkResolutionChange: + searchImplicit(newCtxImplicits).recoverWith: + failure2 => failure2.reason match + case _: AmbiguousImplicits => failure2 + case _ => + reason match + case (_: DivergingImplicit) => failure + case _ => List(failure, failure2).maxBy(_.tree.treeSize) else failure end searchImplicit diff --git a/tests/neg/i15474.check b/tests/neg/i15474.check index 4bf344dc5a71..0b23628d3051 100644 --- a/tests/neg/i15474.check +++ b/tests/neg/i15474.check @@ -1,12 +1,38 @@ +-- Error: tests/neg/i15474.scala:7:35 ---------------------------------------------------------------------------------- +7 | def apply(from: String): Int = from.toInt // error + | ^^^^ + | Warning: result of implicit search for ?{ toInt: ? } will change. + | Current result Test1.c will be no longer eligible + | because it is not defined before the search position. + | Result with new rules: augmentString. + | To opt into the new rules, use the `experimental.avoidLoopingGivens` language import. + | + | To fix the problem without the language import, you could try one of the following: + | - rearrange definitions so that Test1.c comes earlier, + | - use an explicit conversion, + | - use an import to get extension method into scope. +-- Error: tests/neg/i15474.scala:10:39 --------------------------------------------------------------------------------- +10 | given c: Conversion[ String, Int ] = _.toInt // error + | ^ + | Warning: result of implicit search for ?{ toInt: ? } will change. + | Current result Test2.c will be no longer eligible + | because it is not defined before the search position. + | Result with new rules: augmentString. + | To opt into the new rules, use the `experimental.avoidLoopingGivens` language import. + | + | To fix the problem without the language import, you could try one of the following: + | - rearrange definitions so that Test2.c comes earlier, + | - use an explicit conversion, + | - use an import to get extension method into scope. -- Error: tests/neg/i15474.scala:16:56 --------------------------------------------------------------------------------- 16 | given Ordering[Price] = summon[Ordering[BigDecimal]] // error | ^ - | Warning: result of implicit search for Ordering[BigDecimal] will change. - | Current result Prices.Price.given_Ordering_Price will be no longer eligible - | because it is not defined before the search position. - | Result with new rules: scala.math.Ordering.BigDecimal. - | To opt into the new rules, use the `avoidLoopingGivens` language import, + | Warning: result of implicit search for Ordering[BigDecimal] will change. + | Current result Prices.Price.given_Ordering_Price will be no longer eligible + | because it is not defined before the search position. + | Result with new rules: scala.math.Ordering.BigDecimal. + | To opt into the new rules, use the `experimental.avoidLoopingGivens` language import. | - | To fix the problem you could try one of the following: - | - rearrange definitions, - | - use an explicit argument. + | To fix the problem without the language import, you could try one of the following: + | - rearrange definitions so that Prices.Price.given_Ordering_Price comes earlier, + | - use an explicit argument. diff --git a/tests/neg/i15474.scala b/tests/neg/i15474.scala index c5cf934bdd7a..5a66ea016630 100644 --- a/tests/neg/i15474.scala +++ b/tests/neg/i15474.scala @@ -4,10 +4,10 @@ import scala.language.implicitConversions object Test1: given c: Conversion[ String, Int ] with - def apply(from: String): Int = from.toInt // was error, now avoided + def apply(from: String): Int = from.toInt // error object Test2: - given c: Conversion[ String, Int ] = _.toInt // now avoided, was loop not detected, could be used as a fallback to avoid the warning. + given c: Conversion[ String, Int ] = _.toInt // error object Prices { opaque type Price = BigDecimal diff --git a/tests/neg/i6716.check b/tests/neg/i6716.check index 3746eaafad50..6771d736b6af 100644 --- a/tests/neg/i6716.check +++ b/tests/neg/i6716.check @@ -1,12 +1,12 @@ -- Error: tests/neg/i6716.scala:12:39 ---------------------------------------------------------------------------------- 12 | given Monad[Bar] = summon[Monad[Foo]] // error | ^ - | Warning: result of implicit search for Monad[Foo] will change. - | Current result Bar.given_Monad_Bar will be no longer eligible - | because it is not defined before the search position. - | Result with new rules: Foo.given_Monad_Foo. - | To opt into the new rules, use the `avoidLoopingGivens` language import, + | Warning: result of implicit search for Monad[Foo] will change. + | Current result Bar.given_Monad_Bar will be no longer eligible + | because it is not defined before the search position. + | Result with new rules: Foo.given_Monad_Foo. + | To opt into the new rules, use the `experimental.avoidLoopingGivens` language import. | - | To fix the problem you could try one of the following: - | - rearrange definitions, - | - use an explicit argument. + | To fix the problem without the language import, you could try one of the following: + | - rearrange definitions so that Bar.given_Monad_Bar comes earlier, + | - use an explicit argument. diff --git a/tests/neg/i7294-a.check b/tests/neg/i7294-a.check index 9541f7979a7a..887635d89a35 100644 --- a/tests/neg/i7294-a.check +++ b/tests/neg/i7294-a.check @@ -5,19 +5,19 @@ | Current result foo.i7294-a$package.f will be no longer eligible | because it is not defined before the search position. | Result with new rules: No Matching Implicit. - | To opt into the new rules, use the `avoidLoopingGivens` language import, + | To opt into the new rules, use the `experimental.avoidLoopingGivens` language import. | - | To fix the problem you could try one of the following: - | - rearrange definitions, + | To fix the problem without the language import, you could try one of the following: + | - rearrange definitions so that foo.i7294-a$package.f comes earlier, | - use an explicit argument. | | where: T is a type in given instance f with bounds <: foo.Foo --- [E007] Type Mismatch Error: tests/neg/i7294-a.scala:6:15 ------------------------------------------------------------ +-- [E007] Type Mismatch Error: tests/neg/i7294-a.scala:6:18 ------------------------------------------------------------ 6 | case x: T => x.g(10) // error // error - | ^ - | Found: (x : Nothing) - | Required: ?{ g: ? } - | Note that implicit conversions were not tried because the result of an implicit conversion - | must be more specific than ?{ g: [applied to (10) returning T] } + | ^^^^^^^ + | Found: Any + | Required: T + | + | where: T is a type in given instance f with bounds <: foo.Foo | | longer explanation available when compiling with `-explain` diff --git a/tests/neg/looping-givens.scala b/tests/neg/looping-givens.scala new file mode 100644 index 000000000000..572f1707861f --- /dev/null +++ b/tests/neg/looping-givens.scala @@ -0,0 +1,9 @@ +class A +class B + +given joint(using a: A, b: B): (A & B) = ??? + +def foo(using a: A, b: B) = + given aa: A = summon // error + given bb: B = summon // error + given ab: (A & B) = summon // error diff --git a/tests/pos/looping-givens.scala b/tests/pos/looping-givens.scala new file mode 100644 index 000000000000..ed11981c1bf6 --- /dev/null +++ b/tests/pos/looping-givens.scala @@ -0,0 +1,11 @@ +import language.experimental.avoidLoopingGivens + +class A +class B + +given joint(using a: A, b: B): (A & B) = ??? + +def foo(using a: A, b: B) = + given aa: A = summon // error + given bb: B = summon // error + given ab: (A & B) = summon // error From f56aa22e915ec43a076773f06b586ab483d917d1 Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 18 Dec 2023 21:51:19 +0100 Subject: [PATCH 012/220] Restrict the new rules to givens that don't define a new class `given ... with` or `given ... = new { ... }` kinds of definitions now follow the old rules. This allows recursive `given...with` definitions as they are found in protoQuill. We still have the old check in a later phase against directly recursive methods. Of the three loops in the original i15474 we now detect #2 and #3 with new new restrictions. #1 slips through since it is a loop involving a `given...with` instance of `Conversion`, but is caught later with the recursive method check. Previously tests #1 and #3 were detected with the recursive methods check and #2 slipped through altogether. The new rules are enough for defining simple givens with `=` without fear of looping. --- .../dotty/tools/dotc/semanticdb/Scala3.scala | 3 --- .../dotty/tools/dotc/typer/Implicits.scala | 8 +++--- .../quoted/runtime/impl/QuotesImpl.scala | 4 --- tests/neg/i15474.check | 27 +++++-------------- tests/neg/i15474.scala | 4 --- tests/neg/i15474b.check | 5 ++++ tests/neg/i15474b.scala | 8 ++++++ tests/pos/i15474.scala | 4 --- 8 files changed, 25 insertions(+), 38 deletions(-) create mode 100644 tests/neg/i15474b.check create mode 100644 tests/neg/i15474b.scala diff --git a/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala b/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala index fdb9251951e5..f49b00089712 100644 --- a/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala +++ b/compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala @@ -77,9 +77,6 @@ object Scala3: type SemanticSymbol = Symbol | FakeSymbol given SemanticSymbolOps : AnyRef with - import SymbolOps.* - import StringOps.* - extension (sym: SemanticSymbol) def name(using Context): Name = sym match case s: Symbol => s.name diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 77328cdbb33d..3d3320eb7589 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -1569,8 +1569,10 @@ trait Implicits: /** Does candidate `cand` come too late for it to be considered as an * eligible candidate? This is the case if `cand` appears in the same - * scope as a given definition enclosing the search point and comes - * later in the source or coincides with that given definition. + * scope as a given definition enclosing the search point (with no + * class methods between the given definition and the search point) + * and `cand` comes later in the source or coincides with that given + * definition. */ def comesTooLate(cand: Candidate): Boolean = val candSym = cand.ref.symbol @@ -1578,7 +1580,7 @@ trait Implicits: if sym.owner == candSym.owner then if sym.is(ModuleClass) then candSucceedsGiven(sym.sourceModule) else sym.is(Given) && sym.span.exists && sym.span.start <= candSym.span.start - else if sym.is(Package) then false + else if sym.owner.isClass then false else candSucceedsGiven(sym.owner) ctx.isTyper diff --git a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala index 1203e309c484..51f133c972b4 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala @@ -1781,8 +1781,6 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler end TypeRepr given TypeReprMethods: TypeReprMethods with - import SymbolMethods.* - extension (self: TypeRepr) def show(using printer: Printer[TypeRepr]): String = printer.show(self) @@ -2610,8 +2608,6 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler end Symbol given SymbolMethods: SymbolMethods with - import FlagsMethods.* - extension (self: Symbol) def owner: Symbol = self.denot.owner def maybeOwner: Symbol = self.denot.maybeOwner diff --git a/tests/neg/i15474.check b/tests/neg/i15474.check index 0b23628d3051..f99c6778d1ae 100644 --- a/tests/neg/i15474.check +++ b/tests/neg/i15474.check @@ -1,31 +1,18 @@ --- Error: tests/neg/i15474.scala:7:35 ---------------------------------------------------------------------------------- -7 | def apply(from: String): Int = from.toInt // error - | ^^^^ +-- Error: tests/neg/i15474.scala:6:39 ---------------------------------------------------------------------------------- +6 | given c: Conversion[ String, Int ] = _.toInt // error + | ^ | Warning: result of implicit search for ?{ toInt: ? } will change. - | Current result Test1.c will be no longer eligible + | Current result Test2.c will be no longer eligible | because it is not defined before the search position. | Result with new rules: augmentString. | To opt into the new rules, use the `experimental.avoidLoopingGivens` language import. | | To fix the problem without the language import, you could try one of the following: - | - rearrange definitions so that Test1.c comes earlier, + | - rearrange definitions so that Test2.c comes earlier, | - use an explicit conversion, | - use an import to get extension method into scope. --- Error: tests/neg/i15474.scala:10:39 --------------------------------------------------------------------------------- -10 | given c: Conversion[ String, Int ] = _.toInt // error - | ^ - | Warning: result of implicit search for ?{ toInt: ? } will change. - | Current result Test2.c will be no longer eligible - | because it is not defined before the search position. - | Result with new rules: augmentString. - | To opt into the new rules, use the `experimental.avoidLoopingGivens` language import. - | - | To fix the problem without the language import, you could try one of the following: - | - rearrange definitions so that Test2.c comes earlier, - | - use an explicit conversion, - | - use an import to get extension method into scope. --- Error: tests/neg/i15474.scala:16:56 --------------------------------------------------------------------------------- -16 | given Ordering[Price] = summon[Ordering[BigDecimal]] // error +-- Error: tests/neg/i15474.scala:12:56 --------------------------------------------------------------------------------- +12 | given Ordering[Price] = summon[Ordering[BigDecimal]] // error | ^ | Warning: result of implicit search for Ordering[BigDecimal] will change. | Current result Prices.Price.given_Ordering_Price will be no longer eligible diff --git a/tests/neg/i15474.scala b/tests/neg/i15474.scala index 5a66ea016630..b196d1b400ef 100644 --- a/tests/neg/i15474.scala +++ b/tests/neg/i15474.scala @@ -2,10 +2,6 @@ import scala.language.implicitConversions -object Test1: - given c: Conversion[ String, Int ] with - def apply(from: String): Int = from.toInt // error - object Test2: given c: Conversion[ String, Int ] = _.toInt // error diff --git a/tests/neg/i15474b.check b/tests/neg/i15474b.check new file mode 100644 index 000000000000..73ef720af7e3 --- /dev/null +++ b/tests/neg/i15474b.check @@ -0,0 +1,5 @@ +-- Error: tests/neg/i15474b.scala:7:40 --------------------------------------------------------------------------------- +7 | def apply(from: String): Int = from.toInt // error: infinite loop in function body + | ^^^^^^^^^^ + | Infinite loop in function body + | Test1.c.apply(from).toInt diff --git a/tests/neg/i15474b.scala b/tests/neg/i15474b.scala new file mode 100644 index 000000000000..9d496c37ef00 --- /dev/null +++ b/tests/neg/i15474b.scala @@ -0,0 +1,8 @@ +//> using options -Xfatal-warnings + +import scala.language.implicitConversions + +object Test1: + given c: Conversion[ String, Int ] with + def apply(from: String): Int = from.toInt // error: infinite loop in function body + diff --git a/tests/pos/i15474.scala b/tests/pos/i15474.scala index 8adc5ad7233d..6b9e55806ae3 100644 --- a/tests/pos/i15474.scala +++ b/tests/pos/i15474.scala @@ -2,10 +2,6 @@ import scala.language.implicitConversions import scala.language.experimental.avoidLoopingGivens -object Test1: - given c: Conversion[ String, Int ] with - def apply(from: String): Int = from.toInt // was error, now avoided - object Test2: given c: Conversion[ String, Int ] = _.toInt // now avoided, was loop not detected, could be used as a fallback to avoid the warning. From 07c821a1ad5b545fa1f8548ec1ed889fcefc56e9 Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 18 Dec 2023 22:58:34 +0100 Subject: [PATCH 013/220] Add tweaks and docs --- .../src/dotty/tools/dotc/config/Feature.scala | 2 +- .../tools/dotc/config/SourceVersion.scala | 1 + .../dotty/tools/dotc/typer/Implicits.scala | 32 ++++++++-------- .../changed-features/implicit-resolution.md | 23 ----------- .../experimental/given-loop-prevention.md | 31 +++++++++++++++ docs/sidebar.yml | 1 + .../runtime/stdLibPatches/language.scala | 6 +-- tests/neg/i15474.check | 38 ++++++++++--------- tests/neg/i6716.check | 18 +++++---- tests/neg/i7294-a.check | 28 +++++++------- tests/neg/i7294-a.scala | 2 + tests/neg/i7294-b.scala | 2 + tests/neg/looping-givens.scala | 2 + tests/pos/i15474.scala | 2 +- tests/pos/looping-givens.scala | 2 +- tests/run/i6716.scala | 4 +- 16 files changed, 110 insertions(+), 84 deletions(-) create mode 100644 docs/_docs/reference/experimental/given-loop-prevention.md diff --git a/compiler/src/dotty/tools/dotc/config/Feature.scala b/compiler/src/dotty/tools/dotc/config/Feature.scala index e8ca30ecb243..cdd83b15f4fc 100644 --- a/compiler/src/dotty/tools/dotc/config/Feature.scala +++ b/compiler/src/dotty/tools/dotc/config/Feature.scala @@ -33,7 +33,7 @@ object Feature: val pureFunctions = experimental("pureFunctions") val captureChecking = experimental("captureChecking") val into = experimental("into") - val avoidLoopingGivens = experimental("avoidLoopingGivens") + val givenLoopPrevention = experimental("givenLoopPrevention") val globalOnlyImports: Set[TermName] = Set(pureFunctions, captureChecking) diff --git a/compiler/src/dotty/tools/dotc/config/SourceVersion.scala b/compiler/src/dotty/tools/dotc/config/SourceVersion.scala index f6db0bac0452..33b946ed173f 100644 --- a/compiler/src/dotty/tools/dotc/config/SourceVersion.scala +++ b/compiler/src/dotty/tools/dotc/config/SourceVersion.scala @@ -10,6 +10,7 @@ enum SourceVersion: case `3.2-migration`, `3.2` case `3.3-migration`, `3.3` case `3.4-migration`, `3.4` + case `3.5-migration`, `3.5` // !!! Keep in sync with scala.runtime.stdlibPatches.language !!! case `future-migration`, `future` diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 3d3320eb7589..1672c94fd969 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -1569,19 +1569,18 @@ trait Implicits: /** Does candidate `cand` come too late for it to be considered as an * eligible candidate? This is the case if `cand` appears in the same - * scope as a given definition enclosing the search point (with no - * class methods between the given definition and the search point) - * and `cand` comes later in the source or coincides with that given - * definition. + * scope as a given definition of the form `given ... = ...` that + * encloses the search point and `cand` comes later in the source or + * coincides with that given definition. */ def comesTooLate(cand: Candidate): Boolean = val candSym = cand.ref.symbol def candSucceedsGiven(sym: Symbol): Boolean = - if sym.owner == candSym.owner then - if sym.is(ModuleClass) then candSucceedsGiven(sym.sourceModule) - else sym.is(Given) && sym.span.exists && sym.span.start <= candSym.span.start - else if sym.owner.isClass then false - else candSucceedsGiven(sym.owner) + val owner = sym.owner + if owner == candSym.owner then + sym.is(GivenVal) && sym.span.exists && sym.span.start <= candSym.span.start + else if owner.isClass then false + else candSucceedsGiven(owner) ctx.isTyper && !candSym.isOneOf(TermParamOrAccessor | Synthetic) @@ -1596,7 +1595,7 @@ trait Implicits: def checkResolutionChange(result: SearchResult) = if (eligible ne preEligible) - && !Feature.enabled(Feature.avoidLoopingGivens) + && !Feature.enabled(Feature.givenLoopPrevention) then val prevResult = searchImplicit(preEligible, contextual) prevResult match @@ -1617,17 +1616,20 @@ trait Implicits: case result: SearchSuccess if prevResult.ref frozen_=:= result.ref => // OK case _ => - report.error( - em"""Warning: result of implicit search for $pt will change. + val msg = + em"""Result of implicit search for $pt will change. |Current result ${showResult(prevResult)} will be no longer eligible | because it is not defined before the search position. |Result with new rules: ${showResult(result)}. - |To opt into the new rules, use the `experimental.avoidLoopingGivens` language import. + |To opt into the new rules, use the `experimental.givenLoopPrevention` language import. | |To fix the problem without the language import, you could try one of the following: + | - use a `given ... with` clause as the enclosing given, | - rearrange definitions so that ${showResult(prevResult)} comes earlier, - | - use an explicit $remedy.""", - srcPos) + | - use an explicit $remedy.""" + if sourceVersion.isAtLeast(SourceVersion.`3.5`) + then report.error(msg, srcPos) + else report.warning(msg.append("\nThis will be an error in Scala 3.5 and later."), srcPos) case _ => prevResult else result diff --git a/docs/_docs/reference/changed-features/implicit-resolution.md b/docs/_docs/reference/changed-features/implicit-resolution.md index ab8293724a4e..861a63bd4a05 100644 --- a/docs/_docs/reference/changed-features/implicit-resolution.md +++ b/docs/_docs/reference/changed-features/implicit-resolution.md @@ -164,26 +164,3 @@ The new rules are as follows: An implicit `a` defined in `A` is more specific th Condition (*) is new. It is necessary to ensure that the defined relation is transitive. [//]: # todo: expand with precise rules - -**9.** Implicit resolution now tries to avoid recursive givens that can lead to an infinite loop at runtime. Here is an example: - -```scala -object Prices { - opaque type Price = BigDecimal - - object Price{ - given Ordering[Price] = summon[Ordering[BigDecimal]] // was error, now avoided - } -} -``` - -Previously, implicit resolution would resolve the `summon` to the given in `Price`, leading to an infinite loop (a warning was issued in that case). We now use the underlying given in `BigDecimal` instead. We achieve that by adding the following rule for implicit search: - - - When doing an implicit search while checking the implementation of a `given` definition `G`, discard all search results that lead back to `G` or to a given -with the same owner as `G` that comes later in the source than `G`. - -The new behavior is enabled under `-source future`. In earlier versions, a -warning is issued where that behavior will change. - -Old-style implicit definitions are unaffected by this change. - diff --git a/docs/_docs/reference/experimental/given-loop-prevention.md b/docs/_docs/reference/experimental/given-loop-prevention.md new file mode 100644 index 000000000000..e306ba977d45 --- /dev/null +++ b/docs/_docs/reference/experimental/given-loop-prevention.md @@ -0,0 +1,31 @@ +--- +layout: doc-page +title: Given Loop Prevention +redirectFrom: /docs/reference/other-new-features/into-modifier.html +nightlyOf: https://docs.scala-lang.org/scala3/reference/experimental/into-modifier.html +--- + +Implicit resolution now avoids generating recursive givens that can lead to an infinite loop at runtime. Here is an example: + +```scala +object Prices { + opaque type Price = BigDecimal + + object Price{ + given Ordering[Price] = summon[Ordering[BigDecimal]] // was error, now avoided + } +} +``` + +Previously, implicit resolution would resolve the `summon` to the given in `Price`, leading to an infinite loop (a warning was issued in that case). We now use the underlying given in `BigDecimal` instead. We achieve that by adding the following rule for implicit search: + + - When doing an implicit search while checking the implementation of a `given` definition `G` of the form + ``` + given ... = .... + ``` + discard all search results that lead back to `G` or to a given with the same owner as `G` that comes later in the source than `G`. + +The new behavior is enabled with the `experimental.givenLoopPrevention` language import. If no such import or setting is given, a warning is issued where the behavior would change under that import (for source version 3.4 and later). + +Old-style implicit definitions are unaffected by this change. + diff --git a/docs/sidebar.yml b/docs/sidebar.yml index 65d7ac2f9ee4..d9f86d5141c3 100644 --- a/docs/sidebar.yml +++ b/docs/sidebar.yml @@ -153,6 +153,7 @@ subsection: - page: reference/experimental/cc.md - page: reference/experimental/purefuns.md - page: reference/experimental/tupled-function.md + - page: reference/experimental/given-loop-prevention.md - page: reference/syntax.md - title: Language Versions index: reference/language-versions/language-versions.md diff --git a/library/src/scala/runtime/stdLibPatches/language.scala b/library/src/scala/runtime/stdLibPatches/language.scala index 9fa8bff120af..9a2a034c6b7d 100644 --- a/library/src/scala/runtime/stdLibPatches/language.scala +++ b/library/src/scala/runtime/stdLibPatches/language.scala @@ -95,10 +95,10 @@ object language: * givens. By the new rules, a given may not implicitly use itself or givens * defined after it. * - * @see [[https://dotty.epfl.ch/docs/reference/experimental/avoid-looping-givens]] + * @see [[https://dotty.epfl.ch/docs/reference/experimental/given-loop-prevention]] */ - @compileTimeOnly("`avoidLoopingGivens` can only be used at compile time in import statements") - object avoidLoopingGivens + @compileTimeOnly("`givenLoopPrevention` can only be used at compile time in import statements") + object givenLoopPrevention /** Was needed to add support for relaxed imports of extension methods. * The language import is no longer needed as this is now a standard feature since SIP was accepted. diff --git a/tests/neg/i15474.check b/tests/neg/i15474.check index f99c6778d1ae..6a60aed304aa 100644 --- a/tests/neg/i15474.check +++ b/tests/neg/i15474.check @@ -1,25 +1,29 @@ -- Error: tests/neg/i15474.scala:6:39 ---------------------------------------------------------------------------------- 6 | given c: Conversion[ String, Int ] = _.toInt // error | ^ - | Warning: result of implicit search for ?{ toInt: ? } will change. - | Current result Test2.c will be no longer eligible - | because it is not defined before the search position. - | Result with new rules: augmentString. - | To opt into the new rules, use the `experimental.avoidLoopingGivens` language import. + | Result of implicit search for ?{ toInt: ? } will change. + | Current result Test2.c will be no longer eligible + | because it is not defined before the search position. + | Result with new rules: augmentString. + | To opt into the new rules, use the `experimental.givenLoopPrevention` language import. | - | To fix the problem without the language import, you could try one of the following: - | - rearrange definitions so that Test2.c comes earlier, - | - use an explicit conversion, - | - use an import to get extension method into scope. + | To fix the problem without the language import, you could try one of the following: + | - use a `given ... with` clause as the enclosing given, + | - rearrange definitions so that Test2.c comes earlier, + | - use an explicit conversion, + | - use an import to get extension method into scope. + | This will be an error in Scala 3.5 and later. -- Error: tests/neg/i15474.scala:12:56 --------------------------------------------------------------------------------- 12 | given Ordering[Price] = summon[Ordering[BigDecimal]] // error | ^ - | Warning: result of implicit search for Ordering[BigDecimal] will change. - | Current result Prices.Price.given_Ordering_Price will be no longer eligible - | because it is not defined before the search position. - | Result with new rules: scala.math.Ordering.BigDecimal. - | To opt into the new rules, use the `experimental.avoidLoopingGivens` language import. + | Result of implicit search for Ordering[BigDecimal] will change. + | Current result Prices.Price.given_Ordering_Price will be no longer eligible + | because it is not defined before the search position. + | Result with new rules: scala.math.Ordering.BigDecimal. + | To opt into the new rules, use the `experimental.givenLoopPrevention` language import. | - | To fix the problem without the language import, you could try one of the following: - | - rearrange definitions so that Prices.Price.given_Ordering_Price comes earlier, - | - use an explicit argument. + | To fix the problem without the language import, you could try one of the following: + | - use a `given ... with` clause as the enclosing given, + | - rearrange definitions so that Prices.Price.given_Ordering_Price comes earlier, + | - use an explicit argument. + | This will be an error in Scala 3.5 and later. diff --git a/tests/neg/i6716.check b/tests/neg/i6716.check index 6771d736b6af..e70ac4b15f9c 100644 --- a/tests/neg/i6716.check +++ b/tests/neg/i6716.check @@ -1,12 +1,14 @@ -- Error: tests/neg/i6716.scala:12:39 ---------------------------------------------------------------------------------- 12 | given Monad[Bar] = summon[Monad[Foo]] // error | ^ - | Warning: result of implicit search for Monad[Foo] will change. - | Current result Bar.given_Monad_Bar will be no longer eligible - | because it is not defined before the search position. - | Result with new rules: Foo.given_Monad_Foo. - | To opt into the new rules, use the `experimental.avoidLoopingGivens` language import. + | Result of implicit search for Monad[Foo] will change. + | Current result Bar.given_Monad_Bar will be no longer eligible + | because it is not defined before the search position. + | Result with new rules: Foo.given_Monad_Foo. + | To opt into the new rules, use the `experimental.givenLoopPrevention` language import. | - | To fix the problem without the language import, you could try one of the following: - | - rearrange definitions so that Bar.given_Monad_Bar comes earlier, - | - use an explicit argument. + | To fix the problem without the language import, you could try one of the following: + | - use a `given ... with` clause as the enclosing given, + | - rearrange definitions so that Bar.given_Monad_Bar comes earlier, + | - use an explicit argument. + | This will be an error in Scala 3.5 and later. diff --git a/tests/neg/i7294-a.check b/tests/neg/i7294-a.check index 887635d89a35..319ed8e1c9d0 100644 --- a/tests/neg/i7294-a.check +++ b/tests/neg/i7294-a.check @@ -1,23 +1,25 @@ --- Error: tests/neg/i7294-a.scala:6:10 --------------------------------------------------------------------------------- -6 | case x: T => x.g(10) // error // error +-- [E007] Type Mismatch Error: tests/neg/i7294-a.scala:8:18 ------------------------------------------------------------ +8 | case x: T => x.g(10) // error // error + | ^^^^^^^ + | Found: Any + | Required: T + | + | where: T is a type in given instance f with bounds <: foo.Foo + | + | longer explanation available when compiling with `-explain` +-- Error: tests/neg/i7294-a.scala:8:10 --------------------------------------------------------------------------------- +8 | case x: T => x.g(10) // error // error | ^ - | Warning: result of implicit search for scala.reflect.TypeTest[Nothing, T] will change. + | Result of implicit search for scala.reflect.TypeTest[Nothing, T] will change. | Current result foo.i7294-a$package.f will be no longer eligible | because it is not defined before the search position. | Result with new rules: No Matching Implicit. - | To opt into the new rules, use the `experimental.avoidLoopingGivens` language import. + | To opt into the new rules, use the `experimental.givenLoopPrevention` language import. | | To fix the problem without the language import, you could try one of the following: + | - use a `given ... with` clause as the enclosing given, | - rearrange definitions so that foo.i7294-a$package.f comes earlier, | - use an explicit argument. + | This will be an error in Scala 3.5 and later. | | where: T is a type in given instance f with bounds <: foo.Foo --- [E007] Type Mismatch Error: tests/neg/i7294-a.scala:6:18 ------------------------------------------------------------ -6 | case x: T => x.g(10) // error // error - | ^^^^^^^ - | Found: Any - | Required: T - | - | where: T is a type in given instance f with bounds <: foo.Foo - | - | longer explanation available when compiling with `-explain` diff --git a/tests/neg/i7294-a.scala b/tests/neg/i7294-a.scala index 538dc3159fb8..b0710413eefd 100644 --- a/tests/neg/i7294-a.scala +++ b/tests/neg/i7294-a.scala @@ -1,3 +1,5 @@ +//> using options -Xfatal-warnings + package foo trait Foo { def g(x: Int): Any } diff --git a/tests/neg/i7294-b.scala b/tests/neg/i7294-b.scala index b06d814444e8..8c6f9328cc20 100644 --- a/tests/neg/i7294-b.scala +++ b/tests/neg/i7294-b.scala @@ -1,3 +1,5 @@ +//> using options -Xfatal-warnings + package foo trait Foo { def g(x: Any): Any } diff --git a/tests/neg/looping-givens.scala b/tests/neg/looping-givens.scala index 572f1707861f..357a417f0ed9 100644 --- a/tests/neg/looping-givens.scala +++ b/tests/neg/looping-givens.scala @@ -1,3 +1,5 @@ +//> using options -Xfatal-warnings + class A class B diff --git a/tests/pos/i15474.scala b/tests/pos/i15474.scala index 6b9e55806ae3..b006f8b61cf4 100644 --- a/tests/pos/i15474.scala +++ b/tests/pos/i15474.scala @@ -1,6 +1,6 @@ //> using options -Xfatal-warnings import scala.language.implicitConversions -import scala.language.experimental.avoidLoopingGivens +import scala.language.experimental.givenLoopPrevention object Test2: given c: Conversion[ String, Int ] = _.toInt // now avoided, was loop not detected, could be used as a fallback to avoid the warning. diff --git a/tests/pos/looping-givens.scala b/tests/pos/looping-givens.scala index ed11981c1bf6..1b620b5c113e 100644 --- a/tests/pos/looping-givens.scala +++ b/tests/pos/looping-givens.scala @@ -1,4 +1,4 @@ -import language.experimental.avoidLoopingGivens +import language.experimental.givenLoopPrevention class A class B diff --git a/tests/run/i6716.scala b/tests/run/i6716.scala index 6208a52190fe..4cca37f96a6f 100644 --- a/tests/run/i6716.scala +++ b/tests/run/i6716.scala @@ -1,6 +1,6 @@ //> using options -Xfatal-warnings -import scala.language.experimental.avoidLoopingGivens +import scala.language.experimental.givenLoopPrevention trait Monad[T]: def id: String @@ -11,7 +11,7 @@ object Foo { opaque type Bar = Foo object Bar { - given Monad[Bar] = summon[Monad[Foo]] // was error fixed by avoidLoopingGivens + given Monad[Bar] = summon[Monad[Foo]] // was error, fixed by givenLoopPrevention } object Test extends App { From 87e45fa95a08d0f0a70ab295e12cd066de2cc858 Mon Sep 17 00:00:00 2001 From: odersky Date: Tue, 19 Dec 2023 13:38:33 +0100 Subject: [PATCH 014/220] Swap two givens in Specs2 to satisfy new restriuction --- community-build/community-projects/specs2 | 2 +- tests/neg/i7294-a.check | 50 +++++++++++------------ tests/neg/i7294-a.scala | 10 +++-- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/community-build/community-projects/specs2 b/community-build/community-projects/specs2 index e42f7987b4ce..ba01cca013d9 160000 --- a/community-build/community-projects/specs2 +++ b/community-build/community-projects/specs2 @@ -1 +1 @@ -Subproject commit e42f7987b4ce30d95fca3f30b9d508021f2fdac7 +Subproject commit ba01cca013d9d99e390d17619664bdedd716e0d7 diff --git a/tests/neg/i7294-a.check b/tests/neg/i7294-a.check index 319ed8e1c9d0..6fac76a9faa5 100644 --- a/tests/neg/i7294-a.check +++ b/tests/neg/i7294-a.check @@ -1,25 +1,25 @@ --- [E007] Type Mismatch Error: tests/neg/i7294-a.scala:8:18 ------------------------------------------------------------ -8 | case x: T => x.g(10) // error // error - | ^^^^^^^ - | Found: Any - | Required: T - | - | where: T is a type in given instance f with bounds <: foo.Foo - | - | longer explanation available when compiling with `-explain` --- Error: tests/neg/i7294-a.scala:8:10 --------------------------------------------------------------------------------- -8 | case x: T => x.g(10) // error // error - | ^ - | Result of implicit search for scala.reflect.TypeTest[Nothing, T] will change. - | Current result foo.i7294-a$package.f will be no longer eligible - | because it is not defined before the search position. - | Result with new rules: No Matching Implicit. - | To opt into the new rules, use the `experimental.givenLoopPrevention` language import. - | - | To fix the problem without the language import, you could try one of the following: - | - use a `given ... with` clause as the enclosing given, - | - rearrange definitions so that foo.i7294-a$package.f comes earlier, - | - use an explicit argument. - | This will be an error in Scala 3.5 and later. - | - | where: T is a type in given instance f with bounds <: foo.Foo +-- [E007] Type Mismatch Error: tests/neg/i7294-a.scala:10:20 ----------------------------------------------------------- +10 | case x: T => x.g(10) // error // error + | ^^^^^^^ + | Found: Any + | Required: T + | + | where: T is a type in given instance f with bounds <: foo.Foo + | + | longer explanation available when compiling with `-explain` +-- Error: tests/neg/i7294-a.scala:10:12 -------------------------------------------------------------------------------- +10 | case x: T => x.g(10) // error // error + | ^ + | Result of implicit search for scala.reflect.TypeTest[Nothing, T] will change. + | Current result foo.Test.f will be no longer eligible + | because it is not defined before the search position. + | Result with new rules: No Matching Implicit. + | To opt into the new rules, use the `experimental.givenLoopPrevention` language import. + | + | To fix the problem without the language import, you could try one of the following: + | - use a `given ... with` clause as the enclosing given, + | - rearrange definitions so that foo.Test.f comes earlier, + | - use an explicit argument. + | This will be an error in Scala 3.5 and later. + | + | where: T is a type in given instance f with bounds <: foo.Foo diff --git a/tests/neg/i7294-a.scala b/tests/neg/i7294-a.scala index b0710413eefd..3453e88cf741 100644 --- a/tests/neg/i7294-a.scala +++ b/tests/neg/i7294-a.scala @@ -4,8 +4,10 @@ package foo trait Foo { def g(x: Int): Any } -inline given f[T <: Foo]: T = ??? match { - case x: T => x.g(10) // error // error -} +object Test: -@main def Test = f + inline given f[T <: Foo]: T = ??? match { + case x: T => x.g(10) // error // error + } + + @main def Test = f From b5479c561ff5bd8140a3a87bd768bf9671fe1695 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 20 Dec 2023 10:47:37 +0100 Subject: [PATCH 015/220] Show `git diff` command on checkfile failure This diff is more familiar and consistent across systems. We can assume that all developers of Dotty have git installed. When a checkfile fails we now show ```diff Test output dumped in: tests/run/xyz.check.out - See diff of the checkfile (`brew install icdiff` for colored diff) - > diff tests/run/xyz.check tests/run/xyz.check.out + See diff of the checkfile (`--color=always` for colored diff) + > git diff --no-index -- tests/run/xyz.check tests/run/xyz.check.out Replace checkfile with current output > mv tests/run/xyz.check.out tests/run/xyz.check ``` --- compiler/test/dotty/tools/vulpix/FileDiff.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/test/dotty/tools/vulpix/FileDiff.scala b/compiler/test/dotty/tools/vulpix/FileDiff.scala index 5e882be6425a..80fb2bf43534 100644 --- a/compiler/test/dotty/tools/vulpix/FileDiff.scala +++ b/compiler/test/dotty/tools/vulpix/FileDiff.scala @@ -12,10 +12,13 @@ import java.nio.charset.StandardCharsets object FileDiff { + def diffCommand(expectFile: String, actualFile: String): String = + s"git diff --no-index -- $expectFile $actualFile" + def diffMessage(expectFile: String, actualFile: String): String = s"""Test output dumped in: $actualFile - | See diff of the checkfile (`brew install icdiff` for colored diff) - | > diff $expectFile $actualFile + | See diff of the checkfile (`--color=always` for colored diff) + | > ${FileDiff.diffCommand(expectFile, actualFile)} | Replace checkfile with current output | > mv $actualFile $expectFile """.stripMargin From 63bf7f3349dd2f3844d5d53cae38a5fa625da4ce Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 20 Dec 2023 14:00:10 +0100 Subject: [PATCH 016/220] Properly identify empty bounds in error message This caused a trailing space which can easily misbehave in checkfiles. --- compiler/src/dotty/tools/dotc/reporting/Message.scala | 2 +- tests/neg/i13780-1.check | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/Message.scala b/compiler/src/dotty/tools/dotc/reporting/Message.scala index 484789a7fe45..22eac074a0fd 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Message.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Message.scala @@ -147,7 +147,7 @@ object Message: } def addendum(cat: String, info: Type): String = info match { - case bounds @ TypeBounds(lo, hi) if bounds ne TypeBounds.empty => + case bounds @ TypeBounds(lo, hi) if !(bounds =:= TypeBounds.empty) => if (lo eq hi) i" which is an alias of $lo" else i" with $cat ${boundsStr(bounds)}" case _ => diff --git a/tests/neg/i13780-1.check b/tests/neg/i13780-1.check index 029ef3f3ac4b..07cc03b35dce 100644 --- a/tests/neg/i13780-1.check +++ b/tests/neg/i13780-1.check @@ -5,7 +5,7 @@ | Required: h | | where: VS is a type in method foo with bounds <: Tuple - | h is a type in method foo with bounds + | h is a type in method foo | t is a type in method foo with bounds <: Tuple | | From bde6bf3775e2e532fe47b38fd222601c16c8523d Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 20 Dec 2023 17:32:14 +0100 Subject: [PATCH 017/220] Add 3.5 versions --- .../dotty/tools/dotc/config/SourceVersion.scala | 1 + .../src/scala/runtime/stdLibPatches/language.scala | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/compiler/src/dotty/tools/dotc/config/SourceVersion.scala b/compiler/src/dotty/tools/dotc/config/SourceVersion.scala index f6db0bac0452..33b946ed173f 100644 --- a/compiler/src/dotty/tools/dotc/config/SourceVersion.scala +++ b/compiler/src/dotty/tools/dotc/config/SourceVersion.scala @@ -10,6 +10,7 @@ enum SourceVersion: case `3.2-migration`, `3.2` case `3.3-migration`, `3.3` case `3.4-migration`, `3.4` + case `3.5-migration`, `3.5` // !!! Keep in sync with scala.runtime.stdlibPatches.language !!! case `future-migration`, `future` diff --git a/library/src/scala/runtime/stdLibPatches/language.scala b/library/src/scala/runtime/stdLibPatches/language.scala index c2a12cec2ecc..c37555f26653 100644 --- a/library/src/scala/runtime/stdLibPatches/language.scala +++ b/library/src/scala/runtime/stdLibPatches/language.scala @@ -249,6 +249,20 @@ object language: @compileTimeOnly("`3.4` can only be used at compile time in import statements") object `3.4` + /** Set source version to 3.5-migration. + * + * @see [[https://docs.scala-lang.org/scala3/guides/migration/compatibility-intro.html]] + */ + @compileTimeOnly("`3.5-migration` can only be used at compile time in import statements") + object `3.5-migration` + + /** Set source version to 3.5 + * + * @see [[https://docs.scala-lang.org/scala3/guides/migration/compatibility-intro.html]] + */ + @compileTimeOnly("`3.5` can only be used at compile time in import statements") + object `3.5` + // !!! Keep in sync with dotty.tools.dotc.config.SourceVersion !!! // Also add tests in `tests/pos/source-import-3-x.scala` and `tests/pos/source-import-3-x-migration.scala` From 3c5e21636f50db1afaa192b42f643b42b5807ee3 Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Wed, 20 Dec 2023 18:00:26 +0100 Subject: [PATCH 018/220] improvement: Support completions for implicit classes Previously, we would only support extension methods and not the old style implicit classes. Now, those are supported also. Introduced in https://github.com/scalameta/metals/pull/5904/ --- .../tools/pc/CompilerSearchVisitor.scala | 9 +- .../dotty/tools/pc/SemanticdbSymbols.scala | 11 ++ .../pc/completions/CompletionProvider.scala | 4 +- .../pc/completions/CompletionValue.scala | 14 ++ .../tools/pc/completions/Completions.scala | 28 ++- .../completion/CompletionExtensionSuite.scala | 170 +++++++++++++++++- 6 files changed, 230 insertions(+), 6 deletions(-) diff --git a/presentation-compiler/src/main/dotty/tools/pc/CompilerSearchVisitor.scala b/presentation-compiler/src/main/dotty/tools/pc/CompilerSearchVisitor.scala index d217a0acd9b1..d20537f0239e 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/CompilerSearchVisitor.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/CompilerSearchVisitor.scala @@ -9,6 +9,7 @@ import scala.meta.pc.* import scala.util.control.NonFatal import dotty.tools.dotc.core.Contexts.* +import dotty.tools.dotc.core.Flags import dotty.tools.dotc.core.Names.* import dotty.tools.dotc.core.Symbols.* @@ -19,8 +20,14 @@ class CompilerSearchVisitor( val logger: Logger = Logger.getLogger(classOf[CompilerSearchVisitor].getName().nn).nn + private def isAccessibleImplicitClass(sym: Symbol) = + val owner = sym.maybeOwner + owner != NoSymbol && owner.isClass && + owner.is(Flags.Implicit) && + owner.isStatic && owner.isPublic + private def isAccessible(sym: Symbol): Boolean = try - sym != NoSymbol && sym.isPublic && sym.isStatic + sym != NoSymbol && sym.isPublic && sym.isStatic || isAccessibleImplicitClass(sym) catch case err: AssertionError => logger.log(Level.WARNING, err.getMessage()) diff --git a/presentation-compiler/src/main/dotty/tools/pc/SemanticdbSymbols.scala b/presentation-compiler/src/main/dotty/tools/pc/SemanticdbSymbols.scala index c6e43186cef2..da8add9df327 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/SemanticdbSymbols.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/SemanticdbSymbols.scala @@ -49,7 +49,16 @@ object SemanticdbSymbols: // however in scalac this method is defined only in `module Files` if typeSym.is(JavaDefined) then typeSym :: owner.info.decl(termName(value)).symbol :: Nil + /** + * Looks like decl doesn't work for: + * package a: + * implicit class <> (i: Int): + * def inc = i + 1 + */ + else if typeSym == NoSymbol then + owner.info.member(typeName(value)).symbol :: Nil else typeSym :: Nil + end if case Descriptor.Term(value) => val outSymbol = owner.info.decl(termName(value)).symbol if outSymbol.exists @@ -92,6 +101,8 @@ object SemanticdbSymbols: .map(_.symbol) .filter(sym => symbolName(sym) == s) .toList + end match + end tryMember parentSymbol.flatMap(tryMember) try diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala index f008ea5a9dbb..b3b7d1fde07d 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala @@ -215,7 +215,7 @@ class CompletionProvider( def mkItemWithImports( v: CompletionValue.Workspace | CompletionValue.Extension | - CompletionValue.Interpolator + CompletionValue.Interpolator | CompletionValue.ImplicitClass ) = val sym = v.symbol path match @@ -260,7 +260,7 @@ class CompletionProvider( end mkItemWithImports completion match - case v: (CompletionValue.Workspace | CompletionValue.Extension) => + case v: (CompletionValue.Workspace | CompletionValue.Extension | CompletionValue.ImplicitClass) => mkItemWithImports(v) case v: CompletionValue.Interpolator if v.isWorkspace || v.isExtension => mkItemWithImports(v) diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionValue.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionValue.scala index a5b2fb40f418..a890afa3cb67 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionValue.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionValue.scala @@ -143,6 +143,20 @@ object CompletionValue: override def isFromWorkspace: Boolean = true override def completionItemDataKind: Integer = CompletionSource.WorkspaceKind.ordinal + /** + * CompletionValue for old implicit classes methods via SymbolSearch + */ + case class ImplicitClass( + label: String, + symbol: Symbol, + override val snippetSuffix: CompletionSuffix, + override val importSymbol: Symbol, + ) extends Symbolic: + override def completionItemKind(using Context): CompletionItemKind = + CompletionItemKind.Method + override def description(printer: ShortenedTypePrinter)(using Context): String = + s"${printer.completionSymbol(symbol)} (implicit)" + /** * CompletionValue for extension methods via SymbolSearch */ diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala index 1e2dbb5cdaa1..118a9edae816 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala @@ -520,14 +520,38 @@ class Completions( Some(search.search(query, buildTargetIdentifier, visitor).nn) case CompletionKind.Members => val visitor = new CompilerSearchVisitor(sym => - if sym.is(ExtensionMethod) && + def isExtensionMethod = sym.is(ExtensionMethod) && qualType.widenDealias <:< sym.extensionParam.info.widenDealias - then + def isImplicitClass(owner: Symbol) = + val constructorParam = + owner.info + .membersBasedOnFlags( + Flags.ParamAccessor, + Flags.EmptyFlags, + ) + .headOption + .map(_.info) + owner.isClass && owner.is(Flags.Implicit) && + constructorParam.exists(p => + qualType.widenDealias <:< p.widenDealias + ) + end isImplicitClass + + def isImplicitClassMethod = sym.is(Flags.Method) && !sym.isConstructor && + isImplicitClass(sym.maybeOwner) + + if isExtensionMethod then completionsWithSuffix( sym, sym.decodedName, CompletionValue.Extension(_, _, _) ).map(visit).forall(_ == true) + else if isImplicitClassMethod then + completionsWithSuffix( + sym, + sym.decodedName, + CompletionValue.ImplicitClass(_, _, _, sym.maybeOwner), + ).map(visit).forall(_ == true) else false, ) Some(search.searchMethods(query, buildTargetIdentifier, visitor).nn) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionExtensionSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionExtensionSuite.scala index a260fe8b6e52..c01b38e7cf61 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionExtensionSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionExtensionSuite.scala @@ -20,6 +20,20 @@ class CompletionExtensionSuite extends BaseCompletionSuite: |""".stripMargin ) + @Test def `simple-old-syntax` = + check( + """|package example + | + |object Test: + | implicit class TestOps(a: Int): + | def testOps(b: Int): String = ??? + | + |def main = 100.test@@ + |""".stripMargin, + """|testOps(b: Int): String (implicit) + |""".stripMargin + ) + @Test def `simple2` = check( """|package example @@ -35,6 +49,21 @@ class CompletionExtensionSuite extends BaseCompletionSuite: filter = _.contains("(extension)") ) + @Test def `simple2-old-syntax` = + check( + """|package example + | + |object enrichments: + | implicit class TestOps(a: Int): + | def testOps(b: Int): String = ??? + | + |def main = 100.t@@ + |""".stripMargin, + """|testOps(b: Int): String (implicit) + |""".stripMargin, + filter = _.contains("(implicit)") + ) + @Test def `filter-by-type` = check( """|package example @@ -52,6 +81,22 @@ class CompletionExtensionSuite extends BaseCompletionSuite: filter = _.contains("(extension)") ) + @Test def `filter-by-type-old` = + check( + """|package example + | + |object enrichments: + | implicit class A(num: Int): + | def identity2: Int = num + 1 + | implicit class B(str: String): + | def identity: String = str + | + |def main = "foo".iden@@ + |""".stripMargin, + """|identity: String (implicit) + |""".stripMargin // identity2 won't be available + ) + @Test def `filter-by-type-subtype` = check( """|package example @@ -70,6 +115,24 @@ class CompletionExtensionSuite extends BaseCompletionSuite: filter = _.contains("(extension)") ) + @Test def `filter-by-type-subtype-old` = + check( + """|package example + | + |class A + |class B extends A + | + |object enrichments: + | implicit class Test(a: A): + | def doSomething: A = a + | + |def main = (new B).do@@ + |""".stripMargin, + """|doSomething: A (implicit) + |""".stripMargin, + filter = _.contains("(implicit)") + ) + @Test def `simple-edit` = checkEdit( """|package example @@ -92,6 +155,28 @@ class CompletionExtensionSuite extends BaseCompletionSuite: |""".stripMargin ) + @Test def `simple-edit-old` = + checkEdit( + """|package example + | + |object enrichments: + | implicit class A (num: Int): + | def incr: Int = num + 1 + | + |def main = 100.inc@@ + |""".stripMargin, + """|package example + | + |import example.enrichments.A + | + |object enrichments: + | implicit class A (num: Int): + | def incr: Int = num + 1 + | + |def main = 100.incr + |""".stripMargin + ) + @Test def `simple-edit-suffix` = checkEdit( """|package example @@ -114,6 +199,28 @@ class CompletionExtensionSuite extends BaseCompletionSuite: |""".stripMargin ) + @Test def `simple-edit-suffix-old` = + checkEdit( + """|package example + | + |object enrichments: + | implicit class A (val num: Int): + | def plus(other: Int): Int = num + other + | + |def main = 100.pl@@ + |""".stripMargin, + """|package example + | + |import example.enrichments.A + | + |object enrichments: + | implicit class A (val num: Int): + | def plus(other: Int): Int = num + other + | + |def main = 100.plus($0) + |""".stripMargin + ) + @Test def `simple-empty` = check( """|package example @@ -129,6 +236,21 @@ class CompletionExtensionSuite extends BaseCompletionSuite: filter = _.contains("(extension)") ) + @Test def `simple-empty-old` = + check( + """|package example + | + |object enrichments: + | implicit class TestOps(a: Int): + | def testOps(b: Int): String = ??? + | + |def main = 100.@@ + |""".stripMargin, + """|testOps(b: Int): String (implicit) + |""".stripMargin, + filter = _.contains("(implicit)") + ) + @Test def `directly-in-pkg1` = check( """| @@ -143,6 +265,20 @@ class CompletionExtensionSuite extends BaseCompletionSuite: |""".stripMargin ) + @Test def `directly-in-pkg1-old` = + check( + """| + |package examples: + | implicit class A(num: Int): + | def incr: Int = num + 1 + | + |package examples2: + | def main = 100.inc@@ + |""".stripMargin, + """|incr: Int (implicit) + |""".stripMargin + ) + @Test def `directly-in-pkg2` = check( """|package example: @@ -157,6 +293,20 @@ class CompletionExtensionSuite extends BaseCompletionSuite: |""".stripMargin ) + @Test def `directly-in-pkg2-old` = + check( + """|package examples: + | object X: + | def fooBar(num: Int) = num + 1 + | implicit class A (num: Int) { def incr: Int = num + 1 } + | + |package examples2: + | def main = 100.inc@@ + |""".stripMargin, + """|incr: Int (implicit) + |""".stripMargin + ) + @Test def `nested-pkg` = check( """|package a: // some comment @@ -175,7 +325,25 @@ class CompletionExtensionSuite extends BaseCompletionSuite: |""".stripMargin ) - @Test def `name-conflict` = + @Test def `nested-pkg-old` = + check( + """|package aa: // some comment + | package cc: + | implicit class A (num: Int): + | def increment2 = num + 2 + | implicit class A (num: Int): + | def increment = num + 1 + | + | + |package bb: + | def main: Unit = 123.incre@@ + |""".stripMargin, + """|increment: Int (implicit) + |increment2: Int (implicit) + |""".stripMargin + ) + + @Test def `name-conflict` = checkEdit( """ |package example From 87180844d3bbe290eca4496e44ddf53110af3707 Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 20 Dec 2023 21:47:36 +0100 Subject: [PATCH 019/220] Run CheckStatic after UncacheGivenAliases --- compiler/src/dotty/tools/dotc/Compiler.scala | 2 +- .../src/dotty/tools/dotc/transform/CheckStatic.scala | 3 +++ tests/pos/i19304.scala | 9 +++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i19304.scala diff --git a/compiler/src/dotty/tools/dotc/Compiler.scala b/compiler/src/dotty/tools/dotc/Compiler.scala index aaa14a052936..290df761d117 100644 --- a/compiler/src/dotty/tools/dotc/Compiler.scala +++ b/compiler/src/dotty/tools/dotc/Compiler.scala @@ -64,7 +64,6 @@ class Compiler { new CheckReentrant, // Internal use only: Check that compiled program has no data races involving global vars new ElimPackagePrefixes, // Eliminate references to package prefixes in Select nodes new CookComments, // Cook the comments: expand variables, doc, etc. - new CheckStatic, // Check restrictions that apply to @static members new CheckLoopingImplicits, // Check that implicit defs do not call themselves in an infinite loop new BetaReduce, // Reduce closure applications new InlineVals, // Check right hand-sides of an `inline val`s @@ -76,6 +75,7 @@ class Compiler { List(new ProtectedAccessors, // Add accessors for protected members new ExtensionMethods, // Expand methods of value classes with extension methods new UncacheGivenAliases, // Avoid caching RHS of simple parameterless given aliases + new CheckStatic, // Check restrictions that apply to @static members new ElimByName, // Map by-name parameters to functions new HoistSuperArgs, // Hoist complex arguments of supercalls to enclosing scope new ForwardDepChecks, // Check that there are no forward references to local vals diff --git a/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala b/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala index 26c94407f35b..6c74f302b65d 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckStatic.scala @@ -30,6 +30,9 @@ class CheckStatic extends MiniPhase { override def description: String = CheckStatic.description + override def runsAfter: Set[String] = Set(UncacheGivenAliases.name) + // UncachedGivenAliases eliminates static lazy vals, which are flagged as errors here + override def transformTemplate(tree: tpd.Template)(using Context): tpd.Tree = { val defns = tree.body.collect{case t: ValOrDefDef => t} var hadNonStaticField = false diff --git a/tests/pos/i19304.scala b/tests/pos/i19304.scala new file mode 100644 index 000000000000..c8dee26f00fb --- /dev/null +++ b/tests/pos/i19304.scala @@ -0,0 +1,9 @@ +import scala.annotation.static +trait Foo[A] +object Foo: + @static val foo: Foo[String] = new {} + @static given Foo[String] = foo + + def bar = + val foo: Foo[String] = new {} + given Foo[String] = foo From a40fb19270cab56a3e14e8afe5690c47afe6a036 Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Thu, 21 Dec 2023 15:08:40 +0100 Subject: [PATCH 020/220] Avoid calling `addOuterRefs` when actual type is box-adapted --- .../src/dotty/tools/dotc/cc/CheckCaptures.scala | 6 +++++- .../captures/cc-selftype-unsound.scala | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 tests/neg-custom-args/captures/cc-selftype-unsound.scala diff --git a/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala b/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala index d635096b2318..e51bc8e36470 100644 --- a/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala +++ b/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala @@ -847,9 +847,13 @@ class CheckCaptures extends Recheck, SymTransformer: * where local capture roots are instantiated to root variables. */ override def checkConformsExpr(actual: Type, expected: Type, tree: Tree, addenda: Addenda)(using Context): Type = - val expected1 = alignDependentFunction(addOuterRefs(expected, actual), actual.stripCapturing) + var expected1 = alignDependentFunction(expected, actual.stripCapturing) val actualBoxed = adaptBoxed(actual, expected1, tree.srcPos) //println(i"check conforms $actualBoxed <<< $expected1") + + if actualBoxed eq actual then + // Only `addOuterRefs` when there is no box adaptation + expected1 = addOuterRefs(expected1, actual) if isCompatible(actualBoxed, expected1) then if debugSuccesses then tree match case Ident(_) => diff --git a/tests/neg-custom-args/captures/cc-selftype-unsound.scala b/tests/neg-custom-args/captures/cc-selftype-unsound.scala new file mode 100644 index 000000000000..5aaaf5e8b8ca --- /dev/null +++ b/tests/neg-custom-args/captures/cc-selftype-unsound.scala @@ -0,0 +1,15 @@ +import language.experimental.captureChecking +trait Logger +case class Boxed[T](unbox: T) + +// a horrible function, but it typechecks +def magic(l: Logger^): Logger = + class Foo: + def foo: Boxed[Logger^{this}] = + // for the following line to typecheck + // the capture checker assumes {l} <: {this} + Boxed[Logger^{this}](l) // error + val x = new Foo + val y = x.foo.unbox // y: Logger^{x} + val z: Logger = y // now the capability becomes pure + z From a8d807bfad84785bbe4dc92836a1aa848665d6c1 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 17 Nov 2023 15:46:13 +0100 Subject: [PATCH 021/220] Add `scala2-library-cc-tasty` project We can override the sources of the standard library with cc annotation in this project and generate a TASTy version of the standard library. Usage: ``` sbt> set ThisBuild/Build.scala2Library := Build.Scala2LibraryCCTasty sbt> scala3-bootstrapped/testCompilation sbt> scala3-bootstrapped/test sbt> scala3-bootstrapped/run ... ``` --- .github/workflows/ci.yaml | 11 ++++- build.sbt | 2 + project/Build.scala | 98 ++++++++++++++++++++++++++++++--------- 3 files changed, 88 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fd1fe30d3fa9..9075abcdf36e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -145,7 +145,10 @@ jobs: ./project/scripts/sbt ";sjsSandbox/run ;sjsSandbox/test ;sjsJUnitTests/test ;set sjsJUnitTests/scalaJSLinkerConfig ~= switchToESModules ;sjsJUnitTests/test ;sjsCompilerTests/test" - name: Test with Scala 2 library TASTy (fast) - run: ./project/scripts/sbt ";set ThisBuild/Build.useScala2LibraryTasty := true ;scala3-bootstrapped/testCompilation i5; scala3-bootstrapped/testCompilation tests/run/typelevel-peano.scala; scala3-bootstrapped/testOnly dotty.tools.backend.jvm.DottyBytecodeTests" # only test a subset of test to avoid doubling the CI execution time + run: ./project/scripts/sbt ";set ThisBuild/Build.scala2Library := Build.Scala2LibraryTasty ;scala3-bootstrapped/testCompilation i5; scala3-bootstrapped/testCompilation tests/run/typelevel-peano.scala; scala3-bootstrapped/testOnly dotty.tools.backend.jvm.DottyBytecodeTests" # only test a subset of test to avoid doubling the CI execution time + + - name: Test with Scala 2 library with CC TASTy (fast) + run: ./project/scripts/sbt ";set ThisBuild/Build.scala2Library := Build.Scala2LibraryCCTasty ;scala2-library-tasty/compile" # TODO test all the test configurations in non-CC library (currently disabled due to bug while loading the library) test_scala2_library_tasty: runs-on: [self-hosted, Linux] @@ -186,7 +189,11 @@ jobs: run: cp -vf .github/workflows/repositories /root/.sbt/ ; true - name: Test with Scala 2 library TASTy - run: ./project/scripts/sbt ";set ThisBuild/Build.useScala2LibraryTasty := true ;scala3-bootstrapped/test" + run: ./project/scripts/sbt ";set ThisBuild/Build.scala2Library := Build.Scala2LibraryTasty ;scala3-bootstrapped/test" + + # TODO test all the test configurations in non-CC library (currently disabled due to bug while loading the library) + # - name: Test with Scala 2 library with CC TASTy + # run: ./project/scripts/sbt ";set ThisBuild/Build.scala2Library := Build.Scala2LibraryCCTasty ;scala3-bootstrapped/test" test_windows_fast: diff --git a/build.sbt b/build.sbt index 9b6ebc194ea0..1712e80405ae 100644 --- a/build.sbt +++ b/build.sbt @@ -17,6 +17,8 @@ val `scala3-bench-micro` = Build.`scala3-bench-micro` val `scala2-library-bootstrapped` = Build.`scala2-library-bootstrapped` val `scala2-library-tasty` = Build.`scala2-library-tasty` val `scala2-library-tasty-tests` = Build.`scala2-library-tasty-tests` +val `scala2-library-cc` = Build.`scala2-library-cc` +val `scala2-library-cc-tasty` = Build.`scala2-library-cc-tasty` val `tasty-core` = Build.`tasty-core` val `tasty-core-bootstrapped` = Build.`tasty-core-bootstrapped` val `tasty-core-scala2` = Build.`tasty-core-scala2` diff --git a/project/Build.scala b/project/Build.scala index b799c32eb65a..2dcbfb0b29f9 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -173,11 +173,23 @@ object Build { // Run tests with filter through vulpix test suite val testCompilation = inputKey[Unit]("runs integration test with the supplied filter") + sealed trait Scala2Library + // Use Scala 2 compiled library JAR + object Scala2LibraryJar extends Scala2Library // Use the TASTy jar from `scala2-library-tasty` in the classpath // This only works with `scala3-bootstrapped/scalac` and tests in `scala3-bootstrapped` // - // Enable in SBT with: `set ThisBuild/Build.useScala2LibraryTasty := true` - val useScala2LibraryTasty = settingKey[Boolean]("Use the TASTy jar from `scala2-library-tasty` in the classpath") + object Scala2LibraryTasty extends Scala2Library + // Use the TASTy jar from `scala2-library-cc-tasty` in the classpath + // This only works with `scala3-bootstrapped/scalac` and tests in `scala3-bootstrapped` + // + object Scala2LibraryCCTasty extends Scala2Library + + // Set in SBT with: + // - `set ThisBuild/Build.scala2Library := Build.Scala2LibraryJar` (default) + // - `set ThisBuild/Build.scala2Library := Build.Scala2LibraryTasty` + // - `set ThisBuild/Build.scala2Library := Build.Scala2LibraryCCTasty` + val scala2Library = settingKey[Scala2Library]("Choose which version of the Scala 2 library should be used") // Used to compile files similar to ./bin/scalac script val scalac = inputKey[Unit]("run the compiler using the correct classpath, or the user supplied classpath") @@ -225,7 +237,7 @@ object Build { outputStrategy := Some(StdoutOutput), - useScala2LibraryTasty := false, + scala2Library := Scala2LibraryJar, // enable verbose exception messages for JUnit (Test / testOptions) += Tests.Argument(TestFrameworks.JUnit, "-a", "-v", "-s"), @@ -645,12 +657,18 @@ object Build { val externalDeps = externalCompilerClasspathTask.value val jars = packageAll.value - val scala2LibraryTasty = jars.get("scala2-library-tasty") match { - case Some(scala2LibraryTastyJar) if useScala2LibraryTasty.value => - Seq("-Ddotty.tests.tasties.scalaLibrary=" + scala2LibraryTastyJar) - case _ => - if (useScala2LibraryTasty.value) log.warn("useScala2LibraryTasty is ignored on non-bootstrapped compiler") - Seq.empty + def libraryPathProperty(jarName: String): Seq[String] = + jars.get(jarName) match { + case Some(jar) => + Seq(s"-Ddotty.tests.tasties.scalaLibrary=$jar") + case None => + log.warn("Scala 2 library TASTy is ignored on non-bootstrapped compiler") + Seq.empty + } + val scala2LibraryTasty = scala2Library.value match { + case Scala2LibraryJar => Seq.empty + case Scala2LibraryTasty => libraryPathProperty("scala2-library-tasty") + case Scala2LibraryCCTasty => libraryPathProperty("scala2-library-cc-tasty") } scala2LibraryTasty ++ Seq( @@ -764,14 +782,24 @@ object Build { else if (debugFromTasty) "dotty.tools.dotc.fromtasty.Debug" else "dotty.tools.dotc.Main" - var extraClasspath = - scalaLibTastyOpt match { - case Some(scalaLibTasty) if useScala2LibraryTasty.value => - Seq(scalaLibTasty, scalaLib, dottyLib) - case _ => - if (useScala2LibraryTasty.value) log.warn("useScala2LibraryTasty is ignored on non-bootstrapped compiler") - Seq(scalaLib, dottyLib) - } + val scala2LibraryTasty = scala2Library.value match { + case Scala2LibraryJar => Seq.empty + case Scala2LibraryTasty => + jars.get("scala2-library-tasty") match { + case Some(jar) => Seq(jar) + case None => + log.warn("Scala2LibraryTasty is ignored on non-bootstrapped compiler") + Seq.empty + } + case Scala2LibraryCCTasty => + jars.get("scala2-library-cc-tasty") match { + case Some(jar) => Seq(jar) + case None => + log.warn("Scala2LibraryCCTasty is ignored on non-bootstrapped compiler") + Seq.empty + } + } + var extraClasspath = scala2LibraryTasty ++ Seq(scalaLib, dottyLib) if (decompile && !args.contains("-classpath")) extraClasspath ++= Seq(".") @@ -882,6 +910,7 @@ object Build { "scala3-tasty-inspector" -> (LocalProject("scala3-tasty-inspector") / Compile / packageBin).value.getAbsolutePath, "tasty-core" -> (LocalProject("tasty-core-bootstrapped") / Compile / packageBin).value.getAbsolutePath, "scala2-library-tasty" -> (LocalProject("scala2-library-tasty") / Compile / packageBin).value.getAbsolutePath, + "scala2-library-cc-tasty" -> (LocalProject("scala2-library-cc-tasty") / Compile / packageBin).value.getAbsolutePath, ) }, @@ -1010,8 +1039,24 @@ object Build { withCommonSettings(Bootstrapped). dependsOn(dottyCompiler(Bootstrapped) % "provided; compile->runtime; test->test"). settings(commonBootstrappedSettings). + settings(scala2LibraryBootstrappedSettings). + settings(moduleName := "scala2-library") + + /** Scala 2 library compiled by dotty using the latest published sources of the library. + * + * This version of the library is not (yet) TASTy/binary compatible with the Scala 2 compiled library. + */ + lazy val `scala2-library-cc` = project.in(file("scala2-library-cc")). + withCommonSettings(Bootstrapped). + dependsOn(dottyCompiler(Bootstrapped) % "provided; compile->runtime; test->test"). + settings(commonBootstrappedSettings). + settings(scala2LibraryBootstrappedSettings). settings( - moduleName := "scala2-library", + moduleName := "scala2-library-cc", + scalacOptions += "-Ycheck:all", + ) + + lazy val scala2LibraryBootstrappedSettings = Seq( javaOptions := (`scala3-compiler-bootstrapped` / javaOptions).value, Compile / scalacOptions ++= { Seq("-sourcepath", ((Compile/sourceManaged).value / "scala-library-src").toString) @@ -1096,13 +1141,13 @@ object Build { | - final val MinorVersion = $minorVersion | - final val ExperimentalVersion = 0 | * Clean everything to generate a compiler with those new TASTy versions - | * Run scala2-library-bootstrapped/tastyMiMaReportIssues + | * Run ${name.value}/tastyMiMaReportIssues |""".stripMargin) }).value, Compile / exportJars := true, artifactName := { (sv: ScalaVersion, module: ModuleID, artifact: Artifact) => - "scala2-library-" + dottyVersion + "." + artifact.extension + moduleName.value + "-" + dottyVersion + "." + artifact.extension }, run := { val log = streams.value.log @@ -1174,7 +1219,7 @@ object Build { |""".stripMargin) } } - ) + ) /** Packages the TASTy files of `scala2-library-bootstrapped` in a jar */ lazy val `scala2-library-tasty` = project.in(file("scala2-library-tasty")). @@ -1187,6 +1232,17 @@ object Build { }, ) + /** Packages the TASTy files of `scala2-library-cc` in a jar */ + lazy val `scala2-library-cc-tasty` = project.in(file("scala2-library-cc-tasty")). + withCommonSettings(Bootstrapped). + settings( + exportJars := true, + Compile / packageBin / mappings := { + (`scala2-library-cc` / Compile / packageBin / mappings).value + .filter(_._2.endsWith(".tasty")) + }, + ) + /** Test the tasty generated by `scala2-library-bootstrapped` * * The sources in src are compiled using TASTy from scala2-library-tasty but then run From e1efffdea9c55fe8741e8e5324ce8a1615f4d04e Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 20 Nov 2023 10:07:26 +0100 Subject: [PATCH 022/220] Clone `scala/language.scala` --- scala2-library-cc/src/scala/language.scala | 207 +++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 scala2-library-cc/src/scala/language.scala diff --git a/scala2-library-cc/src/scala/language.scala b/scala2-library-cc/src/scala/language.scala new file mode 100644 index 000000000000..63c6f1f76fa6 --- /dev/null +++ b/scala2-library-cc/src/scala/language.scala @@ -0,0 +1,207 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala + +/** + * The `scala.language` object controls the language features available to the programmer, as proposed in the + * [[https://docs.google.com/document/d/1nlkvpoIRkx7at1qJEZafJwthZ3GeIklTFhqmXMvTX9Q/edit '''SIP-18 document''']]. + * + * Each of these features has to be explicitly imported into the current scope to become available: + * {{{ + * import language.postfixOps // or language._ + * List(1, 2, 3) reverse + * }}} + * + * The language features are: + * - [[dynamics `dynamics`]] enables defining calls rewriting using the [[scala.Dynamic `Dynamic`]] trait + * - [[existentials `existentials`]] enables writing existential types + * - [[higherKinds `higherKinds`]] enables writing higher-kinded types + * - [[implicitConversions `implicitConversions`]] enables defining implicit methods and members + * - [[postfixOps `postfixOps`]] enables postfix operators (not recommended) + * - [[reflectiveCalls `reflectiveCalls`]] enables using structural types + * - [[experimental `experimental`]] contains newer features that have not yet been tested in production + * + * @groupname production Language Features + * @groupname experimental Experimental Language Features + * @groupprio experimental 10 + */ +object language { + + import languageFeature._ + + /** Only where this feature is enabled, can direct or indirect subclasses of trait scala.Dynamic + * be defined. If `dynamics` is not enabled, a definition of a class, trait, + * or object that has `Dynamic` as a base trait is rejected by the compiler. + * + * Selections of dynamic members of existing subclasses of trait `Dynamic` are unaffected; + * they can be used anywhere. + * + * '''Why introduce the feature?''' To enable flexible DSLs and convenient interfacing + * with dynamic languages. + * + * '''Why control it?''' Dynamic member selection can undermine static checkability + * of programs. Furthermore, dynamic member selection often relies on reflection, + * which is not available on all platforms. + * + * @group production + */ + implicit lazy val dynamics: dynamics = languageFeature.dynamics + + /** Only where this feature is enabled, is postfix operator notation `(expr op)` permitted. + * If `postfixOps` is not enabled, an expression using postfix notation is rejected by the compiler. + * + * '''Why keep the feature?''' Postfix notation is preserved for backward + * compatibility only. Historically, several DSLs written in Scala need the notation. + * + * '''Why control it?''' Postfix operators interact poorly with semicolon inference. + * Most programmers avoid them for this reason alone. Postfix syntax is + * associated with an abuse of infix notation, `a op1 b op2 c op3`, + * that can be harder to read than ordinary method invocation with judicious + * use of parentheses. It is recommended not to enable this feature except for + * legacy code. + * + * @group production + */ + implicit lazy val postfixOps: postfixOps = languageFeature.postfixOps + + /** Where this feature is enabled, accesses to members of structural types that need + * reflection are supported. If `reflectiveCalls` is not enabled, an expression + * requiring reflection will trigger a warning from the compiler. + * + * A structural type is a type of the form + * `Parents { Decls }` where `Decls` contains declarations of new members that do + * not override any member in `Parents`. To access one of these members, a + * reflective call is needed. + * + * '''Why keep the feature?''' Structural types provide great flexibility because + * they avoid the need to define inheritance hierarchies a priori. Besides, + * their definition falls out quite naturally from Scala’s concept of type refinement. + * + * '''Why control it?''' Reflection is not available on all platforms. Popular tools + * such as ProGuard have problems dealing with it. Even where reflection is available, + * reflective dispatch can lead to surprising performance degradations. + * + * @group production + */ + implicit lazy val reflectiveCalls: reflectiveCalls = languageFeature.reflectiveCalls + + /** Where this feature is enabled, definitions of implicit conversions are allowed. + * If `implicitConversions` is not enabled, the definition of an implicit + * conversion will trigger a warning from the compiler. + * + * An implicit conversion is an implicit value of unary function type `A => B`, + * or an implicit method that has in its first parameter section a single, + * non-implicit parameter. Examples: + * + * {{{ + * implicit def stringToInt(s: String): Int = s.length + * implicit val conv = (s: String) => s.length + * implicit def listToX(xs: List[T])(implicit f: T => X): X = ... + * }}} + * + * Implicit classes and implicit values of other types are not governed by this + * language feature. + * + * '''Why keep the feature?''' Implicit conversions are central to many aspects + * of Scala’s core libraries. + * + * '''Why control it?''' Implicit conversions are known to cause many pitfalls + * if over-used. And there is a tendency to over-use them because they look + * very powerful and their effects seem to be easy to understand. Also, in + * most situations using implicit parameters leads to a better design than + * implicit conversions. + * + * @group production + */ + implicit lazy val implicitConversions: implicitConversions = languageFeature.implicitConversions + + /** Where this feature is enabled, higher-kinded types can be written. + * If `higherKinds` is not enabled, a higher-kinded type such as `F[A]` + * will trigger a warning from the compiler. + * + * '''Why keep the feature?''' Higher-kinded types enable the definition of very general + * abstractions such as functor, monad, or arrow. A significant set of advanced + * libraries relies on them. Higher-kinded types are also at the core of the + * scala-virtualized effort to produce high-performance parallel DSLs through staging. + * + * '''Why control it?''' Higher kinded types in Scala lead to a Turing-complete + * type system, where compiler termination is no longer guaranteed. They tend + * to be useful mostly for type-level computation and for highly generic design + * patterns. The level of abstraction implied by these design patterns is often + * a barrier to understanding for newcomers to a Scala codebase. Some syntactic + * aspects of higher-kinded types are hard to understand for the uninitiated and + * type inference is less effective for them than for normal types. Because we are + * not completely happy with them yet, it is possible that some aspects of + * higher-kinded types will change in future versions of Scala. So an explicit + * enabling also serves as a warning that code involving higher-kinded types + * might have to be slightly revised in the future. + * + * @group production + */ + @deprecated("higherKinds no longer needs to be imported explicitly", "2.13.1") + implicit lazy val higherKinds: higherKinds = languageFeature.higherKinds + + /** Where this feature is enabled, existential types that cannot be expressed as wildcard + * types can be written and are allowed in inferred types of values or return + * types of methods. If `existentials` is not enabled, those cases will trigger + * a warning from the compiler. + * + * Existential types with wildcard type syntax such as `List[_]`, + * or `Map[String, _]` are not affected. + * + * '''Why keep the feature?''' Existential types are needed to make sense of Java’s wildcard + * types and raw types and the erased types of run-time values. + * + * '''Why control it?''' Having complex existential types in a code base usually makes + * application code very brittle, with a tendency to produce type errors with + * obscure error messages. Therefore, going overboard with existential types + * is generally perceived not to be a good idea. Also, complicated existential types + * might be no longer supported in a future simplification of the language. + * + * @group production + */ + implicit lazy val existentials: existentials = languageFeature.existentials + + /** The experimental object contains features that are known to have unstable API or + * behavior that may change in future releases. + * + * Experimental features '''may undergo API changes''' in future releases, so production + * code should not rely on them. + * + * Programmers are encouraged to try out experimental features and + * [[https://github.com/scala/bug/issues report any bugs or API inconsistencies]] + * they encounter so they can be improved in future releases. + * + * @group experimental + */ + object experimental { + + import languageFeature.experimental._ + + /** Only where this feature is enabled, are macro definitions allowed. + * If `macros` is not enabled, macro definitions are rejected by the compiler. + * + * Macro implementations and macro applications are not governed by this + * language feature; they can be used anywhere. + * + * '''Why introduce the feature?''' Macros promise to make the language more regular, + * replacing ad-hoc language constructs with a general powerful abstraction + * capability that can express them. Macros are also a more disciplined and + * powerful replacement for compiler plugins. + * + * '''Why control it?''' For their very power, macros can lead to code that is hard + * to debug and understand. + */ + implicit lazy val macros: macros = languageFeature.experimental.macros + } +} From af897ca7a06527ad8e3d2e8a8b7db7005d4e2f5b Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 20 Nov 2023 10:08:00 +0100 Subject: [PATCH 023/220] Add capture checking to `scala/language.scala` Note that to compile this version of the library we do not patch the library with `scala.runtime.stdLibPatches`. --- scala2-library-cc/src/scala/language.scala | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scala2-library-cc/src/scala/language.scala b/scala2-library-cc/src/scala/language.scala index 63c6f1f76fa6..757b9dac1076 100644 --- a/scala2-library-cc/src/scala/language.scala +++ b/scala2-library-cc/src/scala/language.scala @@ -188,6 +188,12 @@ object language { import languageFeature.experimental._ + /** Experimental support for capture checking; implies support for pureFunctions + * + * @see [[https://dotty.epfl.ch/docs/reference/experimental/cc]] + */ + implicit lazy val captureChecking: existentials = languageFeature.existentials + /** Only where this feature is enabled, are macro definitions allowed. * If `macros` is not enabled, macro definitions are rejected by the compiler. * From d0c481763c408de33b1736dc5e5b223e4e8c5fef Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 20 Nov 2023 17:37:22 +0100 Subject: [PATCH 024/220] Patch self type of Function1 and PartialFunction --- scala2-library-cc/src/scala/Function1.scala | 90 ++++ .../src/scala/PartialFunction.scala | 403 ++++++++++++++++++ scala2-library-cc/src/scala/TODO | 1 + 3 files changed, 494 insertions(+) create mode 100644 scala2-library-cc/src/scala/Function1.scala create mode 100644 scala2-library-cc/src/scala/PartialFunction.scala create mode 100644 scala2-library-cc/src/scala/TODO diff --git a/scala2-library-cc/src/scala/Function1.scala b/scala2-library-cc/src/scala/Function1.scala new file mode 100644 index 000000000000..96ca493739ed --- /dev/null +++ b/scala2-library-cc/src/scala/Function1.scala @@ -0,0 +1,90 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +// GENERATED CODE: DO NOT EDIT. See scala.Function0 for timestamp. + +package scala + + +object Function1 { + + implicit final class UnliftOps[A, B] private[Function1](private val f: A => Option[B]) extends AnyVal { + /** Converts an optional function to a partial function. + * + * @example Unlike [[Function.unlift]], this [[UnliftOps.unlift]] method can be used in extractors. + * {{{ + * val of: Int => Option[String] = { i => + * if (i == 2) { + * Some("matched by an optional function") + * } else { + * None + * } + * } + * + * util.Random.nextInt(4) match { + * case of.unlift(m) => // Convert an optional function to a pattern + * println(m) + * case _ => + * println("Not matched") + * } + * }}} + */ + def unlift: PartialFunction[A, B] = Function.unlift(f) + } + +} + +/** A function of 1 parameter. + * + * In the following example, the definition of `succ` is + * shorthand, conceptually, for the anonymous class definition + * `anonfun1`, although the implementation details of how the + * function value is constructed may differ: + * + * {{{ + * object Main extends App { + * val succ = (x: Int) => x + 1 + * val anonfun1 = new Function1[Int, Int] { + * def apply(x: Int): Int = x + 1 + * } + * assert(succ(0) == anonfun1(0)) + * } + * }}} + * + * Note that the difference between `Function1` and [[scala.PartialFunction]] + * is that the latter can specify inputs which it will not handle. + */ +@annotation.implicitNotFound(msg = "No implicit view available from ${T1} => ${R}.") +trait Function1[@specialized(Specializable.Arg) -T1, @specialized(Specializable.Return) +R] extends AnyRef { // FIXME: self => + /** Apply the body of this function to the argument. + * @return the result of function application. + */ + def apply(v1: T1): R + + /** Composes two instances of Function1 in a new Function1, with this function applied last. + * + * @tparam A the type to which function `g` can be applied + * @param g a function A => T1 + * @return a new function `f` such that `f(x) == apply(g(x))` + */ + @annotation.unspecialized def compose[A](g: A => T1): A => R = { x => apply(g(x)) } + + /** Composes two instances of Function1 in a new Function1, with this function applied first. + * + * @tparam A the result type of function `g` + * @param g a function R => A + * @return a new function `f` such that `f(x) == g(apply(x))` + */ + @annotation.unspecialized def andThen[A](g: R => A): T1 => A = { x => g(apply(x)) } + + override def toString(): String = "" +} diff --git a/scala2-library-cc/src/scala/PartialFunction.scala b/scala2-library-cc/src/scala/PartialFunction.scala new file mode 100644 index 000000000000..671d58be33e5 --- /dev/null +++ b/scala2-library-cc/src/scala/PartialFunction.scala @@ -0,0 +1,403 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala + +import scala.annotation.nowarn + +/** A partial function of type `PartialFunction[A, B]` is a unary function + * where the domain does not necessarily include all values of type `A`. + * The function [[isDefinedAt]] allows to test dynamically if a value is in + * the domain of the function. + * + * Even if `isDefinedAt` returns true for an `a: A`, calling `apply(a)` may + * still throw an exception, so the following code is legal: + * + * {{{ + * val f: PartialFunction[Int, Any] = { case x => x / 0 } // ArithmeticException: / by zero + * }}} + * + * It is the responsibility of the caller to call `isDefinedAt` before + * calling `apply`, because if `isDefinedAt` is false, it is not guaranteed + * `apply` will throw an exception to indicate an error condition. If an + * exception is not thrown, evaluation may result in an arbitrary value. + * + * The usual way to respect this contract is to call [[applyOrElse]], + * which is expected to be more efficient than calling both `isDefinedAt` + * and `apply`. + * + * The main distinction between `PartialFunction` and [[scala.Function1]] is + * that the user of a `PartialFunction` may choose to do something different + * with input that is declared to be outside its domain. For example: + * + * {{{ + * val sample = 1 to 10 + * def isEven(n: Int) = n % 2 == 0 + * val eveningNews: PartialFunction[Int, String] = { + * case x if isEven(x) => s"\$x is even" + * } + * + * // The method collect is described as "filter + map" + * // because it uses a PartialFunction to select elements + * // to which the function is applied. + * val evenNumbers = sample.collect(eveningNews) + * + * val oddlyEnough: PartialFunction[Int, String] = { + * case x if !isEven(x) => s"\$x is odd" + * } + * + * // The method orElse allows chaining another PartialFunction + * // to handle input outside the declared domain. + * val numbers = sample.map(eveningNews orElse oddlyEnough) + * + * // same as + * val numbers = sample.map(n => eveningNews.applyOrElse(n, oddlyEnough)) + * + * val half: PartialFunction[Int, Int] = { + * case x if isEven(x) => x / 2 + * } + * + * // Calculating the domain of a composition can be expensive. + * val oddByHalf = half.andThen(oddlyEnough) + * + * // Invokes `half.apply` on even elements! + * val oddBalls = sample.filter(oddByHalf.isDefinedAt) + * + * // Better than filter(oddByHalf.isDefinedAt).map(oddByHalf) + * val oddBalls = sample.collect(oddByHalf) + * + * // Providing "default" values. + * val oddsAndEnds = sample.map(n => oddByHalf.applyOrElse(n, (i: Int) => s"[\$i]")) + * }}} + * + * @note Optional [[Function]]s, [[PartialFunction]]s and extractor objects + * can be converted to each other as shown in the following table. + *   + * | How to convert ... | to a [[PartialFunction]] | to an optional [[Function]] | to an extractor | + * | :---: | --- | --- | --- | + * | from a [[PartialFunction]] | [[Predef.identity]] | [[lift]] | [[Predef.identity]] | + * | from optional [[Function]] | [[Function1.UnliftOps#unlift]] or [[Function.unlift]] | [[Predef.identity]] | [[Function1.UnliftOps#unlift]] | + * | from an extractor | `{ case extractor(x) => x }` | `extractor.unapply _` | [[Predef.identity]] | + *   + * + * @define applyOrElseOrElse Note that calling [[isDefinedAt]] on the resulting partial function + * may apply the first partial function and execute its side effect. + * For efficiency, it is recommended to call [[applyOrElse]] instead of [[isDefinedAt]] or [[apply]]. + */ +trait PartialFunction[-A, +B] extends (A => B) { // FIXME: self => + import PartialFunction._ + + /** Tries to extract a `B` from an `A` in a pattern matching expression. */ + def unapply(a: A): Option[B] = lift(a) + + /** Returns an extractor object with a `unapplySeq` method, which extracts each element of a sequence data. + * + * @example {{{ + * val firstChar: String => Option[Char] = _.headOption + * + * Seq("foo", "bar", "baz") match { + * case firstChar.unlift.elementWise(c0, c1, c2) => + * println(s"\$c0, \$c1, \$c2") // Output: f, b, b + * } + * }}} + */ + def elementWise: ElementWiseExtractor[A, B] = new ElementWiseExtractor[A, B](this) + + /** Checks if a value is contained in the function's domain. + * + * @param x the value to test + * @return `'''true'''`, iff `x` is in the domain of this function, `'''false'''` otherwise. + */ + def isDefinedAt(x: A): Boolean + + /** Composes this partial function with a fallback partial function which + * gets applied where this partial function is not defined. + * + * @param that the fallback function + * @tparam A1 the argument type of the fallback function + * @tparam B1 the result type of the fallback function + * @return a partial function which has as domain the union of the domains + * of this partial function and `that`. The resulting partial function + * takes `x` to `this(x)` where `this` is defined, and to `that(x)` where it is not. + */ + def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]): PartialFunction[A1, B1] = + new OrElse[A1, B1] (this, that) + //TODO: why not overload it with orElse(that: F1): F1? + + /** Composes this partial function with a transformation function that + * gets applied to results of this partial function. + * + * If the runtime type of the function is a `PartialFunction` then the + * other `andThen` method is used (note its cautions). + * + * @param k the transformation function + * @tparam C the result type of the transformation function. + * @return a partial function with the domain of this partial function, + * possibly narrowed by the specified function, which maps + * arguments `x` to `k(this(x))`. + */ + override def andThen[C](k: B => C): PartialFunction[A, C] = k match { + case pf: PartialFunction[B, C] => andThen(pf) + case _ => new AndThen[A, B, C](this, k) + } + + /** + * Composes this partial function with another partial function that + * gets applied to results of this partial function. + * + * $applyOrElseOrElse + * + * @param k the transformation function + * @tparam C the result type of the transformation function. + * @return a partial function with the domain of this partial function narrowed by + * other partial function, which maps arguments `x` to `k(this(x))`. + */ + def andThen[C](k: PartialFunction[B, C]): PartialFunction[A, C] = + new Combined[A, B, C](this, k) + + /** + * Composes another partial function `k` with this partial function so that this + * partial function gets applied to results of `k`. + * + * $applyOrElseOrElse + * + * @param k the transformation function + * @tparam R the parameter type of the transformation function. + * @return a partial function with the domain of other partial function narrowed by + * this partial function, which maps arguments `x` to `this(k(x))`. + */ + def compose[R](k: PartialFunction[R, A]): PartialFunction[R, B] = + new Combined[R, A, B](k, this) + + /** Turns this partial function into a plain function returning an `Option` result. + * @see Function.unlift + * @return a function that takes an argument `x` to `Some(this(x))` if `this` + * is defined for `x`, and to `None` otherwise. + */ + def lift: A => Option[B] = new Lifted(this) + + /** Applies this partial function to the given argument when it is contained in the function domain. + * Applies fallback function where this partial function is not defined. + * + * Note that expression `pf.applyOrElse(x, default)` is equivalent to + * {{{ if(pf isDefinedAt x) pf(x) else default(x) }}} + * except that `applyOrElse` method can be implemented more efficiently. + * For all partial function literals the compiler generates an `applyOrElse` implementation which + * avoids double evaluation of pattern matchers and guards. + * This makes `applyOrElse` the basis for the efficient implementation for many operations and scenarios, such as: + * + * - combining partial functions into `orElse`/`andThen` chains does not lead to + * excessive `apply`/`isDefinedAt` evaluation + * - `lift` and `unlift` do not evaluate source functions twice on each invocation + * - `runWith` allows efficient imperative-style combining of partial functions + * with conditionally applied actions + * + * For non-literal partial function classes with nontrivial `isDefinedAt` method + * it is recommended to override `applyOrElse` with custom implementation that avoids + * double `isDefinedAt` evaluation. This may result in better performance + * and more predictable behavior w.r.t. side effects. + * + * @param x the function argument + * @param default the fallback function + * @return the result of this function or fallback function application. + */ + def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 = + if (isDefinedAt(x)) apply(x) else default(x) + + /** Composes this partial function with an action function which + * gets applied to results of this partial function. + * The action function is invoked only for its side effects; its result is ignored. + * + * Note that expression `pf.runWith(action)(x)` is equivalent to + * {{{ if(pf isDefinedAt x) { action(pf(x)); true } else false }}} + * except that `runWith` is implemented via `applyOrElse` and thus potentially more efficient. + * Using `runWith` avoids double evaluation of pattern matchers and guards for partial function literals. + * @see `applyOrElse`. + * + * @param action the action function + * @return a function which maps arguments `x` to `isDefinedAt(x)`. The resulting function + * runs `action(this(x))` where `this` is defined. + */ + def runWith[U](action: B => U): A => Boolean = { x => + val z = applyOrElse(x, checkFallback[B]) + if (!fallbackOccurred(z)) { action(z); true } else false + } +} + +/** A few handy operations which leverage the extra bit of information + * available in partial functions. Examples: + * {{{ + * import PartialFunction._ + * + * def strangeConditional(other: Any): Boolean = cond(other) { + * case x: String if x == "abc" || x == "def" => true + * case x: Int => true + * } + * def onlyInt(v: Any): Option[Int] = condOpt(v) { case x: Int => x } + * }}} + */ +object PartialFunction { + + final class ElementWiseExtractor[-A, +B] private[PartialFunction] (private val pf: PartialFunction[A, B]) extends AnyVal { + @nowarn("cat=lint-nonlocal-return") + def unapplySeq(seq: Seq[A]): Option[Seq[B]] = { + Some(seq.map { + case pf(b) => b + case _ => return None + }) + } + } + + /** Composite function produced by `PartialFunction#orElse` method + */ + private class OrElse[-A, +B] (f1: PartialFunction[A, B], f2: PartialFunction[A, B]) + extends scala.runtime.AbstractPartialFunction[A, B] with Serializable { + def isDefinedAt(x: A) = f1.isDefinedAt(x) || f2.isDefinedAt(x) + + override def apply(x: A): B = f1.applyOrElse(x, f2) + + override def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 = { + val z = f1.applyOrElse(x, checkFallback[B]) + if (!fallbackOccurred(z)) z else f2.applyOrElse(x, default) + } + + override def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]): OrElse[A1, B1] = + new OrElse[A1, B1] (f1, f2 orElse that) + + override def andThen[C](k: B => C): OrElse[A, C] = + new OrElse[A, C] (f1 andThen k, f2 andThen k) + } + + /** Composite function produced by `PartialFunction#andThen` method + */ + private class AndThen[-A, B, +C] (pf: PartialFunction[A, B], k: B => C) extends PartialFunction[A, C] with Serializable { + def isDefinedAt(x: A) = pf.isDefinedAt(x) + + def apply(x: A): C = k(pf(x)) + + override def applyOrElse[A1 <: A, C1 >: C](x: A1, default: A1 => C1): C1 = { + val z = pf.applyOrElse(x, checkFallback[B]) + if (!fallbackOccurred(z)) k(z) else default(x) + } + } + + /** Composite function produced by `PartialFunction#andThen` method + */ + private class Combined[-A, B, +C] (pf: PartialFunction[A, B], k: PartialFunction[B, C]) extends PartialFunction[A, C] with Serializable { + def isDefinedAt(x: A): Boolean = { + val b: B = pf.applyOrElse(x, checkFallback[B]) + if (!fallbackOccurred(b)) k.isDefinedAt(b) else false + } + + def apply(x: A): C = k(pf(x)) + + override def applyOrElse[A1 <: A, C1 >: C](x: A1, default: A1 => C1): C1 = { + val pfv = pf.applyOrElse(x, checkFallback[B]) + if (!fallbackOccurred(pfv)) k.applyOrElse(pfv, (_: B) => default(x)) else default(x) + } + } + + /** To implement patterns like {{{ if(pf isDefinedAt x) f1(pf(x)) else f2(x) }}} efficiently + * the following trick is used: + * + * To avoid double evaluation of pattern matchers & guards `applyOrElse` method is used here + * instead of `isDefinedAt`/`apply` pair. + * + * After call to `applyOrElse` we need both the function result it returned and + * the fact if the function's argument was contained in its domain. The only degree of freedom we have here + * to achieve this goal is tweaking with the continuation argument (`default`) of `applyOrElse` method. + * The obvious way is to throw an exception from `default` function and to catch it after + * calling `applyOrElse` but I consider this somewhat inefficient. + * + * I know only one way how you can do this task efficiently: `default` function should return unique marker object + * which never may be returned by any other (regular/partial) function. This way after calling `applyOrElse` you need + * just one reference comparison to distinguish if `pf isDefined x` or not. + * + * This correctly interacts with specialization as return type of `applyOrElse` + * (which is parameterized upper bound) can never be specialized. + * + * Here `fallback_fn` is used as both unique marker object and special fallback function that returns it. + */ + private[this] val fallback_fn: Any => Any = _ => fallback_fn + private def checkFallback[B] = fallback_fn.asInstanceOf[Any => B] + private def fallbackOccurred[B](x: B) = fallback_fn eq x.asInstanceOf[AnyRef] + + private class Lifted[-A, +B] (val pf: PartialFunction[A, B]) + extends scala.runtime.AbstractFunction1[A, Option[B]] with Serializable { + + def apply(x: A): Option[B] = { + val z = pf.applyOrElse(x, checkFallback[B]) + if (!fallbackOccurred(z)) Some(z) else None + } + } + + private class Unlifted[A, B] (f: A => Option[B]) extends scala.runtime.AbstractPartialFunction[A, B] with Serializable { + def isDefinedAt(x: A): Boolean = f(x).isDefined + + override def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 = { + f(x).getOrElse(default(x)) + } + + override def lift = f + } + + private[scala] def unlifted[A, B](f: A => Option[B]): PartialFunction[A, B] = f match { + case lf: Lifted[A, B] => lf.pf + case ff => new Unlifted(ff) + } + + /** Converts an ordinary function to a partial function. Note that calling `isDefinedAt(x)` on + * this partial function will return `true` for every `x`. + * @param f an ordinary function + * @return a partial function which delegates to the ordinary function `f` + */ + def fromFunction[A, B](f: A => B): PartialFunction[A, B] = { case x => f(x) } + + private[this] val constFalse: Any => Boolean = { _ => false} + + private[this] val empty_pf: PartialFunction[Any, Nothing] = new PartialFunction[Any, Nothing] with Serializable { + def isDefinedAt(x: Any) = false + def apply(x: Any) = throw new MatchError(x) + override def orElse[A1, B1](that: PartialFunction[A1, B1]) = that + override def andThen[C](k: Nothing => C): PartialFunction[Any, Nothing] = this + override val lift: Any => None.type = (x: Any) => None + override def runWith[U](action: Nothing => U) = constFalse + } + + /** The partial function with empty domain. + * Any attempt to invoke empty partial function leads to throwing [[scala.MatchError]] exception. + */ + def empty[A, B] : PartialFunction[A, B] = empty_pf + + /** A Boolean test that is the result of the given function where defined, + * and false otherwise. + * + * It behaves like a `case _ => false` were added to the partial function. + * + * @param x the value to test + * @param pf the partial function + * @return true, iff `x` is in the domain of `pf` and `pf(x) == true`. + */ + def cond[A](x: A)(pf: PartialFunction[A, Boolean]): Boolean = pf.applyOrElse(x, constFalse) + + /** Apply the function to the given value if defined, and return the result + * in a `Some`; otherwise, return `None`. + * + * @param x the value to test + * @param pf the PartialFunction[T, U] + * @return `Some(pf(x))` if `pf isDefinedAt x`, `None` otherwise. + */ + def condOpt[A, B](x: A)(pf: PartialFunction[A, B]): Option[B] = { + val z = pf.applyOrElse(x, checkFallback[B]) + if (!fallbackOccurred(z)) Some(z) else None + } +} diff --git a/scala2-library-cc/src/scala/TODO b/scala2-library-cc/src/scala/TODO new file mode 100644 index 000000000000..241779ab8dd9 --- /dev/null +++ b/scala2-library-cc/src/scala/TODO @@ -0,0 +1 @@ +- Delete or re-clone Function1 and PartialFunction. These where edited to remove the self type. From 5c6e542817c347051281ae69a498a32fb17a900a Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 24 Nov 2023 08:18:03 +0100 Subject: [PATCH 025/220] Move sources from `tests/pos-special/stdlib` to `scala2-library-cc` Also reduce diff with the original Scala 2 library sources. --- compiler/test/dotty/Properties.scala | 3 ++ .../dotty/tools/dotc/CompilationTests.scala | 6 +-- .../src/scala}/collection/ArrayOps.scala | 21 +++++---- .../src/scala}/collection/BitSet.scala | 0 .../scala}/collection/BufferedIterator.scala | 0 .../src/scala}/collection/BuildFrom.scala | 2 +- .../src/scala}/collection/DefaultMap.scala | 0 .../src/scala}/collection/Factory.scala | 0 .../src/scala}/collection/Hashing.scala | 0 .../src/scala}/collection/IndexedSeq.scala | 18 +++++++- .../scala}/collection/IndexedSeqView.scala | 0 .../src/scala}/collection/Iterable.scala | 0 .../src/scala}/collection/IterableOnce.scala | 13 +++--- .../src/scala}/collection/Iterator.scala | 0 .../scala}/collection/JavaConverters.scala | 0 .../src/scala}/collection/LazyZipOps.scala | 0 .../src/scala}/collection/LinearSeq.scala | 0 .../src/scala}/collection/Map.scala | 0 .../src/scala}/collection/MapView.scala | 2 +- .../src/scala}/collection/Searching.scala | 0 .../src/scala}/collection/Seq.scala | 0 .../src/scala}/collection/SeqMap.scala | 0 .../src/scala}/collection/SeqView.scala | 0 .../src/scala}/collection/Set.scala | 0 .../src/scala}/collection/SortedMap.scala | 0 .../src/scala}/collection/SortedOps.scala | 0 .../src/scala}/collection/SortedSet.scala | 1 - .../src/scala}/collection/Stepper.scala | 0 .../src/scala}/collection/StepperShape.scala | 0 .../StrictOptimizedIterableOps.scala | 0 .../collection/StrictOptimizedMapOps.scala | 0 .../collection/StrictOptimizedSeqOps.scala | 0 .../collection/StrictOptimizedSetOps.scala | 0 .../StrictOptimizedSortedMapOps.scala | 0 .../StrictOptimizedSortedSetOps.scala | 0 .../src/scala}/collection/StringOps.scala | 0 .../src/scala}/collection/StringParsers.scala | 5 -- .../src/scala}/collection/View.scala | 0 .../src/scala}/collection/WithFilter.scala | 0 .../scala}/collection/concurrent/Map.scala | 0 .../collection/concurrent/TrieMap.scala | 0 .../collection/convert/AsJavaConverters.scala | 0 .../collection/convert/AsJavaExtensions.scala | 0 .../convert/AsScalaConverters.scala | 0 .../convert/AsScalaExtensions.scala | 0 .../convert/ImplicitConversions.scala | 0 .../convert/JavaCollectionWrappers.scala | 0 .../collection/convert/StreamExtensions.scala | 0 .../convert/impl/ArrayStepper.scala | 0 .../convert/impl/BinaryTreeStepper.scala | 0 .../convert/impl/BitSetStepper.scala | 0 .../convert/impl/ChampStepper.scala | 0 .../convert/impl/InOrderStepperBase.scala | 0 .../convert/impl/IndexedSeqStepper.scala | 0 .../convert/impl/IndexedStepperBase.scala | 0 .../convert/impl/IteratorStepper.scala | 0 .../convert/impl/NumericRangeStepper.scala | 0 .../convert/impl/RangeStepper.scala | 0 .../convert/impl/StringStepper.scala | 0 .../convert/impl/TableStepper.scala | 0 .../convert/impl/VectorStepper.scala | 0 .../collection/generic/BitOperations.scala | 0 .../generic/DefaultSerializationProxy.scala | 0 .../collection/generic/IsIterable.scala | 0 .../collection/generic/IsIterableOnce.scala | 0 .../src/scala}/collection/generic/IsMap.scala | 0 .../src/scala}/collection/generic/IsSeq.scala | 0 .../collection/generic/Subtractable.scala | 0 .../scala}/collection/generic/package.scala | 0 .../collection/immutable/ArraySeq.scala | 0 .../scala}/collection/immutable/BitSet.scala | 0 .../collection/immutable/ChampCommon.scala | 1 - .../scala}/collection/immutable/HashMap.scala | 0 .../scala}/collection/immutable/HashSet.scala | 0 .../scala}/collection/immutable/IntMap.scala | 0 .../collection/immutable/Iterable.scala | 0 .../immutable/LazyListIterable.scala | 0 .../scala}/collection/immutable/List.scala | 0 .../scala}/collection/immutable/ListMap.scala | 0 .../scala}/collection/immutable/ListSet.scala | 0 .../scala}/collection/immutable/LongMap.scala | 0 .../src/scala}/collection/immutable/Map.scala | 0 .../collection/immutable/NumericRange.scala | 0 .../scala}/collection/immutable/Queue.scala | 0 .../scala}/collection/immutable/Range.scala | 0 .../collection/immutable/RedBlackTree.scala | 0 .../src/scala}/collection/immutable/Seq.scala | 0 .../scala}/collection/immutable/SeqMap.scala | 0 .../src/scala}/collection/immutable/Set.scala | 0 .../collection/immutable/SortedMap.scala | 0 .../collection/immutable/SortedSet.scala | 0 .../immutable/StrictOptimizedSeqOps.scala | 0 .../scala}/collection/immutable/TreeMap.scala | 0 .../collection/immutable/TreeSeqMap.scala | 8 ++-- .../scala}/collection/immutable/TreeSet.scala | 0 .../scala}/collection/immutable/Vector.scala | 0 .../collection/immutable/VectorMap.scala | 0 .../collection/immutable/WrappedString.scala | 0 .../scala}/collection/immutable/package.scala | 0 .../scala}/collection/mutable/AnyRefMap.scala | 34 +++++++------- .../collection/mutable/ArrayBuffer.scala | 0 .../collection/mutable/ArrayBuilder.scala | 0 .../collection/mutable/ArrayDeque.scala | 0 .../scala}/collection/mutable/ArraySeq.scala | 0 .../scala}/collection/mutable/BitSet.scala | 0 .../scala}/collection/mutable/Buffer.scala | 1 - .../scala}/collection/mutable/Builder.scala | 0 .../mutable/CheckedIndexedSeqView.scala | 0 .../scala}/collection/mutable/Cloneable.scala | 0 .../mutable/CollisionProofHashMap.scala | 24 +++++----- .../scala}/collection/mutable/Growable.scala | 0 .../collection/mutable/GrowableBuilder.scala | 0 .../scala}/collection/mutable/HashMap.scala | 12 ++--- .../scala}/collection/mutable/HashSet.scala | 0 .../scala}/collection/mutable/HashTable.scala | 2 +- .../collection/mutable/ImmutableBuilder.scala | 0 .../collection/mutable/IndexedSeq.scala | 0 .../scala}/collection/mutable/Iterable.scala | 0 .../collection/mutable/LinkedHashMap.scala | 10 ++-- .../collection/mutable/LinkedHashSet.scala | 0 .../collection/mutable/ListBuffer.scala | 0 .../scala}/collection/mutable/ListMap.scala | 8 ++-- .../scala}/collection/mutable/LongMap.scala | 0 .../src/scala}/collection/mutable/Map.scala | 0 .../scala}/collection/mutable/MultiMap.scala | 2 +- .../collection/mutable/MutationTracker.scala | 0 .../collection/mutable/OpenHashMap.scala | 10 ++-- .../collection/mutable/PriorityQueue.scala | 0 .../src/scala}/collection/mutable/Queue.scala | 0 .../collection/mutable/RedBlackTree.scala | 28 +++++------ .../collection/mutable/ReusableBuilder.scala | 0 .../src/scala}/collection/mutable/Seq.scala | 0 .../scala}/collection/mutable/SeqMap.scala | 0 .../src/scala}/collection/mutable/Set.scala | 0 .../collection/mutable/Shrinkable.scala | 0 .../scala}/collection/mutable/SortedMap.scala | 0 .../scala}/collection/mutable/SortedSet.scala | 0 .../src/scala}/collection/mutable/Stack.scala | 0 .../collection/mutable/StringBuilder.scala | 0 .../scala}/collection/mutable/TreeMap.scala | 8 ++-- .../scala}/collection/mutable/TreeSet.scala | 0 .../collection/mutable/UnrolledBuffer.scala | 0 .../collection/mutable/WeakHashMap.scala | 8 ++-- .../scala}/collection/mutable/package.scala | 0 .../src/scala}/collection/package.scala | 0 .../src/scala}/runtime/PStatics.scala | 0 .../collection/concurrent/BasicNode.java | 19 -------- .../collection/concurrent/CNodeBase.java | 37 --------------- .../stdlib/collection/concurrent/Gen.java | 15 ------ .../collection/concurrent/INodeBase.java | 39 ---------------- .../collection/concurrent/MainNode.java | 46 ------------------- 151 files changed, 119 insertions(+), 264 deletions(-) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/ArrayOps.scala (98%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/BitSet.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/BufferedIterator.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/BuildFrom.scala (99%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/DefaultMap.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/Factory.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/Hashing.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/IndexedSeq.scala (91%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/IndexedSeqView.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/Iterable.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/IterableOnce.scala (99%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/Iterator.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/JavaConverters.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/LazyZipOps.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/LinearSeq.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/Map.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/MapView.scala (98%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/Searching.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/Seq.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/SeqMap.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/SeqView.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/Set.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/SortedMap.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/SortedOps.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/SortedSet.scala (99%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/Stepper.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/StepperShape.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/StrictOptimizedIterableOps.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/StrictOptimizedMapOps.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/StrictOptimizedSeqOps.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/StrictOptimizedSetOps.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/StrictOptimizedSortedMapOps.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/StrictOptimizedSortedSetOps.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/StringOps.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/StringParsers.scala (99%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/View.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/WithFilter.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/concurrent/Map.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/concurrent/TrieMap.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/AsJavaConverters.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/AsJavaExtensions.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/AsScalaConverters.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/AsScalaExtensions.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/ImplicitConversions.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/JavaCollectionWrappers.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/StreamExtensions.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/impl/ArrayStepper.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/impl/BinaryTreeStepper.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/impl/BitSetStepper.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/impl/ChampStepper.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/impl/InOrderStepperBase.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/impl/IndexedSeqStepper.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/impl/IndexedStepperBase.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/impl/IteratorStepper.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/impl/NumericRangeStepper.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/impl/RangeStepper.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/impl/StringStepper.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/impl/TableStepper.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/convert/impl/VectorStepper.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/generic/BitOperations.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/generic/DefaultSerializationProxy.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/generic/IsIterable.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/generic/IsIterableOnce.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/generic/IsMap.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/generic/IsSeq.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/generic/Subtractable.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/generic/package.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/ArraySeq.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/BitSet.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/ChampCommon.scala (99%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/HashMap.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/HashSet.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/IntMap.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/Iterable.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/LazyListIterable.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/List.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/ListMap.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/ListSet.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/LongMap.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/Map.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/NumericRange.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/Queue.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/Range.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/RedBlackTree.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/Seq.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/SeqMap.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/Set.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/SortedMap.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/SortedSet.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/StrictOptimizedSeqOps.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/TreeMap.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/TreeSeqMap.scala (98%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/TreeSet.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/Vector.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/VectorMap.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/WrappedString.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/immutable/package.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/AnyRefMap.scala (91%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/ArrayBuffer.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/ArrayBuilder.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/ArrayDeque.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/ArraySeq.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/BitSet.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/Buffer.scala (99%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/Builder.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/CheckedIndexedSeqView.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/Cloneable.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/CollisionProofHashMap.scala (95%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/Growable.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/GrowableBuilder.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/HashMap.scala (97%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/HashSet.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/HashTable.scala (99%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/ImmutableBuilder.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/IndexedSeq.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/Iterable.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/LinkedHashMap.scala (98%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/LinkedHashSet.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/ListBuffer.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/ListMap.scala (90%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/LongMap.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/Map.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/MultiMap.scala (98%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/MutationTracker.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/OpenHashMap.scala (97%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/PriorityQueue.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/Queue.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/RedBlackTree.scala (93%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/ReusableBuilder.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/Seq.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/SeqMap.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/Set.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/Shrinkable.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/SortedMap.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/SortedSet.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/Stack.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/StringBuilder.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/TreeMap.scala (96%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/TreeSet.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/UnrolledBuffer.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/WeakHashMap.scala (83%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/mutable/package.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/collection/package.scala (100%) rename {tests/pos-special/stdlib => scala2-library-cc/src/scala}/runtime/PStatics.scala (100%) delete mode 100644 tests/pos-special/stdlib/collection/concurrent/BasicNode.java delete mode 100644 tests/pos-special/stdlib/collection/concurrent/CNodeBase.java delete mode 100644 tests/pos-special/stdlib/collection/concurrent/Gen.java delete mode 100644 tests/pos-special/stdlib/collection/concurrent/INodeBase.java delete mode 100644 tests/pos-special/stdlib/collection/concurrent/MainNode.java diff --git a/compiler/test/dotty/Properties.scala b/compiler/test/dotty/Properties.scala index 4bb3628722ad..e085b0de4875 100644 --- a/compiler/test/dotty/Properties.scala +++ b/compiler/test/dotty/Properties.scala @@ -87,6 +87,9 @@ object Properties { /** If we are using the scala-library TASTy jar */ def usingScalaLibraryTasty: Boolean = scalaLibraryTasty.isDefined + /** If we are using the scala-library TASTy jar */ + + def usingScalaLibraryCCTasty: Boolean = scalaLibraryTasty.exists(_.contains("scala2-library-cc-tasty")) /** scala-asm jar */ def scalaAsm: String = sys.props("dotty.tests.classes.scalaAsm") diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 120b7373f7cc..b9e412d8e0fb 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -45,9 +45,9 @@ class CompilationTests { compileFilesInDir("tests/pos", defaultOptions.and("-Ysafe-init", "-Ylegacy-lazy-vals", "-Ycheck-constraint-deps"), FileFilter.include(TestSources.posLazyValsAllowlist)), compileDir("tests/pos-special/java-param-names", defaultOptions.withJavacOnlyOptions("-parameters")), ) ::: ( - // FIXME: This fails due to a bug involving self types and capture checking - if Properties.usingScalaLibraryTasty then Nil - else List(compileDir("tests/pos-special/stdlib", allowDeepSubtypes)) + // TODO create a folder for capture checking tests with the stdlib, or use tests/pos-custom-args/captures under this mode? + if Properties.usingScalaLibraryCCTasty then List(compileDir("tests/pos-special/stdlib", allowDeepSubtypes)) + else Nil ) if scala.util.Properties.isJavaAtLeast("16") then diff --git a/tests/pos-special/stdlib/collection/ArrayOps.scala b/scala2-library-cc/src/scala/collection/ArrayOps.scala similarity index 98% rename from tests/pos-special/stdlib/collection/ArrayOps.scala rename to scala2-library-cc/src/scala/collection/ArrayOps.scala index bb6174f59598..e8548c12751f 100644 --- a/tests/pos-special/stdlib/collection/ArrayOps.scala +++ b/scala2-library-cc/src/scala/collection/ArrayOps.scala @@ -113,7 +113,7 @@ object ArrayOps { b.result() } - def flatMap[BS, B](f: A => BS)(implicit asIterable: BS => Iterable[B], m: ClassTag[B]): Array[B] = + def flatMap[BS, B](f: A => BS)(implicit asIterable: BS => Iterable[B], m: ClassTag[B]): Array[B] = flatMap[B](x => asIterable(f(x))) /** Creates a new non-strict filter which combines this filter with the given predicate. */ @@ -505,7 +505,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { * * @return a pair of arrays: the first one made of those values returned by `f` that were wrapped in [[scala.util.Left]], * and the second one made of those wrapped in [[scala.util.Right]]. */ - def partitionMap[A1: ClassTag, A2: ClassTag](f: A => Either[A1, A2]): (Array[A1], Array[A2]) = { + def partitionMap[A1: ClassTag, A2: ClassTag](f: A => Either[A1, A2]): (Array[A1], Array[A2]) = { val res1 = ArrayBuilder.make[A1] val res2 = ArrayBuilder.make[A2] var i = 0 @@ -816,7 +816,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { * }}} * */ - def scanLeft[B : ClassTag](z: B)(op: (B, A) => B): Array[B] = { + def scanLeft[ B : ClassTag ](z: B)(op: (B, A) => B): Array[B] = { var v = z var i = 0 val res = new Array[B](xs.length + 1) @@ -855,7 +855,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { * }}} * */ - def scanRight[B : ClassTag](z: B)(op: (A, B) => B): Array[B] = { + def scanRight[ B : ClassTag ](z: B)(op: (A, B) => B): Array[B] = { var v = z var i = xs.length - 1 val res = new Array[B](xs.length + 1) @@ -973,7 +973,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { b.result() } - def flatMap[BS, B](f: A => BS)(implicit asIterable: BS => Iterable[B], m: ClassTag[B]): Array[B] = + def flatMap[BS, B](f: A => BS)(implicit asIterable: BS => Iterable[B], m: ClassTag[B]): Array[B] = flatMap[B](x => asIterable(f(x))) /** Flattens a two-dimensional array by concatenating all its rows @@ -1095,7 +1095,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { * If this array is shorter than `that`, `thisElem` values are used to pad the result. * If `that` is shorter than this array, `thatElem` values are used to pad the result. */ - def zipAll[A1 >: A, B](that: Iterable[B], thisElem: A1, thatElem: B): Array[(A1, B)] = { + def zipAll[A1 >: A, B](that: Iterable[B], thisElem: A1, thatElem: B): Array[(A1, B)] = { val b = new ArrayBuilder.ofRef[(A1, B)]() val k = that.knownSize b.sizeHint(max(k, xs.length)) @@ -1244,7 +1244,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { * @return a pair of Arrays, containing, respectively, the first and second half * of each element pair of this Array. */ - def unzip[A1, A2](implicit asPair: A => (A1, A2), ct1: ClassTag[A1], ct2: ClassTag[A2]): (Array[A1], Array[A2]) = { + def unzip[A1, A2](implicit asPair: A => (A1, A2), ct1: ClassTag[A1], ct2: ClassTag[A2]): (Array[A1], Array[A2]) = { val a1 = new Array[A1](xs.length) val a2 = new Array[A2](xs.length) var i = 0 @@ -1273,7 +1273,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { * @return a triple of Arrays, containing, respectively, the first, second, and third * elements from each element triple of this Array. */ - def unzip3[A1, A2, A3](implicit asTriple: A => (A1, A2, A3), ct1: ClassTag[A1], ct2: ClassTag[A2], + def unzip3[A1, A2, A3](implicit asTriple: A => (A1, A2, A3), ct1: ClassTag[A1], ct2: ClassTag[A2], ct3: ClassTag[A3]): (Array[A1], Array[A2], Array[A3]) = { val a1 = new Array[A1](xs.length) val a2 = new Array[A2](xs.length) @@ -1418,7 +1418,7 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { * @tparam K the type of keys returned by the discriminator function * @tparam B the type of values returned by the transformation function */ - def groupMap[K, B : ClassTag](key: A => K)(f: A => B): immutable.Map[K, Array[B]] = { + def groupMap[K, B : ClassTag](key: A => K)(f: A => B): immutable.Map[K, Array[B]] = { val m = mutable.Map.empty[K, ArrayBuilder[B]] val len = xs.length var i = 0 @@ -1479,7 +1479,8 @@ final class ArrayOps[A](private val xs: Array[A]) extends AnyVal { /** Create a copy of this array with the specified element type. */ def toArray[B >: A: ClassTag]: Array[B] = { val destination = new Array[B](xs.length) - copyToArray(destination, 0) + @annotation.unused val copied = copyToArray(destination, 0) + //assert(copied == xs.length) destination } diff --git a/tests/pos-special/stdlib/collection/BitSet.scala b/scala2-library-cc/src/scala/collection/BitSet.scala similarity index 100% rename from tests/pos-special/stdlib/collection/BitSet.scala rename to scala2-library-cc/src/scala/collection/BitSet.scala diff --git a/tests/pos-special/stdlib/collection/BufferedIterator.scala b/scala2-library-cc/src/scala/collection/BufferedIterator.scala similarity index 100% rename from tests/pos-special/stdlib/collection/BufferedIterator.scala rename to scala2-library-cc/src/scala/collection/BufferedIterator.scala diff --git a/tests/pos-special/stdlib/collection/BuildFrom.scala b/scala2-library-cc/src/scala/collection/BuildFrom.scala similarity index 99% rename from tests/pos-special/stdlib/collection/BuildFrom.scala rename to scala2-library-cc/src/scala/collection/BuildFrom.scala index 05df32856d82..d82e90777d3e 100644 --- a/tests/pos-special/stdlib/collection/BuildFrom.scala +++ b/scala2-library-cc/src/scala/collection/BuildFrom.scala @@ -87,7 +87,7 @@ object BuildFrom extends BuildFromLowPriority1 { def newBuilder(from: Array[_]): Builder[A, Array[A]] = Factory.arrayFactory[A].newBuilder } - implicit def buildFromView[A, B]: BuildFrom[View[A], B, View[B]] = + implicit def buildFromView[A, B]: BuildFrom[View[A], B, View[B]] = new BuildFrom[View[A], B, View[B]] { def fromSpecific(from: View[A])(it: IterableOnce[B]^): View[B] = View.from(it).unsafeAssumePure def newBuilder(from: View[A]): Builder[B, View[B]] = View.newBuilder diff --git a/tests/pos-special/stdlib/collection/DefaultMap.scala b/scala2-library-cc/src/scala/collection/DefaultMap.scala similarity index 100% rename from tests/pos-special/stdlib/collection/DefaultMap.scala rename to scala2-library-cc/src/scala/collection/DefaultMap.scala diff --git a/tests/pos-special/stdlib/collection/Factory.scala b/scala2-library-cc/src/scala/collection/Factory.scala similarity index 100% rename from tests/pos-special/stdlib/collection/Factory.scala rename to scala2-library-cc/src/scala/collection/Factory.scala diff --git a/tests/pos-special/stdlib/collection/Hashing.scala b/scala2-library-cc/src/scala/collection/Hashing.scala similarity index 100% rename from tests/pos-special/stdlib/collection/Hashing.scala rename to scala2-library-cc/src/scala/collection/Hashing.scala diff --git a/tests/pos-special/stdlib/collection/IndexedSeq.scala b/scala2-library-cc/src/scala/collection/IndexedSeq.scala similarity index 91% rename from tests/pos-special/stdlib/collection/IndexedSeq.scala rename to scala2-library-cc/src/scala/collection/IndexedSeq.scala index a2d4cc942231..998d1a5a635f 100644 --- a/tests/pos-special/stdlib/collection/IndexedSeq.scala +++ b/scala2-library-cc/src/scala/collection/IndexedSeq.scala @@ -94,11 +94,25 @@ trait IndexedSeqOps[+A, +CC[_], +C] extends Any with IndexedSeqViewOps[A, CC, C] override def slice(from: Int, until: Int): C = fromSpecific(new IndexedSeqView.Slice(this, from, until)) - override def head: A = apply(0) + override def head: A = + if (!isEmpty) apply(0) + else throw new NoSuchElementException(s"head of empty ${ + self match { + case self: IndexedSeq[_] => self.collectionClassName + case _ => toString + } + }") override def headOption: Option[A] = if (isEmpty) None else Some(head) - override def last: A = apply(length - 1) + override def last: A = + if (!isEmpty) apply(length - 1) + else throw new NoSuchElementException(s"last of empty ${ + self match { + case self: IndexedSeq[_] => self.collectionClassName + case _ => toString + } + }") // We already inherit an efficient `lastOption = if (isEmpty) None else Some(last)` diff --git a/tests/pos-special/stdlib/collection/IndexedSeqView.scala b/scala2-library-cc/src/scala/collection/IndexedSeqView.scala similarity index 100% rename from tests/pos-special/stdlib/collection/IndexedSeqView.scala rename to scala2-library-cc/src/scala/collection/IndexedSeqView.scala diff --git a/tests/pos-special/stdlib/collection/Iterable.scala b/scala2-library-cc/src/scala/collection/Iterable.scala similarity index 100% rename from tests/pos-special/stdlib/collection/Iterable.scala rename to scala2-library-cc/src/scala/collection/Iterable.scala diff --git a/tests/pos-special/stdlib/collection/IterableOnce.scala b/scala2-library-cc/src/scala/collection/IterableOnce.scala similarity index 99% rename from tests/pos-special/stdlib/collection/IterableOnce.scala rename to scala2-library-cc/src/scala/collection/IterableOnce.scala index a0b184410428..30eb142ae156 100644 --- a/tests/pos-special/stdlib/collection/IterableOnce.scala +++ b/scala2-library-cc/src/scala/collection/IterableOnce.scala @@ -19,7 +19,7 @@ import scala.collection.mutable.StringBuilder import scala.language.implicitConversions import scala.math.{Numeric, Ordering} import scala.reflect.ClassTag -import scala.runtime.AbstractFunction2 +import scala.runtime.{AbstractFunction1, AbstractFunction2} import language.experimental.captureChecking /** @@ -272,7 +272,7 @@ object IterableOnce { math.max(math.min(math.min(len, srcLen), destLen - start), 0) /** Calls `copyToArray` on the given collection, regardless of whether or not it is an `Iterable`. */ - @inline private[collection] def copyElemsToArray[A, B >: A]( + @inline private[collection] def copyElemsToArray[A, B >: A]( elems: IterableOnce[A]^, xs: Array[B], start: Int = 0, @@ -1117,8 +1117,8 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A]^ => def collectFirst[B](pf: PartialFunction[A, B]): Option[B] = { // Presumably the fastest way to get in and out of a partial function is for a sentinel function to return itself // (Tested to be lower-overhead than runWith. Would be better yet to not need to (formally) allocate it) - val sentinel: scala.Function1[A, Any] = new scala.runtime.AbstractFunction1[A, Any] { - def apply(a: A) = this + val sentinel: scala.Function1[A, Any] = new AbstractFunction1[A, Any] { + def apply(a: A): AbstractFunction1[A, Any] = this } val it = iterator while (it.hasNext) { @@ -1322,7 +1322,8 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A]^ => def toArray[B >: A: ClassTag]: Array[B] = if (knownSize >= 0) { val destination = new Array[B](knownSize) - copyToArray(destination, 0) + @annotation.unused val copied = copyToArray(destination, 0) + //assert(copied == destination.length) destination } else mutable.ArrayBuilder.make[B].addAll(this).result() @@ -1362,4 +1363,4 @@ object IterableOnceOps: m } } -end IterableOnceOps \ No newline at end of file +end IterableOnceOps diff --git a/tests/pos-special/stdlib/collection/Iterator.scala b/scala2-library-cc/src/scala/collection/Iterator.scala similarity index 100% rename from tests/pos-special/stdlib/collection/Iterator.scala rename to scala2-library-cc/src/scala/collection/Iterator.scala diff --git a/tests/pos-special/stdlib/collection/JavaConverters.scala b/scala2-library-cc/src/scala/collection/JavaConverters.scala similarity index 100% rename from tests/pos-special/stdlib/collection/JavaConverters.scala rename to scala2-library-cc/src/scala/collection/JavaConverters.scala diff --git a/tests/pos-special/stdlib/collection/LazyZipOps.scala b/scala2-library-cc/src/scala/collection/LazyZipOps.scala similarity index 100% rename from tests/pos-special/stdlib/collection/LazyZipOps.scala rename to scala2-library-cc/src/scala/collection/LazyZipOps.scala diff --git a/tests/pos-special/stdlib/collection/LinearSeq.scala b/scala2-library-cc/src/scala/collection/LinearSeq.scala similarity index 100% rename from tests/pos-special/stdlib/collection/LinearSeq.scala rename to scala2-library-cc/src/scala/collection/LinearSeq.scala diff --git a/tests/pos-special/stdlib/collection/Map.scala b/scala2-library-cc/src/scala/collection/Map.scala similarity index 100% rename from tests/pos-special/stdlib/collection/Map.scala rename to scala2-library-cc/src/scala/collection/Map.scala diff --git a/tests/pos-special/stdlib/collection/MapView.scala b/scala2-library-cc/src/scala/collection/MapView.scala similarity index 98% rename from tests/pos-special/stdlib/collection/MapView.scala rename to scala2-library-cc/src/scala/collection/MapView.scala index 595fe20538d3..5909fe24fbbc 100644 --- a/tests/pos-special/stdlib/collection/MapView.scala +++ b/scala2-library-cc/src/scala/collection/MapView.scala @@ -161,7 +161,7 @@ object MapView extends MapViewFactory { override def isEmpty: Boolean = underlying.isEmpty } - override def newBuilder[X, Y]: Builder[(X, Y), MapView[X, Y]] = mutable.HashMap.newBuilder[X, Y].mapResult(_.view) + override def newBuilder[X, Y]: Builder[(X, Y), MapView[X, Y]] = mutable.HashMap.newBuilder[X, Y].mapResult(_.view) override def empty[K, V]: MapView[K, V] = EmptyMapView.asInstanceOf[MapView[K, V]] diff --git a/tests/pos-special/stdlib/collection/Searching.scala b/scala2-library-cc/src/scala/collection/Searching.scala similarity index 100% rename from tests/pos-special/stdlib/collection/Searching.scala rename to scala2-library-cc/src/scala/collection/Searching.scala diff --git a/tests/pos-special/stdlib/collection/Seq.scala b/scala2-library-cc/src/scala/collection/Seq.scala similarity index 100% rename from tests/pos-special/stdlib/collection/Seq.scala rename to scala2-library-cc/src/scala/collection/Seq.scala diff --git a/tests/pos-special/stdlib/collection/SeqMap.scala b/scala2-library-cc/src/scala/collection/SeqMap.scala similarity index 100% rename from tests/pos-special/stdlib/collection/SeqMap.scala rename to scala2-library-cc/src/scala/collection/SeqMap.scala diff --git a/tests/pos-special/stdlib/collection/SeqView.scala b/scala2-library-cc/src/scala/collection/SeqView.scala similarity index 100% rename from tests/pos-special/stdlib/collection/SeqView.scala rename to scala2-library-cc/src/scala/collection/SeqView.scala diff --git a/tests/pos-special/stdlib/collection/Set.scala b/scala2-library-cc/src/scala/collection/Set.scala similarity index 100% rename from tests/pos-special/stdlib/collection/Set.scala rename to scala2-library-cc/src/scala/collection/Set.scala diff --git a/tests/pos-special/stdlib/collection/SortedMap.scala b/scala2-library-cc/src/scala/collection/SortedMap.scala similarity index 100% rename from tests/pos-special/stdlib/collection/SortedMap.scala rename to scala2-library-cc/src/scala/collection/SortedMap.scala diff --git a/tests/pos-special/stdlib/collection/SortedOps.scala b/scala2-library-cc/src/scala/collection/SortedOps.scala similarity index 100% rename from tests/pos-special/stdlib/collection/SortedOps.scala rename to scala2-library-cc/src/scala/collection/SortedOps.scala diff --git a/tests/pos-special/stdlib/collection/SortedSet.scala b/scala2-library-cc/src/scala/collection/SortedSet.scala similarity index 99% rename from tests/pos-special/stdlib/collection/SortedSet.scala rename to scala2-library-cc/src/scala/collection/SortedSet.scala index fb2f879edcd2..639dc9ddead0 100644 --- a/tests/pos-special/stdlib/collection/SortedSet.scala +++ b/scala2-library-cc/src/scala/collection/SortedSet.scala @@ -69,7 +69,6 @@ trait SortedSetOps[A, +CC[X] <: SortedSet[X], +C <: SortedSetOps[A, CC, C]] * @param start The lower-bound (inclusive) of the iterator */ def iteratorFrom(start: A): Iterator[A] - @deprecated("Use `iteratorFrom` instead.", "2.13.0") @`inline` def keysIteratorFrom(start: A): Iterator[A] = iteratorFrom(start) diff --git a/tests/pos-special/stdlib/collection/Stepper.scala b/scala2-library-cc/src/scala/collection/Stepper.scala similarity index 100% rename from tests/pos-special/stdlib/collection/Stepper.scala rename to scala2-library-cc/src/scala/collection/Stepper.scala diff --git a/tests/pos-special/stdlib/collection/StepperShape.scala b/scala2-library-cc/src/scala/collection/StepperShape.scala similarity index 100% rename from tests/pos-special/stdlib/collection/StepperShape.scala rename to scala2-library-cc/src/scala/collection/StepperShape.scala diff --git a/tests/pos-special/stdlib/collection/StrictOptimizedIterableOps.scala b/scala2-library-cc/src/scala/collection/StrictOptimizedIterableOps.scala similarity index 100% rename from tests/pos-special/stdlib/collection/StrictOptimizedIterableOps.scala rename to scala2-library-cc/src/scala/collection/StrictOptimizedIterableOps.scala diff --git a/tests/pos-special/stdlib/collection/StrictOptimizedMapOps.scala b/scala2-library-cc/src/scala/collection/StrictOptimizedMapOps.scala similarity index 100% rename from tests/pos-special/stdlib/collection/StrictOptimizedMapOps.scala rename to scala2-library-cc/src/scala/collection/StrictOptimizedMapOps.scala diff --git a/tests/pos-special/stdlib/collection/StrictOptimizedSeqOps.scala b/scala2-library-cc/src/scala/collection/StrictOptimizedSeqOps.scala similarity index 100% rename from tests/pos-special/stdlib/collection/StrictOptimizedSeqOps.scala rename to scala2-library-cc/src/scala/collection/StrictOptimizedSeqOps.scala diff --git a/tests/pos-special/stdlib/collection/StrictOptimizedSetOps.scala b/scala2-library-cc/src/scala/collection/StrictOptimizedSetOps.scala similarity index 100% rename from tests/pos-special/stdlib/collection/StrictOptimizedSetOps.scala rename to scala2-library-cc/src/scala/collection/StrictOptimizedSetOps.scala diff --git a/tests/pos-special/stdlib/collection/StrictOptimizedSortedMapOps.scala b/scala2-library-cc/src/scala/collection/StrictOptimizedSortedMapOps.scala similarity index 100% rename from tests/pos-special/stdlib/collection/StrictOptimizedSortedMapOps.scala rename to scala2-library-cc/src/scala/collection/StrictOptimizedSortedMapOps.scala diff --git a/tests/pos-special/stdlib/collection/StrictOptimizedSortedSetOps.scala b/scala2-library-cc/src/scala/collection/StrictOptimizedSortedSetOps.scala similarity index 100% rename from tests/pos-special/stdlib/collection/StrictOptimizedSortedSetOps.scala rename to scala2-library-cc/src/scala/collection/StrictOptimizedSortedSetOps.scala diff --git a/tests/pos-special/stdlib/collection/StringOps.scala b/scala2-library-cc/src/scala/collection/StringOps.scala similarity index 100% rename from tests/pos-special/stdlib/collection/StringOps.scala rename to scala2-library-cc/src/scala/collection/StringOps.scala diff --git a/tests/pos-special/stdlib/collection/StringParsers.scala b/scala2-library-cc/src/scala/collection/StringParsers.scala similarity index 99% rename from tests/pos-special/stdlib/collection/StringParsers.scala rename to scala2-library-cc/src/scala/collection/StringParsers.scala index 47281815da71..75dedab7183c 100644 --- a/tests/pos-special/stdlib/collection/StringParsers.scala +++ b/scala2-library-cc/src/scala/collection/StringParsers.scala @@ -167,7 +167,6 @@ private[scala] object StringParsers { else None } } - //floating point final def checkFloatFormat(format: String): Boolean = { //indices are tracked with a start index which points *at* the first index @@ -194,7 +193,6 @@ private[scala] object StringParsers { rec(from) } - def isHexFloatLiteral(startIndex: Int, endIndex: Int): Boolean = { def isHexDigit(ch: Char) = ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || @@ -232,7 +230,6 @@ private[scala] object StringParsers { val pIndex = format.indexWhere(ch => ch == 'p' || ch == 'P', startIndex) (pIndex <= endIndex) && prefixOK(startIndex, pIndex) && postfixOK(pIndex + 1, endIndex) } - def isDecFloatLiteral(startIndex: Int, endIndex: Int): Boolean = { //invariant: endIndex > startIndex @@ -279,7 +276,6 @@ private[scala] object StringParsers { //count 0x00 to 0x20 as "whitespace", and nothing else val unspacedStart = format.indexWhere(ch => ch.toInt > 0x20) val unspacedEnd = format.lastIndexWhere(ch => ch.toInt > 0x20) + 1 - if (unspacedStart == -1 || unspacedStart >= unspacedEnd || unspacedEnd <= 0) false else { //all formats can have a sign @@ -306,7 +302,6 @@ private[scala] object StringParsers { } } } - @inline def parseFloat(from: String): Option[Float] = if (checkFloatFormat(from)) Some(java.lang.Float.parseFloat(from)) diff --git a/tests/pos-special/stdlib/collection/View.scala b/scala2-library-cc/src/scala/collection/View.scala similarity index 100% rename from tests/pos-special/stdlib/collection/View.scala rename to scala2-library-cc/src/scala/collection/View.scala diff --git a/tests/pos-special/stdlib/collection/WithFilter.scala b/scala2-library-cc/src/scala/collection/WithFilter.scala similarity index 100% rename from tests/pos-special/stdlib/collection/WithFilter.scala rename to scala2-library-cc/src/scala/collection/WithFilter.scala diff --git a/tests/pos-special/stdlib/collection/concurrent/Map.scala b/scala2-library-cc/src/scala/collection/concurrent/Map.scala similarity index 100% rename from tests/pos-special/stdlib/collection/concurrent/Map.scala rename to scala2-library-cc/src/scala/collection/concurrent/Map.scala diff --git a/tests/pos-special/stdlib/collection/concurrent/TrieMap.scala b/scala2-library-cc/src/scala/collection/concurrent/TrieMap.scala similarity index 100% rename from tests/pos-special/stdlib/collection/concurrent/TrieMap.scala rename to scala2-library-cc/src/scala/collection/concurrent/TrieMap.scala diff --git a/tests/pos-special/stdlib/collection/convert/AsJavaConverters.scala b/scala2-library-cc/src/scala/collection/convert/AsJavaConverters.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/AsJavaConverters.scala rename to scala2-library-cc/src/scala/collection/convert/AsJavaConverters.scala diff --git a/tests/pos-special/stdlib/collection/convert/AsJavaExtensions.scala b/scala2-library-cc/src/scala/collection/convert/AsJavaExtensions.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/AsJavaExtensions.scala rename to scala2-library-cc/src/scala/collection/convert/AsJavaExtensions.scala diff --git a/tests/pos-special/stdlib/collection/convert/AsScalaConverters.scala b/scala2-library-cc/src/scala/collection/convert/AsScalaConverters.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/AsScalaConverters.scala rename to scala2-library-cc/src/scala/collection/convert/AsScalaConverters.scala diff --git a/tests/pos-special/stdlib/collection/convert/AsScalaExtensions.scala b/scala2-library-cc/src/scala/collection/convert/AsScalaExtensions.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/AsScalaExtensions.scala rename to scala2-library-cc/src/scala/collection/convert/AsScalaExtensions.scala diff --git a/tests/pos-special/stdlib/collection/convert/ImplicitConversions.scala b/scala2-library-cc/src/scala/collection/convert/ImplicitConversions.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/ImplicitConversions.scala rename to scala2-library-cc/src/scala/collection/convert/ImplicitConversions.scala diff --git a/tests/pos-special/stdlib/collection/convert/JavaCollectionWrappers.scala b/scala2-library-cc/src/scala/collection/convert/JavaCollectionWrappers.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/JavaCollectionWrappers.scala rename to scala2-library-cc/src/scala/collection/convert/JavaCollectionWrappers.scala diff --git a/tests/pos-special/stdlib/collection/convert/StreamExtensions.scala b/scala2-library-cc/src/scala/collection/convert/StreamExtensions.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/StreamExtensions.scala rename to scala2-library-cc/src/scala/collection/convert/StreamExtensions.scala diff --git a/tests/pos-special/stdlib/collection/convert/impl/ArrayStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/ArrayStepper.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/impl/ArrayStepper.scala rename to scala2-library-cc/src/scala/collection/convert/impl/ArrayStepper.scala diff --git a/tests/pos-special/stdlib/collection/convert/impl/BinaryTreeStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/BinaryTreeStepper.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/impl/BinaryTreeStepper.scala rename to scala2-library-cc/src/scala/collection/convert/impl/BinaryTreeStepper.scala diff --git a/tests/pos-special/stdlib/collection/convert/impl/BitSetStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/BitSetStepper.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/impl/BitSetStepper.scala rename to scala2-library-cc/src/scala/collection/convert/impl/BitSetStepper.scala diff --git a/tests/pos-special/stdlib/collection/convert/impl/ChampStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/ChampStepper.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/impl/ChampStepper.scala rename to scala2-library-cc/src/scala/collection/convert/impl/ChampStepper.scala diff --git a/tests/pos-special/stdlib/collection/convert/impl/InOrderStepperBase.scala b/scala2-library-cc/src/scala/collection/convert/impl/InOrderStepperBase.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/impl/InOrderStepperBase.scala rename to scala2-library-cc/src/scala/collection/convert/impl/InOrderStepperBase.scala diff --git a/tests/pos-special/stdlib/collection/convert/impl/IndexedSeqStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/IndexedSeqStepper.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/impl/IndexedSeqStepper.scala rename to scala2-library-cc/src/scala/collection/convert/impl/IndexedSeqStepper.scala diff --git a/tests/pos-special/stdlib/collection/convert/impl/IndexedStepperBase.scala b/scala2-library-cc/src/scala/collection/convert/impl/IndexedStepperBase.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/impl/IndexedStepperBase.scala rename to scala2-library-cc/src/scala/collection/convert/impl/IndexedStepperBase.scala diff --git a/tests/pos-special/stdlib/collection/convert/impl/IteratorStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/IteratorStepper.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/impl/IteratorStepper.scala rename to scala2-library-cc/src/scala/collection/convert/impl/IteratorStepper.scala diff --git a/tests/pos-special/stdlib/collection/convert/impl/NumericRangeStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/NumericRangeStepper.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/impl/NumericRangeStepper.scala rename to scala2-library-cc/src/scala/collection/convert/impl/NumericRangeStepper.scala diff --git a/tests/pos-special/stdlib/collection/convert/impl/RangeStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/RangeStepper.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/impl/RangeStepper.scala rename to scala2-library-cc/src/scala/collection/convert/impl/RangeStepper.scala diff --git a/tests/pos-special/stdlib/collection/convert/impl/StringStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/StringStepper.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/impl/StringStepper.scala rename to scala2-library-cc/src/scala/collection/convert/impl/StringStepper.scala diff --git a/tests/pos-special/stdlib/collection/convert/impl/TableStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/TableStepper.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/impl/TableStepper.scala rename to scala2-library-cc/src/scala/collection/convert/impl/TableStepper.scala diff --git a/tests/pos-special/stdlib/collection/convert/impl/VectorStepper.scala b/scala2-library-cc/src/scala/collection/convert/impl/VectorStepper.scala similarity index 100% rename from tests/pos-special/stdlib/collection/convert/impl/VectorStepper.scala rename to scala2-library-cc/src/scala/collection/convert/impl/VectorStepper.scala diff --git a/tests/pos-special/stdlib/collection/generic/BitOperations.scala b/scala2-library-cc/src/scala/collection/generic/BitOperations.scala similarity index 100% rename from tests/pos-special/stdlib/collection/generic/BitOperations.scala rename to scala2-library-cc/src/scala/collection/generic/BitOperations.scala diff --git a/tests/pos-special/stdlib/collection/generic/DefaultSerializationProxy.scala b/scala2-library-cc/src/scala/collection/generic/DefaultSerializationProxy.scala similarity index 100% rename from tests/pos-special/stdlib/collection/generic/DefaultSerializationProxy.scala rename to scala2-library-cc/src/scala/collection/generic/DefaultSerializationProxy.scala diff --git a/tests/pos-special/stdlib/collection/generic/IsIterable.scala b/scala2-library-cc/src/scala/collection/generic/IsIterable.scala similarity index 100% rename from tests/pos-special/stdlib/collection/generic/IsIterable.scala rename to scala2-library-cc/src/scala/collection/generic/IsIterable.scala diff --git a/tests/pos-special/stdlib/collection/generic/IsIterableOnce.scala b/scala2-library-cc/src/scala/collection/generic/IsIterableOnce.scala similarity index 100% rename from tests/pos-special/stdlib/collection/generic/IsIterableOnce.scala rename to scala2-library-cc/src/scala/collection/generic/IsIterableOnce.scala diff --git a/tests/pos-special/stdlib/collection/generic/IsMap.scala b/scala2-library-cc/src/scala/collection/generic/IsMap.scala similarity index 100% rename from tests/pos-special/stdlib/collection/generic/IsMap.scala rename to scala2-library-cc/src/scala/collection/generic/IsMap.scala diff --git a/tests/pos-special/stdlib/collection/generic/IsSeq.scala b/scala2-library-cc/src/scala/collection/generic/IsSeq.scala similarity index 100% rename from tests/pos-special/stdlib/collection/generic/IsSeq.scala rename to scala2-library-cc/src/scala/collection/generic/IsSeq.scala diff --git a/tests/pos-special/stdlib/collection/generic/Subtractable.scala b/scala2-library-cc/src/scala/collection/generic/Subtractable.scala similarity index 100% rename from tests/pos-special/stdlib/collection/generic/Subtractable.scala rename to scala2-library-cc/src/scala/collection/generic/Subtractable.scala diff --git a/tests/pos-special/stdlib/collection/generic/package.scala b/scala2-library-cc/src/scala/collection/generic/package.scala similarity index 100% rename from tests/pos-special/stdlib/collection/generic/package.scala rename to scala2-library-cc/src/scala/collection/generic/package.scala diff --git a/tests/pos-special/stdlib/collection/immutable/ArraySeq.scala b/scala2-library-cc/src/scala/collection/immutable/ArraySeq.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/ArraySeq.scala rename to scala2-library-cc/src/scala/collection/immutable/ArraySeq.scala diff --git a/tests/pos-special/stdlib/collection/immutable/BitSet.scala b/scala2-library-cc/src/scala/collection/immutable/BitSet.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/BitSet.scala rename to scala2-library-cc/src/scala/collection/immutable/BitSet.scala diff --git a/tests/pos-special/stdlib/collection/immutable/ChampCommon.scala b/scala2-library-cc/src/scala/collection/immutable/ChampCommon.scala similarity index 99% rename from tests/pos-special/stdlib/collection/immutable/ChampCommon.scala rename to scala2-library-cc/src/scala/collection/immutable/ChampCommon.scala index fc9bcb022874..3da269dccbd8 100644 --- a/tests/pos-special/stdlib/collection/immutable/ChampCommon.scala +++ b/scala2-library-cc/src/scala/collection/immutable/ChampCommon.scala @@ -113,7 +113,6 @@ private[immutable] abstract class ChampBaseIterator[T <: Node[T]] { // ChampBaseReverseIterator and in convert.impl.ChampStepperBase. // If you change this code, check those also in case they also // need to be modified. - protected var currentValueCursor: Int = 0 protected var currentValueLength: Int = 0 protected var currentValueNode: T = _ diff --git a/tests/pos-special/stdlib/collection/immutable/HashMap.scala b/scala2-library-cc/src/scala/collection/immutable/HashMap.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/HashMap.scala rename to scala2-library-cc/src/scala/collection/immutable/HashMap.scala diff --git a/tests/pos-special/stdlib/collection/immutable/HashSet.scala b/scala2-library-cc/src/scala/collection/immutable/HashSet.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/HashSet.scala rename to scala2-library-cc/src/scala/collection/immutable/HashSet.scala diff --git a/tests/pos-special/stdlib/collection/immutable/IntMap.scala b/scala2-library-cc/src/scala/collection/immutable/IntMap.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/IntMap.scala rename to scala2-library-cc/src/scala/collection/immutable/IntMap.scala diff --git a/tests/pos-special/stdlib/collection/immutable/Iterable.scala b/scala2-library-cc/src/scala/collection/immutable/Iterable.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/Iterable.scala rename to scala2-library-cc/src/scala/collection/immutable/Iterable.scala diff --git a/tests/pos-special/stdlib/collection/immutable/LazyListIterable.scala b/scala2-library-cc/src/scala/collection/immutable/LazyListIterable.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/LazyListIterable.scala rename to scala2-library-cc/src/scala/collection/immutable/LazyListIterable.scala diff --git a/tests/pos-special/stdlib/collection/immutable/List.scala b/scala2-library-cc/src/scala/collection/immutable/List.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/List.scala rename to scala2-library-cc/src/scala/collection/immutable/List.scala diff --git a/tests/pos-special/stdlib/collection/immutable/ListMap.scala b/scala2-library-cc/src/scala/collection/immutable/ListMap.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/ListMap.scala rename to scala2-library-cc/src/scala/collection/immutable/ListMap.scala diff --git a/tests/pos-special/stdlib/collection/immutable/ListSet.scala b/scala2-library-cc/src/scala/collection/immutable/ListSet.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/ListSet.scala rename to scala2-library-cc/src/scala/collection/immutable/ListSet.scala diff --git a/tests/pos-special/stdlib/collection/immutable/LongMap.scala b/scala2-library-cc/src/scala/collection/immutable/LongMap.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/LongMap.scala rename to scala2-library-cc/src/scala/collection/immutable/LongMap.scala diff --git a/tests/pos-special/stdlib/collection/immutable/Map.scala b/scala2-library-cc/src/scala/collection/immutable/Map.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/Map.scala rename to scala2-library-cc/src/scala/collection/immutable/Map.scala diff --git a/tests/pos-special/stdlib/collection/immutable/NumericRange.scala b/scala2-library-cc/src/scala/collection/immutable/NumericRange.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/NumericRange.scala rename to scala2-library-cc/src/scala/collection/immutable/NumericRange.scala diff --git a/tests/pos-special/stdlib/collection/immutable/Queue.scala b/scala2-library-cc/src/scala/collection/immutable/Queue.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/Queue.scala rename to scala2-library-cc/src/scala/collection/immutable/Queue.scala diff --git a/tests/pos-special/stdlib/collection/immutable/Range.scala b/scala2-library-cc/src/scala/collection/immutable/Range.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/Range.scala rename to scala2-library-cc/src/scala/collection/immutable/Range.scala diff --git a/tests/pos-special/stdlib/collection/immutable/RedBlackTree.scala b/scala2-library-cc/src/scala/collection/immutable/RedBlackTree.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/RedBlackTree.scala rename to scala2-library-cc/src/scala/collection/immutable/RedBlackTree.scala diff --git a/tests/pos-special/stdlib/collection/immutable/Seq.scala b/scala2-library-cc/src/scala/collection/immutable/Seq.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/Seq.scala rename to scala2-library-cc/src/scala/collection/immutable/Seq.scala diff --git a/tests/pos-special/stdlib/collection/immutable/SeqMap.scala b/scala2-library-cc/src/scala/collection/immutable/SeqMap.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/SeqMap.scala rename to scala2-library-cc/src/scala/collection/immutable/SeqMap.scala diff --git a/tests/pos-special/stdlib/collection/immutable/Set.scala b/scala2-library-cc/src/scala/collection/immutable/Set.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/Set.scala rename to scala2-library-cc/src/scala/collection/immutable/Set.scala diff --git a/tests/pos-special/stdlib/collection/immutable/SortedMap.scala b/scala2-library-cc/src/scala/collection/immutable/SortedMap.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/SortedMap.scala rename to scala2-library-cc/src/scala/collection/immutable/SortedMap.scala diff --git a/tests/pos-special/stdlib/collection/immutable/SortedSet.scala b/scala2-library-cc/src/scala/collection/immutable/SortedSet.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/SortedSet.scala rename to scala2-library-cc/src/scala/collection/immutable/SortedSet.scala diff --git a/tests/pos-special/stdlib/collection/immutable/StrictOptimizedSeqOps.scala b/scala2-library-cc/src/scala/collection/immutable/StrictOptimizedSeqOps.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/StrictOptimizedSeqOps.scala rename to scala2-library-cc/src/scala/collection/immutable/StrictOptimizedSeqOps.scala diff --git a/tests/pos-special/stdlib/collection/immutable/TreeMap.scala b/scala2-library-cc/src/scala/collection/immutable/TreeMap.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/TreeMap.scala rename to scala2-library-cc/src/scala/collection/immutable/TreeMap.scala diff --git a/tests/pos-special/stdlib/collection/immutable/TreeSeqMap.scala b/scala2-library-cc/src/scala/collection/immutable/TreeSeqMap.scala similarity index 98% rename from tests/pos-special/stdlib/collection/immutable/TreeSeqMap.scala rename to scala2-library-cc/src/scala/collection/immutable/TreeSeqMap.scala index fe194fa9de5a..dc59d21b8b19 100644 --- a/tests/pos-special/stdlib/collection/immutable/TreeSeqMap.scala +++ b/scala2-library-cc/src/scala/collection/immutable/TreeSeqMap.scala @@ -303,7 +303,7 @@ object TreeSeqMap extends MapFactory[TreeSeqMap] { else EmptyByInsertion }.asInstanceOf[TreeSeqMap[K, V]] - def from[K, V](it: collection.IterableOnce[(K, V)]^): TreeSeqMap[K, V] = + def from[K, V](it: collection.IterableOnce[(K, V)]^): TreeSeqMap[K, V] = it match { case om: TreeSeqMap[K, V] => om case _ => (newBuilder[K, V] ++= it).result() @@ -311,10 +311,10 @@ object TreeSeqMap extends MapFactory[TreeSeqMap] { @inline private def increment(ord: Int) = if (ord == Int.MaxValue) Int.MinValue else ord + 1 - def newBuilder[K, V]: mutable.Builder[(K, V), TreeSeqMap[K, V]] = newBuilder(OrderBy.Insertion) - def newBuilder[K, V](orderedBy: OrderBy): mutable.Builder[(K, V), TreeSeqMap[K, V]] = new Builder[K, V](orderedBy) + def newBuilder[K, V]: mutable.Builder[(K, V), TreeSeqMap[K, V]] = newBuilder(OrderBy.Insertion) + def newBuilder[K, V](orderedBy: OrderBy): mutable.Builder[(K, V), TreeSeqMap[K, V]] = new Builder[K, V](orderedBy) - final class Builder[K, V](orderedBy: OrderBy) extends mutable.Builder[(K, V), TreeSeqMap[K, V]] { + final class Builder[K, V](orderedBy: OrderBy) extends mutable.Builder[(K, V), TreeSeqMap[K, V]] { private[this] val bdr = new MapBuilderImpl[K, (Int, V)] private[this] var ong = Ordering.empty[K] private[this] var ord = 0 diff --git a/tests/pos-special/stdlib/collection/immutable/TreeSet.scala b/scala2-library-cc/src/scala/collection/immutable/TreeSet.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/TreeSet.scala rename to scala2-library-cc/src/scala/collection/immutable/TreeSet.scala diff --git a/tests/pos-special/stdlib/collection/immutable/Vector.scala b/scala2-library-cc/src/scala/collection/immutable/Vector.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/Vector.scala rename to scala2-library-cc/src/scala/collection/immutable/Vector.scala diff --git a/tests/pos-special/stdlib/collection/immutable/VectorMap.scala b/scala2-library-cc/src/scala/collection/immutable/VectorMap.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/VectorMap.scala rename to scala2-library-cc/src/scala/collection/immutable/VectorMap.scala diff --git a/tests/pos-special/stdlib/collection/immutable/WrappedString.scala b/scala2-library-cc/src/scala/collection/immutable/WrappedString.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/WrappedString.scala rename to scala2-library-cc/src/scala/collection/immutable/WrappedString.scala diff --git a/tests/pos-special/stdlib/collection/immutable/package.scala b/scala2-library-cc/src/scala/collection/immutable/package.scala similarity index 100% rename from tests/pos-special/stdlib/collection/immutable/package.scala rename to scala2-library-cc/src/scala/collection/immutable/package.scala diff --git a/tests/pos-special/stdlib/collection/mutable/AnyRefMap.scala b/scala2-library-cc/src/scala/collection/mutable/AnyRefMap.scala similarity index 91% rename from tests/pos-special/stdlib/collection/mutable/AnyRefMap.scala rename to scala2-library-cc/src/scala/collection/mutable/AnyRefMap.scala index 8f1ac07e725e..480babbf4b91 100644 --- a/tests/pos-special/stdlib/collection/mutable/AnyRefMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/AnyRefMap.scala @@ -43,7 +43,7 @@ import language.experimental.captureChecking * rapidly as 2^30^ is approached. * */ -class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K -> V, initialBufferSize: Int, initBlank: Boolean) +class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K -> V, initialBufferSize: Int, initBlank: Boolean) extends AbstractMap[K, V] with MapOps[K, V, Map, AnyRefMap[K, V]] with StrictOptimizedIterableOps[(K, V), Iterable, AnyRefMap[K, V]] @@ -478,11 +478,11 @@ class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K -> V, init } // The implicit dummy parameter is necessary to distinguish these methods from the base methods they overload (not override) - def map[K2 <: AnyRef, V2](f: ((K, V)) => (K2, V2))(implicit dummy: DummyImplicit): AnyRefMap[K2, V2] = + def map[K2 <: AnyRef, V2](f: ((K, V)) => (K2, V2))(implicit dummy: DummyImplicit): AnyRefMap[K2, V2] = AnyRefMap.from(new View.Map(this, f)) - def flatMap[K2 <: AnyRef, V2](f: ((K, V)) => IterableOnce[(K2, V2)])(implicit dummy: DummyImplicit): AnyRefMap[K2, V2] = + def flatMap[K2 <: AnyRef, V2](f: ((K, V)) => IterableOnce[(K2, V2)])(implicit dummy: DummyImplicit): AnyRefMap[K2, V2] = AnyRefMap.from(new View.FlatMap(this, f)) - def collect[K2 <: AnyRef, V2](pf: PartialFunction[(K, V), (K2, V2)])(implicit dummy: DummyImplicit): AnyRefMap[K2, V2] = + def collect[K2 <: AnyRef, V2](pf: PartialFunction[(K, V), (K2, V2)])(implicit dummy: DummyImplicit): AnyRefMap[K2, V2] = strictOptimizedCollect(AnyRefMap.newBuilder[K2, V2], pf) override def clear(): Unit = { @@ -515,7 +515,7 @@ object AnyRefMap { * * This builder can be reused to create multiple instances. */ - final class AnyRefMapBuilder[K <: AnyRef, V] extends ReusableBuilder[(K, V), AnyRefMap[K, V]] { + final class AnyRefMapBuilder[K <: AnyRef, V] extends ReusableBuilder[(K, V), AnyRefMap[K, V]] { private[collection] var elems: AnyRefMap[K, V] = new AnyRefMap[K, V] def addOne(entry: (K, V)): this.type = { elems += entry @@ -527,11 +527,11 @@ object AnyRefMap { } /** Creates a new `AnyRefMap` with zero or more key/value pairs. */ - def apply[K <: AnyRef, V](elems: (K, V)*): AnyRefMap[K, V] = buildFromIterableOnce(elems) + def apply[K <: AnyRef, V](elems: (K, V)*): AnyRefMap[K, V] = buildFromIterableOnce(elems) - def newBuilder[K <: AnyRef, V]: ReusableBuilder[(K, V), AnyRefMap[K, V]] = new AnyRefMapBuilder[K, V] + def newBuilder[K <: AnyRef, V]: ReusableBuilder[(K, V), AnyRefMap[K, V]] = new AnyRefMapBuilder[K, V] - private def buildFromIterableOnce[K <: AnyRef, V](elems: IterableOnce[(K, V)]^): AnyRefMap[K, V] = { + private def buildFromIterableOnce[K <: AnyRef, V](elems: IterableOnce[(K, V)]^): AnyRefMap[K, V] = { var sz = elems.knownSize if(sz < 0) sz = 4 val arm = new AnyRefMap[K, V](sz * 2) @@ -541,10 +541,10 @@ object AnyRefMap { } /** Creates a new empty `AnyRefMap`. */ - def empty[K <: AnyRef, V]: AnyRefMap[K, V] = new AnyRefMap[K, V] + def empty[K <: AnyRef, V]: AnyRefMap[K, V] = new AnyRefMap[K, V] /** Creates a new empty `AnyRefMap` with the supplied default */ - def withDefault[K <: AnyRef, V](default: K -> V): AnyRefMap[K, V] = new AnyRefMap[K, V](default) + def withDefault[K <: AnyRef, V](default: K -> V): AnyRefMap[K, V] = new AnyRefMap[K, V](default) /** Creates a new `AnyRefMap` from an existing source collection. A source collection * which is already an `AnyRefMap` gets cloned. @@ -554,7 +554,7 @@ object AnyRefMap { * @tparam V the type of the values * @return a new `AnyRefMap` with the elements of `source` */ - def from[K <: AnyRef, V](source: IterableOnce[(K, V)]^): AnyRefMap[K, V] = source match { + def from[K <: AnyRef, V](source: IterableOnce[(K, V)]^): AnyRefMap[K, V] = source match { case source: AnyRefMap[_, _] => source.clone().asInstanceOf[AnyRefMap[K, V]] case _ => buildFromIterableOnce(source) } @@ -562,7 +562,7 @@ object AnyRefMap { /** Creates a new `AnyRefMap` from arrays of keys and values. * Equivalent to but more efficient than `AnyRefMap((keys zip values): _*)`. */ - def fromZip[K <: AnyRef, V](keys: Array[K], values: Array[V]): AnyRefMap[K, V] = { + def fromZip[K <: AnyRef, V](keys: Array[K], values: Array[V]): AnyRefMap[K, V] = { val sz = math.min(keys.length, values.length) val arm = new AnyRefMap[K, V](sz * 2) var i = 0 @@ -574,7 +574,7 @@ object AnyRefMap { /** Creates a new `AnyRefMap` from keys and values. * Equivalent to but more efficient than `AnyRefMap((keys zip values): _*)`. */ - def fromZip[K <: AnyRef, V](keys: Iterable[K]^, values: Iterable[V]^): AnyRefMap[K, V] = { + def fromZip[K <: AnyRef, V](keys: Iterable[K]^, values: Iterable[V]^): AnyRefMap[K, V] = { val sz = math.min(keys.size, values.size) val arm = new AnyRefMap[K, V](sz * 2) val ki = keys.iterator @@ -584,7 +584,7 @@ object AnyRefMap { arm } - implicit def toFactory[K <: AnyRef, V](dummy: AnyRefMap.type): Factory[(K, V), AnyRefMap[K, V]] = ToFactory.asInstanceOf[Factory[(K, V), AnyRefMap[K, V]]] + implicit def toFactory[K <: AnyRef, V](dummy: AnyRefMap.type): Factory[(K, V), AnyRefMap[K, V]] = ToFactory.asInstanceOf[Factory[(K, V), AnyRefMap[K, V]]] @SerialVersionUID(3L) private[this] object ToFactory extends Factory[(AnyRef, AnyRef), AnyRefMap[AnyRef, AnyRef]] with Serializable { @@ -592,12 +592,12 @@ object AnyRefMap { def newBuilder: Builder[(AnyRef, AnyRef), AnyRefMap[AnyRef, AnyRef]] = AnyRefMap.newBuilder[AnyRef, AnyRef] } - implicit def toBuildFrom[K <: AnyRef, V](factory: AnyRefMap.type): BuildFrom[Any, (K, V), AnyRefMap[K, V]] = ToBuildFrom.asInstanceOf[BuildFrom[Any, (K, V), AnyRefMap[K, V]]] + implicit def toBuildFrom[K <: AnyRef, V](factory: AnyRefMap.type): BuildFrom[Any, (K, V), AnyRefMap[K, V]] = ToBuildFrom.asInstanceOf[BuildFrom[Any, (K, V), AnyRefMap[K, V]]] private[this] object ToBuildFrom extends BuildFrom[Any, (AnyRef, AnyRef), AnyRefMap[AnyRef, AnyRef]] { def fromSpecific(from: Any)(it: IterableOnce[(AnyRef, AnyRef)]^) = AnyRefMap.from(it) def newBuilder(from: Any) = AnyRefMap.newBuilder[AnyRef, AnyRef] } - implicit def iterableFactory[K <: AnyRef, V]: Factory[(K, V), AnyRefMap[K, V]] = toFactory[K, V](this) - implicit def buildFromAnyRefMap[K <: AnyRef, V]: BuildFrom[AnyRefMap[_, _], (K, V), AnyRefMap[K, V]] = toBuildFrom(this) + implicit def iterableFactory[K <: AnyRef, V]: Factory[(K, V), AnyRefMap[K, V]] = toFactory[K, V](this) + implicit def buildFromAnyRefMap[K <: AnyRef, V]: BuildFrom[AnyRefMap[_, _], (K, V), AnyRefMap[K, V]] = toBuildFrom(this) } diff --git a/tests/pos-special/stdlib/collection/mutable/ArrayBuffer.scala b/scala2-library-cc/src/scala/collection/mutable/ArrayBuffer.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/ArrayBuffer.scala rename to scala2-library-cc/src/scala/collection/mutable/ArrayBuffer.scala diff --git a/tests/pos-special/stdlib/collection/mutable/ArrayBuilder.scala b/scala2-library-cc/src/scala/collection/mutable/ArrayBuilder.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/ArrayBuilder.scala rename to scala2-library-cc/src/scala/collection/mutable/ArrayBuilder.scala diff --git a/tests/pos-special/stdlib/collection/mutable/ArrayDeque.scala b/scala2-library-cc/src/scala/collection/mutable/ArrayDeque.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/ArrayDeque.scala rename to scala2-library-cc/src/scala/collection/mutable/ArrayDeque.scala diff --git a/tests/pos-special/stdlib/collection/mutable/ArraySeq.scala b/scala2-library-cc/src/scala/collection/mutable/ArraySeq.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/ArraySeq.scala rename to scala2-library-cc/src/scala/collection/mutable/ArraySeq.scala diff --git a/tests/pos-special/stdlib/collection/mutable/BitSet.scala b/scala2-library-cc/src/scala/collection/mutable/BitSet.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/BitSet.scala rename to scala2-library-cc/src/scala/collection/mutable/BitSet.scala diff --git a/tests/pos-special/stdlib/collection/mutable/Buffer.scala b/scala2-library-cc/src/scala/collection/mutable/Buffer.scala similarity index 99% rename from tests/pos-special/stdlib/collection/mutable/Buffer.scala rename to scala2-library-cc/src/scala/collection/mutable/Buffer.scala index 1f7fc76972a2..f9aa9cf28c72 100644 --- a/tests/pos-special/stdlib/collection/mutable/Buffer.scala +++ b/scala2-library-cc/src/scala/collection/mutable/Buffer.scala @@ -104,7 +104,6 @@ trait Buffer[A] @throws[IndexOutOfBoundsException] @throws[IllegalArgumentException] def remove(idx: Int, count: Int): Unit - /** Removes a single element from this buffer, at its first occurrence. * If the buffer does not contain that element, it is unchanged. * diff --git a/tests/pos-special/stdlib/collection/mutable/Builder.scala b/scala2-library-cc/src/scala/collection/mutable/Builder.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/Builder.scala rename to scala2-library-cc/src/scala/collection/mutable/Builder.scala diff --git a/tests/pos-special/stdlib/collection/mutable/CheckedIndexedSeqView.scala b/scala2-library-cc/src/scala/collection/mutable/CheckedIndexedSeqView.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/CheckedIndexedSeqView.scala rename to scala2-library-cc/src/scala/collection/mutable/CheckedIndexedSeqView.scala diff --git a/tests/pos-special/stdlib/collection/mutable/Cloneable.scala b/scala2-library-cc/src/scala/collection/mutable/Cloneable.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/Cloneable.scala rename to scala2-library-cc/src/scala/collection/mutable/Cloneable.scala diff --git a/tests/pos-special/stdlib/collection/mutable/CollisionProofHashMap.scala b/scala2-library-cc/src/scala/collection/mutable/CollisionProofHashMap.scala similarity index 95% rename from tests/pos-special/stdlib/collection/mutable/CollisionProofHashMap.scala rename to scala2-library-cc/src/scala/collection/mutable/CollisionProofHashMap.scala index 0679ab7be201..ff3bab1dd818 100644 --- a/tests/pos-special/stdlib/collection/mutable/CollisionProofHashMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/CollisionProofHashMap.scala @@ -33,7 +33,7 @@ import language.experimental.captureChecking * @define mayNotTerminateInf * @define willNotTerminateInf */ -final class CollisionProofHashMap[K, V](initialCapacity: Int, loadFactor: Double)(implicit ordering: Ordering[K]) +final class CollisionProofHashMap[K, V](initialCapacity: Int, loadFactor: Double)(implicit ordering: Ordering[K]) extends AbstractMap[K, V] with MapOps[K, V, Map, CollisionProofHashMap[K, V]] //-- with StrictOptimizedIterableOps[(K, V), Iterable, CollisionProofHashMap[K, V]] @@ -744,17 +744,17 @@ final class CollisionProofHashMap[K, V](initialCapacity: Int, loadFactor: Doubl object CollisionProofHashMap extends SortedMapFactory[CollisionProofHashMap] { private[collection] final val ordMsg = "No implicit Ordering[${K2}] found to build a CollisionProofHashMap[${K2}, ${V2}]. You may want to upcast to a Map[${K}, ${V}] first by calling `unsorted`." - def from[K : Ordering, V](it: scala.collection.IterableOnce[(K, V)]^): CollisionProofHashMap[K, V] = { + def from[K : Ordering, V](it: scala.collection.IterableOnce[(K, V)]^): CollisionProofHashMap[K, V] = { val k = it.knownSize val cap = if(k > 0) ((k + 1).toDouble / defaultLoadFactor).toInt else defaultInitialCapacity new CollisionProofHashMap[K, V](cap, defaultLoadFactor) ++= it } - def empty[K : Ordering, V]: CollisionProofHashMap[K, V] = new CollisionProofHashMap[K, V] + def empty[K : Ordering, V]: CollisionProofHashMap[K, V] = new CollisionProofHashMap[K, V] - def newBuilder[K : Ordering, V]: Builder[(K, V), CollisionProofHashMap[K, V]] = newBuilder(defaultInitialCapacity, defaultLoadFactor) + def newBuilder[K : Ordering, V]: Builder[(K, V), CollisionProofHashMap[K, V]] = newBuilder(defaultInitialCapacity, defaultLoadFactor) - def newBuilder[K : Ordering, V](initialCapacity: Int, loadFactor: Double): Builder[(K, V), CollisionProofHashMap[K, V]] = + def newBuilder[K : Ordering, V](initialCapacity: Int, loadFactor: Double): Builder[(K, V), CollisionProofHashMap[K, V]] = new GrowableBuilder[(K, V), CollisionProofHashMap[K, V]](new CollisionProofHashMap[K, V](initialCapacity, loadFactor)) { override def sizeHint(size: Int) = elems.sizeHint(size) } @@ -766,7 +766,7 @@ object CollisionProofHashMap extends SortedMapFactory[CollisionProofHashMap] { final def defaultInitialCapacity: Int = 16 @SerialVersionUID(3L) - private final class DeserializationFactory[K, V](val tableLength: Int, val loadFactor: Double, val ordering: Ordering[K]) extends Factory[(K, V), CollisionProofHashMap[K, V]] with Serializable { + private final class DeserializationFactory[K, V](val tableLength: Int, val loadFactor: Double, val ordering: Ordering[K]) extends Factory[(K, V), CollisionProofHashMap[K, V]] with Serializable { def fromSpecific(it: IterableOnce[(K, V)]^): CollisionProofHashMap[K, V] = new CollisionProofHashMap[K, V](tableLength, loadFactor)(ordering) ++= it def newBuilder: Builder[(K, V), CollisionProofHashMap[K, V]] = CollisionProofHashMap.newBuilder(tableLength, loadFactor)(ordering) } @@ -789,7 +789,7 @@ object CollisionProofHashMap extends SortedMapFactory[CollisionProofHashMap] { /////////////////////////// Red-Black Tree Node - final class RBNode[K, V](var key: K, var hash: Int, var value: V, var red: Boolean, var left: RBNode[K, V], var right: RBNode[K, V], var parent: RBNode[K, V]) extends Node { + final class RBNode[K, V](var key: K, var hash: Int, var value: V, var red: Boolean, var left: RBNode[K, V], var right: RBNode[K, V], var parent: RBNode[K, V]) extends Node { override def toString: String = "RBNode(" + key + ", " + hash + ", " + value + ", " + red + ", " + left + ", " + right + ")" @tailrec def getNode(k: K, h: Int)(implicit ord: Ordering[K]): RBNode[K, V] = { @@ -820,17 +820,17 @@ object CollisionProofHashMap extends SortedMapFactory[CollisionProofHashMap] { } } - @`inline` private def leaf[A, B](key: A, hash: Int, value: B, red: Boolean, parent: RBNode[A, B]): RBNode[A, B] = + @`inline` private def leaf[A, B](key: A, hash: Int, value: B, red: Boolean, parent: RBNode[A, B]): RBNode[A, B] = new RBNode(key, hash, value, red, null, null, parent) - @tailrec private def minNodeNonNull[A, B](node: RBNode[A, B]): RBNode[A, B] = + @tailrec private def minNodeNonNull[A, B](node: RBNode[A, B]): RBNode[A, B] = if (node.left eq null) node else minNodeNonNull(node.left) /** * Returns the node that follows `node` in an in-order tree traversal. If `node` has the maximum key (and is, * therefore, the last node), this method returns `null`. */ - private def successor[A, B](node: RBNode[A, B]): RBNode[A, B] = { + private def successor[A, B](node: RBNode[A, B]): RBNode[A, B] = { if (node.right ne null) minNodeNonNull(node.right) else { var x = node @@ -843,7 +843,7 @@ object CollisionProofHashMap extends SortedMapFactory[CollisionProofHashMap] { } } - private final class RBNodesIterator[A, B](tree: RBNode[A, B])(implicit @unused ord: Ordering[A]) extends AbstractIterator[RBNode[A, B]] { + private final class RBNodesIterator[A, B](tree: RBNode[A, B])(implicit @unused ord: Ordering[A]) extends AbstractIterator[RBNode[A, B]] { private[this] var nextNode: RBNode[A, B] = if(tree eq null) null else minNodeNonNull(tree) def hasNext: Boolean = nextNode ne null @@ -859,7 +859,7 @@ object CollisionProofHashMap extends SortedMapFactory[CollisionProofHashMap] { /////////////////////////// Linked List Node - private final class LLNode[K, V](var key: K, var hash: Int, var value: V, var next: LLNode[K, V]) extends Node { + private final class LLNode[K, V](var key: K, var hash: Int, var value: V, var next: LLNode[K, V]) extends Node { override def toString = s"LLNode($key, $value, $hash) -> $next" private[this] def eq(a: Any, b: Any): Boolean = diff --git a/tests/pos-special/stdlib/collection/mutable/Growable.scala b/scala2-library-cc/src/scala/collection/mutable/Growable.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/Growable.scala rename to scala2-library-cc/src/scala/collection/mutable/Growable.scala diff --git a/tests/pos-special/stdlib/collection/mutable/GrowableBuilder.scala b/scala2-library-cc/src/scala/collection/mutable/GrowableBuilder.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/GrowableBuilder.scala rename to scala2-library-cc/src/scala/collection/mutable/GrowableBuilder.scala diff --git a/tests/pos-special/stdlib/collection/mutable/HashMap.scala b/scala2-library-cc/src/scala/collection/mutable/HashMap.scala similarity index 97% rename from tests/pos-special/stdlib/collection/mutable/HashMap.scala rename to scala2-library-cc/src/scala/collection/mutable/HashMap.scala index 1ba651b47819..89a9f3f186f7 100644 --- a/tests/pos-special/stdlib/collection/mutable/HashMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/HashMap.scala @@ -33,7 +33,7 @@ import language.experimental.captureChecking * @define willNotTerminateInf */ @deprecatedInheritance("HashMap will be made final; use .withDefault for the common use case of computing a default value", "2.13.0") -class HashMap[K, V](initialCapacity: Int, loadFactor: Double) +class HashMap[K, V](initialCapacity: Int, loadFactor: Double) extends AbstractMap[K, V] with MapOps[K, V, HashMap, HashMap[K, V]] with StrictOptimizedIterableOps[(K, V), Iterable, HashMap[K, V]] @@ -597,17 +597,17 @@ class HashMap[K, V](initialCapacity: Int, loadFactor: Double) @SerialVersionUID(3L) object HashMap extends MapFactory[HashMap] { - def empty[K, V]: HashMap[K, V] = new HashMap[K, V] + def empty[K, V]: HashMap[K, V] = new HashMap[K, V] - def from[K, V](it: collection.IterableOnce[(K, V)]^): HashMap[K, V] = { + def from[K, V](it: collection.IterableOnce[(K, V)]^): HashMap[K, V] = { val k = it.knownSize val cap = if(k > 0) ((k + 1).toDouble / defaultLoadFactor).toInt else defaultInitialCapacity new HashMap[K, V](cap, defaultLoadFactor).addAll(it) } - def newBuilder[K, V]: Builder[(K, V), HashMap[K, V]] = newBuilder(defaultInitialCapacity, defaultLoadFactor) + def newBuilder[K, V]: Builder[(K, V), HashMap[K, V]] = newBuilder(defaultInitialCapacity, defaultLoadFactor) - def newBuilder[K, V](initialCapacity: Int, loadFactor: Double): Builder[(K, V), HashMap[K, V]] = + def newBuilder[K, V](initialCapacity: Int, loadFactor: Double): Builder[(K, V), HashMap[K, V]] = new GrowableBuilder[(K, V), HashMap[K, V]](new HashMap[K, V](initialCapacity, loadFactor)) { override def sizeHint(size: Int) = elems.sizeHint(size) } @@ -619,7 +619,7 @@ object HashMap extends MapFactory[HashMap] { final def defaultInitialCapacity: Int = 16 @SerialVersionUID(3L) - private final class DeserializationFactory[K, V](val tableLength: Int, val loadFactor: Double) extends Factory[(K, V), HashMap[K, V]] with Serializable { + private final class DeserializationFactory[K, V](val tableLength: Int, val loadFactor: Double) extends Factory[(K, V), HashMap[K, V]] with Serializable { def fromSpecific(it: IterableOnce[(K, V)]^): HashMap[K, V] = new HashMap[K, V](tableLength, loadFactor).addAll(it) def newBuilder: Builder[(K, V), HashMap[K, V]] = HashMap.newBuilder(tableLength, loadFactor) } diff --git a/tests/pos-special/stdlib/collection/mutable/HashSet.scala b/scala2-library-cc/src/scala/collection/mutable/HashSet.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/HashSet.scala rename to scala2-library-cc/src/scala/collection/mutable/HashSet.scala diff --git a/tests/pos-special/stdlib/collection/mutable/HashTable.scala b/scala2-library-cc/src/scala/collection/mutable/HashTable.scala similarity index 99% rename from tests/pos-special/stdlib/collection/mutable/HashTable.scala rename to scala2-library-cc/src/scala/collection/mutable/HashTable.scala index 64af941eac1f..461df6cea22c 100644 --- a/tests/pos-special/stdlib/collection/mutable/HashTable.scala +++ b/scala2-library-cc/src/scala/collection/mutable/HashTable.scala @@ -412,7 +412,7 @@ private[collection] object HashTable { /** Class used internally. */ -private[collection] trait HashEntry[A, E <: HashEntry[A, E]] { +private[collection] trait HashEntry[A, E <: HashEntry[A, E]] { val key: A var next: E = _ } diff --git a/tests/pos-special/stdlib/collection/mutable/ImmutableBuilder.scala b/scala2-library-cc/src/scala/collection/mutable/ImmutableBuilder.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/ImmutableBuilder.scala rename to scala2-library-cc/src/scala/collection/mutable/ImmutableBuilder.scala diff --git a/tests/pos-special/stdlib/collection/mutable/IndexedSeq.scala b/scala2-library-cc/src/scala/collection/mutable/IndexedSeq.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/IndexedSeq.scala rename to scala2-library-cc/src/scala/collection/mutable/IndexedSeq.scala diff --git a/tests/pos-special/stdlib/collection/mutable/Iterable.scala b/scala2-library-cc/src/scala/collection/mutable/Iterable.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/Iterable.scala rename to scala2-library-cc/src/scala/collection/mutable/Iterable.scala diff --git a/tests/pos-special/stdlib/collection/mutable/LinkedHashMap.scala b/scala2-library-cc/src/scala/collection/mutable/LinkedHashMap.scala similarity index 98% rename from tests/pos-special/stdlib/collection/mutable/LinkedHashMap.scala rename to scala2-library-cc/src/scala/collection/mutable/LinkedHashMap.scala index 528c39e49bdf..e3fc9d6aefd6 100644 --- a/tests/pos-special/stdlib/collection/mutable/LinkedHashMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/LinkedHashMap.scala @@ -34,7 +34,7 @@ import language.experimental.captureChecking * @define orderDependentFold */ @deprecatedInheritance("LinkedHashMap will be made final; use .withDefault for the common use case of computing a default value", "2.13.11") -class LinkedHashMap[K, V] +class LinkedHashMap[K, V] extends AbstractMap[K, V] with SeqMap[K, V] with MapOps[K, V, LinkedHashMap, LinkedHashMap[K, V]] @@ -477,20 +477,20 @@ class LinkedHashMap[K, V] @SerialVersionUID(3L) object LinkedHashMap extends MapFactory[LinkedHashMap] { - def empty[K, V] = new LinkedHashMap[K, V] + def empty[K, V] = new LinkedHashMap[K, V] - def from[K, V](it: collection.IterableOnce[(K, V)]^) = { + def from[K, V](it: collection.IterableOnce[(K, V)]^) = { val newlhm = empty[K, V] newlhm.sizeHint(it.knownSize) newlhm.addAll(it) newlhm } - def newBuilder[K, V] = new GrowableBuilder(empty[K, V]) + def newBuilder[K, V] = new GrowableBuilder(empty[K, V]) /** Class for the linked hash map entry, used internally. */ - private[mutable] final class LinkedEntry[K, V](val key: K, val hash: Int, var value: V) { + private[mutable] final class LinkedEntry[K, V](val key: K, val hash: Int, var value: V) { var earlier: LinkedEntry[K, V] = null var later: LinkedEntry[K, V] = null var next: LinkedEntry[K, V] = null diff --git a/tests/pos-special/stdlib/collection/mutable/LinkedHashSet.scala b/scala2-library-cc/src/scala/collection/mutable/LinkedHashSet.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/LinkedHashSet.scala rename to scala2-library-cc/src/scala/collection/mutable/LinkedHashSet.scala diff --git a/tests/pos-special/stdlib/collection/mutable/ListBuffer.scala b/scala2-library-cc/src/scala/collection/mutable/ListBuffer.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/ListBuffer.scala rename to scala2-library-cc/src/scala/collection/mutable/ListBuffer.scala diff --git a/tests/pos-special/stdlib/collection/mutable/ListMap.scala b/scala2-library-cc/src/scala/collection/mutable/ListMap.scala similarity index 90% rename from tests/pos-special/stdlib/collection/mutable/ListMap.scala rename to scala2-library-cc/src/scala/collection/mutable/ListMap.scala index e4f9322050d5..26e904e271a1 100644 --- a/tests/pos-special/stdlib/collection/mutable/ListMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/ListMap.scala @@ -31,7 +31,7 @@ import language.experimental.captureChecking * @define orderDependentFold */ @deprecated("Use an immutable.ListMap assigned to a var instead of mutable.ListMap", "2.13.0") -class ListMap[K, V] +class ListMap[K, V] extends AbstractMap[K, V] with MapOps[K, V, ListMap, ListMap[K, V]] with StrictOptimizedIterableOps[(K, V), Iterable, ListMap[K, V]] @@ -77,7 +77,7 @@ class ListMap[K, V] @SerialVersionUID(3L) @deprecated("Use an immutable.ListMap assigned to a var instead of mutable.ListMap", "2.13.0") object ListMap extends MapFactory[ListMap] { - def empty[K, V]: ListMap[K, V] = new ListMap[K, V] - def from[K, V](it: IterableOnce[(K, V)]^): ListMap[K,V] = Growable.from(empty[K, V], it) - def newBuilder[K, V]: Builder[(K, V), ListMap[K,V]] = new GrowableBuilder(empty[K, V]) + def empty[K, V]: ListMap[K, V] = new ListMap[K, V] + def from[K, V](it: IterableOnce[(K, V)]^): ListMap[K,V] = Growable.from(empty[K, V], it) + def newBuilder[K, V]: Builder[(K, V), ListMap[K,V]] = new GrowableBuilder(empty[K, V]) } diff --git a/tests/pos-special/stdlib/collection/mutable/LongMap.scala b/scala2-library-cc/src/scala/collection/mutable/LongMap.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/LongMap.scala rename to scala2-library-cc/src/scala/collection/mutable/LongMap.scala diff --git a/tests/pos-special/stdlib/collection/mutable/Map.scala b/scala2-library-cc/src/scala/collection/mutable/Map.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/Map.scala rename to scala2-library-cc/src/scala/collection/mutable/Map.scala diff --git a/tests/pos-special/stdlib/collection/mutable/MultiMap.scala b/scala2-library-cc/src/scala/collection/mutable/MultiMap.scala similarity index 98% rename from tests/pos-special/stdlib/collection/mutable/MultiMap.scala rename to scala2-library-cc/src/scala/collection/mutable/MultiMap.scala index 93b0d6ae4d73..0b250a5548ef 100644 --- a/tests/pos-special/stdlib/collection/mutable/MultiMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/MultiMap.scala @@ -52,7 +52,7 @@ import language.experimental.captureChecking * @define Coll `MultiMap` */ @deprecated("Use a scala.collection.mutable.MultiDict in the scala-collection-contrib module", "2.13.0") -trait MultiMap[K, V] extends Map[K, Set[V]] { +trait MultiMap[K, V] extends Map[K, Set[V]] { /** Creates a new set. * * Classes that use this trait as a mixin can override this method diff --git a/tests/pos-special/stdlib/collection/mutable/MutationTracker.scala b/scala2-library-cc/src/scala/collection/mutable/MutationTracker.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/MutationTracker.scala rename to scala2-library-cc/src/scala/collection/mutable/MutationTracker.scala diff --git a/tests/pos-special/stdlib/collection/mutable/OpenHashMap.scala b/scala2-library-cc/src/scala/collection/mutable/OpenHashMap.scala similarity index 97% rename from tests/pos-special/stdlib/collection/mutable/OpenHashMap.scala rename to scala2-library-cc/src/scala/collection/mutable/OpenHashMap.scala index 978245d5bffb..d29be3ffea5e 100644 --- a/tests/pos-special/stdlib/collection/mutable/OpenHashMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/OpenHashMap.scala @@ -26,10 +26,10 @@ import language.experimental.captureChecking @SerialVersionUID(3L) object OpenHashMap extends MapFactory[OpenHashMap] { - def empty[K, V] = new OpenHashMap[K, V] - def from[K, V](it: IterableOnce[(K, V)]^): OpenHashMap[K,V] = empty ++= it + def empty[K, V] = new OpenHashMap[K, V] + def from[K, V](it: IterableOnce[(K, V)]^): OpenHashMap[K,V] = empty ++= it - def newBuilder[K, V]: Builder[(K, V), OpenHashMap[K,V]] = + def newBuilder[K, V]: Builder[(K, V), OpenHashMap[K,V]] = new GrowableBuilder[(K, V), OpenHashMap[K, V]](empty) /** A hash table entry. @@ -39,7 +39,7 @@ object OpenHashMap extends MapFactory[OpenHashMap] { * If its `key` is not the default value of type `Key`, the entry is occupied. * If the entry is occupied, `hash` contains the hash value of `key`. */ - final private class OpenEntry[Key, Value](var key: Key, + final private class OpenEntry[Key, Value](var key: Key, var hash: Int, var value: Option[Value]) @@ -62,7 +62,7 @@ object OpenHashMap extends MapFactory[OpenHashMap] { * @define willNotTerminateInf */ @deprecated("Use HashMap or one of the specialized versions (LongMap, AnyRefMap) instead of OpenHashMap", "2.13.0") -class OpenHashMap[Key, Value](initialSize : Int) +class OpenHashMap[Key, Value](initialSize : Int) extends AbstractMap[Key, Value] with MapOps[Key, Value, OpenHashMap, OpenHashMap[Key, Value]] with StrictOptimizedIterableOps[(Key, Value), Iterable, OpenHashMap[Key, Value]] diff --git a/tests/pos-special/stdlib/collection/mutable/PriorityQueue.scala b/scala2-library-cc/src/scala/collection/mutable/PriorityQueue.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/PriorityQueue.scala rename to scala2-library-cc/src/scala/collection/mutable/PriorityQueue.scala diff --git a/tests/pos-special/stdlib/collection/mutable/Queue.scala b/scala2-library-cc/src/scala/collection/mutable/Queue.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/Queue.scala rename to scala2-library-cc/src/scala/collection/mutable/Queue.scala diff --git a/tests/pos-special/stdlib/collection/mutable/RedBlackTree.scala b/scala2-library-cc/src/scala/collection/mutable/RedBlackTree.scala similarity index 93% rename from tests/pos-special/stdlib/collection/mutable/RedBlackTree.scala rename to scala2-library-cc/src/scala/collection/mutable/RedBlackTree.scala index 4e079bca3245..f808a4257eef 100644 --- a/tests/pos-special/stdlib/collection/mutable/RedBlackTree.scala +++ b/scala2-library-cc/src/scala/collection/mutable/RedBlackTree.scala @@ -32,25 +32,25 @@ private[collection] object RedBlackTree { // Therefore, while obtaining the size of the whole tree is O(1), knowing the number of entries inside a range is O(n) // on the size of the range. - final class Tree[A, B](var root: Node[A, B], var size: Int) { + final class Tree[A, B](var root: Node[A, B], var size: Int) { def treeCopy(): Tree[A, B] = new Tree(copyTree(root), size) } - final class Node[A, B](var key: A, var value: B, var red: Boolean, var left: Node[A, B], var right: Node[A, B], var parent: Node[A, B]) { + final class Node[A, B](var key: A, var value: B, var red: Boolean, var left: Node[A, B], var right: Node[A, B], var parent: Node[A, B]) { override def toString: String = "Node(" + key + ", " + value + ", " + red + ", " + left + ", " + right + ")" } object Tree { - def empty[A, B]: Tree[A, B] = new Tree(null, 0) + def empty[A, B]: Tree[A, B] = new Tree(null, 0) } object Node { - @`inline` def apply[A, B](key: A, value: B, red: Boolean, + @`inline` def apply[A, B](key: A, value: B, red: Boolean, left: Node[A, B], right: Node[A, B], parent: Node[A, B]): Node[A, B] = new Node(key, value, red, left, right, parent) - @`inline` def leaf[A, B](key: A, value: B, red: Boolean, parent: Node[A, B]): Node[A, B] = + @`inline` def leaf[A, B](key: A, value: B, red: Boolean, parent: Node[A, B]): Node[A, B] = new Node(key, value, red, null, null, parent) def unapply[A, B](t: Node[A, B]) = Some((t.key, t.value, t.left, t.right, t.parent)) @@ -181,7 +181,7 @@ private[collection] object RedBlackTree { // ---- insertion ---- - def insert[A, B](tree: Tree[A, B], key: A, value: B)(implicit ord: Ordering[A]): Unit = { + def insert[A, B](tree: Tree[A, B], key: A, value: B)(implicit ord: Ordering[A]): Unit = { var y: Node[A, B] = null var x = tree.root var cmp = 1 @@ -477,16 +477,16 @@ private[collection] object RedBlackTree { if (node.right ne null) transformNodeNonNull(node.right, f) } - def iterator[A: Ordering, B](tree: Tree[A, B], start: Option[A] = None, end: Option[A] = None): Iterator[(A, B)] = + def iterator[A: Ordering, B](tree: Tree[A, B], start: Option[A] = None, end: Option[A] = None): Iterator[(A, B)] = new EntriesIterator(tree, start, end) def keysIterator[A: Ordering](tree: Tree[A, _], start: Option[A] = None, end: Option[A] = None): Iterator[A] = new KeysIterator(tree, start, end) - def valuesIterator[A: Ordering, B](tree: Tree[A, B], start: Option[A] = None, end: Option[A] = None): Iterator[B] = + def valuesIterator[A: Ordering, B](tree: Tree[A, B], start: Option[A] = None, end: Option[A] = None): Iterator[B] = new ValuesIterator(tree, start, end) - private[this] abstract class TreeIterator[A, B, R](tree: Tree[A, B], start: Option[A], end: Option[A]) + private[this] abstract class TreeIterator[A, B, R](tree: Tree[A, B], start: Option[A], end: Option[A]) (implicit ord: Ordering[A]) extends AbstractIterator[R] { protected def nextResult(node: Node[A, B]): R @@ -514,19 +514,19 @@ private[collection] object RedBlackTree { setNullIfAfterEnd() } - private[this] final class EntriesIterator[A: Ordering, B](tree: Tree[A, B], start: Option[A], end: Option[A]) + private[this] final class EntriesIterator[A: Ordering, B](tree: Tree[A, B], start: Option[A], end: Option[A]) extends TreeIterator[A, B, (A, B)](tree, start, end) { def nextResult(node: Node[A, B]) = (node.key, node.value) } - private[this] final class KeysIterator[A: Ordering, B](tree: Tree[A, B], start: Option[A], end: Option[A]) + private[this] final class KeysIterator[A: Ordering, B](tree: Tree[A, B], start: Option[A], end: Option[A]) extends TreeIterator[A, B, A](tree, start, end) { def nextResult(node: Node[A, B]) = node.key } - private[this] final class ValuesIterator[A: Ordering, B](tree: Tree[A, B], start: Option[A], end: Option[A]) + private[this] final class ValuesIterator[A: Ordering, B](tree: Tree[A, B], start: Option[A], end: Option[A]) extends TreeIterator[A, B, B](tree, start, end) { def nextResult(node: Node[A, B]) = node.value @@ -623,7 +623,7 @@ private[collection] object RedBlackTree { } /** Build a Tree suitable for a TreeMap from an ordered sequence of key/value pairs */ - def fromOrderedEntries[A, B](xs: Iterator[(A, B)], size: Int): Tree[A, B] = { + def fromOrderedEntries[A, B](xs: Iterator[(A, B)], size: Int): Tree[A, B] = { val maxUsedDepth = 32 - Integer.numberOfLeadingZeros(size) // maximum depth of non-leaf nodes def f(level: Int, size: Int): Node[A, B] = size match { case 0 => null @@ -643,7 +643,7 @@ private[collection] object RedBlackTree { new Tree(f(1, size), size) } - def copyTree[A, B](n: Node[A, B]): Node[A, B] = + def copyTree[A, B](n: Node[A, B]): Node[A, B] = if(n eq null) null else { val c = new Node(n.key, n.value, n.red, copyTree(n.left), copyTree(n.right), null) if(c.left != null) c.left.parent = c diff --git a/tests/pos-special/stdlib/collection/mutable/ReusableBuilder.scala b/scala2-library-cc/src/scala/collection/mutable/ReusableBuilder.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/ReusableBuilder.scala rename to scala2-library-cc/src/scala/collection/mutable/ReusableBuilder.scala diff --git a/tests/pos-special/stdlib/collection/mutable/Seq.scala b/scala2-library-cc/src/scala/collection/mutable/Seq.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/Seq.scala rename to scala2-library-cc/src/scala/collection/mutable/Seq.scala diff --git a/tests/pos-special/stdlib/collection/mutable/SeqMap.scala b/scala2-library-cc/src/scala/collection/mutable/SeqMap.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/SeqMap.scala rename to scala2-library-cc/src/scala/collection/mutable/SeqMap.scala diff --git a/tests/pos-special/stdlib/collection/mutable/Set.scala b/scala2-library-cc/src/scala/collection/mutable/Set.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/Set.scala rename to scala2-library-cc/src/scala/collection/mutable/Set.scala diff --git a/tests/pos-special/stdlib/collection/mutable/Shrinkable.scala b/scala2-library-cc/src/scala/collection/mutable/Shrinkable.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/Shrinkable.scala rename to scala2-library-cc/src/scala/collection/mutable/Shrinkable.scala diff --git a/tests/pos-special/stdlib/collection/mutable/SortedMap.scala b/scala2-library-cc/src/scala/collection/mutable/SortedMap.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/SortedMap.scala rename to scala2-library-cc/src/scala/collection/mutable/SortedMap.scala diff --git a/tests/pos-special/stdlib/collection/mutable/SortedSet.scala b/scala2-library-cc/src/scala/collection/mutable/SortedSet.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/SortedSet.scala rename to scala2-library-cc/src/scala/collection/mutable/SortedSet.scala diff --git a/tests/pos-special/stdlib/collection/mutable/Stack.scala b/scala2-library-cc/src/scala/collection/mutable/Stack.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/Stack.scala rename to scala2-library-cc/src/scala/collection/mutable/Stack.scala diff --git a/tests/pos-special/stdlib/collection/mutable/StringBuilder.scala b/scala2-library-cc/src/scala/collection/mutable/StringBuilder.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/StringBuilder.scala rename to scala2-library-cc/src/scala/collection/mutable/StringBuilder.scala diff --git a/tests/pos-special/stdlib/collection/mutable/TreeMap.scala b/scala2-library-cc/src/scala/collection/mutable/TreeMap.scala similarity index 96% rename from tests/pos-special/stdlib/collection/mutable/TreeMap.scala rename to scala2-library-cc/src/scala/collection/mutable/TreeMap.scala index dbb87a950d74..d36e1b9d207d 100644 --- a/tests/pos-special/stdlib/collection/mutable/TreeMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/TreeMap.scala @@ -29,7 +29,7 @@ import language.experimental.captureChecking * @define Coll mutable.TreeMap * @define coll mutable tree map */ -sealed class TreeMap[K, V] private (tree: RB.Tree[K, V])(implicit val ordering: Ordering[K]) +sealed class TreeMap[K, V] private (tree: RB.Tree[K, V])(implicit val ordering: Ordering[K]) extends AbstractMap[K, V] with SortedMap[K, V] with SortedMapOps[K, V, TreeMap, TreeMap[K, V]] @@ -248,11 +248,11 @@ sealed class TreeMap[K, V] private (tree: RB.Tree[K, V])(implicit val ordering: @SerialVersionUID(3L) object TreeMap extends SortedMapFactory[TreeMap] { - def from[K : Ordering, V](it: IterableOnce[(K, V)]^): TreeMap[K, V] = + def from[K : Ordering, V](it: IterableOnce[(K, V)]^): TreeMap[K, V] = Growable.from(empty[K, V], it) - def empty[K : Ordering, V]: TreeMap[K, V] = new TreeMap[K, V]() + def empty[K : Ordering, V]: TreeMap[K, V] = new TreeMap[K, V]() - def newBuilder[K: Ordering, V]: Builder[(K, V), TreeMap[K, V]] = new GrowableBuilder(empty[K, V]) + def newBuilder[K: Ordering, V]: Builder[(K, V), TreeMap[K, V]] = new GrowableBuilder(empty[K, V]) } diff --git a/tests/pos-special/stdlib/collection/mutable/TreeSet.scala b/scala2-library-cc/src/scala/collection/mutable/TreeSet.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/TreeSet.scala rename to scala2-library-cc/src/scala/collection/mutable/TreeSet.scala diff --git a/tests/pos-special/stdlib/collection/mutable/UnrolledBuffer.scala b/scala2-library-cc/src/scala/collection/mutable/UnrolledBuffer.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/UnrolledBuffer.scala rename to scala2-library-cc/src/scala/collection/mutable/UnrolledBuffer.scala diff --git a/tests/pos-special/stdlib/collection/mutable/WeakHashMap.scala b/scala2-library-cc/src/scala/collection/mutable/WeakHashMap.scala similarity index 83% rename from tests/pos-special/stdlib/collection/mutable/WeakHashMap.scala rename to scala2-library-cc/src/scala/collection/mutable/WeakHashMap.scala index 1f94281a0b59..1ccd36c3e25f 100644 --- a/tests/pos-special/stdlib/collection/mutable/WeakHashMap.scala +++ b/scala2-library-cc/src/scala/collection/mutable/WeakHashMap.scala @@ -34,7 +34,7 @@ import language.experimental.captureChecking * @define willNotTerminateInf */ @SerialVersionUID(3L) -class WeakHashMap[K, V] extends JMapWrapper[K, V](new java.util.WeakHashMap) +class WeakHashMap[K, V] extends JMapWrapper[K, V](new java.util.WeakHashMap) with JMapWrapperLike[K, V, WeakHashMap, WeakHashMap[K, V]] with MapFactoryDefaults[K, V, WeakHashMap, Iterable] { override def empty = new WeakHashMap[K, V] @@ -49,8 +49,8 @@ class WeakHashMap[K, V] extends JMapWrapper[K, V](new java.util.WeakHashMap) */ @SerialVersionUID(3L) object WeakHashMap extends MapFactory[WeakHashMap] { - def empty[K, V]: WeakHashMap[K,V] = new WeakHashMap[K, V] - def from[K, V](it: collection.IterableOnce[(K, V)]^): WeakHashMap[K,V] = Growable.from(empty[K, V], it) - def newBuilder[K, V]: Builder[(K, V), WeakHashMap[K,V]] = new GrowableBuilder(WeakHashMap.empty[K, V]) + def empty[K, V]: WeakHashMap[K,V] = new WeakHashMap[K, V] + def from[K, V](it: collection.IterableOnce[(K, V)]^): WeakHashMap[K,V] = Growable.from(empty[K, V], it) + def newBuilder[K, V]: Builder[(K, V), WeakHashMap[K,V]] = new GrowableBuilder(WeakHashMap.empty[K, V]) } diff --git a/tests/pos-special/stdlib/collection/mutable/package.scala b/scala2-library-cc/src/scala/collection/mutable/package.scala similarity index 100% rename from tests/pos-special/stdlib/collection/mutable/package.scala rename to scala2-library-cc/src/scala/collection/mutable/package.scala diff --git a/tests/pos-special/stdlib/collection/package.scala b/scala2-library-cc/src/scala/collection/package.scala similarity index 100% rename from tests/pos-special/stdlib/collection/package.scala rename to scala2-library-cc/src/scala/collection/package.scala diff --git a/tests/pos-special/stdlib/runtime/PStatics.scala b/scala2-library-cc/src/scala/runtime/PStatics.scala similarity index 100% rename from tests/pos-special/stdlib/runtime/PStatics.scala rename to scala2-library-cc/src/scala/runtime/PStatics.scala diff --git a/tests/pos-special/stdlib/collection/concurrent/BasicNode.java b/tests/pos-special/stdlib/collection/concurrent/BasicNode.java deleted file mode 100644 index c6ec91e4fde8..000000000000 --- a/tests/pos-special/stdlib/collection/concurrent/BasicNode.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.collection.concurrent; - -public abstract class BasicNode { - - public abstract String string(int lev); - -} diff --git a/tests/pos-special/stdlib/collection/concurrent/CNodeBase.java b/tests/pos-special/stdlib/collection/concurrent/CNodeBase.java deleted file mode 100644 index ddffa365234e..000000000000 --- a/tests/pos-special/stdlib/collection/concurrent/CNodeBase.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.collection.concurrent; - -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; - -abstract class CNodeBase extends MainNode { - - @SuppressWarnings("unchecked") - public static final AtomicIntegerFieldUpdater> updater = - AtomicIntegerFieldUpdater.newUpdater((Class>) (Class) CNodeBase.class, "csize"); - - public volatile int csize = -1; - - public boolean CAS_SIZE(int oldval, int nval) { - return updater.compareAndSet(this, oldval, nval); - } - - public void WRITE_SIZE(int nval) { - updater.set(this, nval); - } - - public int READ_SIZE() { - return updater.get(this); - } - -} diff --git a/tests/pos-special/stdlib/collection/concurrent/Gen.java b/tests/pos-special/stdlib/collection/concurrent/Gen.java deleted file mode 100644 index 07af2983f32d..000000000000 --- a/tests/pos-special/stdlib/collection/concurrent/Gen.java +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.collection.concurrent; - -final class Gen {} diff --git a/tests/pos-special/stdlib/collection/concurrent/INodeBase.java b/tests/pos-special/stdlib/collection/concurrent/INodeBase.java deleted file mode 100644 index dfb99806594f..000000000000 --- a/tests/pos-special/stdlib/collection/concurrent/INodeBase.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.collection.concurrent; - -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - -abstract class INodeBase extends BasicNode { - - @SuppressWarnings("unchecked") - public static final AtomicReferenceFieldUpdater, MainNode> updater = - AtomicReferenceFieldUpdater.newUpdater((Class>) (Class) INodeBase.class, (Class>) (Class) MainNode.class, "mainnode"); - - static final Object RESTART = new Object(); - - static final Object NO_SUCH_ELEMENT_SENTINEL = new Object(); - - public volatile MainNode mainnode = null; - - public final Gen gen; - - public INodeBase(Gen generation) { - gen = generation; - } - - public BasicNode prev() { - return null; - } - -} diff --git a/tests/pos-special/stdlib/collection/concurrent/MainNode.java b/tests/pos-special/stdlib/collection/concurrent/MainNode.java deleted file mode 100644 index f7f022974e9e..000000000000 --- a/tests/pos-special/stdlib/collection/concurrent/MainNode.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -package scala.collection.concurrent; - -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - -abstract class MainNode extends BasicNode { - - @SuppressWarnings("unchecked") - public static final AtomicReferenceFieldUpdater, MainNode> updater = - AtomicReferenceFieldUpdater.newUpdater((Class>) (Class) MainNode.class, (Class>) (Class) MainNode.class, "prev"); - - public volatile MainNode prev = null; - - public abstract int cachedSize(Object ct); - - // standard contract - public abstract int knownSize(); - - public boolean CAS_PREV(MainNode oldval, MainNode nval) { - return updater.compareAndSet(this, oldval, nval); - } - - public void WRITE_PREV(MainNode nval) { - updater.set(this, nval); - } - - // do we need this? unclear in the javadocs... - // apparently not - volatile reads are supposed to be safe - // regardless of whether there are concurrent ARFU updates - @Deprecated @SuppressWarnings("unchecked") - public MainNode READ_PREV() { - return (MainNode) updater.get(this); - } - -} From 075ee3446102a7b820793fa31e5b2ba0e8443c59 Mon Sep 17 00:00:00 2001 From: Florian3k Date: Fri, 22 Dec 2023 15:46:29 +0100 Subject: [PATCH 026/220] Scaladoc - add option for dynamic side menu --- project/ScaladocGeneration.scala | 4 + scaladoc/resources/dotty_res/scripts/ux.js | 195 +++++++++++++++--- .../src/dotty/tools/scaladoc/Scaladoc.scala | 6 +- .../tools/scaladoc/ScaladocSettings.scala | 5 +- .../scaladoc/renderers/HtmlRenderer.scala | 34 ++- 5 files changed, 214 insertions(+), 30 deletions(-) diff --git a/project/ScaladocGeneration.scala b/project/ScaladocGeneration.scala index ade9b65d5445..aac9f187a888 100644 --- a/project/ScaladocGeneration.scala +++ b/project/ScaladocGeneration.scala @@ -137,6 +137,10 @@ object ScaladocGeneration { def key: String = "-quick-links" } + case class DynamicSideMenu(value: Boolean) extends Arg[Boolean] { + def key: String = "-dynamic-side-menu" + } + import _root_.scala.reflect._ trait GenerationConfig { diff --git a/scaladoc/resources/dotty_res/scripts/ux.js b/scaladoc/resources/dotty_res/scripts/ux.js index dd6e798f17a5..7b875fbcef8e 100644 --- a/scaladoc/resources/dotty_res/scripts/ux.js +++ b/scaladoc/resources/dotty_res/scripts/ux.js @@ -4,6 +4,8 @@ const attrsToCopy = [ "data-githubContributorsUrl", "data-githubContributorsFilename", "data-pathToRoot", + "data-rawLocation", + "data-dynamicSideMenu", ] /** @@ -25,7 +27,7 @@ function savePageState(doc) { } return { mainDiv: doc.querySelector("#main")?.innerHTML, - leftColumn: doc.querySelector("#leftColumn").innerHTML, + leftColumn: dynamicSideMenu ? null : doc.querySelector("#leftColumn").innerHTML, title: doc.title, attrs, }; @@ -38,12 +40,15 @@ function savePageState(doc) { function loadPageState(doc, saved) { doc.title = saved.title; doc.querySelector("#main").innerHTML = saved.mainDiv; - doc.querySelector("#leftColumn").innerHTML = saved.leftColumn; + if (!dynamicSideMenu) + doc.querySelector("#leftColumn").innerHTML = saved.leftColumn; for (const attr of attrsToCopy) { doc.documentElement.setAttribute(attr, saved.attrs[attr]); } } +const attachedElements = new WeakSet() + function attachAllListeners() { if (observer) { observer.disconnect(); @@ -97,19 +102,19 @@ function attachAllListeners() { } } -document - .querySelectorAll(".documentableElement .signature") - .forEach((signature) => { - const short = signature.querySelector(".signature-short"); - const long = signature.querySelector(".signature-long"); - const extender = document.createElement("span"); - const extenderDots = document.createTextNode("..."); - extender.appendChild(extenderDots); - extender.classList.add("extender"); - if (short && long && signature.children[1].hasChildNodes()) { - signature.children[0].append(extender); - } - }); + document + .querySelectorAll(".documentableElement .signature") + .forEach((signature) => { + const short = signature.querySelector(".signature-short"); + const long = signature.querySelector(".signature-long"); + const extender = document.createElement("span"); + const extenderDots = document.createTextNode("..."); + extender.appendChild(extenderDots); + extender.classList.add("extender"); + if (short && long && signature.children[1].hasChildNodes()) { + signature.children[0].append(extender); + } + }); const documentableLists = document.getElementsByClassName("documentableList"); [...documentableLists].forEach((list) => { @@ -151,6 +156,8 @@ document return; } const url = new URL(href); + if (attachedElements.has(el)) return; + attachedElements.add(el); el.addEventListener("click", (e) => { if ( url.href.replace(/#.*/, "") === window.location.href.replace(/#.*/, "") @@ -166,6 +173,7 @@ document e.preventDefault(); e.stopPropagation(); $.get(href, function (data) { + const oldLoc = getRawLoc(); if (window.history.state === null) { window.history.replaceState(savePageState(document), ""); } @@ -174,6 +182,11 @@ document const state = savePageState(parsedDocument); window.history.pushState(state, "", href); loadPageState(document, state); + const newLoc = getRawLoc(); + if (dynamicSideMenu) { + updateMenu(oldLoc, newLoc); + } + window.dispatchEvent(new Event(DYNAMIC_PAGE_LOAD)); document .querySelector("#main") @@ -182,11 +195,15 @@ document }); }); - $(".ar").on("click", function (e) { - $(this).parent().parent().toggleClass("expanded"); - $(this).toggleClass("expanded"); - e.stopPropagation(); - }); + document.querySelectorAll('.ar').forEach((el) => { + if (attachedElements.has(el)) return; + attachedElements.add(el); + el.addEventListener('click', (e) => { + e.stopPropagation(); + el.parentElement.parentElement.classList.toggle("expanded"); + el.classList.toggle("expanded"); + }) + }) document.querySelectorAll(".documentableList .ar").forEach((arrow) => { arrow.addEventListener("click", () => { @@ -195,7 +212,9 @@ document }); }); - document.querySelectorAll(".nh").forEach((el) => + document.querySelectorAll(".nh").forEach((el) => { + if (attachedElements.has(el)) return; + attachedElements.add(el); el.addEventListener("click", () => { if ( el.lastChild.href.replace("#", "") === @@ -206,8 +225,8 @@ document } else { el.lastChild.click(); } - }), - ); + }); + }); const toggleShowAllElem = (element) => { if (element.textContent == "Show all") { @@ -345,7 +364,7 @@ window.addEventListener(DYNAMIC_PAGE_LOAD, () => { attachAllListeners(); }); -window.addEventListener("dynamicPageLoad", () => { +window.addEventListener(DYNAMIC_PAGE_LOAD, () => { const sideMenuOpen = sessionStorage.getItem("sideMenuOpen"); if (sideMenuOpen) { if (document.querySelector("#leftColumn").classList.contains("show")) { @@ -365,10 +384,136 @@ window.addEventListener("dynamicPageLoad", () => { } }); +let dynamicSideMenu = false; +/** @param {Element} elem @param {boolean} hide */ +function updatePath(elem, hide, first = true) { + if (elem.classList.contains("side-menu")) return; + const span = elem.firstElementChild + const btn = span.firstElementChild + if (hide) { + elem.classList.remove("expanded"); + span.classList.remove("h100", "selected", "expanded", "cs"); + if (btn) btn.classList.remove("expanded"); + } else { + elem.classList.add("expanded"); + span.classList.add("h100", "expanded", "cs"); + if (btn) btn.classList.add("expanded"); + if (first) span.classList.add("selected"); + } + updatePath(elem.parentElement, hide, false); +} +let updateMenu = null; +function getRawLoc() { + return document.documentElement.getAttribute("data-rawLocation")?.split("/")?.filter(c => c !== ""); +} + +/** + * @template {keyof HTMLElementTagNameMap} T + * @param {T} el type of element to create + * @param {{ cls?: string | null, id?: string | null, href?: string | null }} attrs element attributes + * @param {Array} chldr element children + * @returns {HTMLElementTagNameMap[T]} + */ +function render(el, { cls = null, id = null, href = null, loc = null } = {}, chldr = []) { + const r = document.createElement(el); + if (cls) cls.split(" ").filter(x => x !== "").forEach(c => r.classList.add(c)); + if (id) r.id = id; + if (href) r.href = href; + if (loc) r.setAttribute("data-loc", loc); + chldr.filter(c => c !== null).forEach(c => + r.appendChild(typeof c === "string" ? document.createTextNode(c) : c) + ); + return r; +} +function renderDynamicSideMenu() { + const pathToRoot = document.documentElement.getAttribute("data-pathToRoot") + const path = pathToRoot + "dynamicSideMenu.json"; + const rawLocation = getRawLoc(); + const baseUrl = window.location.pathname.split("/").slice(0, + -1 - pathToRoot.split("/").filter(c => c != "").length + ); + function linkTo(loc) { + return `${baseUrl}/${loc.join("/")}.html`; + } + fetch(path).then(r => r.json()).then(menu => { + function renderNested(item, nestLevel, prefix, isApi) { + const name = item.name; + const newName = + isApi && item.kind === "package" && name.startsWith(prefix + ".") + ? name.substring(prefix.length + 1) + : name; + const newPrefix = + prefix == "" + ? newName + : prefix + "." + newName; + const chldr = + item.children.map(x => renderNested(x, nestLevel + 1, newPrefix, isApi)); + const link = render("span", { cls: `nh ${isApi ? "" : "de"}` }, [ + chldr.length ? render("button", { cls: "ar icon-button" }) : null, + render("a", { href: linkTo(item.location) }, [ + item.kind && render("span", { cls: `micon ${item.kind.slice(0, 2)}` }), + render("span", {}, [newName]), + ]), + ]); + const loc = item.location.join("/"); + const ret = render("div", { cls: `ni n${nestLevel}`, loc: item.location.join("/") }, [link, ...chldr]); + return ret; + } + const d = render("div", { cls: "switcher-container" }, [ + menu.docs && render("a", { + id: "docs-nav-button", + cls: "switcher h100", + href: linkTo(menu.docs.location) + }, ["Docs"]), + menu.api && render("a", { + id: "api-nav-button", + cls: "switcher h100", + href: linkTo(menu.api.location) + }, ["API"]), + ]); + const d1 = menu.docs && render("nav", { cls: "side-menu", id: "docs-nav" }, + menu.docs.children.map(item => renderNested(item, 0, "", false)) + ); + const d2 = menu.api && render("nav", { cls: "side-menu", id: "api-nav" }, + menu.api.children.map(item => renderNested(item, 0, "", true)) + ); + + document.getElementById("leftColumn").appendChild(d); + d1 && document.getElementById("leftColumn").appendChild(d1); + d2 && document.getElementById("leftColumn").appendChild(d2); + updateMenu = (oldLoc, newLoc) => { + if (oldLoc) { + const elem = document.querySelector(`[data-loc="${oldLoc.join("/")}"]`); + if (elem) updatePath(elem, true); + } + if (d1 && d2) { + if (newLoc[0] && newLoc[0] == menu.api.location[0]) { + d1.hidden = true; + d2.hidden = false; + } else { + d1.hidden = false; + d2.hidden = true; + } + } + const elem = document.querySelector(`[data-loc="${newLoc.join("/")}"]`); + if (elem) updatePath(elem, false) + } + updateMenu(null, rawLocation); + + window.dispatchEvent(new Event(DYNAMIC_PAGE_LOAD)); + }) +} + window.addEventListener("DOMContentLoaded", () => { hljs.registerLanguage("scala", highlightDotty); hljs.registerAliases(["dotty", "scala3"], "scala"); - window.dispatchEvent(new Event(DYNAMIC_PAGE_LOAD)); + + dynamicSideMenu = document.documentElement.getAttribute("data-dynamicSideMenu") === "true"; + if (dynamicSideMenu) { + renderDynamicSideMenu(); + } else { + window.dispatchEvent(new Event(DYNAMIC_PAGE_LOAD)); + } }); const elements = document.querySelectorAll(".documentableElement"); diff --git a/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala b/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala index 260529b024db..a2485085a927 100644 --- a/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala +++ b/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala @@ -45,7 +45,8 @@ object Scaladoc: apiSubdirectory : Boolean = false, scastieConfiguration: String = "", defaultTemplate: Option[String] = None, - quickLinks: List[QuickLink] = List.empty + quickLinks: List[QuickLink] = List.empty, + dynamicSideMenu: Boolean = false, ) def run(args: Array[String], rootContext: CompilerContext): Reporter = @@ -228,7 +229,8 @@ object Scaladoc: apiSubdirectory.get, scastieConfiguration.get, defaultTemplate.nonDefault, - quickLinksParsed + quickLinksParsed, + dynamicSideMenu.get, ) (Some(docArgs), newContext) } diff --git a/scaladoc/src/dotty/tools/scaladoc/ScaladocSettings.scala b/scaladoc/src/dotty/tools/scaladoc/ScaladocSettings.scala index 403acb19305d..4802f5d24ecc 100644 --- a/scaladoc/src/dotty/tools/scaladoc/ScaladocSettings.scala +++ b/scaladoc/src/dotty/tools/scaladoc/ScaladocSettings.scala @@ -133,5 +133,8 @@ class ScaladocSettings extends SettingGroup with AllScalaSettings: "List of quick links that is displayed in the header of documentation." ) + val dynamicSideMenu: Setting[Boolean] = + BooleanSetting("-dynamic-side-menu", "Generate side menu via JS instead of embedding it in every html file", false) + def scaladocSpecificSettings: Set[Setting[?]] = - Set(sourceLinks, legacySourceLink, syntax, revision, externalDocumentationMappings, socialLinks, skipById, skipByRegex, deprecatedSkipPackages, docRootContent, snippetCompiler, generateInkuire, defaultTemplate, scastieConfiguration, quickLinks) + Set(sourceLinks, legacySourceLink, syntax, revision, externalDocumentationMappings, socialLinks, skipById, skipByRegex, deprecatedSkipPackages, docRootContent, snippetCompiler, generateInkuire, defaultTemplate, scastieConfiguration, quickLinks, dynamicSideMenu) diff --git a/scaladoc/src/dotty/tools/scaladoc/renderers/HtmlRenderer.scala b/scaladoc/src/dotty/tools/scaladoc/renderers/HtmlRenderer.scala index 20f3335a44ef..7dff3e5637c6 100644 --- a/scaladoc/src/dotty/tools/scaladoc/renderers/HtmlRenderer.scala +++ b/scaladoc/src/dotty/tools/scaladoc/renderers/HtmlRenderer.scala @@ -31,6 +31,8 @@ class HtmlRenderer(rootPackage: Member, members: Map[DRI, Member])(using ctx: Do case _ => Nil case _ => Nil) :+ (Attr("data-pathToRoot") := pathToRoot(page.link.dri)) + :+ (Attr("data-rawLocation") := rawLocation(page.link.dri).mkString("/")) + :+ (Attr("data-dynamicSideMenu") := ctx.args.dynamicSideMenu.toString) val htmlTag = html(attrs*)( head((mkHead(page) :+ docHead)*), @@ -46,8 +48,35 @@ class HtmlRenderer(rootPackage: Member, members: Map[DRI, Member])(using ctx: Do override def render(): Unit = val renderedResources = renderResources() + if ctx.args.dynamicSideMenu then serializeSideMenu() super.render() + private def serializeSideMenu() = + import com.fasterxml.jackson.databind.* + import com.fasterxml.jackson.databind.node.ObjectNode + import com.fasterxml.jackson.databind.node.TextNode + val mapper = new ObjectMapper(); + + def serializePage(page: Page): ObjectNode = + import scala.jdk.CollectionConverters.SeqHasAsJava + val children = mapper.createArrayNode().addAll(page.children.filterNot(_.hidden).map(serializePage).asJava) + val location = mapper.createArrayNode().addAll(rawLocation(page.link.dri).map(TextNode(_)).asJava) + val obj = mapper.createObjectNode() + obj.set("name", new TextNode(page.link.name)) + obj.set("location", location) + obj.set("kind", page.content match + case m: Member if m.needsOwnPage => new TextNode(m.kind.name) + case _ => null + ) + obj.set("children", children) + obj + + val rootNode = mapper.createObjectNode() + rootNode.set("docs", rootDocsPage.map(serializePage).orNull) + rootNode.set("api", rootApiPage.map(serializePage).orNull) + val jsonString = mapper.writer().writeValueAsString(rootNode); + renderResource(Resource.Text("dynamicSideMenu.json", jsonString)) + private def renderResources(): Seq[String] = import scala.util.Using import scala.jdk.CollectionConverters._ @@ -218,7 +247,8 @@ class HtmlRenderer(rootPackage: Member, members: Map[DRI, Member])(using ctx: Do )).dropRight(1) div(cls := "breadcrumbs container")(innerTags*) - val (apiNavOpt, docsNavOpt): (Option[(Boolean, Seq[AppliedTag])], Option[(Boolean, Seq[AppliedTag])]) = buildNavigation(link) + val dynamicSideMenu = ctx.args.dynamicSideMenu + val (apiNavOpt, docsNavOpt) = if dynamicSideMenu then (None, None) else buildNavigation(link) def textFooter: String = args.projectFooter.getOrElse("") @@ -266,7 +296,7 @@ class HtmlRenderer(rootPackage: Member, members: Map[DRI, Member])(using ctx: Do ), span(id := "mobile-sidebar-toggle", cls := "floating-button"), div(id := "leftColumn", cls := "body-small")( - Seq( + if dynamicSideMenu then Nil else Seq( div(cls:= "switcher-container")( docsNavOpt match { case Some(isDocsActive, docsNav) => From b42c310635b6cc4249a0a247f7cd2bef001f464e Mon Sep 17 00:00:00 2001 From: Bersier Date: Fri, 22 Dec 2023 13:03:56 -0500 Subject: [PATCH 027/220] Update explicit-nulls.md Fix link --- docs/_docs/reference/experimental/explicit-nulls.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_docs/reference/experimental/explicit-nulls.md b/docs/_docs/reference/experimental/explicit-nulls.md index f8f9ac8e11be..47b21d3a5e23 100644 --- a/docs/_docs/reference/experimental/explicit-nulls.md +++ b/docs/_docs/reference/experimental/explicit-nulls.md @@ -1,7 +1,7 @@ --- layout: doc-page title: "Explicit Nulls" -nightlyOf: https://docs.scala-lang.org/scala3/reference/other-new-features/explicit-nulls.html +nightlyOf: https://docs.scala-lang.org/scala3/reference/experimental/explicit-nulls.html --- Explicit nulls is an opt-in feature that modifies the Scala type system, which makes reference types From 8d7eda44260db1a2baf4434a06c448c078b462f4 Mon Sep 17 00:00:00 2001 From: Nikita Gazarov Date: Sat, 23 Dec 2023 01:43:17 -0800 Subject: [PATCH 028/220] Add tests to verify that crash is fixed elsewhere. Fixes #19328 --- tests/neg/i19328.check | 4 ++++ tests/neg/i19328.scala | 14 ++++++++++++++ tests/neg/i19328conversion.check | 4 ++++ tests/neg/i19328conversion.scala | 13 +++++++++++++ 4 files changed, 35 insertions(+) create mode 100644 tests/neg/i19328.check create mode 100644 tests/neg/i19328.scala create mode 100644 tests/neg/i19328conversion.check create mode 100644 tests/neg/i19328conversion.scala diff --git a/tests/neg/i19328.check b/tests/neg/i19328.check new file mode 100644 index 000000000000..357be5b2d530 --- /dev/null +++ b/tests/neg/i19328.check @@ -0,0 +1,4 @@ +-- [E172] Type Error: tests/neg/i19328.scala:14:5 ---------------------------------------------------------------------- +14 | bar // error: missing implicit (should not crash) + | ^ + | No given instance of type Boolean was found for parameter bool of method bar in object i19328 diff --git a/tests/neg/i19328.scala b/tests/neg/i19328.scala new file mode 100644 index 000000000000..246491e663bd --- /dev/null +++ b/tests/neg/i19328.scala @@ -0,0 +1,14 @@ +import scala.language.implicitConversions + +object i19328: + + trait Foo[B] + given foo[C]: Foo[C] = new Foo[C] {} + + type Id[A] = A + + implicit def wrapId[A](a: A): Id[A] = a + + def bar(using bool: Boolean): Unit = () + + bar // error: missing implicit (should not crash) diff --git a/tests/neg/i19328conversion.check b/tests/neg/i19328conversion.check new file mode 100644 index 000000000000..46d05211d43d --- /dev/null +++ b/tests/neg/i19328conversion.check @@ -0,0 +1,4 @@ +-- [E172] Type Error: tests/neg/i19328conversion.scala:13:5 ------------------------------------------------------------ +13 | bar // error: missing implicit (should not crash) + | ^ + | No given instance of type Boolean was found for parameter bool of method bar in object i19328conversion diff --git a/tests/neg/i19328conversion.scala b/tests/neg/i19328conversion.scala new file mode 100644 index 000000000000..46dd1058b579 --- /dev/null +++ b/tests/neg/i19328conversion.scala @@ -0,0 +1,13 @@ +object i19328conversion: + + trait Foo[B] + given foo[C]: Foo[C] = new Foo[C] {} + + type Id[A] = A + + given wrapId[A]: Conversion[A, Id[A]] with + def apply(x: A): Id[A] = x + + def bar(using bool: Boolean): Unit = () + + bar // error: missing implicit (should not crash) From 2d6afcab52825a4f3ab1b87f6fe48a8d0cdc11ac Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 3 Jan 2024 13:01:16 +0100 Subject: [PATCH 029/220] Update copyright year in cmdScaladocTests Fixes #19360 --- project/scripts/cmdScaladocTests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/scripts/cmdScaladocTests b/project/scripts/cmdScaladocTests index 26e39e13796f..7ffa2506b1dd 100755 --- a/project/scripts/cmdScaladocTests +++ b/project/scripts/cmdScaladocTests @@ -37,7 +37,7 @@ dist/target/pack/bin/scaladoc \ "-snippet-compiler:scaladoc-testcases/docs=compile" \ "-comment-syntax:scaladoc-testcases/src/example/comment-md=markdown,scaladoc-testcases/src/example/comment-wiki=wiki" \ -siteroot scaladoc-testcases/docs \ - -project-footer "Copyright (c) 2002-2023, LAMP/EPFL" \ + -project-footer "Copyright (c) 2002-2024, LAMP/EPFL" \ -default-template static-site-main \ -author -groups -revision main -project-version "${DOTTY_BOOTSTRAPPED_VERSION}" \ "-quick-links:Learn::https://docs.scala-lang.org/,Install::https://www.scala-lang.org/download/,Playground::https://scastie.scala-lang.org,Find A Library::https://index.scala-lang.org,Community::https://www.scala-lang.org/community/,Blog::https://www.scala-lang.org/blog/," \ From d5053b4583e0ce56fea64b4edf4c440db46854f7 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 3 Jan 2024 13:03:53 +0100 Subject: [PATCH 030/220] Get current year for copyright footer --- project/scripts/cmdScaladocTests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/scripts/cmdScaladocTests b/project/scripts/cmdScaladocTests index 7ffa2506b1dd..e9403d988b98 100755 --- a/project/scripts/cmdScaladocTests +++ b/project/scripts/cmdScaladocTests @@ -37,7 +37,7 @@ dist/target/pack/bin/scaladoc \ "-snippet-compiler:scaladoc-testcases/docs=compile" \ "-comment-syntax:scaladoc-testcases/src/example/comment-md=markdown,scaladoc-testcases/src/example/comment-wiki=wiki" \ -siteroot scaladoc-testcases/docs \ - -project-footer "Copyright (c) 2002-2024, LAMP/EPFL" \ + -project-footer "Copyright (c) 2002-$(date +%Y), LAMP/EPFL" \ -default-template static-site-main \ -author -groups -revision main -project-version "${DOTTY_BOOTSTRAPPED_VERSION}" \ "-quick-links:Learn::https://docs.scala-lang.org/,Install::https://www.scala-lang.org/download/,Playground::https://scastie.scala-lang.org,Find A Library::https://index.scala-lang.org,Community::https://www.scala-lang.org/community/,Blog::https://www.scala-lang.org/blog/," \ From f9f8b0b54b10d72b946cbea84c63fb430ccccb1b Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 3 Jan 2024 10:12:45 +0100 Subject: [PATCH 031/220] Fix `Test with Scala 2 library with CC TASTy (fast)` We compiled `scala2-library-tasty` by mistake instead of `scala2-library-cc` and `scala2-library-cc-tasty`. The setting `scala2Library` is useless until we are able to execute `scala3-bootstrapped/test`. --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 9075abcdf36e..acfd1b978886 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -148,7 +148,7 @@ jobs: run: ./project/scripts/sbt ";set ThisBuild/Build.scala2Library := Build.Scala2LibraryTasty ;scala3-bootstrapped/testCompilation i5; scala3-bootstrapped/testCompilation tests/run/typelevel-peano.scala; scala3-bootstrapped/testOnly dotty.tools.backend.jvm.DottyBytecodeTests" # only test a subset of test to avoid doubling the CI execution time - name: Test with Scala 2 library with CC TASTy (fast) - run: ./project/scripts/sbt ";set ThisBuild/Build.scala2Library := Build.Scala2LibraryCCTasty ;scala2-library-tasty/compile" # TODO test all the test configurations in non-CC library (currently disabled due to bug while loading the library) + run: ./project/scripts/sbt "scala2-library-cc/compile; scala2-library-cc-tasty/compile" # TODO test all the test configurations in non-CC library (currently disabled due to bug while loading the library) test_scala2_library_tasty: runs-on: [self-hosted, Linux] From 2cf6955ac3addd1f9dca9bf75982c37632e3f8a6 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 4 Jan 2024 09:18:18 +0100 Subject: [PATCH 032/220] Fix Scala 2 library TASTy testing docs Update docs to align with update in #18967. --- docs/_docs/contributing/testing.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/docs/_docs/contributing/testing.md b/docs/_docs/contributing/testing.md index f755bcafcd66..84ce4053f124 100644 --- a/docs/_docs/contributing/testing.md +++ b/docs/_docs/contributing/testing.md @@ -177,12 +177,26 @@ We can enable this library in the build using the SBT setting `useScala2LibraryT ``` $ sbt -> set ThisBuild/Build.useScala2LibraryTasty := true +> set ThisBuild/Build.scala2Library := Build.Scala2LibraryTasty > scala3-compiler-bootstrapped/scalac MyFile.scala > scala3-compiler-bootstrapped/test > scala3-compiler-bootstrapped/testCompilation ``` +By default `scala2Library` is set to `Scala2LibraryJar`. This setting can be set to stop using the Scala 2 library TASTy. +``` +> set ThisBuild/Build.scala2Library := Build.Scala2LibraryJar +``` + +#### Scala 2 library with CC TASTy tests +These follow the same structure as the _Scala 2 library TASTy tests_ but add captured checked signatures to the library. The library is compiled in `scala2-library-cc` (instead of `scala2-library-bootstrapped`) and `scala2-library-cc-tasty` (instead of `scala2-library-cc-tasty`). + +We can also enable this library in the build using the SBT setting `useScala2LibraryTasty`. +``` +> set ThisBuild/Build.scala2Library := Build.Scala2LibraryCCTasty +``` + + ### From TASTy tests `testCompilation` has an additional mode to run tests that compile code from a `.tasty` file. From cbb533b5ed5a8e7bdc3adb08e69bb940a41475cc Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Thu, 4 Jan 2024 10:15:25 +0100 Subject: [PATCH 033/220] Extend copyright into 2024 --- NOTICE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NOTICE.md b/NOTICE.md index 64c1ede1a5eb..e9b64ac262f2 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -1,6 +1,6 @@ Dotty (https://dotty.epfl.ch) -Copyright 2012-2023 EPFL -Copyright 2012-2023 Lightbend, Inc. +Copyright 2012-2024 EPFL +Copyright 2012-2024 Lightbend, Inc. Licensed under the Apache License, Version 2.0 (the "License"): http://www.apache.org/licenses/LICENSE-2.0 From edc74b717046bb1360c85f9c94ceb1bc35eade22 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 8 Dec 2023 00:02:41 +0000 Subject: [PATCH 034/220] Space: Replace showType & make Space Showable Replace showType with a small tweak to RefinedPrinter, so the rest of the logic is followed. For instance, show infix types and tuples correctly. Also, make Space Showable, reusing the existing logic for Space, but additionally specifying the Space class name, which is important for following Space traces. --- .../tools/dotc/transform/patmat/Space.scala | 234 +++++++----------- .../transform/patmat/SpaceEngineTest.scala | 27 +- tests/patmat/aliasing.check | 6 +- tests/patmat/i12020.check | 2 +- tests/patmat/i2502.check | 2 +- tests/patmat/i2502b.check | 2 +- tests/patmat/i3938.check | 2 +- tests/patmat/i6255b.check | 2 +- tests/patmat/t10100.check | 2 +- tests/patmat/t9779.check | 2 +- 10 files changed, 107 insertions(+), 174 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 0df81f756925..babebcfad8f0 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -3,23 +3,13 @@ package dotc package transform package patmat -import core.* -import Types.* -import Contexts.* -import Flags.* -import ast.* -import Decorators.{ show => _, * } -import Symbols.* -import StdNames.* -import NameOps.* -import Constants.* -import typer.* -import Applications.* -import Inferencing.* -import ProtoTypes.* +import core.*, Constants.*, Contexts.*, Decorators.*, Flags.*, Names.*, NameOps.*, StdNames.*, Symbols.*, Types.* +import ast.*, tpd.* +import config.Printers.* +import printing.{ Printer, * }, Texts.* import reporting.* -import config.Printers.{exhaustivity => debug} -import util.{SrcPos, NoSourcePosition} +import typer.*, Applications.*, Inferencing.*, ProtoTypes.* +import util.* import scala.annotation.internal.sharable import scala.collection.mutable @@ -56,7 +46,7 @@ import SpaceEngine.* */ /** space definition */ -sealed trait Space: +sealed trait Space extends Showable: @sharable private val isSubspaceCache = mutable.HashMap.empty[Space, Boolean] @@ -67,9 +57,7 @@ sealed trait Space: if (a ne a2) || (b ne b2) then a2.isSubspace(b2) else if a == Empty then true else if b == Empty then false - else trace(s"isSubspace(${show(this)}, ${show(b)})", debug) { - isSubspaceCache.getOrElseUpdate(b, computeIsSubspace(a, b)) - } + else isSubspaceCache.getOrElseUpdate(b, computeIsSubspace(a, b)) @sharable private var mySimplified: Space | Null = null @@ -80,6 +68,13 @@ sealed trait Space: mySimplified = simplified simplified else simplified + + def toText(p: Printer): Text = inContext(p.printerContext)(this match { + case Empty => s"Empty" + case sp: Typ => s"Typ(${display(sp)})" + case sp: Prod => s"Prod(${display(sp)})" + case sp: Or => s"Or(${display(sp)})" + }) end Space /** Empty space */ @@ -114,15 +109,13 @@ case class Prod(tp: Type, unappTp: TermRef, params: List[Space]) extends Space case class Or(spaces: Seq[Space]) extends Space object SpaceEngine { - import tpd.* - def simplify(space: Space)(using Context): Space = space.simplify def isSubspace(a: Space, b: Space)(using Context): Boolean = a.isSubspace(b) def canDecompose(typ: Typ)(using Context): Boolean = typ.canDecompose def decompose(typ: Typ)(using Context): List[Typ] = typ.decompose /** Simplify space such that a space equal to `Empty` becomes `Empty` */ - def computeSimplify(space: Space)(using Context): Space = trace(s"simplify ${show(space)} --> ", debug, show)(space match { + def computeSimplify(space: Space)(using Context): Space = trace(s"simplify($space)")(space match { case Prod(tp, fun, spaces) => val sps = spaces.mapconserve(simplify) if sps.contains(Empty) then Empty @@ -173,7 +166,7 @@ object SpaceEngine { } /** Is `a` a subspace of `b`? Equivalent to `simplify(simplify(a) - simplify(b)) == Empty`, but faster */ - def computeIsSubspace(a: Space, b: Space)(using Context): Boolean = { + def computeIsSubspace(a: Space, b: Space)(using Context): Boolean = trace(s"isSubspace($a, $b)") { val a2 = simplify(a) val b2 = simplify(b) if (a ne a2) || (b ne b2) then isSubspace(a2, b2) @@ -202,7 +195,7 @@ object SpaceEngine { } /** Intersection of two spaces */ - def intersect(a: Space, b: Space)(using Context): Space = trace(s"${show(a)} & ${show(b)}", debug, show) { + def intersect(a: Space, b: Space)(using Context): Space = trace(s"$a & $b") { (a, b) match { case (Empty, _) | (_, Empty) => Empty case (_, Or(ss)) => Or(ss.map(intersect(a, _)).filter(_ ne Empty)) @@ -211,11 +204,11 @@ object SpaceEngine { if isSubType(tp1, tp2) then a else if isSubType(tp2, tp1) then b else intersectUnrelatedAtomicTypes(tp1, tp2)(a) - case (a @ Typ(tp1, _), Prod(tp2, fun, ss)) => + case (a @ Typ(tp1, _), b @ Prod(tp2, fun, ss)) => if isSubType(tp2, tp1) then b else if isSubType(tp1, tp2) then a // problematic corner case: inheriting a case class else intersectUnrelatedAtomicTypes(tp1, tp2)(b) - case (Prod(tp1, fun, ss), b @ Typ(tp2, _)) => + case (a @ Prod(tp1, fun, ss), b @ Typ(tp2, _)) => if isSubType(tp1, tp2) then a else if isSubType(tp2, tp1) then a // problematic corner case: inheriting a case class else intersectUnrelatedAtomicTypes(tp1, tp2)(a) @@ -227,7 +220,7 @@ object SpaceEngine { } /** The space of a not covered by b */ - def minus(a: Space, b: Space)(using Context): Space = trace(s"${show(a)} - ${show(b)}", debug, show) { + def minus(a: Space, b: Space)(using Context): Space = trace(s"$a - $b") { (a, b) match { case (Empty, _) => Empty case (_, Empty) => a @@ -291,8 +284,8 @@ object SpaceEngine { /** Is the unapply or unapplySeq irrefutable? * @param unapp The unapply function tree */ - def isIrrefutable(unapp: tpd.Tree, argLen: Int)(using Context): Boolean = { - tpd.funPart(unapp).tpe match + def isIrrefutable(unapp: Tree, argLen: Int)(using Context): Boolean = { + funPart(unapp).tpe match case funRef: TermRef => isIrrefutable(funRef, argLen) case _: ErrorType => false } @@ -301,7 +294,7 @@ object SpaceEngine { * @param body The body of the quoted pattern * @param bodyPt The scrutinee body type */ - def isIrrefutableQuotePattern(pat: tpd.QuotePattern, pt: Type)(using Context): Boolean = { + def isIrrefutableQuotePattern(pat: QuotePattern, pt: Type)(using Context): Boolean = { if pat.body.isType then pat.bindings.isEmpty && pt =:= pat.tpe else pat.body match case _: SplicePattern | Typed(_: SplicePattern, _) => pat.bindings.isEmpty && pt <:< pat.tpe @@ -313,24 +306,24 @@ object SpaceEngine { * The types should be atomic (non-decomposable) and unrelated (neither * should be a subtype of the other). */ - def intersectUnrelatedAtomicTypes(tp1: Type, tp2: Type)(sp: Space)(using Context): Space = trace(i"atomic intersection: ${AndType(tp1, tp2)}", debug, show) { + def intersectUnrelatedAtomicTypes(tp1: Type, tp2: Type)(sp: Typ | Prod)(using Context): Space = trace(i"intersectUnrelatedAtomicTypes($tp1, $tp2)(${sp.className})") { // Precondition: !isSubType(tp1, tp2) && !isSubType(tp2, tp1). + def intersection = sp match + case sp: Prod => sp.copy(AndType(tp1, tp2)) + case sp: Typ => sp.copy(AndType(tp1, tp2)) if !ctx.mode.is(Mode.SafeNulls) && (tp1.isNullType || tp2.isNullType) then // Since projections of types don't include null, intersection with null is empty. Empty - else - val intersection = sp match - case sp: Prod => sp.copy(AndType(tp1, tp2)) - case _ => Typ(AndType(tp1, tp2), decomposed = false) + else if tp1.classSymbol.isNumericValueClass && tp2.classSymbol.isNumericValueClass then // unrelated numeric value classes can equal each other, so let's not consider type space intersection empty - if tp1.classSymbol.isNumericValueClass && tp2.classSymbol.isNumericValueClass then intersection - else if isPrimToBox(tp1, tp2) || isPrimToBox(tp2, tp1) then intersection - else if TypeComparer.provablyDisjoint(tp1, tp2) then Empty - else intersection + intersection + else if isPrimToBox(tp1, tp2) || isPrimToBox(tp2, tp1) then intersection + else if TypeComparer.provablyDisjoint(tp1, tp2) then Empty + else intersection } /** Return the space that represents the pattern `pat` */ - def project(pat: Tree)(using Context): Space = trace(i"project($pat ${pat.className} ${pat.tpe})", debug, show)(pat match { + def project(pat: Tree)(using Context): Space = trace(i"project($pat ${pat.className} ${pat.tpe})")(pat match { case Literal(c) => if (c.value.isInstanceOf[Symbol]) Typ(c.value.asInstanceOf[Symbol].termRef, decomposed = false) @@ -447,7 +440,10 @@ object SpaceEngine { * This is needed to avoid spurious unreachable warnings. See tests/patmat/i6197.scala. */ private def erase(tp: Type, inArray: Boolean = false, isValue: Boolean = false, isTyped: Boolean = false)(using Context): Type = - trace(i"erase($tp${if inArray then " inArray" else ""}${if isValue then " isValue" else ""}${if isTyped then " isTyped" else ""})", debug)(tp match { + val inArr = if inArray then " inArray" else "" + val isVal = if isValue then " isValue" else "" + val isTyp = if isTyped then " isTyped" else "" + trace(i"erase($tp ${tp.className}$inArr$isVal$isTyp)")(tp match { case tp @ AppliedType(tycon, args) if tycon.typeSymbol.isPatternBound => WildcardType @@ -496,7 +492,7 @@ object SpaceEngine { tp.isPrimitiveValueType && (defn.boxedType(tp).classSymbol eq pt.classSymbol) /** Is `tp1` a subtype of `tp2`? */ - def isSubType(tp1: Type, tp2: Type)(using Context): Boolean = trace(i"$tp1 <:< $tp2", debug, show = true) { + def isSubType(tp1: Type, tp2: Type)(using Context): Boolean = trace(i"$tp1 <:< $tp2") { if tp1 == ConstantType(Constant(null)) && !ctx.mode.is(Mode.SafeNulls) then tp2 == ConstantType(Constant(null)) else if tp1.isTupleXXLExtract(tp2) then true // See isTupleXXLExtract, fixes TupleXXL parameter type @@ -520,11 +516,9 @@ object SpaceEngine { /** Return term parameter types of the extractor `unapp`. * Parameter types of the case class type `tp`. Adapted from `unapplyPlan` in patternMatcher */ - def signature(unapp: TermRef, scrutineeTp: Type, argLen: Int)(using Context): List[Type] = { + def signature(unapp: TermRef, scrutineeTp: Type, argLen: Int)(using Context): List[Type] = trace(i"signature($unapp, $scrutineeTp, $argLen)") { val unappSym = unapp.symbol - // println("scrutineeTp = " + scrutineeTp.show) - val mt: MethodType = unapp.widen match { case mt: MethodType => mt case pt: PolyType => @@ -583,8 +577,6 @@ object SpaceEngine { } } - debug.println(s"signature of ${unappSym.showFullName} ----> ${sig.map(_.show).mkString(", ")}") - sig.map(_.annotatedToRepeated) } @@ -602,7 +594,7 @@ object SpaceEngine { } /** Decompose a type into subspaces -- assume the type can be decomposed */ - def decompose(tp: Type)(using Context): List[Type] = trace(i"decompose($tp)", debug) { + def decompose(tp: Type)(using Context): List[Type] = trace(i"decompose($tp)") { def rec(tp: Type, mixins: List[Type]): List[Type] = tp.dealias match case AndType(tp1, tp2) => var tpB = tp2 @@ -640,13 +632,11 @@ object SpaceEngine { else if (child.is(Private) || child.is(Sealed)) && child.isOneOf(AbstractOrTrait) then getChildren(child) else List(child) } - val children = getChildren(tp.classSymbol) - debug.println(i"candidates for $tp : $children") + val children = trace(i"getChildren($tp)")(getChildren(tp.classSymbol)) val parts = children.map { sym => val sym1 = if (sym.is(ModuleClass)) sym.sourceModule else sym - val refined = TypeOps.refineUsingParent(tp, sym1, mixins) - debug.println(i"$sym1 refined to $refined") + val refined = trace(i"refineUsingParent($tp, $sym1, $mixins)")(TypeOps.refineUsingParent(tp, sym1, mixins)) def inhabited(tp: Type): Boolean = tp.dealias match case AndType(tp1, tp2) => !TypeComparer.provablyDisjoint(tp1, tp2) @@ -658,7 +648,6 @@ object SpaceEngine { if inhabited(refined) then refined else NoType }.filter(_.exists) - debug.println(i"$tp decomposes to $parts") parts case _ => ListOfNoType @@ -693,49 +682,13 @@ object SpaceEngine { * * E.g. C.this.B --> B if current owner is C * C.this.x.T --> x.T if current owner is C - * X[T] --> X * C --> C if current owner is C !!! - * */ - def showType(tp: Type, showTypeArgs: Boolean = false)(using Context): String = { + private class LocalPrinter(_ctx: Context) extends RefinedPrinter(_ctx): val enclosingCls = ctx.owner.enclosingClass - - def isOmittable(sym: Symbol) = - sym.isEffectiveRoot || sym.isAnonymousClass || sym.name.isReplWrapperName || - ctx.definitions.unqualifiedOwnerTypes.exists(_.symbol == sym) || - sym.showFullName.startsWith("scala.") || - sym == enclosingCls || sym == enclosingCls.sourceModule - - def refinePrefix(tp: Type): String = tp match { - case NoPrefix => "" - case tp: NamedType if isOmittable(tp.symbol) => "" - case tp: ThisType => refinePrefix(tp.tref) - case tp: RefinedType => refinePrefix(tp.parent) - case tp: NamedType => tp.name.show.stripSuffix("$") - case tp: TypeVar => refinePrefix(tp.instanceOpt) - case _ => tp.show - } - - def refine(tp: Type): String = tp.stripped match { - case tp: RefinedType => refine(tp.parent) - case tp: AppliedType => - refine(tp.typeConstructor) + ( - if (showTypeArgs) tp.argInfos.map(refine).mkString("[", ",", "]") - else "" - ) - case tp: ThisType => refine(tp.tref) - case tp: NamedType => - val pre = refinePrefix(tp.prefix) - if (tp.name == tpnme.higherKinds) pre - else if (pre.isEmpty) tp.name.show.stripSuffix("$") - else pre + "." + tp.name.show.stripSuffix("$") - case tp: OrType => refine(tp.tp1) + " | " + refine(tp.tp2) - case _: TypeBounds => "_" - case _ => tp.show.stripSuffix("$") - } - - refine(tp) - } + override def isOmittablePrefix(sym: Symbol) = + super.isOmittablePrefix(sym) + || sym == enclosingCls || sym == enclosingCls.sourceModule /** Whether the counterexample is satisfiable. The space is flattened and non-empty. */ def satisfiable(sp: Space)(using Context): Boolean = { @@ -769,10 +722,8 @@ object SpaceEngine { checkConstraint(genConstraint(sp))(using ctx.fresh.setNewTyperState()) } - def showSpaces(ss: Seq[Space])(using Context): Seq[String] = ss.map(show) - - /** Display spaces */ - def show(s: Space)(using Context): String = { + /** Display spaces. Used for printing uncovered spaces in the in-exhaustive error message. */ + def display(s: Space)(using Context): String = inContext(ctx.fresh.setPrinterFn(LocalPrinter(_))) { def params(tp: Type): List[Type] = tp.classSymbol.primaryConstructor.info.firstParamTypes /** does the companion object of the given symbol have custom unapply */ @@ -789,39 +740,38 @@ object SpaceEngine { if (flattenList && tp <:< defn.NilType) "" else tp.symbol.showName case Typ(tp, decomposed) => - - val sym = tp.classSymbol - - if (ctx.definitions.isTupleNType(tp)) + val cls = tp.classSymbol + if ctx.definitions.isTupleNType(tp) then params(tp).map(_ => "_").mkString("(", ", ", ")") - else if (defn.ListType.isRef(sym)) - if (flattenList) "_*" else "_: List" - else if (defn.ConsType.isRef(sym)) - if (flattenList) "_, _*" else "List(_, _*)" - else if (tp.classSymbol.is(Sealed) && tp.classSymbol.hasAnonymousChild) - "_: " + showType(tp) + " (anonymous)" - else if (tp.classSymbol.is(CaseClass) && !hasCustomUnapply(tp.classSymbol)) - // use constructor syntax for case class - showType(tp) + params(tp).map(_ => "_").mkString("(", ", ", ")") - else if (decomposed) "_: " + showType(tp, showTypeArgs = true) - else "_" + else if defn.ListType.isRef(cls) then + if flattenList then "_*" else "_: List" + else if (defn.ConsType.isRef(cls)) + if flattenList then "_, _*" else "List(_, _*)" + else if cls.hasAnonymousChild then + s"_: ${tp.typeConstructor.show} (anonymous)" + else if cls.is(CaseClass) && !hasCustomUnapply(cls) then + // use constructor syntax for case class + tp.typeConstructor.show + params(tp).map(_ => "_").mkString("(", ", ", ")") + else if !decomposed then "_" + else "_: " + tp.show case Prod(tp, fun, params) => - if (ctx.definitions.isTupleNType(tp)) + if ctx.definitions.isTupleNType(tp) then "(" + params.map(doShow(_)).mkString(", ") + ")" - else if (tp.isRef(defn.ConsType.symbol)) - if (flattenList) params.map(doShow(_, flattenList)).filter(_.nonEmpty).mkString(", ") - else params.map(doShow(_, flattenList = true)).filter(!_.isEmpty).mkString("List(", ", ", ")") - else { - val sym = fun.symbol - val isUnapplySeq = sym.name.eq(nme.unapplySeq) + else if tp.isRef(defn.ConsType.symbol) then + val body = params.map(doShow(_, flattenList = true)).filter(_.nonEmpty).mkString(", ") + if flattenList then body else s"List($body)" + else + val isUnapplySeq = fun.symbol.name eq nme.unapplySeq val paramsStr = params.map(doShow(_, flattenList = isUnapplySeq)).mkString("(", ", ", ")") - showType(fun.prefix) + paramsStr - } + val prefix = fun.prefix match + case pre: TermRef => pre.symbol.typeRef + case pre => pre + prefix.typeConstructor.show + paramsStr case Or(ss) => ss.map(doShow(_, flattenList)).mkString(" | ") } - doShow(s, flattenList = false) + doShow(s) } private def exhaustivityCheckable(sel: Tree)(using Context): Boolean = { @@ -845,13 +795,11 @@ object SpaceEngine { else true // recursive case class: return true and other members can still fail the check } - val res = !sel.tpe.hasAnnotation(defn.UncheckedAnnot) && { + !sel.tpe.hasAnnotation(defn.UncheckedAnnot) + && { ctx.settings.YcheckAllPatmat.value || isCheckable(sel.tpe) } - - debug.println(s"exhaustivity checkable: ${sel.show} = $res") - res } /** Whether counter-examples should be further checked? True for GADTs. */ @@ -866,7 +814,7 @@ object SpaceEngine { /** Return the underlying type of non-module, non-constant, non-enum case singleton types. * Also widen ExprType to its result type, and rewrap any annotation wrappers. * For example, with `val opt = None`, widen `opt.type` to `None.type`. */ - def toUnderlying(tp: Type)(using Context): Type = trace(i"toUnderlying($tp)", show = true)(tp match { + def toUnderlying(tp: Type)(using Context): Type = trace(i"toUnderlying($tp)")(tp match { case _: ConstantType => tp case tp: TermRef if tp.symbol.is(Module) => tp case tp: TermRef if tp.symbol.isAllOf(EnumCase) => tp @@ -876,27 +824,25 @@ object SpaceEngine { case _ => tp }) - def checkExhaustivity(m: Match)(using Context): Unit = trace(i"checkExhaustivity($m)", debug) { + def checkExhaustivity(m: Match)(using Context): Unit = trace(i"checkExhaustivity($m)") { val selTyp = toUnderlying(m.selector.tpe).dealias - debug.println(i"selTyp = $selTyp") + val targetSpace = trace(i"targetSpace($selTyp)")(project(selTyp)) val patternSpace = Or(m.cases.foldLeft(List.empty[Space]) { (acc, x) => - val space = if (x.guard.isEmpty) project(x.pat) else Empty - debug.println(s"${x.pat.show} ====> ${show(space)}") + val space = if x.guard.isEmpty then trace(i"project(${x.pat})")(project(x.pat)) else Empty space :: acc }) val checkGADTSAT = shouldCheckExamples(selTyp) val uncovered = - flatten(simplify(minus(project(selTyp), patternSpace))).filter({ s => + flatten(simplify(minus(targetSpace, patternSpace))).filter({ s => s != Empty && (!checkGADTSAT || satisfiable(s)) }) - if uncovered.nonEmpty then val deduped = dedup(uncovered) - report.warning(PatternMatchExhaustivity(showSpaces(deduped), m), m.selector) + report.warning(PatternMatchExhaustivity(deduped.map(display), m), m.selector) } private def reachabilityCheckable(sel: Tree)(using Context): Boolean = @@ -909,17 +855,16 @@ object SpaceEngine { && !sel.tpe.widen.isRef(defn.QuotedExprClass) && !sel.tpe.widen.isRef(defn.QuotedTypeClass) - def checkReachability(m: Match)(using Context): Unit = trace(i"checkReachability($m)", debug) { + def checkReachability(m: Match)(using Context): Unit = trace(i"checkReachability($m)") { val cases = m.cases.toIndexedSeq val selTyp = toUnderlying(m.selector.tpe).dealias - debug.println(i"selTyp = $selTyp") val isNullable = selTyp.classSymbol.isNullableClass - val targetSpace = if isNullable + val targetSpace = trace(i"targetSpace($selTyp)")(if isNullable then project(OrType(selTyp, ConstantType(Constant(null)), soft = false)) else project(selTyp) - debug.println(s"targetSpace: ${show(targetSpace)}") + ) var i = 0 val len = cases.length @@ -929,16 +874,11 @@ object SpaceEngine { while (i < len) { val CaseDef(pat, guard, _) = cases(i) - debug.println(i"case pattern: $pat") - - val curr = project(pat) - debug.println(i"reachable? ${show(curr)}") + val curr = trace(i"project($pat)")(project(pat)) - val prev = simplify(Or(prevs)) - debug.println(s"prev: ${show(prev)}") + val covered = trace("covered")(simplify(intersect(curr, targetSpace))) - val covered = simplify(intersect(curr, targetSpace)) - debug.println(s"covered: ${show(covered)}") + val prev = trace("prev")(simplify(Or(prevs))) if prev == Empty && covered == Empty then // defer until a case is reachable deferred ::= pat diff --git a/compiler/test/dotty/tools/dotc/transform/patmat/SpaceEngineTest.scala b/compiler/test/dotty/tools/dotc/transform/patmat/SpaceEngineTest.scala index c13ef0532348..d7b2fd6a5173 100644 --- a/compiler/test/dotty/tools/dotc/transform/patmat/SpaceEngineTest.scala +++ b/compiler/test/dotty/tools/dotc/transform/patmat/SpaceEngineTest.scala @@ -27,12 +27,12 @@ class SpaceEngineTest: val a = Prod(tp, unappTp, params) val b = Empty - val res1 = isSubspace(a, b) + val res1 = a.isSubspace(b) - val a2 = simplify(a) - val b2 = simplify(b) + val a2 = a.simplify + val b2 = b.simplify val rem1 = minus(a2, b2) - val rem2 = simplify(rem1) + val rem2 = rem1.simplify val res2 = rem2 == Empty assertEquals( @@ -46,19 +46,12 @@ class SpaceEngineTest: |simplify(rem1) == Empty |rem2 == Empty | - |a = ${show(a)} - |b = ${show(b)} - |a2 = ${show(a2)} - |b2 = ${show(b2)} - |rem1 = ${show(rem1)} - |rem2 = ${show(rem2)} - | - |a = ${a.toString} - |b = ${b.toString} - |a2 = ${a2.toString} - |b2 = ${b2.toString} - |rem1 = ${rem1.toString} - |rem2 = ${rem2.toString} + |a = $a + |b = $b + |a2 = $a2 + |b2 = $b2 + |rem1 = $rem1 + |rem2 = $rem2 | |""".stripMargin, res1, res2) } diff --git a/tests/patmat/aliasing.check b/tests/patmat/aliasing.check index c367626d6f1e..018905abf47e 100644 --- a/tests/patmat/aliasing.check +++ b/tests/patmat/aliasing.check @@ -1,3 +1,3 @@ -14: Pattern Match Exhaustivity: _: Trait & Test.Alias1, _: Clazz & Test.Alias1 -19: Pattern Match Exhaustivity: _: Trait & Test.Alias2 -23: Pattern Match Exhaustivity: _: Trait & (Test.Alias2 & OpenTrait2){val x: Int} +14: Pattern Match Exhaustivity: _: Trait & Alias1, _: Clazz & Alias1 +19: Pattern Match Exhaustivity: _: Trait & Alias2 +23: Pattern Match Exhaustivity: _: Trait & (Alias2 & OpenTrait2){val x: Int} diff --git a/tests/patmat/i12020.check b/tests/patmat/i12020.check index b89bdc8314e5..13b07e2e5992 100644 --- a/tests/patmat/i12020.check +++ b/tests/patmat/i12020.check @@ -1 +1 @@ -19: Pattern Match Exhaustivity: _: TypeDef +19: Pattern Match Exhaustivity: _: x$1.reflect.TypeDef diff --git a/tests/patmat/i2502.check b/tests/patmat/i2502.check index fe2194e650cf..56cd3f6c0b8c 100644 --- a/tests/patmat/i2502.check +++ b/tests/patmat/i2502.check @@ -1 +1 @@ -5: Pattern Match Exhaustivity: _: BTypes.ClassBType \ No newline at end of file +5: Pattern Match Exhaustivity: _: BTypes.this.ClassBType diff --git a/tests/patmat/i2502b.check b/tests/patmat/i2502b.check index fe2194e650cf..56cd3f6c0b8c 100644 --- a/tests/patmat/i2502b.check +++ b/tests/patmat/i2502b.check @@ -1 +1 @@ -5: Pattern Match Exhaustivity: _: BTypes.ClassBType \ No newline at end of file +5: Pattern Match Exhaustivity: _: BTypes.this.ClassBType diff --git a/tests/patmat/i3938.check b/tests/patmat/i3938.check index 5aaefe2263e1..2acd1040ead4 100644 --- a/tests/patmat/i3938.check +++ b/tests/patmat/i3938.check @@ -1 +1 @@ -34: Pattern Match Exhaustivity: bar.C() +34: Pattern Match Exhaustivity: foo.bar.C() diff --git a/tests/patmat/i6255b.check b/tests/patmat/i6255b.check index 265ec9fa9c4b..bd9585becc56 100644 --- a/tests/patmat/i6255b.check +++ b/tests/patmat/i6255b.check @@ -1 +1 @@ -3: Pattern Match Exhaustivity: _: Expr[Int] +3: Pattern Match Exhaustivity: _: scala.quoted.Expr[Int] diff --git a/tests/patmat/t10100.check b/tests/patmat/t10100.check index d11715a5f371..19a89cd08a74 100644 --- a/tests/patmat/t10100.check +++ b/tests/patmat/t10100.check @@ -1 +1 @@ -12: Pattern Match Exhaustivity: (_, FancyFoo(_)) +12: Pattern Match Exhaustivity: (_, NonExhaustive#FancyFoo(_)) diff --git a/tests/patmat/t9779.check b/tests/patmat/t9779.check index 63f3b8963cac..c1886064d8ef 100644 --- a/tests/patmat/t9779.check +++ b/tests/patmat/t9779.check @@ -1 +1 @@ -10: Pattern Match Exhaustivity: _: a.Elem[_] +10: Pattern Match Exhaustivity: _: a.Elem[?] From a2b0091b4a9012c78ff960848ac8a9c9106cd901 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 4 Jan 2024 10:29:25 +0000 Subject: [PATCH 035/220] Fix false unreachable due to opaqueness --- compiler/src/dotty/tools/dotc/core/Types.scala | 2 +- .../tools/dotc/transform/patmat/Space.scala | 18 ++++++++---------- tests/warn/i19275.scala | 6 ++++++ 3 files changed, 15 insertions(+), 11 deletions(-) create mode 100644 tests/warn/i19275.scala diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 5e867e3eee97..ed558ea6de82 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -197,7 +197,7 @@ object Types extends TypeUtils { */ def isRef(sym: Symbol, skipRefined: Boolean = true)(using Context): Boolean = this match { case this1: TypeRef => - this1.info match { // see comment in Namer#typeDefSig + this1.info match { // see comment in Namer#TypeDefCompleter#typeSig case TypeAlias(tp) => tp.isRef(sym, skipRefined) case _ => this1.symbol eq sym } diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 0df81f756925..a4cd63aac231 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -668,17 +668,15 @@ object SpaceEngine { } extension (tp: Type) - /** A type is decomposable to children if it has a simple kind, it's sealed, - * abstract (or a trait) - so its not a sealed concrete class that can be instantiated on its own, - * has no anonymous children, which we wouldn't be able to name as counter-examples, - * but does have children. - * - * A sealed trait with no subclasses is considered not decomposable and thus is treated as an opaque type. - * A sealed trait with subclasses that then get removed after `refineUsingParent`, decomposes to the empty list. - * So that's why we consider whether a type has children. */ def isDecomposableToChildren(using Context): Boolean = - val cls = tp.classSymbol - tp.hasSimpleKind && cls.is(Sealed) && cls.isOneOf(AbstractOrTrait) && !cls.hasAnonymousChild && cls.children.nonEmpty + val sym = tp.typeSymbol // e.g. Foo[List[Int]] = type Foo (i19275) + val cls = tp.classSymbol // e.g. Foo[List[Int]] = class List + tp.hasSimpleKind // can't decompose higher-kinded types + && cls.is(Sealed) + && cls.isOneOf(AbstractOrTrait) // ignore sealed non-abstract classes + && !cls.hasAnonymousChild // can't name anonymous classes as counter-examples + && cls.children.nonEmpty // can't decompose without children + && !sym.isOpaqueAlias // can't instantiate subclasses to conform to an opaque type (i19275) val ListOfNoType = List(NoType) val ListOfTypNoType = ListOfNoType.map(Typ(_, decomposed = true)) diff --git a/tests/warn/i19275.scala b/tests/warn/i19275.scala new file mode 100644 index 000000000000..da17f9604ee7 --- /dev/null +++ b/tests/warn/i19275.scala @@ -0,0 +1,6 @@ +opaque type Foo[A] <: A = A + +class Test: + def t1(x: Option[Foo[List[Int]]]): Unit = x match + case Some(foo) => + case None => From 6b78047805c9e38f522c48b84d16d2b3a37ce4d5 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Wed, 27 Dec 2023 13:15:03 +0000 Subject: [PATCH 036/220] Improve recursive decompose prefix fix --- .../src/dotty/tools/dotc/transform/patmat/Space.scala | 2 +- tests/{pos => warn}/i19031.ci-reg1.scala | 2 -- tests/{pos => warn}/i19031.ci-reg2.scala | 2 -- tests/{pos => warn}/i19031.scala | 2 -- tests/warn/i19031b.scala | 10 ++++++++++ 5 files changed, 11 insertions(+), 7 deletions(-) rename tests/{pos => warn}/i19031.ci-reg1.scala (91%) rename tests/{pos => warn}/i19031.ci-reg2.scala (91%) rename tests/{pos => warn}/i19031.scala (80%) create mode 100644 tests/warn/i19031b.scala diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 0df81f756925..57ecf0df33ad 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -619,7 +619,7 @@ object SpaceEngine { case OrType(tp1, tp2) => List(tp1, tp2) case tp if tp.isRef(defn.BooleanClass) => List(ConstantType(Constant(true)), ConstantType(Constant(false))) case tp if tp.isRef(defn.UnitClass) => ConstantType(Constant(())) :: Nil - case tp @ NamedType(Parts(parts), _) => parts.map(tp.derivedSelect) + case tp @ NamedType(Parts(parts), _) => if parts.exists(_ eq tp) then ListOfNoType else parts.map(tp.derivedSelect) case _: SingletonType => ListOfNoType case tp if tp.classSymbol.isAllOf(JavaEnum) => tp.classSymbol.children.map(_.termRef) // the class of a java enum value is the enum class, so this must follow SingletonType to not loop infinitely diff --git a/tests/pos/i19031.ci-reg1.scala b/tests/warn/i19031.ci-reg1.scala similarity index 91% rename from tests/pos/i19031.ci-reg1.scala rename to tests/warn/i19031.ci-reg1.scala index 3c15a3eb9afc..6e8c92c377ea 100644 --- a/tests/pos/i19031.ci-reg1.scala +++ b/tests/warn/i19031.ci-reg1.scala @@ -1,5 +1,3 @@ -//> using options -Werror - sealed trait Mark[T] trait Foo[T] diff --git a/tests/pos/i19031.ci-reg2.scala b/tests/warn/i19031.ci-reg2.scala similarity index 91% rename from tests/pos/i19031.ci-reg2.scala rename to tests/warn/i19031.ci-reg2.scala index e5b12cc17655..a4d5a83fa4dd 100644 --- a/tests/pos/i19031.ci-reg2.scala +++ b/tests/warn/i19031.ci-reg2.scala @@ -1,5 +1,3 @@ -//> using options -Werror - trait Outer: sealed trait Foo case class Bar1() extends Foo diff --git a/tests/pos/i19031.scala b/tests/warn/i19031.scala similarity index 80% rename from tests/pos/i19031.scala rename to tests/warn/i19031.scala index e56744017255..174f459460fd 100644 --- a/tests/pos/i19031.scala +++ b/tests/warn/i19031.scala @@ -1,5 +1,3 @@ -//> using options -Werror - sealed trait A: class B extends A diff --git a/tests/warn/i19031b.scala b/tests/warn/i19031b.scala new file mode 100644 index 000000000000..0b6eaff5df1f --- /dev/null +++ b/tests/warn/i19031b.scala @@ -0,0 +1,10 @@ +sealed trait A: + class B extends A + +class C extends A + +class Test: + def t1(a: A): Boolean = + a match + case b: A#B => true + case c: C => true From 497eef7f65af2fff2daf9b51c6412252069809bc Mon Sep 17 00:00:00 2001 From: Kacper Korban Date: Mon, 11 Sep 2023 13:42:12 +0200 Subject: [PATCH 037/220] Correctly prettify names in coverage info --- .../dotty/tools/dotc/coverage/Location.scala | 6 +- .../dotc/transform/InstrumentCoverage.scala | 2 +- .../coverage/pos/Constructor.scoverage.check | 16 ++-- tests/coverage/pos/Enum.scoverage.check | 56 +++++++------- tests/coverage/pos/For.scoverage.check | 64 ++++++++-------- tests/coverage/pos/Inlined.scoverage.check | 56 +++++++------- .../pos/InlinedFromLib.scoverage.check | 56 +++++++------- tests/coverage/pos/Literals.scoverage.check | 24 +++--- .../pos/MatchCaseClasses.scoverage.check | 56 +++++++------- .../coverage/pos/MatchNumbers.scoverage.check | 24 +++--- .../pos/PolymorphicExtensions.scoverage.check | 52 ++++++------- .../pos/PolymorphicMethods.scoverage.check | 16 ++-- tests/coverage/pos/Select.scoverage.check | 24 +++--- .../pos/StructuralTypes.scoverage.check | 16 ++-- .../coverage/pos/TypeLambdas.scoverage.check | 20 ++--- tests/coverage/pos/i16502.scoverage.check | 16 ++-- ...age-samples-implicit-class.scoverage.check | 4 +- .../run/currying/test.scoverage.check | 64 ++++++++-------- .../coverage/run/erased/test.scoverage.check | 44 +++++------ .../extend-case-class/test.scoverage.check | 12 +-- .../run/i16940/i16940.scoverage.check | 72 +++++++++--------- .../run/i18233-min/i18233-min.scoverage.check | 48 ++++++------ .../run/i18233/i18233.scoverage.check | 28 +++---- .../run/inheritance/test.scoverage.check | 20 ++--- .../run/inline-def/test.scoverage.check | 36 ++++----- .../run/interpolation/test.scoverage.check | 68 ++++++++--------- .../run/java-methods/test.scoverage.check | 32 ++++---- .../run/lifting-bool/test.scoverage.check | 68 ++++++++--------- .../coverage/run/lifting/test.scoverage.check | 56 +++++++------- .../run/parameterless/test.scoverage.check | 76 +++++++++---------- tests/coverage/run/trait/test.scoverage.check | 32 ++++---- .../run/type-apply/test.scoverage.check | 20 ++--- .../run/varargs/test_1.scoverage.check | 64 ++++++++-------- 33 files changed, 624 insertions(+), 624 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/coverage/Location.scala b/compiler/src/dotty/tools/dotc/coverage/Location.scala index 88893709b8bd..de1a3db710a3 100644 --- a/compiler/src/dotty/tools/dotc/coverage/Location.scala +++ b/compiler/src/dotty/tools/dotc/coverage/Location.scala @@ -31,9 +31,9 @@ object Location: val ownerDenot = ctx.owner.denot val enclosingClass = ownerDenot.enclosingClass - val packageName = ownerDenot.enclosingPackageClass.fullName.toSimpleName.toString - val className = enclosingClass.name.toSimpleName.toString - val methodName = ownerDenot.enclosingMethod.name.toSimpleName.toString + val packageName = ownerDenot.enclosingPackageClass.fullName.toSimpleName.show + val className = enclosingClass.name.toSimpleName.show + val methodName = ownerDenot.enclosingMethod.name.toSimpleName.show val classType: String = if enclosingClass.is(Trait) then "Trait" diff --git a/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala b/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala index 2723f726f064..eac44e982603 100644 --- a/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala +++ b/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala @@ -101,7 +101,7 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer: // the internal line number is 0-base https://github.com/lampepfl/dotty/blob/18ada516a85532524a39a962b2ddecb243c65376/compiler/src/dotty/tools/dotc/util/SourceFile.scala#L173-L176 line = pos.line + 1, desc = sourceFile.content.slice(pos.start, pos.end).mkString, - symbolName = tree.symbol.name.toSimpleName.toString, + symbolName = tree.symbol.name.toSimpleName.show, treeName = tree.getClass.getSimpleName.nn, branch ) diff --git a/tests/coverage/pos/Constructor.scoverage.check b/tests/coverage/pos/Constructor.scoverage.check index cb676686eac5..a95bb21488b8 100644 --- a/tests/coverage/pos/Constructor.scoverage.check +++ b/tests/coverage/pos/Constructor.scoverage.check @@ -174,9 +174,9 @@ def g 9 Constructor.scala covtest -O$ +O Object -covtest.O$ +covtest.O g 203 208 @@ -191,9 +191,9 @@ def g 10 Constructor.scala covtest -O$ +O Object -covtest.O$ +covtest.O y 223 228 @@ -208,9 +208,9 @@ def y 11 Constructor.scala covtest -O$ +O Object -covtest.O$ +covtest.O 235 239 @@ -225,9 +225,9 @@ g(y) 12 Constructor.scala covtest -O$ +O Object -covtest.O$ +covtest.O 237 238 diff --git a/tests/coverage/pos/Enum.scoverage.check b/tests/coverage/pos/Enum.scoverage.check index 3baa74fc2e5e..6806934e0dec 100644 --- a/tests/coverage/pos/Enum.scoverage.check +++ b/tests/coverage/pos/Enum.scoverage.check @@ -72,9 +72,9 @@ def surfaceWeight 3 Enum.scala covtest -EnumTypes$ +EnumTypes Object -covtest.EnumTypes$ +covtest.EnumTypes test 1043 1077 @@ -89,9 +89,9 @@ println("Example 1: \\n"+emptyList) 4 Enum.scala covtest -EnumTypes$ +EnumTypes Object -covtest.EnumTypes$ +covtest.EnumTypes test 1051 1076 @@ -106,9 +106,9 @@ false 5 Enum.scala covtest -EnumTypes$ +EnumTypes Object -covtest.EnumTypes$ +covtest.EnumTypes test 1082 1103 @@ -123,9 +123,9 @@ println(s"${list}\\n") 6 Enum.scala covtest -EnumTypes$ +EnumTypes Object -covtest.EnumTypes$ +covtest.EnumTypes test 1090 1102 @@ -140,9 +140,9 @@ s"${list}\\n" 7 Enum.scala covtest -EnumTypes$ +EnumTypes Object -covtest.EnumTypes$ +covtest.EnumTypes calculateEarthWeightOnPlanets 1195 1222 @@ -157,9 +157,9 @@ Planet.Earth.surfaceGravity 8 Enum.scala covtest -EnumTypes$ +EnumTypes Object -covtest.EnumTypes$ +covtest.EnumTypes calculateEarthWeightOnPlanets 1229 1320 @@ -174,9 +174,9 @@ for p <- Planet.values do\n println(s"Your weight on $p is ${p.surfaceWei 9 Enum.scala covtest -EnumTypes$ +EnumTypes Object -covtest.EnumTypes$ +covtest.EnumTypes calculateEarthWeightOnPlanets 1238 1251 @@ -191,9 +191,9 @@ Planet.values 10 Enum.scala covtest -EnumTypes$ +EnumTypes Object -covtest.EnumTypes$ +covtest.EnumTypes $anonfun 1263 1320 @@ -208,9 +208,9 @@ println(s"Your weight on $p is ${p.surfaceWeight(mass)}") 11 Enum.scala covtest -EnumTypes$ +EnumTypes Object -covtest.EnumTypes$ +covtest.EnumTypes $anonfun 1271 1319 @@ -225,9 +225,9 @@ s"Your weight on $p is ${p.surfaceWeight(mass)}" 12 Enum.scala covtest -EnumTypes$ +EnumTypes Object -covtest.EnumTypes$ +covtest.EnumTypes $anonfun 1296 1317 @@ -242,9 +242,9 @@ p.surfaceWeight(mass) 13 Enum.scala covtest -EnumTypes$ +EnumTypes Object -covtest.EnumTypes$ +covtest.EnumTypes calculateEarthWeightOnPlanets 1109 1142 @@ -259,9 +259,9 @@ def calculateEarthWeightOnPlanets 14 Enum.scala covtest -EnumTypes$ +EnumTypes Object -covtest.EnumTypes$ +covtest.EnumTypes test 1326 1347 @@ -276,9 +276,9 @@ println("Example 2:") 15 Enum.scala covtest -EnumTypes$ +EnumTypes Object -covtest.EnumTypes$ +covtest.EnumTypes test 1352 1385 @@ -293,9 +293,9 @@ calculateEarthWeightOnPlanets(80) 16 Enum.scala covtest -EnumTypes$ +EnumTypes Object -covtest.EnumTypes$ +covtest.EnumTypes test 901 909 diff --git a/tests/coverage/pos/For.scoverage.check b/tests/coverage/pos/For.scoverage.check index 901d34701ced..6eeab746b4c5 100644 --- a/tests/coverage/pos/For.scoverage.check +++ b/tests/coverage/pos/For.scoverage.check @@ -21,9 +21,9 @@ 0 For.scala covtest -For$package$ +For$package Object -covtest.For$package$ +covtest.For$package testForLoop 43 77 @@ -38,9 +38,9 @@ for i <- 1 to 10 do\n println(i) 1 For.scala covtest -For$package$ +For$package Object -covtest.For$package$ +covtest.For$package testForLoop 52 59 @@ -55,9 +55,9 @@ false 2 For.scala covtest -For$package$ +For$package Object -covtest.For$package$ +covtest.For$package testForLoop 52 53 @@ -72,9 +72,9 @@ false 3 For.scala covtest -For$package$ +For$package Object -covtest.For$package$ +covtest.For$package $anonfun 67 77 @@ -89,9 +89,9 @@ println(i) 4 For.scala covtest -For$package$ +For$package Object -covtest.For$package$ +covtest.For$package testForLoop 17 32 @@ -106,9 +106,9 @@ def testForLoop 5 For.scala covtest -For$package$ +For$package Object -covtest.For$package$ +covtest.For$package f 109 114 @@ -123,9 +123,9 @@ def f 6 For.scala covtest -For$package$ +For$package Object -covtest.For$package$ +covtest.For$package testForAdvanced 141 183 @@ -140,9 +140,9 @@ for j <- 1 to 10 if f(j) do\n println(j) 7 For.scala covtest -For$package$ +For$package Object -covtest.For$package$ +covtest.For$package testForAdvanced 145 165 @@ -157,9 +157,9 @@ j <- 1 to 10 if f(j) 8 For.scala covtest -For$package$ +For$package Object -covtest.For$package$ +covtest.For$package testForAdvanced 150 157 @@ -174,9 +174,9 @@ false 9 For.scala covtest -For$package$ +For$package Object -covtest.For$package$ +covtest.For$package testForAdvanced 150 151 @@ -191,9 +191,9 @@ false 10 For.scala covtest -For$package$ +For$package Object -covtest.For$package$ +covtest.For$package $anonfun 161 165 @@ -208,9 +208,9 @@ f(j) 11 For.scala covtest -For$package$ +For$package Object -covtest.For$package$ +covtest.For$package $anonfun 173 183 @@ -225,9 +225,9 @@ println(j) 12 For.scala covtest -For$package$ +For$package Object -covtest.For$package$ +covtest.For$package testForAdvanced 79 98 @@ -242,9 +242,9 @@ def testForAdvanced 13 For.scala covtest -For$package$ +For$package Object -covtest.For$package$ +covtest.For$package testForeach 301 344 @@ -259,9 +259,9 @@ Nil.foreach(_ => println("user code here")) 14 For.scala covtest -For$package$ +For$package Object -covtest.For$package$ +covtest.For$package $anonfun 318 343 @@ -276,9 +276,9 @@ println("user code here") 15 For.scala covtest -For$package$ +For$package Object -covtest.For$package$ +covtest.For$package testForeach 185 200 diff --git a/tests/coverage/pos/Inlined.scoverage.check b/tests/coverage/pos/Inlined.scoverage.check index bc0ab9d99892..c74868219b67 100644 --- a/tests/coverage/pos/Inlined.scoverage.check +++ b/tests/coverage/pos/Inlined.scoverage.check @@ -21,9 +21,9 @@ 0 Inlined.scala covtest -Inlined$package$ +Inlined$package Object -covtest.Inlined$package$ +covtest.Inlined$package testInlined 288 330 @@ -38,9 +38,9 @@ scala.runtime.Scala3RunTime.assertFailed() 1 Inlined.scala covtest -Inlined$package$ +Inlined$package Object -covtest.Inlined$package$ +covtest.Inlined$package testInlined 288 330 @@ -55,9 +55,9 @@ scala.runtime.Scala3RunTime.assertFailed() 2 Inlined.scala covtest -Inlined$package$ +Inlined$package Object -covtest.Inlined$package$ +covtest.Inlined$package testInlined 330 330 @@ -72,9 +72,9 @@ false 3 Inlined.scala covtest -Inlined$package$ +Inlined$package Object -covtest.Inlined$package$ +covtest.Inlined$package testInlined 155 162 @@ -89,9 +89,9 @@ List(l) 4 Inlined.scala covtest -Inlined$package$ +Inlined$package Object -covtest.Inlined$package$ +covtest.Inlined$package testInlined 155 169 @@ -106,9 +106,9 @@ List(l).length 5 Inlined.scala covtest -Inlined$package$ +Inlined$package Object -covtest.Inlined$package$ +covtest.Inlined$package testInlined 288 330 @@ -123,9 +123,9 @@ scala.runtime.Scala3RunTime.assertFailed() 6 Inlined.scala covtest -Inlined$package$ +Inlined$package Object -covtest.Inlined$package$ +covtest.Inlined$package testInlined 288 330 @@ -140,9 +140,9 @@ scala.runtime.Scala3RunTime.assertFailed() 7 Inlined.scala covtest -Inlined$package$ +Inlined$package Object -covtest.Inlined$package$ +covtest.Inlined$package testInlined 330 330 @@ -157,9 +157,9 @@ false 8 Inlined.scala covtest -Inlined$package$ +Inlined$package Object -covtest.Inlined$package$ +covtest.Inlined$package testInlined 180 187 @@ -174,9 +174,9 @@ List(l) 9 Inlined.scala covtest -Inlined$package$ +Inlined$package Object -covtest.Inlined$package$ +covtest.Inlined$package testInlined 180 194 @@ -191,9 +191,9 @@ List(l).length 10 Inlined.scala covtest -Inlined$package$ +Inlined$package Object -covtest.Inlined$package$ +covtest.Inlined$package testInlined 288 330 @@ -208,9 +208,9 @@ scala.runtime.Scala3RunTime.assertFailed() 11 Inlined.scala covtest -Inlined$package$ +Inlined$package Object -covtest.Inlined$package$ +covtest.Inlined$package testInlined 288 330 @@ -225,9 +225,9 @@ scala.runtime.Scala3RunTime.assertFailed() 12 Inlined.scala covtest -Inlined$package$ +Inlined$package Object -covtest.Inlined$package$ +covtest.Inlined$package testInlined 330 330 @@ -242,9 +242,9 @@ false 13 Inlined.scala covtest -Inlined$package$ +Inlined$package Object -covtest.Inlined$package$ +covtest.Inlined$package testInlined 86 101 diff --git a/tests/coverage/pos/InlinedFromLib.scoverage.check b/tests/coverage/pos/InlinedFromLib.scoverage.check index 263281cfad39..5aff5473f6d9 100644 --- a/tests/coverage/pos/InlinedFromLib.scoverage.check +++ b/tests/coverage/pos/InlinedFromLib.scoverage.check @@ -21,9 +21,9 @@ 0 InlinedFromLib.scala covtest -InlinedFromLib$package$ +InlinedFromLib$package Object -covtest.InlinedFromLib$package$ +covtest.InlinedFromLib$package testInlined 169 183 @@ -38,9 +38,9 @@ assert(l == 1) 1 InlinedFromLib.scala covtest -InlinedFromLib$package$ +InlinedFromLib$package Object -covtest.InlinedFromLib$package$ +covtest.InlinedFromLib$package testInlined 169 183 @@ -55,9 +55,9 @@ assert(l == 1) 2 InlinedFromLib.scala covtest -InlinedFromLib$package$ +InlinedFromLib$package Object -covtest.InlinedFromLib$package$ +covtest.InlinedFromLib$package testInlined 169 183 @@ -72,9 +72,9 @@ assert(l == 1) 3 InlinedFromLib.scala covtest -InlinedFromLib$package$ +InlinedFromLib$package Object -covtest.InlinedFromLib$package$ +covtest.InlinedFromLib$package testInlined 198 205 @@ -89,9 +89,9 @@ List(l) 4 InlinedFromLib.scala covtest -InlinedFromLib$package$ +InlinedFromLib$package Object -covtest.InlinedFromLib$package$ +covtest.InlinedFromLib$package testInlined 198 212 @@ -106,9 +106,9 @@ List(l).length 5 InlinedFromLib.scala covtest -InlinedFromLib$package$ +InlinedFromLib$package Object -covtest.InlinedFromLib$package$ +covtest.InlinedFromLib$package testInlined 186 213 @@ -123,9 +123,9 @@ assert(l == List(l).length) 6 InlinedFromLib.scala covtest -InlinedFromLib$package$ +InlinedFromLib$package Object -covtest.InlinedFromLib$package$ +covtest.InlinedFromLib$package testInlined 186 213 @@ -140,9 +140,9 @@ assert(l == List(l).length) 7 InlinedFromLib.scala covtest -InlinedFromLib$package$ +InlinedFromLib$package Object -covtest.InlinedFromLib$package$ +covtest.InlinedFromLib$package testInlined 186 213 @@ -157,9 +157,9 @@ assert(l == List(l).length) 8 InlinedFromLib.scala covtest -InlinedFromLib$package$ +InlinedFromLib$package Object -covtest.InlinedFromLib$package$ +covtest.InlinedFromLib$package testInlined 223 230 @@ -174,9 +174,9 @@ List(l) 9 InlinedFromLib.scala covtest -InlinedFromLib$package$ +InlinedFromLib$package Object -covtest.InlinedFromLib$package$ +covtest.InlinedFromLib$package testInlined 223 237 @@ -191,9 +191,9 @@ List(l).length 10 InlinedFromLib.scala covtest -InlinedFromLib$package$ +InlinedFromLib$package Object -covtest.InlinedFromLib$package$ +covtest.InlinedFromLib$package testInlined 216 243 @@ -208,9 +208,9 @@ assert(List(l).length == 1) 11 InlinedFromLib.scala covtest -InlinedFromLib$package$ +InlinedFromLib$package Object -covtest.InlinedFromLib$package$ +covtest.InlinedFromLib$package testInlined 216 243 @@ -225,9 +225,9 @@ assert(List(l).length == 1) 12 InlinedFromLib.scala covtest -InlinedFromLib$package$ +InlinedFromLib$package Object -covtest.InlinedFromLib$package$ +covtest.InlinedFromLib$package testInlined 216 243 @@ -242,9 +242,9 @@ assert(List(l).length == 1) 13 InlinedFromLib.scala covtest -InlinedFromLib$package$ +InlinedFromLib$package Object -covtest.InlinedFromLib$package$ +covtest.InlinedFromLib$package testInlined 129 144 diff --git a/tests/coverage/pos/Literals.scoverage.check b/tests/coverage/pos/Literals.scoverage.check index f23c481c1145..cd58a841d5b6 100644 --- a/tests/coverage/pos/Literals.scoverage.check +++ b/tests/coverage/pos/Literals.scoverage.check @@ -21,9 +21,9 @@ 0 Literals.scala covtest -Literals$package$ +Literals$package Object -covtest.Literals$package$ +covtest.Literals$package block 31 50 @@ -38,9 +38,9 @@ println("not this") 1 Literals.scala covtest -Literals$package$ +Literals$package Object -covtest.Literals$package$ +covtest.Literals$package block 17 26 @@ -55,9 +55,9 @@ def block 2 Literals.scala covtest -Literals$package$ +Literals$package Object -covtest.Literals$package$ +covtest.Literals$package f 177 180 @@ -72,9 +72,9 @@ false 3 Literals.scala covtest -Literals$package$ +Literals$package Object -covtest.Literals$package$ +covtest.Literals$package f 137 142 @@ -89,9 +89,9 @@ def f 4 Literals.scala covtest -Literals$package$ +Literals$package Object -covtest.Literals$package$ +covtest.Literals$package main 201 212 @@ -106,9 +106,9 @@ f(0,1,2)(3) 5 Literals.scala covtest -Literals$package$ +Literals$package Object -covtest.Literals$package$ +covtest.Literals$package main 182 190 diff --git a/tests/coverage/pos/MatchCaseClasses.scoverage.check b/tests/coverage/pos/MatchCaseClasses.scoverage.check index 0911532b1977..16574b6c770e 100644 --- a/tests/coverage/pos/MatchCaseClasses.scoverage.check +++ b/tests/coverage/pos/MatchCaseClasses.scoverage.check @@ -21,9 +21,9 @@ 0 MatchCaseClasses.scala covtest -MatchCaseClasses$ +MatchCaseClasses Object -covtest.MatchCaseClasses$ +covtest.MatchCaseClasses f 151 163 @@ -38,9 +38,9 @@ println("a") 1 MatchCaseClasses.scala covtest -MatchCaseClasses$ +MatchCaseClasses Object -covtest.MatchCaseClasses$ +covtest.MatchCaseClasses f 148 163 @@ -55,9 +55,9 @@ false 2 MatchCaseClasses.scala covtest -MatchCaseClasses$ +MatchCaseClasses Object -covtest.MatchCaseClasses$ +covtest.MatchCaseClasses f 184 196 @@ -72,9 +72,9 @@ println("b") 3 MatchCaseClasses.scala covtest -MatchCaseClasses$ +MatchCaseClasses Object -covtest.MatchCaseClasses$ +covtest.MatchCaseClasses f 181 196 @@ -89,9 +89,9 @@ false 4 MatchCaseClasses.scala covtest -MatchCaseClasses$ +MatchCaseClasses Object -covtest.MatchCaseClasses$ +covtest.MatchCaseClasses f 225 237 @@ -106,9 +106,9 @@ println("c") 5 MatchCaseClasses.scala covtest -MatchCaseClasses$ +MatchCaseClasses Object -covtest.MatchCaseClasses$ +covtest.MatchCaseClasses f 222 237 @@ -123,9 +123,9 @@ false 6 MatchCaseClasses.scala covtest -MatchCaseClasses$ +MatchCaseClasses Object -covtest.MatchCaseClasses$ +covtest.MatchCaseClasses f 275 285 @@ -140,9 +140,9 @@ println(y) 7 MatchCaseClasses.scala covtest -MatchCaseClasses$ +MatchCaseClasses Object -covtest.MatchCaseClasses$ +covtest.MatchCaseClasses f 292 304 @@ -157,9 +157,9 @@ println("d") 8 MatchCaseClasses.scala covtest -MatchCaseClasses$ +MatchCaseClasses Object -covtest.MatchCaseClasses$ +covtest.MatchCaseClasses f 275 304 @@ -174,9 +174,9 @@ println(y)\n println("d") 9 MatchCaseClasses.scala covtest -MatchCaseClasses$ +MatchCaseClasses Object -covtest.MatchCaseClasses$ +covtest.MatchCaseClasses f 325 337 @@ -191,9 +191,9 @@ println("e") 10 MatchCaseClasses.scala covtest -MatchCaseClasses$ +MatchCaseClasses Object -covtest.MatchCaseClasses$ +covtest.MatchCaseClasses f 322 337 @@ -208,9 +208,9 @@ false 11 MatchCaseClasses.scala covtest -MatchCaseClasses$ +MatchCaseClasses Object -covtest.MatchCaseClasses$ +covtest.MatchCaseClasses f 352 368 @@ -225,9 +225,9 @@ println("other") 12 MatchCaseClasses.scala covtest -MatchCaseClasses$ +MatchCaseClasses Object -covtest.MatchCaseClasses$ +covtest.MatchCaseClasses f 349 368 @@ -242,9 +242,9 @@ false 13 MatchCaseClasses.scala covtest -MatchCaseClasses$ +MatchCaseClasses Object -covtest.MatchCaseClasses$ +covtest.MatchCaseClasses f 101 106 diff --git a/tests/coverage/pos/MatchNumbers.scoverage.check b/tests/coverage/pos/MatchNumbers.scoverage.check index ccb8a627f46e..43e01018f0ac 100644 --- a/tests/coverage/pos/MatchNumbers.scoverage.check +++ b/tests/coverage/pos/MatchNumbers.scoverage.check @@ -21,9 +21,9 @@ 0 MatchNumbers.scala covtest -MatchNumbers$ +MatchNumbers Object -covtest.MatchNumbers$ +covtest.MatchNumbers f 127 132 @@ -38,9 +38,9 @@ false 1 MatchNumbers.scala covtest -MatchNumbers$ +MatchNumbers Object -covtest.MatchNumbers$ +covtest.MatchNumbers f 149 153 @@ -55,9 +55,9 @@ false 2 MatchNumbers.scala covtest -MatchNumbers$ +MatchNumbers Object -covtest.MatchNumbers$ +covtest.MatchNumbers f 171 181 @@ -72,9 +72,9 @@ false 3 MatchNumbers.scala covtest -MatchNumbers$ +MatchNumbers Object -covtest.MatchNumbers$ +covtest.MatchNumbers f 69 74 @@ -89,9 +89,9 @@ def f 4 MatchNumbers.scala covtest -MatchNumbers$ +MatchNumbers Object -covtest.MatchNumbers$ +covtest.MatchNumbers 185 189 @@ -106,9 +106,9 @@ f(0) 5 MatchNumbers.scala covtest -MatchNumbers$ +MatchNumbers Object -covtest.MatchNumbers$ +covtest.MatchNumbers 192 197 diff --git a/tests/coverage/pos/PolymorphicExtensions.scoverage.check b/tests/coverage/pos/PolymorphicExtensions.scoverage.check index 33be52244cdf..64795070b34f 100644 --- a/tests/coverage/pos/PolymorphicExtensions.scoverage.check +++ b/tests/coverage/pos/PolymorphicExtensions.scoverage.check @@ -21,9 +21,9 @@ 0 PolymorphicExtensions.scala covtest -PolyExt$ +PolyExt Object -covtest.PolyExt$ +covtest.PolyExt foo 61 68 @@ -38,9 +38,9 @@ def foo 1 PolymorphicExtensions.scala covtest -PolyExt$ +PolyExt Object -covtest.PolyExt$ +covtest.PolyExt get 114 121 @@ -55,9 +55,9 @@ def get 2 PolymorphicExtensions.scala covtest -PolyExt$ +PolyExt Object -covtest.PolyExt$ +covtest.PolyExt tap 170 173 @@ -72,9 +72,9 @@ false 3 PolymorphicExtensions.scala covtest -PolyExt$ +PolyExt Object -covtest.PolyExt$ +covtest.PolyExt tap 139 146 @@ -89,9 +89,9 @@ def tap 4 PolymorphicExtensions.scala covtest -PolyExt$ +PolyExt Object -covtest.PolyExt$ +covtest.PolyExt 177 189 @@ -106,9 +106,9 @@ false 5 PolymorphicExtensions.scala covtest -PolyExt$ +PolyExt Object -covtest.PolyExt$ +covtest.PolyExt 177 186 @@ -123,9 +123,9 @@ false 6 PolymorphicExtensions.scala covtest -PolyExt$ +PolyExt Object -covtest.PolyExt$ +covtest.PolyExt 277 287 @@ -140,9 +140,9 @@ false 7 PolymorphicExtensions.scala covtest -PolyExt$ +PolyExt Object -covtest.PolyExt$ +covtest.PolyExt foo 370 377 @@ -157,9 +157,9 @@ def foo 8 PolymorphicExtensions.scala covtest -PolyExt$ +PolyExt Object -covtest.PolyExt$ +covtest.PolyExt bar 405 421 @@ -174,9 +174,9 @@ foo.tap(println) 9 PolymorphicExtensions.scala covtest -PolyExt$ +PolyExt Object -covtest.PolyExt$ +covtest.PolyExt bar 405 412 @@ -191,9 +191,9 @@ foo.tap 10 PolymorphicExtensions.scala covtest -PolyExt$ +PolyExt Object -covtest.PolyExt$ +covtest.PolyExt bar 405 408 @@ -208,9 +208,9 @@ foo 11 PolymorphicExtensions.scala covtest -PolyExt$ +PolyExt Object -covtest.PolyExt$ +covtest.PolyExt $anonfun 413 420 @@ -225,9 +225,9 @@ println 12 PolymorphicExtensions.scala covtest -PolyExt$ +PolyExt Object -covtest.PolyExt$ +covtest.PolyExt bar 390 397 diff --git a/tests/coverage/pos/PolymorphicMethods.scoverage.check b/tests/coverage/pos/PolymorphicMethods.scoverage.check index ae6413869f06..b66aaeb92661 100644 --- a/tests/coverage/pos/PolymorphicMethods.scoverage.check +++ b/tests/coverage/pos/PolymorphicMethods.scoverage.check @@ -21,9 +21,9 @@ 0 PolymorphicMethods.scala covtest -PolyMeth$ +PolyMeth Object -covtest.PolyMeth$ +covtest.PolyMeth f 36 41 @@ -38,9 +38,9 @@ def f 1 PolymorphicMethods.scala covtest -PolyMeth$ +PolyMeth Object -covtest.PolyMeth$ +covtest.PolyMeth 60 69 @@ -55,9 +55,9 @@ this.f(0) 2 PolymorphicMethods.scala covtest -PolyMeth$ +PolyMeth Object -covtest.PolyMeth$ +covtest.PolyMeth 147 170 @@ -72,9 +72,9 @@ C[String]().f("str", 0) 3 PolymorphicMethods.scala covtest -PolyMeth$ +PolyMeth Object -covtest.PolyMeth$ +covtest.PolyMeth 147 158 diff --git a/tests/coverage/pos/Select.scoverage.check b/tests/coverage/pos/Select.scoverage.check index 5300716cae90..cfe719552e44 100644 --- a/tests/coverage/pos/Select.scoverage.check +++ b/tests/coverage/pos/Select.scoverage.check @@ -140,9 +140,9 @@ override def print 7 Select.scala covtest -Select$package$ +Select$package Object -covtest.Select$package$ +covtest.Select$package test 237 240 @@ -157,9 +157,9 @@ A() 8 Select.scala covtest -Select$package$ +Select$package Object -covtest.Select$package$ +covtest.Select$package test 254 259 @@ -174,9 +174,9 @@ new A 9 Select.scala covtest -Select$package$ +Select$package Object -covtest.Select$package$ +covtest.Select$package test 263 281 @@ -191,9 +191,9 @@ a.instance.print() 10 Select.scala covtest -Select$package$ +Select$package Object -covtest.Select$package$ +covtest.Select$package test 263 273 @@ -208,9 +208,9 @@ a.instance 11 Select.scala covtest -Select$package$ +Select$package Object -covtest.Select$package$ +covtest.Select$package test 345 354 @@ -225,9 +225,9 @@ a.print() 12 Select.scala covtest -Select$package$ +Select$package Object -covtest.Select$package$ +covtest.Select$package test 208 216 diff --git a/tests/coverage/pos/StructuralTypes.scoverage.check b/tests/coverage/pos/StructuralTypes.scoverage.check index 2e897f6e8016..a487ac29c9de 100644 --- a/tests/coverage/pos/StructuralTypes.scoverage.check +++ b/tests/coverage/pos/StructuralTypes.scoverage.check @@ -72,9 +72,9 @@ def selectDynamic 3 StructuralTypes.scala covtest -StructuralTypes$ +StructuralTypes Object -covtest.StructuralTypes$ +covtest.StructuralTypes test 277 293 @@ -89,9 +89,9 @@ false 4 StructuralTypes.scala covtest -StructuralTypes$ +StructuralTypes Object -covtest.StructuralTypes$ +covtest.StructuralTypes test 295 306 @@ -106,9 +106,9 @@ false 5 StructuralTypes.scala covtest -StructuralTypes$ +StructuralTypes Object -covtest.StructuralTypes$ +covtest.StructuralTypes test 333 344 @@ -123,9 +123,9 @@ person.name 6 StructuralTypes.scala covtest -StructuralTypes$ +StructuralTypes Object -covtest.StructuralTypes$ +covtest.StructuralTypes test 234 242 diff --git a/tests/coverage/pos/TypeLambdas.scoverage.check b/tests/coverage/pos/TypeLambdas.scoverage.check index 091a5cf4da57..de519038c367 100644 --- a/tests/coverage/pos/TypeLambdas.scoverage.check +++ b/tests/coverage/pos/TypeLambdas.scoverage.check @@ -21,9 +21,9 @@ 0 TypeLambdas.scala covtest -TypeLambdas$ +TypeLambdas Object -covtest.TypeLambdas$ +covtest.TypeLambdas test 306 319 @@ -38,9 +38,9 @@ Map(1 -> "1") 1 TypeLambdas.scala covtest -TypeLambdas$ +TypeLambdas Object -covtest.TypeLambdas$ +covtest.TypeLambdas test 310 318 @@ -55,9 +55,9 @@ false 2 TypeLambdas.scala covtest -TypeLambdas$ +TypeLambdas Object -covtest.TypeLambdas$ +covtest.TypeLambdas test 324 334 @@ -72,9 +72,9 @@ println(m) 3 TypeLambdas.scala covtest -TypeLambdas$ +TypeLambdas Object -covtest.TypeLambdas$ +covtest.TypeLambdas test 382 396 @@ -89,9 +89,9 @@ println(tuple) 4 TypeLambdas.scala covtest -TypeLambdas$ +TypeLambdas Object -covtest.TypeLambdas$ +covtest.TypeLambdas test 259 267 diff --git a/tests/coverage/pos/i16502.scoverage.check b/tests/coverage/pos/i16502.scoverage.check index 4bc50c0f91c3..127c68063f73 100644 --- a/tests/coverage/pos/i16502.scoverage.check +++ b/tests/coverage/pos/i16502.scoverage.check @@ -21,9 +21,9 @@ 0 i16502.scala -i16502$package$ +i16502$package Object -.i16502$package$ +.i16502$package $anonfun 76 85 @@ -38,9 +38,9 @@ Future(1) 1 i16502.scala -i16502$package$ +i16502$package Object -.i16502$package$ +.i16502$package asyncSum 27 39 @@ -55,9 +55,9 @@ def asyncSum 2 i16502.scala -i16502$package$ +i16502$package Object -.i16502$package$ +.i16502$package Test 174 182 @@ -72,9 +72,9 @@ asyncSum 3 i16502.scala -i16502$package$ +i16502$package Object -.i16502$package$ +.i16502$package Test 87 101 diff --git a/tests/coverage/pos/scoverage-samples-implicit-class.scoverage.check b/tests/coverage/pos/scoverage-samples-implicit-class.scoverage.check index d44faf848942..f9bb9e0cd6a3 100644 --- a/tests/coverage/pos/scoverage-samples-implicit-class.scoverage.check +++ b/tests/coverage/pos/scoverage-samples-implicit-class.scoverage.check @@ -191,9 +191,9 @@ def ! 10 scoverage-samples-implicit-class.scala org.scoverage.samples -scoverage-samples-implicit-class$package$ +scoverage-samples-implicit-class$package Object -org.scoverage.samples.scoverage-samples-implicit-class$package$ +org.scoverage.samples.scoverage-samples-implicit-class$package StringOpssssss 79 108 diff --git a/tests/coverage/run/currying/test.scoverage.check b/tests/coverage/run/currying/test.scoverage.check index 183e42fba2d5..abc1876942db 100644 --- a/tests/coverage/run/currying/test.scoverage.check +++ b/tests/coverage/run/currying/test.scoverage.check @@ -21,9 +21,9 @@ 0 currying/test.scala -Test$ +Test Object -.Test$ +.Test f1 15 21 @@ -38,9 +38,9 @@ def f1 1 currying/test.scala -Test$ +Test Object -.Test$ +.Test f2 56 62 @@ -55,9 +55,9 @@ def f2 2 currying/test.scala -Test$ +Test Object -.Test$ +.Test g1 114 120 @@ -72,9 +72,9 @@ def g1 3 currying/test.scala -Test$ +Test Object -.Test$ +.Test g2 175 181 @@ -89,9 +89,9 @@ def g2 4 currying/test.scala -Test$ +Test Object -.Test$ +.Test main 277 297 @@ -106,9 +106,9 @@ println(f1(0)(1)(2)) 5 currying/test.scala -Test$ +Test Object -.Test$ +.Test main 285 296 @@ -123,9 +123,9 @@ f1(0)(1)(2) 6 currying/test.scala -Test$ +Test Object -.Test$ +.Test main 302 322 @@ -140,9 +140,9 @@ println(f2(0)(1)(2)) 7 currying/test.scala -Test$ +Test Object -.Test$ +.Test main 310 321 @@ -157,9 +157,9 @@ f2(0)(1)(2) 8 currying/test.scala -Test$ +Test Object -.Test$ +.Test main 310 318 @@ -174,9 +174,9 @@ f2(0)(1) 9 currying/test.scala -Test$ +Test Object -.Test$ +.Test main 310 315 @@ -191,9 +191,9 @@ f2(0) 10 currying/test.scala -Test$ +Test Object -.Test$ +.Test main 310 312 @@ -208,9 +208,9 @@ f2 11 currying/test.scala -Test$ +Test Object -.Test$ +.Test main 327 365 @@ -225,9 +225,9 @@ println(g1(using 0)(using 1)(using 2)) 12 currying/test.scala -Test$ +Test Object -.Test$ +.Test main 335 364 @@ -242,9 +242,9 @@ g1(using 0)(using 1)(using 2) 13 currying/test.scala -Test$ +Test Object -.Test$ +.Test main 370 408 @@ -259,9 +259,9 @@ println(g2(using 0)(using 1)(using 2)) 14 currying/test.scala -Test$ +Test Object -.Test$ +.Test main 378 407 @@ -276,9 +276,9 @@ g2(using 0)(using 1)(using 2) 15 currying/test.scala -Test$ +Test Object -.Test$ +.Test main 235 243 diff --git a/tests/coverage/run/erased/test.scoverage.check b/tests/coverage/run/erased/test.scoverage.check index 979d88ecd78f..dedf5689c490 100644 --- a/tests/coverage/run/erased/test.scoverage.check +++ b/tests/coverage/run/erased/test.scoverage.check @@ -21,9 +21,9 @@ 0 erased/test.scala -test$package$ +test$package Object -.test$package$ +.test$package foo 181 203 @@ -38,9 +38,9 @@ println(s"foo(a)($b)") 1 erased/test.scala -test$package$ +test$package Object -.test$package$ +.test$package foo 189 202 @@ -55,9 +55,9 @@ s"foo(a)($b)" 2 erased/test.scala -test$package$ +test$package Object -.test$package$ +.test$package foo 132 139 @@ -72,9 +72,9 @@ def foo 3 erased/test.scala -test$package$ +test$package Object -.test$package$ +.test$package identity 245 269 @@ -89,9 +89,9 @@ println(s"identity($s)") 4 erased/test.scala -test$package$ +test$package Object -.test$package$ +.test$package identity 253 268 @@ -106,9 +106,9 @@ s"identity($s)" 5 erased/test.scala -test$package$ +test$package Object -.test$package$ +.test$package identity 209 221 @@ -123,9 +123,9 @@ def identity 6 erased/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 300 323 @@ -140,9 +140,9 @@ foo(parameterless)("b") 7 erased/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 326 342 @@ -157,9 +157,9 @@ foo(e("a"))("b") 8 erased/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 345 374 @@ -174,9 +174,9 @@ foo(e("a"))(identity("idem")) 9 erased/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 357 373 @@ -191,9 +191,9 @@ identity("idem") 10 erased/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 275 289 diff --git a/tests/coverage/run/extend-case-class/test.scoverage.check b/tests/coverage/run/extend-case-class/test.scoverage.check index 891f4ac198ca..b355140d2520 100644 --- a/tests/coverage/run/extend-case-class/test.scoverage.check +++ b/tests/coverage/run/extend-case-class/test.scoverage.check @@ -21,9 +21,9 @@ 0 extend-case-class/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 282 303 @@ -38,9 +38,9 @@ println(c.scaleLimit) 1 extend-case-class/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 306 337 @@ -55,9 +55,9 @@ println(DecimalConf.scaleLimit) 2 extend-case-class/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 206 220 diff --git a/tests/coverage/run/i16940/i16940.scoverage.check b/tests/coverage/run/i16940/i16940.scoverage.check index f8ff25537b0f..357080ba9da8 100644 --- a/tests/coverage/run/i16940/i16940.scoverage.check +++ b/tests/coverage/run/i16940/i16940.scoverage.check @@ -21,9 +21,9 @@ 0 i16940/i16940.scala -Test$ +Test Object -.Test$ +.Test 353 552 @@ -38,9 +38,9 @@ Await.result(\n Future.sequence(Seq(brokenSynchronizedBlock(false), brokenSyn 1 i16940/i16940.scala -Test$ +Test Object -.Test$ +.Test 371 533 @@ -55,9 +55,9 @@ Future.sequence(Seq(brokenSynchronizedBlock(false), brokenSynchronizedBlock(true 2 i16940/i16940.scala -Test$ +Test Object -.Test$ +.Test 371 454 @@ -72,9 +72,9 @@ Future.sequence(Seq(brokenSynchronizedBlock(false), brokenSynchronizedBlock(true 3 i16940/i16940.scala -Test$ +Test Object -.Test$ +.Test 387 453 @@ -89,9 +89,9 @@ Seq(brokenSynchronizedBlock(false), brokenSynchronizedBlock(true)) 4 i16940/i16940.scala -Test$ +Test Object -.Test$ +.Test 391 421 @@ -106,9 +106,9 @@ brokenSynchronizedBlock(false) 5 i16940/i16940.scala -Test$ +Test Object -.Test$ +.Test 423 452 @@ -123,9 +123,9 @@ brokenSynchronizedBlock(true) 6 i16940/i16940.scala -Test$ +Test Object -.Test$ +.Test $anonfun 486 499 @@ -140,9 +140,9 @@ println(test) 7 i16940/i16940.scala -Test$ +Test Object -.Test$ +.Test $anonfun 508 525 @@ -157,9 +157,9 @@ assert(test == 2) 8 i16940/i16940.scala -Test$ +Test Object -.Test$ +.Test $anonfun 508 525 @@ -174,9 +174,9 @@ assert(test == 2) 9 i16940/i16940.scala -Test$ +Test Object -.Test$ +.Test $anonfun 508 525 @@ -191,9 +191,9 @@ assert(test == 2) 10 i16940/i16940.scala -Test$ +Test Object -.Test$ +.Test 539 548 @@ -208,9 +208,9 @@ false 11 i16940/i16940.scala -i16940$package$ +i16940$package Object -.i16940$package$ +.i16940$package brokenSynchronizedBlock 189 323 @@ -225,9 +225,9 @@ Future {\n if (option) {\n Thread.sleep(500)\n }\n synchronized {\n val 12 i16940/i16940.scala -i16940$package$ +i16940$package Object -.i16940$package$ +.i16940$package brokenSynchronizedBlock 218 235 @@ -242,9 +242,9 @@ Thread.sleep(500) 13 i16940/i16940.scala -i16940$package$ +i16940$package Object -.i16940$package$ +.i16940$package brokenSynchronizedBlock 212 239 @@ -259,9 +259,9 @@ false 14 i16940/i16940.scala -i16940$package$ +i16940$package Object -.i16940$package$ +.i16940$package brokenSynchronizedBlock 239 239 @@ -276,9 +276,9 @@ false 15 i16940/i16940.scala -i16940$package$ +i16940$package Object -.i16940$package$ +.i16940$package brokenSynchronizedBlock 242 321 @@ -293,9 +293,9 @@ synchronized {\n val tmp = test\n Thread.sleep(1000)\n test = tmp + 1\n 16 i16940/i16940.scala -i16940$package$ +i16940$package Object -.i16940$package$ +.i16940$package brokenSynchronizedBlock 280 298 @@ -310,9 +310,9 @@ Thread.sleep(1000) 17 i16940/i16940.scala -i16940$package$ +i16940$package Object -.i16940$package$ +.i16940$package brokenSynchronizedBlock 128 155 diff --git a/tests/coverage/run/i18233-min/i18233-min.scoverage.check b/tests/coverage/run/i18233-min/i18233-min.scoverage.check index 7c9144c289bc..7570ebaaed96 100644 --- a/tests/coverage/run/i18233-min/i18233-min.scoverage.check +++ b/tests/coverage/run/i18233-min/i18233-min.scoverage.check @@ -21,9 +21,9 @@ 0 i18233-min/i18233-min.scala -Test$ +Test Object -.Test$ +.Test 131 145 @@ -38,9 +38,9 @@ println(aList) 1 i18233-min/i18233-min.scala -Test$ +Test Object -.Test$ +.Test 139 144 @@ -55,9 +55,9 @@ aList 2 i18233-min/i18233-min.scala -Test$ +Test Object -.Test$ +.Test 148 168 @@ -72,9 +72,9 @@ println(anotherList) 3 i18233-min/i18233-min.scala -Test$ +Test Object -.Test$ +.Test 156 167 @@ -89,9 +89,9 @@ anotherList 4 i18233-min/i18233-min.scala -i18233-min$package$ +i18233-min$package Object -.i18233-min$package$ +.i18233-min$package aList 14 36 @@ -106,9 +106,9 @@ List(Array[String]()*) 5 i18233-min/i18233-min.scala -i18233-min$package$ +i18233-min$package Object -.i18233-min$package$ +.i18233-min$package aList 19 34 @@ -123,9 +123,9 @@ Array[String]() 6 i18233-min/i18233-min.scala -i18233-min$package$ +i18233-min$package Object -.i18233-min$package$ +.i18233-min$package aList 0 9 @@ -140,9 +140,9 @@ def aList 7 i18233-min/i18233-min.scala -i18233-min$package$ +i18233-min$package Object -.i18233-min$package$ +.i18233-min$package arr 50 69 @@ -157,9 +157,9 @@ Array("abc", "def") 8 i18233-min/i18233-min.scala -i18233-min$package$ +i18233-min$package Object -.i18233-min$package$ +.i18233-min$package arr 38 45 @@ -174,9 +174,9 @@ def arr 9 i18233-min/i18233-min.scala -i18233-min$package$ +i18233-min$package Object -.i18233-min$package$ +.i18233-min$package anotherList 91 101 @@ -191,9 +191,9 @@ List(arr*) 10 i18233-min/i18233-min.scala -i18233-min$package$ +i18233-min$package Object -.i18233-min$package$ +.i18233-min$package anotherList 96 99 @@ -208,9 +208,9 @@ arr 11 i18233-min/i18233-min.scala -i18233-min$package$ +i18233-min$package Object -.i18233-min$package$ +.i18233-min$package anotherList 71 86 diff --git a/tests/coverage/run/i18233/i18233.scoverage.check b/tests/coverage/run/i18233/i18233.scoverage.check index e632292e782e..878ca8a14705 100644 --- a/tests/coverage/run/i18233/i18233.scoverage.check +++ b/tests/coverage/run/i18233/i18233.scoverage.check @@ -21,9 +21,9 @@ 0 i18233/i18233.scala -Foo$ +Foo Object -.Foo$ +.Foo render 54 72 @@ -38,9 +38,9 @@ List(values.tail*) 1 i18233/i18233.scala -Foo$ +Foo Object -.Foo$ +.Foo render 59 65 @@ -55,9 +55,9 @@ values 2 i18233/i18233.scala -Foo$ +Foo Object -.Foo$ +.Foo render 59 70 @@ -72,9 +72,9 @@ values.tail 3 i18233/i18233.scala -Foo$ +Foo Object -.Foo$ +.Foo render 54 81 @@ -89,9 +89,9 @@ List(values.tail*).mkString 4 i18233/i18233.scala -Foo$ +Foo Object -.Foo$ +.Foo render 41 51 @@ -106,9 +106,9 @@ def render 5 i18233/i18233.scala -Test$ +Test Object -.Test$ +.Test 111 130 @@ -123,9 +123,9 @@ println(Foo.render) 6 i18233/i18233.scala -Test$ +Test Object -.Test$ +.Test 119 129 diff --git a/tests/coverage/run/inheritance/test.scoverage.check b/tests/coverage/run/inheritance/test.scoverage.check index d4ca12879ea3..387a080463e2 100644 --- a/tests/coverage/run/inheritance/test.scoverage.check +++ b/tests/coverage/run/inheritance/test.scoverage.check @@ -55,9 +55,9 @@ A(2,2) 2 inheritance/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 161 176 @@ -72,9 +72,9 @@ println(C1().x) 3 inheritance/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 169 173 @@ -89,9 +89,9 @@ C1() 4 inheritance/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 211 226 @@ -106,9 +106,9 @@ println(C2().x) 5 inheritance/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 219 223 @@ -123,9 +123,9 @@ C2() 6 inheritance/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 136 150 diff --git a/tests/coverage/run/inline-def/test.scoverage.check b/tests/coverage/run/inline-def/test.scoverage.check index f8a852707146..17fa7c049107 100644 --- a/tests/coverage/run/inline-def/test.scoverage.check +++ b/tests/coverage/run/inline-def/test.scoverage.check @@ -21,9 +21,9 @@ 0 inline-def/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 225 228 @@ -38,9 +38,9 @@ A() 1 inline-def/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 231 243 @@ -55,9 +55,9 @@ println(a.x) 2 inline-def/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 246 260 @@ -72,9 +72,9 @@ println(a.foo) 3 inline-def/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 134 148 @@ -89,9 +89,9 @@ false 4 inline-def/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 263 277 @@ -106,9 +106,9 @@ println(a.bar) 5 inline-def/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 176 190 @@ -123,9 +123,9 @@ false 6 inline-def/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 295 309 @@ -140,9 +140,9 @@ println(b.foo) 7 inline-def/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 303 308 @@ -157,9 +157,9 @@ b.foo 8 inline-def/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 192 206 diff --git a/tests/coverage/run/interpolation/test.scoverage.check b/tests/coverage/run/interpolation/test.scoverage.check index b2373483737e..37562dab5509 100644 --- a/tests/coverage/run/interpolation/test.scoverage.check +++ b/tests/coverage/run/interpolation/test.scoverage.check @@ -21,9 +21,9 @@ 0 interpolation/test.scala -Test$ +Test Object -.Test$ +.Test simple 60 78 @@ -38,9 +38,9 @@ s"$a, ${b.length}" 1 interpolation/test.scala -Test$ +Test Object -.Test$ +.Test simple 68 76 @@ -55,9 +55,9 @@ b.length 2 interpolation/test.scala -Test$ +Test Object -.Test$ +.Test simple 16 26 @@ -72,9 +72,9 @@ def simple 3 interpolation/test.scala -Test$ +Test Object -.Test$ +.Test hexa 113 126 @@ -89,9 +89,9 @@ f"0x${i}%04x" 4 interpolation/test.scala -Test$ +Test Object -.Test$ +.Test hexa 82 90 @@ -106,9 +106,9 @@ def hexa 5 interpolation/test.scala -Test$ +Test Object -.Test$ +.Test main 195 224 @@ -123,9 +123,9 @@ List("d", "o", "t", "t", "y") 6 interpolation/test.scala -Test$ +Test Object -.Test$ +.Test main 229 278 @@ -140,9 +140,9 @@ xs.zipWithIndex.map((s, i) => println(s"$i: $s")) 7 interpolation/test.scala -Test$ +Test Object -.Test$ +.Test main 229 244 @@ -157,9 +157,9 @@ xs.zipWithIndex 8 interpolation/test.scala -Test$ +Test Object -.Test$ +.Test $anonfun 259 277 @@ -174,9 +174,9 @@ println(s"$i: $s") 9 interpolation/test.scala -Test$ +Test Object -.Test$ +.Test $anonfun 267 276 @@ -191,9 +191,9 @@ s"$i: $s" 10 interpolation/test.scala -Test$ +Test Object -.Test$ +.Test main 284 309 @@ -208,9 +208,9 @@ println(simple(1, "abc")) 11 interpolation/test.scala -Test$ +Test Object -.Test$ +.Test main 292 308 @@ -225,9 +225,9 @@ simple(1, "abc") 12 interpolation/test.scala -Test$ +Test Object -.Test$ +.Test main 314 332 @@ -242,9 +242,9 @@ println(hexa(127)) 13 interpolation/test.scala -Test$ +Test Object -.Test$ +.Test main 322 331 @@ -259,9 +259,9 @@ hexa(127) 14 interpolation/test.scala -Test$ +Test Object -.Test$ +.Test main 337 355 @@ -276,9 +276,9 @@ println(raw"a\\nb") 15 interpolation/test.scala -Test$ +Test Object -.Test$ +.Test main 345 354 @@ -293,9 +293,9 @@ raw"a\\nb" 16 interpolation/test.scala -Test$ +Test Object -.Test$ +.Test main 130 138 diff --git a/tests/coverage/run/java-methods/test.scoverage.check b/tests/coverage/run/java-methods/test.scoverage.check index e39efe8f3aa8..891af1804831 100644 --- a/tests/coverage/run/java-methods/test.scoverage.check +++ b/tests/coverage/run/java-methods/test.scoverage.check @@ -21,9 +21,9 @@ 0 java-methods/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 61 83 @@ -38,9 +38,9 @@ StaticMethods.simple() 1 java-methods/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 86 127 @@ -55,9 +55,9 @@ StaticMethods.withTypeParam[Any](a => ()) 2 java-methods/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 140 152 @@ -72,9 +72,9 @@ JavaObject() 3 java-methods/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 155 162 @@ -89,9 +89,9 @@ obj.f() 4 java-methods/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 165 194 @@ -106,9 +106,9 @@ println(obj.identity[Int](0)) 5 java-methods/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 173 193 @@ -123,9 +123,9 @@ obj.identity[Int](0) 6 java-methods/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 197 211 @@ -140,9 +140,9 @@ println("ok!") 7 java-methods/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 36 50 diff --git a/tests/coverage/run/lifting-bool/test.scoverage.check b/tests/coverage/run/lifting-bool/test.scoverage.check index 80d0bfad9c59..5eb3d864939f 100644 --- a/tests/coverage/run/lifting-bool/test.scoverage.check +++ b/tests/coverage/run/lifting-bool/test.scoverage.check @@ -21,9 +21,9 @@ 0 lifting-bool/test.scala -test$package$ +test$package Object -.test$package$ +.test$package notCalled 19 22 @@ -38,9 +38,9 @@ false 1 lifting-bool/test.scala -test$package$ +test$package Object -.test$package$ +.test$package notCalled 1 14 @@ -55,9 +55,9 @@ def notCalled 2 lifting-bool/test.scala -test$package$ +test$package Object -.test$package$ +.test$package f 24 29 @@ -72,9 +72,9 @@ def f 3 lifting-bool/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 109 120 @@ -89,9 +89,9 @@ notCalled() 4 lifting-bool/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 159 170 @@ -106,9 +106,9 @@ notCalled() 5 lifting-bool/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 219 230 @@ -123,9 +123,9 @@ notCalled() 6 lifting-bool/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 267 278 @@ -140,9 +140,9 @@ notCalled() 7 lifting-bool/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 318 329 @@ -157,9 +157,9 @@ notCalled() 8 lifting-bool/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 341 367 @@ -174,9 +174,9 @@ println(s"$a $b $c $d $e") 9 lifting-bool/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 349 366 @@ -191,9 +191,9 @@ s"$a $b $c $d $e" 10 lifting-bool/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 379 393 @@ -208,9 +208,9 @@ f(true, false) 11 lifting-bool/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 396 406 @@ -225,9 +225,9 @@ println(x) 12 lifting-bool/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 422 466 @@ -242,9 +242,9 @@ f(true || notCalled(), false && notCalled()) 13 lifting-bool/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 432 443 @@ -259,9 +259,9 @@ notCalled() 14 lifting-bool/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 454 465 @@ -276,9 +276,9 @@ notCalled() 15 lifting-bool/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 469 479 @@ -293,9 +293,9 @@ println(x) 16 lifting-bool/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 68 82 diff --git a/tests/coverage/run/lifting/test.scoverage.check b/tests/coverage/run/lifting/test.scoverage.check index 0c2ee042e912..136b8e2e4fbb 100644 --- a/tests/coverage/run/lifting/test.scoverage.check +++ b/tests/coverage/run/lifting/test.scoverage.check @@ -208,9 +208,9 @@ def ex 11 lifting/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 221 224 @@ -225,9 +225,9 @@ A() 12 lifting/test.scala -test$package$ +test$package Object -.test$package$ +.test$package f 241 246 @@ -242,9 +242,9 @@ def f 13 lifting/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 264 286 @@ -259,9 +259,9 @@ a.msg(i, 0, a.integer) 14 lifting/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 276 285 @@ -276,9 +276,9 @@ a.integer 15 lifting/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 289 299 @@ -293,9 +293,9 @@ println(x) 16 lifting/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 306 334 @@ -310,9 +310,9 @@ a.ex.msg(i, 0, a.ex.integer) 17 lifting/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 306 310 @@ -327,9 +327,9 @@ a.ex 18 lifting/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 321 325 @@ -344,9 +344,9 @@ a.ex 19 lifting/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 321 333 @@ -361,9 +361,9 @@ a.ex.integer 20 lifting/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 337 347 @@ -378,9 +378,9 @@ println(x) 21 lifting/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 354 370 @@ -395,9 +395,9 @@ a.msg(f(), 0, i) 22 lifting/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 360 363 @@ -412,9 +412,9 @@ f() 23 lifting/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 373 383 @@ -429,9 +429,9 @@ println(x) 24 lifting/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 188 202 diff --git a/tests/coverage/run/parameterless/test.scoverage.check b/tests/coverage/run/parameterless/test.scoverage.check index 6f15f3a5e93f..5050180e7886 100644 --- a/tests/coverage/run/parameterless/test.scoverage.check +++ b/tests/coverage/run/parameterless/test.scoverage.check @@ -21,9 +21,9 @@ 0 parameterless/test.scala -O$ +O Object -.O$ +.O f 32 46 @@ -38,9 +38,9 @@ println("O.f") 1 parameterless/test.scala -O$ +O Object -.O$ +.O f 12 17 @@ -55,9 +55,9 @@ def f 2 parameterless/test.scala -O$ +O Object -.O$ +.O g 87 101 @@ -72,9 +72,9 @@ println("O.g") 3 parameterless/test.scala -O$ +O Object -.O$ +.O g 64 69 @@ -89,9 +89,9 @@ def g 4 parameterless/test.scala -test$package$ +test$package Object -.test$package$ +.test$package f 162 174 @@ -106,9 +106,9 @@ println("f") 5 parameterless/test.scala -test$package$ +test$package Object -.test$package$ +.test$package f 142 147 @@ -123,9 +123,9 @@ def f 6 parameterless/test.scala -test$package$ +test$package Object -.test$package$ +.test$package g 213 225 @@ -140,9 +140,9 @@ println("g") 7 parameterless/test.scala -test$package$ +test$package Object -.test$package$ +.test$package g 190 195 @@ -157,9 +157,9 @@ def g 8 parameterless/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 249 250 @@ -174,9 +174,9 @@ f 9 parameterless/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 261 262 @@ -191,9 +191,9 @@ g 10 parameterless/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 265 275 @@ -208,9 +208,9 @@ println(f) 11 parameterless/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 273 274 @@ -225,9 +225,9 @@ f 12 parameterless/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 278 288 @@ -242,9 +242,9 @@ println(g) 13 parameterless/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 286 287 @@ -259,9 +259,9 @@ g 14 parameterless/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 291 303 @@ -276,9 +276,9 @@ println(O.f) 15 parameterless/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 299 302 @@ -293,9 +293,9 @@ O.f 16 parameterless/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 306 318 @@ -310,9 +310,9 @@ println(O.g) 17 parameterless/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 314 317 @@ -327,9 +327,9 @@ O.g 18 parameterless/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 117 131 diff --git a/tests/coverage/run/trait/test.scoverage.check b/tests/coverage/run/trait/test.scoverage.check index c5b6123e7e2b..19a88ebc7f6f 100644 --- a/tests/coverage/run/trait/test.scoverage.check +++ b/tests/coverage/run/trait/test.scoverage.check @@ -55,9 +55,9 @@ Impl2() 2 trait/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 170 188 @@ -72,9 +72,9 @@ println(Impl1().x) 3 trait/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 178 185 @@ -89,9 +89,9 @@ Impl1() 4 trait/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 178 187 @@ -106,9 +106,9 @@ Impl1().x 5 trait/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 196 214 @@ -123,9 +123,9 @@ println(Impl2().p) 6 trait/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 204 211 @@ -140,9 +140,9 @@ Impl2() 7 trait/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 225 243 @@ -157,9 +157,9 @@ println(Impl3().p) 8 trait/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 233 240 @@ -174,9 +174,9 @@ Impl3() 9 trait/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 145 159 diff --git a/tests/coverage/run/type-apply/test.scoverage.check b/tests/coverage/run/type-apply/test.scoverage.check index 6907a0aa516f..7d76b11f2f8b 100644 --- a/tests/coverage/run/type-apply/test.scoverage.check +++ b/tests/coverage/run/type-apply/test.scoverage.check @@ -21,9 +21,9 @@ 0 type-apply/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 163 201 @@ -38,9 +38,9 @@ println(List(1,2,3).map(a => List(a))) 1 type-apply/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 171 200 @@ -55,9 +55,9 @@ List(1,2,3).map(a => List(a)) 2 type-apply/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 171 182 @@ -72,9 +72,9 @@ List(1,2,3) 3 type-apply/test.scala -test$package$ +test$package Object -.test$package$ +.test$package $anonfun 192 199 @@ -89,9 +89,9 @@ List(a) 4 type-apply/test.scala -test$package$ +test$package Object -.test$package$ +.test$package Test 0 14 diff --git a/tests/coverage/run/varargs/test_1.scoverage.check b/tests/coverage/run/varargs/test_1.scoverage.check index 5b287586a540..3c31f9388409 100644 --- a/tests/coverage/run/varargs/test_1.scoverage.check +++ b/tests/coverage/run/varargs/test_1.scoverage.check @@ -21,9 +21,9 @@ 0 varargs/test_1.scala -test_1$package$ +test_1$package Object -.test_1$package$ +.test_1$package repeated 48 60 @@ -38,9 +38,9 @@ def repeated 1 varargs/test_1.scala -test_1$package$ +test_1$package Object -.test_1$package$ +.test_1$package f 79 84 @@ -55,9 +55,9 @@ def f 2 varargs/test_1.scala -test_1$package$ +test_1$package Object -.test_1$package$ +.test_1$package Test 120 130 @@ -72,9 +72,9 @@ repeated() 3 varargs/test_1.scala -test_1$package$ +test_1$package Object -.test_1$package$ +.test_1$package Test 133 153 @@ -89,9 +89,9 @@ repeated(f(""), "b") 4 varargs/test_1.scala -test_1$package$ +test_1$package Object -.test_1$package$ +.test_1$package Test 142 147 @@ -106,9 +106,9 @@ f("") 5 varargs/test_1.scala -test_1$package$ +test_1$package Object -.test_1$package$ +.test_1$package Test 156 178 @@ -123,9 +123,9 @@ JavaVarargs_1.method() 6 varargs/test_1.scala -test_1$package$ +test_1$package Object -.test_1$package$ +.test_1$package Test 181 205 @@ -140,9 +140,9 @@ JavaVarargs_1.method("") 7 varargs/test_1.scala -test_1$package$ +test_1$package Object -.test_1$package$ +.test_1$package Test 217 248 @@ -157,9 +157,9 @@ JavaVarargs_1.multiple("first") 8 varargs/test_1.scala -test_1$package$ +test_1$package Object -.test_1$package$ +.test_1$package Test 251 261 @@ -174,9 +174,9 @@ println(m) 9 varargs/test_1.scala -test_1$package$ +test_1$package Object -.test_1$package$ +.test_1$package Test 268 302 @@ -191,9 +191,9 @@ JavaVarargs_1.multiple(f("first")) 10 varargs/test_1.scala -test_1$package$ +test_1$package Object -.test_1$package$ +.test_1$package Test 291 301 @@ -208,9 +208,9 @@ f("first") 11 varargs/test_1.scala -test_1$package$ +test_1$package Object -.test_1$package$ +.test_1$package Test 305 315 @@ -225,9 +225,9 @@ println(m) 12 varargs/test_1.scala -test_1$package$ +test_1$package Object -.test_1$package$ +.test_1$package Test 322 371 @@ -242,9 +242,9 @@ JavaVarargs_1.multiple(f("first"), "a", "b", "c") 13 varargs/test_1.scala -test_1$package$ +test_1$package Object -.test_1$package$ +.test_1$package Test 345 355 @@ -259,9 +259,9 @@ f("first") 14 varargs/test_1.scala -test_1$package$ +test_1$package Object -.test_1$package$ +.test_1$package Test 374 384 @@ -276,9 +276,9 @@ println(m) 15 varargs/test_1.scala -test_1$package$ +test_1$package Object -.test_1$package$ +.test_1$package Test 101 115 From 9895daa6d02da544e534f160e0bac1bf33849a44 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 5 Jan 2024 09:58:17 +0100 Subject: [PATCH 038/220] Move `scala2-library-tasty-tests/run` tests to `tests/run/scala2-library-test` The `tests/run/scala2-library-test` test will be tested with the original Scala 2 library JAR and with the Scala 2 library TASTy JAR depending on the `scala2Library` SBT setting. --- .github/workflows/ci.yaml | 4 ++-- docs/_docs/contributing/testing.md | 9 +-------- .../src => tests/run/scala2-library-test}/Main.scala | 7 ++++--- .../run/scala2-library-test}/UnrolledBufferTest.scala | 0 4 files changed, 7 insertions(+), 13 deletions(-) rename {scala2-library-tasty-tests/src => tests/run/scala2-library-test}/Main.scala (92%) rename {scala2-library-tasty-tests/src => tests/run/scala2-library-test}/UnrolledBufferTest.scala (100%) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index acfd1b978886..2cbce1766a0b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -136,7 +136,7 @@ jobs: - name: Cmd Tests run: | - ./project/scripts/sbt ";dist/pack; scala3-bootstrapped/compile; scala3-bootstrapped/test ;sbt-test/scripted scala2-compat/* ;scala2-library-tasty-tests/run ;scala2-library-tasty-tests/test; scala3-compiler-bootstrapped/scala3CompilerCoursierTest:test" + ./project/scripts/sbt ";dist/pack; scala3-bootstrapped/compile; scala3-bootstrapped/test ;sbt-test/scripted scala2-compat/*; scala2-library-tasty-tests/test; scala3-compiler-bootstrapped/scala3CompilerCoursierTest:test" ./project/scripts/cmdTests ./project/scripts/bootstrappedOnlyCmdTests @@ -547,7 +547,7 @@ jobs: - name: Test run: | - ./project/scripts/sbt ";dist/pack ;scala3-bootstrapped/compile ;scala3-bootstrapped/test ;sbt-test/scripted scala2-compat/* ;scala2-library-tasty-tests/run ;scala2-library-tasty-tests/test" + ./project/scripts/sbt ";dist/pack ;scala3-bootstrapped/compile ;scala3-bootstrapped/test ;sbt-test/scripted scala2-compat/*; scala2-library-tasty-tests/test" ./project/scripts/cmdTests ./project/scripts/bootstrappedOnlyCmdTests diff --git a/docs/_docs/contributing/testing.md b/docs/_docs/contributing/testing.md index 84ce4053f124..3f3e5421b9bd 100644 --- a/docs/_docs/contributing/testing.md +++ b/docs/_docs/contributing/testing.md @@ -164,14 +164,7 @@ to load the TASTy and the runtime to load the original classfiles. The library is compiled in `scala2-library-bootstrapped` with TASTy and classfiles. These classfiles should not be used. The `scala2-library-tasty` project repackages the -JAR `scala2-library-bootstrapped` to only keep TASTy files. The `scala2-library-tasty-tests` provides some basic tests using the library TASTy JAR. - -``` -$ sbt -> scala2-library-tasty/compile -> scala2-library-tasty-tests/run -> scala2-library-tasty-tests/test -``` +JAR `scala2-library-bootstrapped` to only keep TASTy files. We can enable this library in the build using the SBT setting `useScala2LibraryTasty`. This setting can only be used by bootstrapped compiler tests and is currently only supported for `test` (or `testCompilation`) and `scalac` (or `run`). diff --git a/scala2-library-tasty-tests/src/Main.scala b/tests/run/scala2-library-test/Main.scala similarity index 92% rename from scala2-library-tasty-tests/src/Main.scala rename to tests/run/scala2-library-test/Main.scala index b33219271201..0629d5de6b7e 100644 --- a/scala2-library-tasty-tests/src/Main.scala +++ b/tests/run/scala2-library-test/Main.scala @@ -1,4 +1,5 @@ -package hello +// This tests language features that have a special handling in the Scala 2 library TASTy. +// These should behave the same way from if compiled against the Scala 2 library class files ot TASTy. import scala.util.* import scala.compiletime.testing.typeChecks @@ -6,7 +7,7 @@ import scala.compiletime.testing.typeChecks enum Color: case Red, Green, Blue -object HelloWorld: +object Test: def main(args: Array[String]): Unit = { println("hello 2.13 library bootstrapped") println(Color.Red) @@ -74,4 +75,4 @@ object HelloWorld: new collection.ArrayOps[String](Array[String]("foo")).exists(x => true) } -end HelloWorld +end Test diff --git a/scala2-library-tasty-tests/src/UnrolledBufferTest.scala b/tests/run/scala2-library-test/UnrolledBufferTest.scala similarity index 100% rename from scala2-library-tasty-tests/src/UnrolledBufferTest.scala rename to tests/run/scala2-library-test/UnrolledBufferTest.scala From 708e64085f28462f2636f032edbafab05ceb3f36 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Tue, 26 Dec 2023 16:24:32 -0800 Subject: [PATCH 039/220] Don't explain erroneous bounds --- .../dotty/tools/dotc/reporting/Message.scala | 18 ++++++++---------- tests/neg/i19334.check | 12 ++++++++++++ tests/neg/i19334.scala | 6 ++++++ 3 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 tests/neg/i19334.check create mode 100644 tests/neg/i19334.scala diff --git a/compiler/src/dotty/tools/dotc/reporting/Message.scala b/compiler/src/dotty/tools/dotc/reporting/Message.scala index f9abead161d2..1ac5c6ecf407 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Message.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Message.scala @@ -76,8 +76,7 @@ object Message: * and following recordings get consecutive superscripts starting with 2. * @return The possibly superscripted version of `str`. */ - def record(str: String, isType: Boolean, entry: Recorded)(using Context): String = - if !recordOK then return str + def record(str: String, isType: Boolean, entry: Recorded)(using Context): String = if !recordOK then str else //println(s"recording $str, $isType, $entry") /** If `e1` is an alias of another class of the same name, return the other @@ -146,7 +145,7 @@ object Message: } def addendum(cat: String, info: Type): String = info match { - case bounds @ TypeBounds(lo, hi) if !(bounds =:= TypeBounds.empty) => + case bounds @ TypeBounds(lo, hi) if !(bounds =:= TypeBounds.empty) && !bounds.isErroneous => if (lo eq hi) i" which is an alias of $lo" else i" with $cat ${boundsStr(bounds)}" case _ => @@ -176,9 +175,8 @@ object Message: def needsExplanation(entry: Recorded) = entry match { case param: TypeParamRef => ctx.typerState.constraint.contains(param) case param: ParamRef => false - case skolem: SkolemType => true - case sym: Symbol => - ctx.gadt.contains(sym) && ctx.gadt.fullBounds(sym) != TypeBounds.empty + case skolem: SkolemType => true + case sym: Symbol => ctx.gadt.contains(sym) && ctx.gadt.fullBounds(sym) != TypeBounds.empty } val toExplain: List[(String, Recorded)] = seen.toList.flatMap { kvs => @@ -191,7 +189,7 @@ object Message: (tickedString, alt) } } - res // help the inferrencer out + res // help the inferencer out }.sortBy(_._1) def columnar(parts: List[(String, String)]): List[String] = { @@ -270,11 +268,11 @@ end Message * * Messages modify the rendendering of interpolated strings in several ways: * - * 1. The size of the printed code is limited with a MessafeLimiter. If the message + * 1. The size of the printed code is limited with a MessageLimiter. If the message * would get too large or too deeply nested, a `...` is printed instead. - * 2. References to module classes are prefixed with `object ` for better recogniability. + * 2. References to module classes are prefixed with `object` for better recognizability. * 3. A where clause is sometimes added which contains the following additional explanations: - * - Rerences are disambiguated: If a message contains occurrences of the same identifier + * - References are disambiguated: If a message contains occurrences of the same identifier * representing different symbols, the duplicates are printed with superscripts * and the where-clause explains where each symbol is located. * - Uninstantiated variables are explained in the where-clause with additional diff --git a/tests/neg/i19334.check b/tests/neg/i19334.check new file mode 100644 index 000000000000..8c0b6b3c299e --- /dev/null +++ b/tests/neg/i19334.check @@ -0,0 +1,12 @@ +-- [E081] Type Error: tests/neg/i19334.scala:6:4 ----------------------------------------------------------------------- +6 | f(_) // error was OOM formatting TypeVar(TypeParamRef(T)) when offering explanations + | ^ + | Missing parameter type + | + | I could not infer the type of the parameter _$1 + | in expanded function: + | _$1 => f(_$1) + | Expected type for the whole anonymous function: + | T + | + | where: T is a type variable diff --git a/tests/neg/i19334.scala b/tests/neg/i19334.scala new file mode 100644 index 000000000000..cd6af1872241 --- /dev/null +++ b/tests/neg/i19334.scala @@ -0,0 +1,6 @@ + +def foo[T](f: T): T = ??? + +@main def main = foo: + def f() = () + f(_) // error was OOM formatting TypeVar(TypeParamRef(T)) when offering explanations From 02b4ec70422ff10f928cea8082de0d7f57fd4378 Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 20 Dec 2023 20:08:57 +0100 Subject: [PATCH 040/220] Make explicit arguments for context bounds an error from 3.5 --- .../src/dotty/tools/dotc/ast/Desugar.scala | 3 +- .../dotty/tools/dotc/typer/Migrations.scala | 61 +++++++++++++++++++ .../src/dotty/tools/dotc/typer/Typer.scala | 29 ++------- tests/neg/context-bounds-migration.scala | 10 +++ tests/neg/hidden-type-errors.check | 26 ++++++++ 5 files changed, 105 insertions(+), 24 deletions(-) create mode 100644 compiler/src/dotty/tools/dotc/typer/Migrations.scala create mode 100644 tests/neg/context-bounds-migration.scala diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 3386dc7d7a6c..36f2d593de1c 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -674,7 +674,8 @@ object desugar { val nu = vparamss.foldLeft(makeNew(classTypeRef)) { (nu, vparams) => val app = Apply(nu, vparams.map(refOfDef)) vparams match { - case vparam :: _ if vparam.mods.is(Given) => app.setApplyKind(ApplyKind.Using) + case vparam :: _ if vparam.mods.is(Given) || vparam.name.is(ContextBoundParamName) => + app.setApplyKind(ApplyKind.Using) case _ => app } } diff --git a/compiler/src/dotty/tools/dotc/typer/Migrations.scala b/compiler/src/dotty/tools/dotc/typer/Migrations.scala new file mode 100644 index 000000000000..284ec1d18799 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/typer/Migrations.scala @@ -0,0 +1,61 @@ +package dotty.tools +package dotc +package typer + +import core.* +import ast.* +import Contexts.* +import Types.* +import Flags.* +import Names.* +import StdNames.* +import Symbols.* +import Trees.* +import ProtoTypes.* +import Decorators.* +import config.MigrationVersion +import config.Feature.{sourceVersion, migrateTo3} +import config.SourceVersion.* +import reporting.* +import NameKinds.ContextBoundParamName +import rewrites.Rewrites.patch +import util.Spans.Span + +/** A utility module containing source-dependent deprecation messages + * and migrations + */ +object Migrations: + + import tpd.* + + /** Flag & migrate `?` used as a higher-kinded type parameter + * Warning in 3.0-migration, error from 3.0 + */ + def migrateKindProjectorQMark(tree: untpd.TypeDef, sym: Symbol)(using Context): Unit = + if tree.name eq tpnme.? then + val addendum = if sym.owner.is(TypeParam) + then ", use `_` to denote a higher-kinded type parameter" + else "" + val namePos = tree.sourcePos.withSpan(tree.nameSpan) + report.errorOrMigrationWarning( + em"`?` is not a valid type name$addendum", namePos, MigrationVersion.Scala2to3) + + /** Flag & migrate explicit normal arguments to parameters coming from context bounds + * Warning in 3.4, error in 3.5, rewrite in 3.5-migration. + */ + def migrateContextBoundParams(tree: Tree, tp: Type, pt: FunProto)(using Context): Unit = + def isContextBoundParams = tp.stripPoly match + case MethodType(ContextBoundParamName(_) :: _) => true + case _ => false + if sourceVersion.isAtLeast(`3.4`) + && isContextBoundParams + && pt.applyKind != ApplyKind.Using + then + def rewriteMsg = Message.rewriteNotice("This code", `3.5-migration`) + report.errorOrMigrationWarning( + em"""Context bounds will map to context parameters. + |A `using` clause is needed to pass explicit arguments to them.$rewriteMsg""", + tree.srcPos, MigrationVersion(`3.4`, `3.5`)) + if sourceVersion.isAtLeast(`3.5-migration`) then + patch(Span(pt.args.head.span.start), "using ") + end migrateContextBoundParams diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 2f03c79754e8..50e5b22fabe0 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -51,6 +51,7 @@ import NullOpsDecorator.* import cc.CheckCaptures import config.Config import config.MigrationVersion +import Migrations.* import scala.annotation.constructorOnly import dotty.tools.dotc.rewrites.Rewrites @@ -3137,13 +3138,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer case tree: untpd.TypeDef => // separate method to keep dispatching method `typedNamed` short which might help the JIT def typedTypeOrClassDef: Tree = - if tree.name eq tpnme.? then - val addendum = if sym.owner.is(TypeParam) - then ", use `_` to denote a higher-kinded type parameter" - else "" - val namePos = tree.sourcePos.withSpan(tree.nameSpan) - report.errorOrMigrationWarning( - em"`?` is not a valid type name$addendum", namePos, MigrationVersion.Scala2to3) + migrateKindProjectorQMark(tree, sym) if tree.isClassDef then typedClassDef(tree, sym.asClass)(using ctx.localContext(tree, sym)) else @@ -3818,24 +3813,12 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer def adaptToArgs(wtp: Type, pt: FunProto): Tree = wtp match { case wtp: MethodOrPoly => def methodStr = methPart(tree).symbol.showLocated - if (matchingApply(wtp, pt)) + if matchingApply(wtp, pt) then + migrateContextBoundParams(tree, wtp, pt) if needsTupledDual(wtp, pt) then adapt(tree, pt.tupledDual, locked) else tree else if wtp.isContextualMethod then - def isContextBoundParams = wtp.stripPoly match - case MethodType(ContextBoundParamName(_) :: _) => true - case _ => false - if sourceVersion == `future-migration` && isContextBoundParams && pt.args.nonEmpty - then // Under future-migration, don't infer implicit arguments yet for parameters - // coming from context bounds. Issue a warning instead and offer a patch. - def rewriteMsg = Message.rewriteNotice("This code", `future-migration`) - report.migrationWarning( - em"""Context bounds will map to context parameters. - |A `using` clause is needed to pass explicit arguments to them.$rewriteMsg""", tree.srcPos) - patch(Span(pt.args.head.span.start), "using ") - tree - else - adaptNoArgs(wtp) // insert arguments implicitly + adaptNoArgs(wtp) // insert arguments implicitly else if (tree.symbol.isPrimaryConstructor && tree.symbol.info.firstParamTypes.isEmpty) readapt(tree.appliedToNone) // insert () to primary constructors else @@ -4441,7 +4424,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer protected def matchingApply(methType: MethodOrPoly, pt: FunProto)(using Context): Boolean = val isUsingApply = pt.applyKind == ApplyKind.Using methType.isContextualMethod == isUsingApply - || methType.isImplicitMethod && isUsingApply // for a transition allow `with` arguments for regular implicit parameters + || methType.isImplicitMethod && isUsingApply // for a transition allow `using` arguments for regular implicit parameters /** Check that `tree == x: pt` is typeable. Used when checking a pattern * against a selector of type `pt`. This implementation accounts for diff --git a/tests/neg/context-bounds-migration.scala b/tests/neg/context-bounds-migration.scala new file mode 100644 index 000000000000..b27dc884692c --- /dev/null +++ b/tests/neg/context-bounds-migration.scala @@ -0,0 +1,10 @@ +//> using options -Xfatal-warnings + +class C[T] +def foo[X: C] = () + +given [T]: C[T] = C[T]() + +def Test = + foo(C[Int]()) // error + foo(using C[Int]()) // ok diff --git a/tests/neg/hidden-type-errors.check b/tests/neg/hidden-type-errors.check index 2f4a1748dc67..2cf77134c2c5 100644 --- a/tests/neg/hidden-type-errors.check +++ b/tests/neg/hidden-type-errors.check @@ -1,3 +1,16 @@ +-- Warning: tests/neg/hidden-type-errors/Test.scala:8:24 --------------------------------------------------------------- + 8 | val x = X.doSomething("XXX") // error + | ^^^^^^^^^^^^^^^^^^^^ + | Context bounds will map to context parameters. + | A `using` clause is needed to pass explicit arguments to them. + | This code can be rewritten automatically under -rewrite -source 3.5-migration. + |-------------------------------------------------------------------------------------------------------------------- + |Inline stack trace + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + |This location contains code that was inlined from Macro.scala:15 +15 | doSomethingImpl('x) + | ^^^^^^^^^^^^^^^^^^^ + -------------------------------------------------------------------------------------------------------------------- -- [E007] Type Mismatch Error: tests/neg/hidden-type-errors/Test.scala:8:24 -------------------------------------------- 8 | val x = X.doSomething("XXX") // error | ^^^^^^^^^^^^^^^^^^^^ @@ -18,3 +31,16 @@ | | The tests were made under the empty constraint --------------------------------------------------------------------------------------------------------------------- +-- Warning: tests/neg/hidden-type-errors/Test.scala:8:24 --------------------------------------------------------------- + 8 | val x = X.doSomething("XXX") // error + | ^^^^^^^^^^^^^^^^^^^^ + | Context bounds will map to context parameters. + | A `using` clause is needed to pass explicit arguments to them. + | This code can be rewritten automatically under -rewrite -source 3.5-migration. + |-------------------------------------------------------------------------------------------------------------------- + |Inline stack trace + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + |This location contains code that was inlined from Macro.scala:15 +15 | doSomethingImpl('x) + | ^^^^^^^^^^^^^^^^^^^ + -------------------------------------------------------------------------------------------------------------------- From 41311bfa78078ea6859017010f4d992ce57e1f04 Mon Sep 17 00:00:00 2001 From: odersky Date: Thu, 21 Dec 2023 16:49:30 +0100 Subject: [PATCH 041/220] Don't run migration operations in ReTypers --- .../dotty/tools/dotc/typer/Migrations.scala | 59 +++++++++++++++++-- .../src/dotty/tools/dotc/typer/ReTyper.scala | 1 + .../src/dotty/tools/dotc/typer/Typer.scala | 58 ++++-------------- 3 files changed, 64 insertions(+), 54 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Migrations.scala b/compiler/src/dotty/tools/dotc/typer/Migrations.scala index 284ec1d18799..9c038abbd851 100644 --- a/compiler/src/dotty/tools/dotc/typer/Migrations.scala +++ b/compiler/src/dotty/tools/dotc/typer/Migrations.scala @@ -20,18 +20,20 @@ import reporting.* import NameKinds.ContextBoundParamName import rewrites.Rewrites.patch import util.Spans.Span +import rewrites.Rewrites -/** A utility module containing source-dependent deprecation messages - * and migrations +/** A utility trait containing source-dependent deprecation messages + * and migrations. */ -object Migrations: +trait Migrations: + this: Typer => import tpd.* /** Flag & migrate `?` used as a higher-kinded type parameter * Warning in 3.0-migration, error from 3.0 */ - def migrateKindProjectorQMark(tree: untpd.TypeDef, sym: Symbol)(using Context): Unit = + def kindProjectorQMark(tree: untpd.TypeDef, sym: Symbol)(using Context): Unit = if tree.name eq tpnme.? then val addendum = if sym.owner.is(TypeParam) then ", use `_` to denote a higher-kinded type parameter" @@ -40,10 +42,53 @@ object Migrations: report.errorOrMigrationWarning( em"`?` is not a valid type name$addendum", namePos, MigrationVersion.Scala2to3) + def typedAsFunction(tree: untpd.PostfixOp, pt: Type)(using Context): Tree = { + val untpd.PostfixOp(qual, Ident(nme.WILDCARD)) = tree: @unchecked + val pt1 = if (defn.isFunctionNType(pt)) pt else AnyFunctionProto + val nestedCtx = ctx.fresh.setNewTyperState() + val res = typed(qual, pt1)(using nestedCtx) + res match { + case closure(_, _, _) => + case _ => + val recovered = typed(qual)(using ctx.fresh.setExploreTyperState()) + val msg = OnlyFunctionsCanBeFollowedByUnderscore(recovered.tpe.widen, tree) + report.errorOrMigrationWarning(msg, tree.srcPos, MigrationVersion.Scala2to3) + if MigrationVersion.Scala2to3.needsPatch then + // Under -rewrite, patch `x _` to `(() => x)` + msg.actions + .headOption + .foreach(Rewrites.applyAction) + return typed(untpd.Function(Nil, qual), pt) + } + nestedCtx.typerState.commit() + + lazy val (prefix, suffix) = res match { + case Block(mdef @ DefDef(_, vparams :: Nil, _, _) :: Nil, _: Closure) => + val arity = vparams.length + if (arity > 0) ("", "") else ("(() => ", "())") + case _ => + ("(() => ", ")") + } + def remedy = + if ((prefix ++ suffix).isEmpty) "simply leave out the trailing ` _`" + else s"use `$prefix$suffix` instead" + def rewrite = Message.rewriteNotice("This construct", `3.4-migration`) + report.errorOrMigrationWarning( + em"""The syntax ` _` is no longer supported; + |you can $remedy$rewrite""", + tree.srcPos, + MigrationVersion.FunctionUnderscore) + if MigrationVersion.FunctionUnderscore.needsPatch then + patch(Span(tree.span.start), prefix) + patch(Span(qual.span.end, tree.span.end), suffix) + + res + } + /** Flag & migrate explicit normal arguments to parameters coming from context bounds * Warning in 3.4, error in 3.5, rewrite in 3.5-migration. */ - def migrateContextBoundParams(tree: Tree, tp: Type, pt: FunProto)(using Context): Unit = + def contextBoundParams(tree: Tree, tp: Type, pt: FunProto)(using Context): Unit = def isContextBoundParams = tp.stripPoly match case MethodType(ContextBoundParamName(_) :: _) => true case _ => false @@ -58,4 +103,6 @@ object Migrations: tree.srcPos, MigrationVersion(`3.4`, `3.5`)) if sourceVersion.isAtLeast(`3.5-migration`) then patch(Span(pt.args.head.span.start), "using ") - end migrateContextBoundParams + end contextBoundParams + +end Migrations diff --git a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala index e152b5e6b9c7..253c4fda9396 100644 --- a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala +++ b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala @@ -189,4 +189,5 @@ class ReTyper(nestingLevel: Int = 0) extends Typer(nestingLevel) with ReChecking override protected def checkEqualityEvidence(tree: tpd.Tree, pt: Type)(using Context): Unit = () override protected def matchingApply(methType: MethodOrPoly, pt: FunProto)(using Context): Boolean = true override protected def typedScala2MacroBody(call: untpd.Tree)(using Context): Tree = promote(call) + override protected def migrate[T](migration: => T, disabled: => T = ()): T = disabled } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 50e5b22fabe0..5cb42f659551 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -43,7 +43,7 @@ import config.Printers.{gadts, typr} import config.Feature import config.Feature.{sourceVersion, migrateTo3} import config.SourceVersion.* -import rewrites.Rewrites.patch +import rewrites.Rewrites, Rewrites.patch import staging.StagingLevel import reporting.* import Nullables.* @@ -51,10 +51,8 @@ import NullOpsDecorator.* import cc.CheckCaptures import config.Config import config.MigrationVersion -import Migrations.* import scala.annotation.constructorOnly -import dotty.tools.dotc.rewrites.Rewrites object Typer { @@ -128,7 +126,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer with Dynamic with Checking with QuotesAndSplices - with Deriving { + with Deriving + with Migrations { import Typer.* import tpd.{cpy => _, _} @@ -159,6 +158,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer // Overridden in derived typers def newLikeThis(nestingLevel: Int): Typer = new Typer(nestingLevel) + // Overridden to do nothing in derived typers + protected def migrate[T](migration: => T, disabled: => T = ()): T = migration + /** Find the type of an identifier with given `name` in given context `ctx`. * @param name the name of the identifier * @param pt the expected type @@ -2979,48 +2981,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer else tree1 } - def typedAsFunction(tree: untpd.PostfixOp, pt: Type)(using Context): Tree = { - val untpd.PostfixOp(qual, Ident(nme.WILDCARD)) = tree: @unchecked - val pt1 = if (defn.isFunctionNType(pt)) pt else AnyFunctionProto - val nestedCtx = ctx.fresh.setNewTyperState() - val res = typed(qual, pt1)(using nestedCtx) - res match { - case closure(_, _, _) => - case _ => - val recovered = typed(qual)(using ctx.fresh.setExploreTyperState()) - val msg = OnlyFunctionsCanBeFollowedByUnderscore(recovered.tpe.widen, tree) - report.errorOrMigrationWarning(msg, tree.srcPos, MigrationVersion.Scala2to3) - if MigrationVersion.Scala2to3.needsPatch then - // Under -rewrite, patch `x _` to `(() => x)` - msg.actions - .headOption - .foreach(Rewrites.applyAction) - return typed(untpd.Function(Nil, qual), pt) - } - nestedCtx.typerState.commit() - - lazy val (prefix, suffix) = res match { - case Block(mdef @ DefDef(_, vparams :: Nil, _, _) :: Nil, _: Closure) => - val arity = vparams.length - if (arity > 0) ("", "") else ("(() => ", "())") - case _ => - ("(() => ", ")") - } - def remedy = - if ((prefix ++ suffix).isEmpty) "simply leave out the trailing ` _`" - else s"use `$prefix$suffix` instead" - def rewrite = Message.rewriteNotice("This construct", `3.4-migration`) - report.errorOrMigrationWarning( - em"""The syntax ` _` is no longer supported; - |you can $remedy$rewrite""", - tree.srcPos, - MigrationVersion.FunctionUnderscore) - if MigrationVersion.FunctionUnderscore.needsPatch then - patch(Span(tree.span.start), prefix) - patch(Span(qual.span.end, tree.span.end), suffix) - - res - } + override def typedAsFunction(tree: untpd.PostfixOp, pt: Type)(using Context): Tree = + migrate(super.typedAsFunction(tree, pt), throw new AssertionError("can't retype a PostfixOp")) /** Translate infix operation expression `l op r` to * @@ -3138,7 +3100,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer case tree: untpd.TypeDef => // separate method to keep dispatching method `typedNamed` short which might help the JIT def typedTypeOrClassDef: Tree = - migrateKindProjectorQMark(tree, sym) + migrate(kindProjectorQMark(tree, sym)) if tree.isClassDef then typedClassDef(tree, sym.asClass)(using ctx.localContext(tree, sym)) else @@ -3814,7 +3776,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer case wtp: MethodOrPoly => def methodStr = methPart(tree).symbol.showLocated if matchingApply(wtp, pt) then - migrateContextBoundParams(tree, wtp, pt) + migrate(contextBoundParams(tree, wtp, pt)) if needsTupledDual(wtp, pt) then adapt(tree, pt.tupledDual, locked) else tree else if wtp.isContextualMethod then From 697f107cec7608cc4c8d351ada885a312ad4a742 Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 23 Dec 2023 16:14:56 +0100 Subject: [PATCH 042/220] Fix test --- tests/neg/hidden-type-errors.check | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/tests/neg/hidden-type-errors.check b/tests/neg/hidden-type-errors.check index 2cf77134c2c5..2f4a1748dc67 100644 --- a/tests/neg/hidden-type-errors.check +++ b/tests/neg/hidden-type-errors.check @@ -1,16 +1,3 @@ --- Warning: tests/neg/hidden-type-errors/Test.scala:8:24 --------------------------------------------------------------- - 8 | val x = X.doSomething("XXX") // error - | ^^^^^^^^^^^^^^^^^^^^ - | Context bounds will map to context parameters. - | A `using` clause is needed to pass explicit arguments to them. - | This code can be rewritten automatically under -rewrite -source 3.5-migration. - |-------------------------------------------------------------------------------------------------------------------- - |Inline stack trace - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from Macro.scala:15 -15 | doSomethingImpl('x) - | ^^^^^^^^^^^^^^^^^^^ - -------------------------------------------------------------------------------------------------------------------- -- [E007] Type Mismatch Error: tests/neg/hidden-type-errors/Test.scala:8:24 -------------------------------------------- 8 | val x = X.doSomething("XXX") // error | ^^^^^^^^^^^^^^^^^^^^ @@ -31,16 +18,3 @@ | | The tests were made under the empty constraint --------------------------------------------------------------------------------------------------------------------- --- Warning: tests/neg/hidden-type-errors/Test.scala:8:24 --------------------------------------------------------------- - 8 | val x = X.doSomething("XXX") // error - | ^^^^^^^^^^^^^^^^^^^^ - | Context bounds will map to context parameters. - | A `using` clause is needed to pass explicit arguments to them. - | This code can be rewritten automatically under -rewrite -source 3.5-migration. - |-------------------------------------------------------------------------------------------------------------------- - |Inline stack trace - |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |This location contains code that was inlined from Macro.scala:15 -15 | doSomethingImpl('x) - | ^^^^^^^^^^^^^^^^^^^ - -------------------------------------------------------------------------------------------------------------------- From 786852c9e6314d207cad9e25ae57dca60e7a7dd8 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 3 Jan 2024 09:27:56 +0100 Subject: [PATCH 043/220] Fix context bound application in enum desugaring --- compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala index 98873dba85c7..7268ec720ce2 100644 --- a/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala +++ b/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala @@ -99,7 +99,7 @@ object DesugarEnums { val clazzOf = TypeApply(ref(defn.Predef_classOf.termRef), tpt :: Nil) val ctag = Apply(TypeApply(ref(defn.ClassTagModule_apply.termRef), tpt :: Nil), clazzOf :: Nil) val apply = Select(ref(defn.ArrayModule.termRef), nme.apply) - Apply(Apply(TypeApply(apply, tpt :: Nil), values), ctag :: Nil) + Apply(Apply(TypeApply(apply, tpt :: Nil), values), ctag :: Nil).setApplyKind(ApplyKind.Using) /** The following lists of definitions for an enum type E and known value cases e_0, ..., e_n: * From e60aa9eeaca4993f2c8dc8b89c76baca40112efe Mon Sep 17 00:00:00 2001 From: odersky Date: Sun, 7 Jan 2024 12:39:09 +0100 Subject: [PATCH 044/220] Turn given loop prevention on for -source future Drop the experimental language import. I believe everybody agrees that this is a desirable improvement, and type inference and implicit search have traditionally been in the realm of the compiler implementers. Experimental language imports have to live forever (albeit as deprecated once the feature is accepted as standard). So they are rather heavyweight and it is unergonomic to require them for smallish improvements to type inference. The new road map is as follows: - In 3.4: warning if behavior would change in the future. - In 3.5: error if behavior would change in the future - In 3.future (at the earliest 3.6): new behavior. --- .../src/dotty/tools/dotc/config/Feature.scala | 1 - .../dotty/tools/dotc/typer/Implicits.scala | 5 ++- .../runtime/stdLibPatches/language.scala | 9 ---- tests/neg/i15474.check | 44 ++++++++++--------- tests/neg/i6716.check | 21 ++++----- tests/neg/i7294-a.check | 3 +- tests/pos/i15474.scala | 2 +- tests/pos/looping-givens.scala | 2 +- tests/run/i6716.scala | 6 +-- 9 files changed, 43 insertions(+), 50 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/Feature.scala b/compiler/src/dotty/tools/dotc/config/Feature.scala index cdd83b15f4fc..fa262a5880ff 100644 --- a/compiler/src/dotty/tools/dotc/config/Feature.scala +++ b/compiler/src/dotty/tools/dotc/config/Feature.scala @@ -33,7 +33,6 @@ object Feature: val pureFunctions = experimental("pureFunctions") val captureChecking = experimental("captureChecking") val into = experimental("into") - val givenLoopPrevention = experimental("givenLoopPrevention") val globalOnlyImports: Set[TermName] = Set(pureFunctions, captureChecking) diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 1672c94fd969..37086cff0b4c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -1595,7 +1595,7 @@ trait Implicits: def checkResolutionChange(result: SearchResult) = if (eligible ne preEligible) - && !Feature.enabled(Feature.givenLoopPrevention) + && !sourceVersion.isAtLeast(SourceVersion.future) then val prevResult = searchImplicit(preEligible, contextual) prevResult match @@ -1621,7 +1621,8 @@ trait Implicits: |Current result ${showResult(prevResult)} will be no longer eligible | because it is not defined before the search position. |Result with new rules: ${showResult(result)}. - |To opt into the new rules, use the `experimental.givenLoopPrevention` language import. + |To opt into the new rules, compile with `-source future` or use + |the `scala.language.future` language import. | |To fix the problem without the language import, you could try one of the following: | - use a `given ... with` clause as the enclosing given, diff --git a/library/src/scala/runtime/stdLibPatches/language.scala b/library/src/scala/runtime/stdLibPatches/language.scala index ae323befa1a4..c37555f26653 100644 --- a/library/src/scala/runtime/stdLibPatches/language.scala +++ b/library/src/scala/runtime/stdLibPatches/language.scala @@ -91,15 +91,6 @@ object language: @compileTimeOnly("`into` can only be used at compile time in import statements") object into - /** Experimental support for new given resolution rules that avoid looping - * givens. By the new rules, a given may not implicitly use itself or givens - * defined after it. - * - * @see [[https://dotty.epfl.ch/docs/reference/experimental/given-loop-prevention]] - */ - @compileTimeOnly("`givenLoopPrevention` can only be used at compile time in import statements") - object givenLoopPrevention - /** Was needed to add support for relaxed imports of extension methods. * The language import is no longer needed as this is now a standard feature since SIP was accepted. * @see [[http://dotty.epfl.ch/docs/reference/contextual/extension-methods]] diff --git a/tests/neg/i15474.check b/tests/neg/i15474.check index 6a60aed304aa..3205f703cd50 100644 --- a/tests/neg/i15474.check +++ b/tests/neg/i15474.check @@ -1,29 +1,31 @@ -- Error: tests/neg/i15474.scala:6:39 ---------------------------------------------------------------------------------- 6 | given c: Conversion[ String, Int ] = _.toInt // error | ^ - | Result of implicit search for ?{ toInt: ? } will change. - | Current result Test2.c will be no longer eligible - | because it is not defined before the search position. - | Result with new rules: augmentString. - | To opt into the new rules, use the `experimental.givenLoopPrevention` language import. + | Result of implicit search for ?{ toInt: ? } will change. + | Current result Test2.c will be no longer eligible + | because it is not defined before the search position. + | Result with new rules: augmentString. + | To opt into the new rules, compile with `-source future` or use + | the `scala.language.future` language import. | - | To fix the problem without the language import, you could try one of the following: - | - use a `given ... with` clause as the enclosing given, - | - rearrange definitions so that Test2.c comes earlier, - | - use an explicit conversion, - | - use an import to get extension method into scope. - | This will be an error in Scala 3.5 and later. + | To fix the problem without the language import, you could try one of the following: + | - use a `given ... with` clause as the enclosing given, + | - rearrange definitions so that Test2.c comes earlier, + | - use an explicit conversion, + | - use an import to get extension method into scope. + | This will be an error in Scala 3.5 and later. -- Error: tests/neg/i15474.scala:12:56 --------------------------------------------------------------------------------- 12 | given Ordering[Price] = summon[Ordering[BigDecimal]] // error | ^ - | Result of implicit search for Ordering[BigDecimal] will change. - | Current result Prices.Price.given_Ordering_Price will be no longer eligible - | because it is not defined before the search position. - | Result with new rules: scala.math.Ordering.BigDecimal. - | To opt into the new rules, use the `experimental.givenLoopPrevention` language import. + | Result of implicit search for Ordering[BigDecimal] will change. + | Current result Prices.Price.given_Ordering_Price will be no longer eligible + | because it is not defined before the search position. + | Result with new rules: scala.math.Ordering.BigDecimal. + | To opt into the new rules, compile with `-source future` or use + | the `scala.language.future` language import. | - | To fix the problem without the language import, you could try one of the following: - | - use a `given ... with` clause as the enclosing given, - | - rearrange definitions so that Prices.Price.given_Ordering_Price comes earlier, - | - use an explicit argument. - | This will be an error in Scala 3.5 and later. + | To fix the problem without the language import, you could try one of the following: + | - use a `given ... with` clause as the enclosing given, + | - rearrange definitions so that Prices.Price.given_Ordering_Price comes earlier, + | - use an explicit argument. + | This will be an error in Scala 3.5 and later. diff --git a/tests/neg/i6716.check b/tests/neg/i6716.check index e70ac4b15f9c..cdf655710452 100644 --- a/tests/neg/i6716.check +++ b/tests/neg/i6716.check @@ -1,14 +1,15 @@ -- Error: tests/neg/i6716.scala:12:39 ---------------------------------------------------------------------------------- 12 | given Monad[Bar] = summon[Monad[Foo]] // error | ^ - | Result of implicit search for Monad[Foo] will change. - | Current result Bar.given_Monad_Bar will be no longer eligible - | because it is not defined before the search position. - | Result with new rules: Foo.given_Monad_Foo. - | To opt into the new rules, use the `experimental.givenLoopPrevention` language import. + | Result of implicit search for Monad[Foo] will change. + | Current result Bar.given_Monad_Bar will be no longer eligible + | because it is not defined before the search position. + | Result with new rules: Foo.given_Monad_Foo. + | To opt into the new rules, compile with `-source future` or use + | the `scala.language.future` language import. | - | To fix the problem without the language import, you could try one of the following: - | - use a `given ... with` clause as the enclosing given, - | - rearrange definitions so that Bar.given_Monad_Bar comes earlier, - | - use an explicit argument. - | This will be an error in Scala 3.5 and later. + | To fix the problem without the language import, you could try one of the following: + | - use a `given ... with` clause as the enclosing given, + | - rearrange definitions so that Bar.given_Monad_Bar comes earlier, + | - use an explicit argument. + | This will be an error in Scala 3.5 and later. diff --git a/tests/neg/i7294-a.check b/tests/neg/i7294-a.check index 6fac76a9faa5..2fe260fcf99a 100644 --- a/tests/neg/i7294-a.check +++ b/tests/neg/i7294-a.check @@ -14,7 +14,8 @@ | Current result foo.Test.f will be no longer eligible | because it is not defined before the search position. | Result with new rules: No Matching Implicit. - | To opt into the new rules, use the `experimental.givenLoopPrevention` language import. + | To opt into the new rules, compile with `-source future` or use + | the `scala.language.future` language import. | | To fix the problem without the language import, you could try one of the following: | - use a `given ... with` clause as the enclosing given, diff --git a/tests/pos/i15474.scala b/tests/pos/i15474.scala index b006f8b61cf4..f2c85120e4b2 100644 --- a/tests/pos/i15474.scala +++ b/tests/pos/i15474.scala @@ -1,6 +1,6 @@ //> using options -Xfatal-warnings import scala.language.implicitConversions -import scala.language.experimental.givenLoopPrevention +import scala.language.future object Test2: given c: Conversion[ String, Int ] = _.toInt // now avoided, was loop not detected, could be used as a fallback to avoid the warning. diff --git a/tests/pos/looping-givens.scala b/tests/pos/looping-givens.scala index 1b620b5c113e..0e615c8251df 100644 --- a/tests/pos/looping-givens.scala +++ b/tests/pos/looping-givens.scala @@ -1,4 +1,4 @@ -import language.experimental.givenLoopPrevention +import language.future class A class B diff --git a/tests/run/i6716.scala b/tests/run/i6716.scala index 4cca37f96a6f..3bef45ac7465 100644 --- a/tests/run/i6716.scala +++ b/tests/run/i6716.scala @@ -1,6 +1,4 @@ -//> using options -Xfatal-warnings - -import scala.language.experimental.givenLoopPrevention +//> using options -Xfatal-warnings -source future trait Monad[T]: def id: String @@ -11,7 +9,7 @@ object Foo { opaque type Bar = Foo object Bar { - given Monad[Bar] = summon[Monad[Foo]] // was error, fixed by givenLoopPrevention + given Monad[Bar] = summon[Monad[Foo]] // was error, fixed by given loop prevention } object Test extends App { From 5eceb3600f84b6f85d8e9f6cc44c7efa9d6ed8a9 Mon Sep 17 00:00:00 2001 From: odersky Date: Sun, 7 Jan 2024 18:46:43 +0100 Subject: [PATCH 045/220] Adapt docs --- .../changed-features/implicit-resolution.md | 32 +++++++++++++++++++ docs/sidebar.yml | 1 - 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/docs/_docs/reference/changed-features/implicit-resolution.md b/docs/_docs/reference/changed-features/implicit-resolution.md index 861a63bd4a05..1396ed04b6d3 100644 --- a/docs/_docs/reference/changed-features/implicit-resolution.md +++ b/docs/_docs/reference/changed-features/implicit-resolution.md @@ -164,3 +164,35 @@ The new rules are as follows: An implicit `a` defined in `A` is more specific th Condition (*) is new. It is necessary to ensure that the defined relation is transitive. [//]: # todo: expand with precise rules + +**9.** The following change is currently enabled in `-source future`: + +Implicit resolution now avoids generating recursive givens that can lead to an infinite loop at runtime. Here is an example: + +```scala +object Prices { + opaque type Price = BigDecimal + + object Price{ + given Ordering[Price] = summon[Ordering[BigDecimal]] // was error, now avoided + } +} +``` + +Previously, implicit resolution would resolve the `summon` to the given in `Price`, leading to an infinite loop (a warning was issued in that case). We now use the underlying given in `BigDecimal` instead. We achieve that by adding the following rule for implicit search: + + - When doing an implicit search while checking the implementation of a `given` definition `G` of the form + ``` + given ... = .... + ``` + discard all search results that lead back to `G` or to a given with the same owner as `G` that comes later in the source than `G`. + +The new behavior is currently enabled in `source.future` and will be enabled at the earliest in Scala 3.6. For earlier source versions, the behavior is as +follows: + + - Scala 3.3: no change + - Scala 3.4: A warning is issued where the behavior will change in 3.future. + - Scala 3.5: An error is issued where the behavior will change in 3.future. + +Old-style implicit definitions are unaffected by this change. + diff --git a/docs/sidebar.yml b/docs/sidebar.yml index d9f86d5141c3..65d7ac2f9ee4 100644 --- a/docs/sidebar.yml +++ b/docs/sidebar.yml @@ -153,7 +153,6 @@ subsection: - page: reference/experimental/cc.md - page: reference/experimental/purefuns.md - page: reference/experimental/tupled-function.md - - page: reference/experimental/given-loop-prevention.md - page: reference/syntax.md - title: Language Versions index: reference/language-versions/language-versions.md From 18795e4117d6e50121b5c139dbd6cba74e137e02 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 8 Jan 2024 09:11:19 +0100 Subject: [PATCH 046/220] Update `private[this]` deprecation warning and documentation --- .../dotty/tools/dotc/parsing/Parsers.scala | 3 ++- .../dropped-features/this-qualifier.md | 2 +- tests/neg-scalajs/js-native-members.check | 15 ++++++++---- ...non-native-members-qualified-private.check | 3 ++- tests/neg/private-this-3.4.check | 6 +++-- tests/semanticdb/metac.expect | 24 ++++++++++++------- 6 files changed, 35 insertions(+), 18 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 47b7ffbbc840..5467f2e1247f 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -3151,7 +3151,8 @@ object Parsers { } if mods1.is(Local) then report.errorOrMigrationWarning( - em"""The [this] qualifier will be deprecated in the future; it should be dropped. + em"""Ignoring [this] qualifier. + |This syntax will be deprecated in the future; it should be dropped. |See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html${rewriteNotice(`3.4-migration`)}""", in.sourcePos(), MigrationVersion.RemoveThisQualifier) diff --git a/docs/_spec/APPLIEDreference/dropped-features/this-qualifier.md b/docs/_spec/APPLIEDreference/dropped-features/this-qualifier.md index 3fcaefb7e0d8..9eb0a77e2b69 100644 --- a/docs/_spec/APPLIEDreference/dropped-features/this-qualifier.md +++ b/docs/_spec/APPLIEDreference/dropped-features/this-qualifier.md @@ -4,7 +4,7 @@ title: "Dropped: private[this] and protected[this]" nightlyOf: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html --- -The `private[this]` and `protected[this]` access modifiers will be deprecated and phased out. +The `private[this]` and `protected[this]` access modifiers will be deprecated and phased out. Migration warning will be shown in Scala 3.4+. Previously, these modifiers were needed for diff --git a/tests/neg-scalajs/js-native-members.check b/tests/neg-scalajs/js-native-members.check index 11acee62af90..60990cbf3d97 100644 --- a/tests/neg-scalajs/js-native-members.check +++ b/tests/neg-scalajs/js-native-members.check @@ -1,31 +1,36 @@ -- Warning: tests/neg-scalajs/js-native-members.scala:24:16 ------------------------------------------------------------ 24 | private[this] def this(x: Int) = this() // ok | ^ - | The [this] qualifier will be deprecated in the future; it should be dropped. + | Ignoring [this] qualifier. + | This syntax will be deprecated in the future; it should be dropped. | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html | This construct can be rewritten automatically under -rewrite -source 3.4-migration. -- Warning: tests/neg-scalajs/js-native-members.scala:28:16 ------------------------------------------------------------ 28 | private[this] val a: Int = js.native // error | ^ - | The [this] qualifier will be deprecated in the future; it should be dropped. + | Ignoring [this] qualifier. + | This syntax will be deprecated in the future; it should be dropped. | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html | This construct can be rewritten automatically under -rewrite -source 3.4-migration. -- Warning: tests/neg-scalajs/js-native-members.scala:32:16 ------------------------------------------------------------ 32 | private[this] var d: Int = js.native // error | ^ - | The [this] qualifier will be deprecated in the future; it should be dropped. + | Ignoring [this] qualifier. + | This syntax will be deprecated in the future; it should be dropped. | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html | This construct can be rewritten automatically under -rewrite -source 3.4-migration. -- Warning: tests/neg-scalajs/js-native-members.scala:36:16 ------------------------------------------------------------ 36 | private[this] def g(): Int = js.native // error | ^ - | The [this] qualifier will be deprecated in the future; it should be dropped. + | Ignoring [this] qualifier. + | This syntax will be deprecated in the future; it should be dropped. | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html | This construct can be rewritten automatically under -rewrite -source 3.4-migration. -- Warning: tests/neg-scalajs/js-native-members.scala:49:25 ------------------------------------------------------------ 49 | class X3 private[this] () extends js.Object { // ok | ^ - | The [this] qualifier will be deprecated in the future; it should be dropped. + | Ignoring [this] qualifier. + | This syntax will be deprecated in the future; it should be dropped. | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html | This construct can be rewritten automatically under -rewrite -source 3.4-migration. -- [E003] Syntax Warning: tests/neg-scalajs/js-native-members.scala:58:44 ---------------------------------------------- diff --git a/tests/neg-scalajs/js-non-native-members-qualified-private.check b/tests/neg-scalajs/js-non-native-members-qualified-private.check index fb06b91f98f8..6befabb7a9c0 100644 --- a/tests/neg-scalajs/js-non-native-members-qualified-private.check +++ b/tests/neg-scalajs/js-non-native-members-qualified-private.check @@ -1,7 +1,8 @@ -- Warning: tests/neg-scalajs/js-non-native-members-qualified-private.scala:52:28 -------------------------------------- 52 | class B private[this] () extends js.Object // ok | ^ - | The [this] qualifier will be deprecated in the future; it should be dropped. + | Ignoring [this] qualifier. + | This syntax will be deprecated in the future; it should be dropped. | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html | This construct can be rewritten automatically under -rewrite -source 3.4-migration. -- Error: tests/neg-scalajs/js-non-native-members-qualified-private.scala:6:32 ----------------------------------------- diff --git a/tests/neg/private-this-3.4.check b/tests/neg/private-this-3.4.check index 29c2fe909ede..8ee55d2b5f29 100644 --- a/tests/neg/private-this-3.4.check +++ b/tests/neg/private-this-3.4.check @@ -1,12 +1,14 @@ -- Error: tests/neg/private-this-3.4.scala:6:16 ------------------------------------------------------------------------ 6 | private[this] def foo: Int = ??? // error: migration warning | ^ - | The [this] qualifier will be deprecated in the future; it should be dropped. + | Ignoring [this] qualifier. + | This syntax will be deprecated in the future; it should be dropped. | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html | This construct can be rewritten automatically under -rewrite -source 3.4-migration. -- Error: tests/neg/private-this-3.4.scala:7:18 ------------------------------------------------------------------------ 7 | protected[this] def bar: Int = ??? // error: migration warning | ^ - | The [this] qualifier will be deprecated in the future; it should be dropped. + | Ignoring [this] qualifier. + | This syntax will be deprecated in the future; it should be dropped. | See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html | This construct can be rewritten automatically under -rewrite -source 3.4-migration. diff --git a/tests/semanticdb/metac.expect b/tests/semanticdb/metac.expect index c8b652d85469..5c35edf734a9 100644 --- a/tests/semanticdb/metac.expect +++ b/tests/semanticdb/metac.expect @@ -44,11 +44,13 @@ Occurrences: Diagnostics: [3:14..3:16): [warning] unused private member -[4:16..4:16): [warning] The [this] qualifier will be deprecated in the future; it should be dropped. +[4:16..4:16): [warning] Ignoring [this] qualifier. +This syntax will be deprecated in the future; it should be dropped. See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html This construct can be rewritten automatically under -rewrite -source 3.4-migration. [4:20..4:22): [warning] unused private member -[7:18..7:18): [warning] The [this] qualifier will be deprecated in the future; it should be dropped. +[7:18..7:18): [warning] Ignoring [this] qualifier. +This syntax will be deprecated in the future; it should be dropped. See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html This construct can be rewritten automatically under -rewrite -source 3.4-migration. @@ -817,11 +819,13 @@ Occurrences: Diagnostics: [18:9..18:10): [warning] unused explicit parameter -[20:23..20:23): [warning] The [this] qualifier will be deprecated in the future; it should be dropped. +[20:23..20:23): [warning] Ignoring [this] qualifier. +This syntax will be deprecated in the future; it should be dropped. See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html This construct can be rewritten automatically under -rewrite -source 3.4-migration. [20:27..20:28): [warning] unused explicit parameter -[22:23..22:23): [warning] The [this] qualifier will be deprecated in the future; it should be dropped. +[22:23..22:23): [warning] Ignoring [this] qualifier. +This syntax will be deprecated in the future; it should be dropped. See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html This construct can be rewritten automatically under -rewrite -source 3.4-migration. [22:27..22:28): [warning] unused explicit parameter @@ -4129,16 +4133,20 @@ Occurrences: Diagnostics: [2:20..2:21): [warning] unused explicit parameter -[5:16..5:16): [warning] The [this] qualifier will be deprecated in the future; it should be dropped. +[5:16..5:16): [warning] Ignoring [this] qualifier. +This syntax will be deprecated in the future; it should be dropped. See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html This construct can be rewritten automatically under -rewrite -source 3.4-migration. -[7:16..7:16): [warning] The [this] qualifier will be deprecated in the future; it should be dropped. +[7:16..7:16): [warning] Ignoring [this] qualifier. +This syntax will be deprecated in the future; it should be dropped. See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html This construct can be rewritten automatically under -rewrite -source 3.4-migration. -[12:16..12:16): [warning] The [this] qualifier will be deprecated in the future; it should be dropped. +[12:16..12:16): [warning] Ignoring [this] qualifier. +This syntax will be deprecated in the future; it should be dropped. See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html This construct can be rewritten automatically under -rewrite -source 3.4-migration. -[13:16..13:16): [warning] The [this] qualifier will be deprecated in the future; it should be dropped. +[13:16..13:16): [warning] Ignoring [this] qualifier. +This syntax will be deprecated in the future; it should be dropped. See: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html This construct can be rewritten automatically under -rewrite -source 3.4-migration. From eb3ca86b5954b289aba1e653059898d0b9755018 Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 8 Jan 2024 09:38:11 +0100 Subject: [PATCH 047/220] Add test showing use of @nowarn --- tests/pos/given-loop-prevention.scala | 14 ++++++++++++++ tests/pos/i6716.scala | 14 ++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 tests/pos/given-loop-prevention.scala create mode 100644 tests/pos/i6716.scala diff --git a/tests/pos/given-loop-prevention.scala b/tests/pos/given-loop-prevention.scala new file mode 100644 index 000000000000..0bae0bb24fed --- /dev/null +++ b/tests/pos/given-loop-prevention.scala @@ -0,0 +1,14 @@ +//> using options -Xfatal-warnings + +class Foo + +object Bar { + given Foo with {} + given List[Foo] = List(summon[Foo]) // ok +} + +object Baz { + @annotation.nowarn + given List[Foo] = List(summon[Foo]) // gives a warning, which is suppressed + given Foo with {} +} diff --git a/tests/pos/i6716.scala b/tests/pos/i6716.scala new file mode 100644 index 000000000000..f02559af1e82 --- /dev/null +++ b/tests/pos/i6716.scala @@ -0,0 +1,14 @@ +//> using options -Xfatal-warnings -source 3.4 + +class Foo + +object Bar { + given Foo with {} + given List[Foo] = List(summon[Foo]) // ok +} + +object Baz { + @annotation.nowarn + given List[Foo] = List(summon[Foo]) // gives a warning, which is suppressed + given Foo with {} +} From 2f91b7b29165d682c30d57d78a3d177460401bb5 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 8 Jan 2024 13:25:03 +0000 Subject: [PATCH 048/220] Allow constraining a parameter to Nothing --- .../tools/dotc/core/ConstraintHandling.scala | 3 ++- tests/warn/i19359.scala | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 tests/warn/i19359.scala diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala index 6be6ec94c1c3..da94226b34af 100644 --- a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala +++ b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala @@ -858,7 +858,8 @@ trait ConstraintHandling { addParamBound(bound) case _ => val pbound = avoidLambdaParams(bound) - kindCompatible(param, pbound) && addBoundTransitively(param, pbound, !fromBelow) + (pbound.isNothingType || kindCompatible(param, pbound)) + && addBoundTransitively(param, pbound, !fromBelow) finally canWidenAbstract = saved addConstraintInvocations -= 1 diff --git a/tests/warn/i19359.scala b/tests/warn/i19359.scala new file mode 100644 index 000000000000..db598a8095e1 --- /dev/null +++ b/tests/warn/i19359.scala @@ -0,0 +1,23 @@ +sealed trait Plan[+E <: Err, +F[+e <: E] <: Fal[e]] + +case class Err() extends Plan[Err, Nothing] +case class Fal[+E <: Err]() extends Plan[E, Fal] +case class Btw[+E <: Err, +F[+e <: E] <: Fal[e]]() extends Plan[E, F] + +class Tests: + def test1(plan: Plan[Err, Nothing]): Unit = plan match + case Err() => + case Btw() => + + def main1 = test1(Btw()) + +/* + +Previously, Plan[Err, Nothing] dropped Btw, +because it didn't instantiate ?F to Nothing + + <== decompose(Plan[Err, Nothing], [Btw[Err, Fal]]) = [Not, Err] + <== decompose(Btw[Err, Fal] & Plan[Err, Nothing]) = [] +<== simplify(Prod(Btw())) = Empty + +*/ From 5309a70eb8e5ebdeb0be30d700efe981b475e438 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 8 Jan 2024 15:51:42 +0100 Subject: [PATCH 049/220] Remove `ascriptionVarargsUnpacking` as we never used it --- compiler/src/dotty/tools/dotc/config/Feature.scala | 1 - library/src/scala/runtime/stdLibPatches/language.scala | 3 --- 2 files changed, 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/Feature.scala b/compiler/src/dotty/tools/dotc/config/Feature.scala index fa262a5880ff..2798828ad9a7 100644 --- a/compiler/src/dotty/tools/dotc/config/Feature.scala +++ b/compiler/src/dotty/tools/dotc/config/Feature.scala @@ -26,7 +26,6 @@ object Feature: val dependent = experimental("dependent") val erasedDefinitions = experimental("erasedDefinitions") val symbolLiterals = deprecated("symbolLiterals") - val ascriptionVarargsUnpacking = deprecated("ascriptionVarargsUnpacking") val fewerBraces = experimental("fewerBraces") val saferExceptions = experimental("saferExceptions") val clauseInterleaving = experimental("clauseInterleaving") diff --git a/library/src/scala/runtime/stdLibPatches/language.scala b/library/src/scala/runtime/stdLibPatches/language.scala index c37555f26653..c0dd8a74419e 100644 --- a/library/src/scala/runtime/stdLibPatches/language.scala +++ b/library/src/scala/runtime/stdLibPatches/language.scala @@ -115,9 +115,6 @@ object language: @compileTimeOnly("`symbolLiterals` can only be used at compile time in import statements") object symbolLiterals - /** TODO */ - @compileTimeOnly("`ascriptionVarargsUnpacking` can only be used at compile time in import statements") - object ascriptionVarargsUnpacking end deprecated /** Where imported, auto-tupling is disabled. From e8733764bc13dd556b81905adb04d70f5ec9111f Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 8 Jan 2024 18:16:00 +0000 Subject: [PATCH 050/220] Consider static and non-static methods as non-double def --- .../src/dotty/tools/dotc/typer/Checking.scala | 3 ++- tests/run/19394.scala | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 tests/run/19394.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 3e5d65070a80..9594fe3f5373 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -1167,7 +1167,8 @@ trait Checking { def javaFieldMethodPair = decl.is(JavaDefined) && other.is(JavaDefined) && decl.is(Method) != other.is(Method) - if (decl.matches(other) && !javaFieldMethodPair) { + def staticNonStaticPair = decl.isScalaStatic != other.isScalaStatic + if (decl.matches(other) && !javaFieldMethodPair && !staticNonStaticPair) { def doubleDefError(decl: Symbol, other: Symbol): Unit = if (!decl.info.isErroneous && !other.info.isErroneous) report.error(DoubleDefinition(decl, other, cls), decl.srcPos) diff --git a/tests/run/19394.scala b/tests/run/19394.scala new file mode 100644 index 000000000000..c57a9471f345 --- /dev/null +++ b/tests/run/19394.scala @@ -0,0 +1,21 @@ +import scala.annotation.{ static, targetName } + +class Foo +object Foo: + @static def foo: String = "foo" + @targetName("foo") def fooBincompat: String = foo + +class Bar +object Bar: + @static def bar: String = "bar" + def bar: String = bar + +object Test: + def main(args: Array[String]): Unit = + assert(Foo.foo == "foo") + assert(classOf[Foo].getMethod("foo").invoke(null) == "foo") // static + assert(Foo.getClass.getMethod("foo").invoke(Foo) == "foo") // instance, on module class + + assert(Bar.bar == "bar") + assert(classOf[Bar].getMethod("bar").invoke(null) == "bar") + assert(Bar.getClass.getMethod("bar").invoke(Bar) == "bar") From 13a71ef6075cc8acec3c2cb248251170d7203943 Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 8 Jan 2024 19:34:33 +0100 Subject: [PATCH 051/220] Address review comments --- .../tools/dotc/config/MigrationVersion.scala | 14 ++++++-- .../tools/dotc/config/SourceVersion.scala | 3 ++ .../dotty/tools/dotc/typer/Migrations.scala | 32 ++++++++++++------- .../src/dotty/tools/dotc/typer/ReTyper.scala | 1 - .../src/dotty/tools/dotc/typer/Typer.scala | 5 +-- .../context-bounds-migration.scala | 4 +-- 6 files changed, 38 insertions(+), 21 deletions(-) rename tests/{neg => warn}/context-bounds-migration.scala (61%) diff --git a/compiler/src/dotty/tools/dotc/config/MigrationVersion.scala b/compiler/src/dotty/tools/dotc/config/MigrationVersion.scala index d4afc599896c..4dd9d065395b 100644 --- a/compiler/src/dotty/tools/dotc/config/MigrationVersion.scala +++ b/compiler/src/dotty/tools/dotc/config/MigrationVersion.scala @@ -6,10 +6,16 @@ import SourceVersion.* import Feature.* import core.Contexts.Context -class MigrationVersion(val warnFrom: SourceVersion, val errorFrom: SourceVersion): - assert(warnFrom.ordinal <= errorFrom.ordinal) +class MigrationVersion( + val warnFrom: SourceVersion, + val errorFrom: SourceVersion): + require(warnFrom.ordinal <= errorFrom.ordinal) + def needsPatch(using Context): Boolean = - sourceVersion.isMigrating && sourceVersion.isAtLeast(errorFrom) + sourceVersion.isMigrating && sourceVersion.isAtLeast(warnFrom) + + def patchFrom: SourceVersion = + warnFrom.prevMigrating object MigrationVersion: @@ -27,6 +33,8 @@ object MigrationVersion: val AscriptionAfterPattern = MigrationVersion(`3.3`, future) + val ExplicitContextBoundArgument = MigrationVersion(`3.4`, `3.5`) + val AlphanumericInfix = MigrationVersion(`3.4`, future) val RemoveThisQualifier = MigrationVersion(`3.4`, future) val UninitializedVars = MigrationVersion(`3.4`, future) diff --git a/compiler/src/dotty/tools/dotc/config/SourceVersion.scala b/compiler/src/dotty/tools/dotc/config/SourceVersion.scala index 33b946ed173f..7a464d331930 100644 --- a/compiler/src/dotty/tools/dotc/config/SourceVersion.scala +++ b/compiler/src/dotty/tools/dotc/config/SourceVersion.scala @@ -19,6 +19,9 @@ enum SourceVersion: def stable: SourceVersion = if isMigrating then SourceVersion.values(ordinal + 1) else this + def prevMigrating: SourceVersion = + if isMigrating then this else SourceVersion.values(ordinal - 1).prevMigrating + def isAtLeast(v: SourceVersion) = stable.ordinal >= v.ordinal def isAtMost(v: SourceVersion) = stable.ordinal <= v.ordinal diff --git a/compiler/src/dotty/tools/dotc/typer/Migrations.scala b/compiler/src/dotty/tools/dotc/typer/Migrations.scala index 9c038abbd851..84db91f9dee9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Migrations.scala +++ b/compiler/src/dotty/tools/dotc/typer/Migrations.scala @@ -13,7 +13,7 @@ import Symbols.* import Trees.* import ProtoTypes.* import Decorators.* -import config.MigrationVersion +import config.MigrationVersion as mv import config.Feature.{sourceVersion, migrateTo3} import config.SourceVersion.* import reporting.* @@ -30,6 +30,15 @@ trait Migrations: import tpd.* + /** Run `migration`, asserting we are in the proper Typer (not a ReTyper) */ + inline def migrate[T](inline migration: T): T = + assert(!this.isInstanceOf[ReTyper]) + migration + + /** Run `migration`, provided we are in the proper Typer (not a ReTyper) */ + inline def migrate(inline migration: Unit): Unit = + if !this.isInstanceOf[ReTyper] then migration + /** Flag & migrate `?` used as a higher-kinded type parameter * Warning in 3.0-migration, error from 3.0 */ @@ -40,7 +49,7 @@ trait Migrations: else "" val namePos = tree.sourcePos.withSpan(tree.nameSpan) report.errorOrMigrationWarning( - em"`?` is not a valid type name$addendum", namePos, MigrationVersion.Scala2to3) + em"`?` is not a valid type name$addendum", namePos, mv.Scala2to3) def typedAsFunction(tree: untpd.PostfixOp, pt: Type)(using Context): Tree = { val untpd.PostfixOp(qual, Ident(nme.WILDCARD)) = tree: @unchecked @@ -52,8 +61,8 @@ trait Migrations: case _ => val recovered = typed(qual)(using ctx.fresh.setExploreTyperState()) val msg = OnlyFunctionsCanBeFollowedByUnderscore(recovered.tpe.widen, tree) - report.errorOrMigrationWarning(msg, tree.srcPos, MigrationVersion.Scala2to3) - if MigrationVersion.Scala2to3.needsPatch then + report.errorOrMigrationWarning(msg, tree.srcPos, mv.Scala2to3) + if mv.Scala2to3.needsPatch then // Under -rewrite, patch `x _` to `(() => x)` msg.actions .headOption @@ -69,16 +78,16 @@ trait Migrations: case _ => ("(() => ", ")") } + val mversion = mv.FunctionUnderscore def remedy = if ((prefix ++ suffix).isEmpty) "simply leave out the trailing ` _`" else s"use `$prefix$suffix` instead" - def rewrite = Message.rewriteNotice("This construct", `3.4-migration`) + def rewrite = Message.rewriteNotice("This construct", mversion.patchFrom) report.errorOrMigrationWarning( em"""The syntax ` _` is no longer supported; |you can $remedy$rewrite""", - tree.srcPos, - MigrationVersion.FunctionUnderscore) - if MigrationVersion.FunctionUnderscore.needsPatch then + tree.srcPos, mversion) + if mversion.needsPatch then patch(Span(tree.span.start), prefix) patch(Span(qual.span.end, tree.span.end), suffix) @@ -89,6 +98,7 @@ trait Migrations: * Warning in 3.4, error in 3.5, rewrite in 3.5-migration. */ def contextBoundParams(tree: Tree, tp: Type, pt: FunProto)(using Context): Unit = + val mversion = mv.ExplicitContextBoundArgument def isContextBoundParams = tp.stripPoly match case MethodType(ContextBoundParamName(_) :: _) => true case _ => false @@ -96,12 +106,12 @@ trait Migrations: && isContextBoundParams && pt.applyKind != ApplyKind.Using then - def rewriteMsg = Message.rewriteNotice("This code", `3.5-migration`) + def rewriteMsg = Message.rewriteNotice("This code", mversion.patchFrom) report.errorOrMigrationWarning( em"""Context bounds will map to context parameters. |A `using` clause is needed to pass explicit arguments to them.$rewriteMsg""", - tree.srcPos, MigrationVersion(`3.4`, `3.5`)) - if sourceVersion.isAtLeast(`3.5-migration`) then + tree.srcPos, mversion) + if mversion.needsPatch then patch(Span(pt.args.head.span.start), "using ") end contextBoundParams diff --git a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala index 253c4fda9396..e152b5e6b9c7 100644 --- a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala +++ b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala @@ -189,5 +189,4 @@ class ReTyper(nestingLevel: Int = 0) extends Typer(nestingLevel) with ReChecking override protected def checkEqualityEvidence(tree: tpd.Tree, pt: Type)(using Context): Unit = () override protected def matchingApply(methType: MethodOrPoly, pt: FunProto)(using Context): Boolean = true override protected def typedScala2MacroBody(call: untpd.Tree)(using Context): Tree = promote(call) - override protected def migrate[T](migration: => T, disabled: => T = ()): T = disabled } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 5cb42f659551..1303b64cbd12 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -158,9 +158,6 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer // Overridden in derived typers def newLikeThis(nestingLevel: Int): Typer = new Typer(nestingLevel) - // Overridden to do nothing in derived typers - protected def migrate[T](migration: => T, disabled: => T = ()): T = migration - /** Find the type of an identifier with given `name` in given context `ctx`. * @param name the name of the identifier * @param pt the expected type @@ -2982,7 +2979,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer } override def typedAsFunction(tree: untpd.PostfixOp, pt: Type)(using Context): Tree = - migrate(super.typedAsFunction(tree, pt), throw new AssertionError("can't retype a PostfixOp")) + migrate(super.typedAsFunction(tree, pt)) /** Translate infix operation expression `l op r` to * diff --git a/tests/neg/context-bounds-migration.scala b/tests/warn/context-bounds-migration.scala similarity index 61% rename from tests/neg/context-bounds-migration.scala rename to tests/warn/context-bounds-migration.scala index b27dc884692c..1094db68f41b 100644 --- a/tests/neg/context-bounds-migration.scala +++ b/tests/warn/context-bounds-migration.scala @@ -1,4 +1,4 @@ -//> using options -Xfatal-warnings +//> using options -source 3.4 class C[T] def foo[X: C] = () @@ -6,5 +6,5 @@ def foo[X: C] = () given [T]: C[T] = C[T]() def Test = - foo(C[Int]()) // error + foo(C[Int]()) // warn foo(using C[Int]()) // ok From 5346c999fb3f99947d706f31ae90c9d658f06e6b Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Tue, 9 Jan 2024 13:52:49 +0100 Subject: [PATCH 052/220] chore: Fix listing release versions for bisect script. (#19356) Use `maven-metadata.xml` to list released Scala versions instead of parsing HTML of Maven index. --- project/scripts/bisect.scala | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/project/scripts/bisect.scala b/project/scripts/bisect.scala index dbb14f2c4587..9e423cf15162 100755 --- a/project/scripts/bisect.scala +++ b/project/scripts/bisect.scala @@ -169,9 +169,13 @@ class Releases(val releases: Vector[Release]) object Releases: lazy val allReleases: Vector[Release] = - val re = raw"""(?<=title=")(.+-bin-\d{8}-\w{7}-NIGHTLY)(?=/")""".r - val html = Source.fromURL("https://repo1.maven.org/maven2/org/scala-lang/scala3-compiler_3/") - re.findAllIn(html.mkString).map(Release.apply).toVector + val re = raw"(.+-bin-\d{8}-\w{7}-NIGHTLY)".r + val xml = io.Source.fromURL( + "https://repo1.maven.org/maven2/org/scala-lang/scala3-compiler_3/maven-metadata.xml" + ) + re.findAllMatchIn(xml.mkString) + .flatMap{ m => Option(m.group(1)).map(Release.apply) } + .toVector def fromRange(range: ReleasesRange): Vector[Release] = range.filter(allReleases) From c6e103a30193ee8f55653696da20ffce1b740cf6 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 9 Jan 2024 15:59:30 +0000 Subject: [PATCH 053/220] Fix static method js backend --- compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala | 6 +++++- tests/run/19394.scala | 9 ++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala index 54af9f8dd088..d1f5f1b63d26 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala @@ -793,6 +793,9 @@ class JSCodeGen()(using genCtx: Context) { name.name }.toSet + val staticNames = moduleClass.companionClass.info.allMembers + .collect { case d if d.name.isTermName && d.symbol.isScalaStatic => d.name }.toSet + val members = { moduleClass.info.membersBasedOnFlags(required = Flags.Method, excluded = Flags.ExcludedForwarder).map(_.symbol) @@ -815,6 +818,7 @@ class JSCodeGen()(using genCtx: Context) { || hasAccessBoundary || isOfJLObject || m.hasAnnotation(jsdefn.JSNativeAnnot) || isDefaultParamOfJSNativeDef // #4557 + || staticNames(m.name) } val forwarders = for { @@ -4769,7 +4773,7 @@ class JSCodeGen()(using genCtx: Context) { } private def isMethodStaticInIR(sym: Symbol): Boolean = - sym.is(JavaStatic) + sym.is(JavaStatic) || sym.isScalaStatic /** Generate a Class[_] value (e.g. coming from classOf[T]) */ private def genClassConstant(tpe: Type)(implicit pos: Position): js.Tree = diff --git a/tests/run/19394.scala b/tests/run/19394.scala index c57a9471f345..7c6938c97503 100644 --- a/tests/run/19394.scala +++ b/tests/run/19394.scala @@ -13,9 +13,8 @@ object Bar: object Test: def main(args: Array[String]): Unit = assert(Foo.foo == "foo") - assert(classOf[Foo].getMethod("foo").invoke(null) == "foo") // static - assert(Foo.getClass.getMethod("foo").invoke(Foo) == "foo") // instance, on module class - assert(Bar.bar == "bar") - assert(classOf[Bar].getMethod("bar").invoke(null) == "bar") - assert(Bar.getClass.getMethod("bar").invoke(Bar) == "bar") + + import scala.reflect.Selectable.reflectiveSelectable + assert(Foo.asInstanceOf[{ def foo: String }].foo == "foo") + assert(Bar.asInstanceOf[{ def bar: String }].bar == "bar") From 2930d2e8a1bb2c00d0744f6754a7d2be02ff1b46 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 10 Jan 2024 12:16:09 +0100 Subject: [PATCH 054/220] Set the correct type when copying reflect Inlined trees Fixes #19191 --- .../quoted/runtime/impl/QuotesImpl.scala | 6 ++- tests/pos-macros/i19191/Lib_1.scala | 15 ++++++ tests/pos-macros/i19191/Macro_1.scala | 54 +++++++++++++++++++ tests/pos-macros/i19191/Test_2.scala | 6 +++ 4 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 tests/pos-macros/i19191/Lib_1.scala create mode 100644 tests/pos-macros/i19191/Macro_1.scala create mode 100644 tests/pos-macros/i19191/Test_2.scala diff --git a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala index 51f133c972b4..04d8d7bc51a0 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala @@ -1030,7 +1030,11 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler def apply(call: Option[Tree], bindings: List[Definition], expansion: Term): Inlined = withDefaultPos(tpd.Inlined(call.getOrElse(tpd.EmptyTree), bindings.map { case b: tpd.MemberDef => b }, xCheckMacroValidExpr(expansion))) def copy(original: Tree)(call: Option[Tree], bindings: List[Definition], expansion: Term): Inlined = - tpd.Inlined(call.getOrElse(tpd.EmptyTree), bindings.asInstanceOf[List[tpd.MemberDef]], xCheckMacroValidExpr(expansion)).withSpan(original.span).withType(original.tpe) + original match + case original: Inlined => + tpd.cpy.Inlined(original)(call.getOrElse(tpd.EmptyTree), bindings.asInstanceOf[List[tpd.MemberDef]], xCheckMacroValidExpr(expansion)) + case original => + throw new IllegalArgumentException(i"Expected argument `original` to be an `Inlined` but was: ${original.show}") def unapply(x: Inlined): (Option[Tree /* Term | TypeTree */], List[Definition], Term) = (optional(x.call), x.bindings, x.body) end Inlined diff --git a/tests/pos-macros/i19191/Lib_1.scala b/tests/pos-macros/i19191/Lib_1.scala new file mode 100644 index 000000000000..dd77aec377b2 --- /dev/null +++ b/tests/pos-macros/i19191/Lib_1.scala @@ -0,0 +1,15 @@ +trait Binding[+A]: + def value: A = ??? +object Binding: + inline def apply[A](inline a: A): Binding[A] = ??? + final case class Constant[+A](override val value: A) extends Binding[A] + +extension [A](inline binding: Binding[A]) + transparent inline def bind: A = null.asInstanceOf[A] + +trait Vars[A] extends BindingSeq[A] +trait BindingSeq[+A]: + def foreachBinding[U](f: A => Binding[U]): Binding[Unit] = ??? + +extension [A](inline bindingSeq: BindingSeq[A]) + transparent inline def foreach[U](inline f: A => U): Unit = ${ Macros.foreach('bindingSeq, 'f) } diff --git a/tests/pos-macros/i19191/Macro_1.scala b/tests/pos-macros/i19191/Macro_1.scala new file mode 100644 index 000000000000..b5ba403d3faa --- /dev/null +++ b/tests/pos-macros/i19191/Macro_1.scala @@ -0,0 +1,54 @@ +import scala.compiletime._ +import scala.deriving._ +import scala.quoted._ +import scala.annotation.meta.field + +object Macros{ + private def bindingFunctionBody[A: quoted.Type, B: quoted.Type](f: quoted.Expr[A => B])(using Quotes) = + import quoted.quotes.reflect.* + f.asTerm match + case inlined @ Inlined( + call, + bindings, + block @ Block( + List( + defDef @ DefDef( + name, + paramss @ List(TermParamClause(List(param @ ValDef(paramName, paramTpt, _)))), + tpt, + Some(rhs) + ) + ), + closureIdent + ) + ) => + Inlined + .copy(inlined)( + call, + bindings, + '{ (a: A) => + ${ + Block( + List( + ValDef + .copy(param)(paramName, paramTpt, Some('a.asTerm)) + .changeOwner(Symbol.spliceOwner) + ), + '{ + Binding(${ rhs.changeOwner(Symbol.spliceOwner).asExprOf[B] }) + }.asTerm.changeOwner(Symbol.spliceOwner) + ) + .asExprOf[Binding[B]] + }: Binding[B] + }.asTerm + ) + .asExprOf[A => Binding[B]] + case _ => + '{ (a: A) => Binding.Constant($f(a)): Binding[B] } + end match + end bindingFunctionBody + + def foreach[A: quoted.Type, U: quoted.Type](self: quoted.Expr[BindingSeq[A]], f: quoted.Expr[A => U])(using + qctx: Quotes + ): quoted.Expr[Unit] = '{ $self.foreachBinding(${ bindingFunctionBody(f) }).bind } +} diff --git a/tests/pos-macros/i19191/Test_2.scala b/tests/pos-macros/i19191/Test_2.scala new file mode 100644 index 000000000000..c7f40d996ed9 --- /dev/null +++ b/tests/pos-macros/i19191/Test_2.scala @@ -0,0 +1,6 @@ +def Test = { + val vars: Vars[Int] = ??? + + val works = vars.foreach { v => () } + val fails = for (v <- vars) () +} From d2becfe054b9f9a989f1f10c563b29f37df14477 Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 10 Jan 2024 13:45:26 +0100 Subject: [PATCH 055/220] Better error diagnostics for cyclic references We now suggest to compile with -explain-cyclic, in which case we give a trace of the forcings that led to the cycle. The reason for the separate option is that maintaining a trace is not free so we should not be doing it by default. --- compiler/src/dotty/tools/dotc/Run.scala | 2 + .../tools/dotc/config/ScalaSettings.scala | 2 + .../tools/dotc/core/SymDenotations.scala | 24 +++++++--- .../dotty/tools/dotc/core/TypeErrors.scala | 39 +++++++++++---- .../tools/dotc/core/tasty/TreeUnpickler.scala | 15 ++++-- .../dotty/tools/dotc/reporting/messages.scala | 48 +++++++++++++------ .../src/dotty/tools/dotc/typer/Checking.scala | 2 +- tests/neg-macros/i14772.check | 9 +++- tests/neg-macros/i14772.scala | 1 + tests/neg-macros/i16582.check | 10 +++- tests/neg-macros/i16582/Test_2.scala | 1 + tests/neg/cyclic.check | 14 ++++++ tests/neg/cyclic.scala | 6 +++ tests/neg/i10870.check | 2 + tests/neg/i11994.check | 20 ++++++-- tests/neg/i11994.scala | 1 + 16 files changed, 151 insertions(+), 45 deletions(-) create mode 100644 tests/neg/cyclic.check create mode 100644 tests/neg/cyclic.scala diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala index bec1c89d7216..c3a91ef1ce1b 100644 --- a/compiler/src/dotty/tools/dotc/Run.scala +++ b/compiler/src/dotty/tools/dotc/Run.scala @@ -343,6 +343,8 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint runCtx.setProfiler(Profiler()) unfusedPhases.foreach(_.initContext(runCtx)) val fusedPhases = runCtx.base.allPhases + if ctx.settings.explainCyclic.value then + runCtx.setProperty(CyclicReference.Trace, new CyclicReference.Trace()) runCtx.withProgressCallback: cb => _progress = Progress(cb, this, fusedPhases.map(_.traversals).sum) runPhases(allPhases = fusedPhases)(using runCtx) diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index d1b91f77f933..85e6ebef751f 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -120,6 +120,7 @@ trait CommonScalaSettings: // -explain-types setting is necessary for cross compilation, since it is mentioned in sbt-tpolecat, for instance // it is otherwise subsumed by -explain, and should be dropped as soon as we can. val explainTypes: Setting[Boolean] = BooleanSetting("-explain-types", "Explain type errors in more detail (deprecated, use -explain instead).", aliases = List("--explain-types", "-explaintypes")) + val explainCyclic: Setting[Boolean] = BooleanSetting("-explain-cyclic", "Explain cyclic reference errors in more detail.", aliases = List("--explain-cyclic")) val unchecked: Setting[Boolean] = BooleanSetting("-unchecked", "Enable additional warnings where generated code depends on assumptions.", initialValue = true, aliases = List("--unchecked")) val language: Setting[List[String]] = MultiStringSetting("-language", "feature", "Enable one or more language features.", aliases = List("--language")) val experimental: Setting[Boolean] = BooleanSetting("-experimental", "Annotate all top-level definitions with @experimental. This enables the use of experimental features anywhere in the project.") @@ -351,6 +352,7 @@ private sealed trait YSettings: val YdebugTypeError: Setting[Boolean] = BooleanSetting("-Ydebug-type-error", "Print the stack trace when a TypeError is caught", false) val YdebugError: Setting[Boolean] = BooleanSetting("-Ydebug-error", "Print the stack trace when any error is caught.", false) val YdebugUnpickling: Setting[Boolean] = BooleanSetting("-Ydebug-unpickling", "Print the stack trace when an error occurs when reading Tasty.", false) + val YdebugCyclic: Setting[Boolean] = BooleanSetting("-Ydebug-cyclic", "Print the stack trace when a cyclic reference error occurs.", false) val YtermConflict: Setting[String] = ChoiceSetting("-Yresolve-term-conflict", "strategy", "Resolve term conflicts", List("package", "object", "error"), "error") val Ylog: Setting[List[String]] = PhasesSetting("-Ylog", "Log operations during") val YlogClasspath: Setting[Boolean] = BooleanSetting("-Ylog-classpath", "Output information about what classpath is being applied.") diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index b1e85f2b4f90..71aa74dd76b1 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -167,12 +167,17 @@ object SymDenotations { println(i"${" " * indent}completed $name in $owner") } } - else { - if (myFlags.is(Touched)) - throw CyclicReference(this)(using ctx.withOwner(symbol)) - myFlags |= Touched - atPhase(validFor.firstPhaseId)(completer.complete(this)) - } + else + val traceCycles = CyclicReference.isTraced + try + if traceCycles then + CyclicReference.pushTrace("complete the info of ", symbol, "") + if myFlags.is(Touched) then + throw CyclicReference(this)(using ctx.withOwner(symbol)) + myFlags |= Touched + atPhase(validFor.firstPhaseId)(completer.complete(this)) + finally + if traceCycles then CyclicReference.popTrace() protected[dotc] def info_=(tp: Type): Unit = { /* // DEBUG @@ -2971,7 +2976,10 @@ object SymDenotations { def apply(clsd: ClassDenotation)(implicit onBehalf: BaseData, ctx: Context) : (List[ClassSymbol], BaseClassSet) = { assert(isValid) + val traceCycles = CyclicReference.isTraced try + if traceCycles then + CyclicReference.pushTrace("compute the base classes of ", clsd.symbol, "") if (cache != null) cache.uncheckedNN else { if (locked) throw CyclicReference(clsd) @@ -2984,7 +2992,9 @@ object SymDenotations { else onBehalf.signalProvisional() computed } - finally addDependent(onBehalf) + finally + if traceCycles then CyclicReference.popTrace() + addDependent(onBehalf) } def sameGroup(p1: Phase, p2: Phase) = p1.sameParentsStartId == p2.sameParentsStartId diff --git a/compiler/src/dotty/tools/dotc/core/TypeErrors.scala b/compiler/src/dotty/tools/dotc/core/TypeErrors.scala index 76be98d9bd65..240bc4eebd84 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErrors.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErrors.scala @@ -12,7 +12,9 @@ import Denotations.* import Decorators.* import reporting.* import ast.untpd +import util.Property import config.Printers.{cyclicErrors, noPrinter} +import collection.mutable import scala.annotation.constructorOnly @@ -27,6 +29,7 @@ abstract class TypeError(using creationContext: Context) extends Exception(""): || ctx.settings.YdebugTypeError.value || ctx.settings.YdebugError.value || ctx.settings.YdebugUnpickling.value + || ctx.settings.YdebugCyclic.value override def fillInStackTrace(): Throwable = if computeStackTrace then super.fillInStackTrace().nn @@ -72,8 +75,7 @@ extends TypeError: def explanation: String = s"$op $details" private def recursions: List[RecursionOverflow] = { - import scala.collection.mutable.ListBuffer - val result = ListBuffer.empty[RecursionOverflow] + val result = mutable.ListBuffer.empty[RecursionOverflow] @annotation.tailrec def loop(throwable: Throwable): List[RecursionOverflow] = throwable match { case ro: RecursionOverflow => result += ro @@ -135,7 +137,10 @@ end handleRecursive * so it requires knowing denot already. * @param denot */ -class CyclicReference(val denot: SymDenotation)(using Context) extends TypeError: +class CyclicReference( + val denot: SymDenotation, + val optTrace: Option[Array[CyclicReference.TraceElement]])(using Context) +extends TypeError: var inImplicitSearch: Boolean = false val cycleSym = denot.symbol @@ -161,11 +166,11 @@ class CyclicReference(val denot: SymDenotation)(using Context) extends TypeError cx.tree match { case tree: untpd.ValOrDefDef if !tree.tpt.typeOpt.exists => if (inImplicitSearch) - TermMemberNeedsResultTypeForImplicitSearch(cycleSym) + TermMemberNeedsResultTypeForImplicitSearch(this) else if (isMethod) - OverloadedOrRecursiveMethodNeedsResultType(cycleSym) + OverloadedOrRecursiveMethodNeedsResultType(this) else if (isVal) - RecursiveValueNeedsResultType(cycleSym) + RecursiveValueNeedsResultType(this) else errorMsg(cx.outer) case _ => @@ -174,22 +179,38 @@ class CyclicReference(val denot: SymDenotation)(using Context) extends TypeError // Give up and give generic errors. else if (cycleSym.isOneOf(GivenOrImplicitVal, butNot = Method) && cycleSym.owner.isTerm) - CyclicReferenceInvolvingImplicit(cycleSym) + CyclicReferenceInvolvingImplicit(this) else - CyclicReferenceInvolving(denot) + CyclicReferenceInvolving(this) errorMsg(ctx) end toMessage object CyclicReference: + def apply(denot: SymDenotation)(using Context): CyclicReference = - val ex = new CyclicReference(denot) + val ex = new CyclicReference(denot, ctx.property(Trace).map(_.toArray)) if ex.computeStackTrace then cyclicErrors.println(s"Cyclic reference involving $denot") val sts = ex.getStackTrace.asInstanceOf[Array[StackTraceElement]] for (elem <- sts take 200) cyclicErrors.println(elem.toString) ex + + type TraceElement = (/*prefix:*/ String, Symbol, /*suffix:*/ String) + type Trace = mutable.ArrayBuffer[TraceElement] + val Trace = Property.Key[Trace] + + def isTraced(using Context) = + ctx.property(CyclicReference.Trace).isDefined + + def pushTrace(info: TraceElement)(using Context): Unit = + for buf <- ctx.property(CyclicReference.Trace) do + buf += info + + def popTrace()(using Context): Unit = + for buf <- ctx.property(CyclicReference.Trace) do + buf.dropRightInPlace(1) end CyclicReference class UnpicklingError(denot: Denotation, where: String, cause: Throwable)(using Context) extends TypeError: diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index b7a25cb75613..b95e4df663a1 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -141,20 +141,25 @@ class TreeUnpickler(reader: TastyReader, val mode = ctx.mode val source = ctx.source def complete(denot: SymDenotation)(using Context): Unit = - def fail(ex: Throwable) = - def where = - val f = denot.symbol.associatedFile - if f == null then "" else s" in $f" - throw UnpicklingError(denot, where, ex) + def where = + val f = denot.symbol.associatedFile + if f == null then "" else s" in $f" + def fail(ex: Throwable) = throw UnpicklingError(denot, where, ex) treeAtAddr(currentAddr) = + val traceCycles = CyclicReference.isTraced try + if traceCycles then + CyclicReference.pushTrace("read the definition of ", denot.symbol, where) atPhaseBeforeTransforms { new TreeReader(reader).readIndexedDef()( using ctx.withOwner(owner).withModeBits(mode).withSource(source)) } catch + case ex: CyclicReference => throw ex case ex: AssertionError => fail(ex) case ex: Exception => fail(ex) + finally + if traceCycles then CyclicReference.popTrace() } class TreeReader(val reader: TastyReader) { diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index 4c7cf003cbc9..d91649e12edb 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -84,6 +84,23 @@ abstract class PatternMatchMsg(errorId: ErrorMessageID)(using Context) extends M abstract class CyclicMsg(errorId: ErrorMessageID)(using Context) extends Message(errorId): def kind = MessageKind.Cyclic + val ex: CyclicReference + protected def cycleSym = ex.denot.symbol + + protected def debugInfo = + if ctx.settings.YdebugCyclic.value then + "\n\nStacktrace:" ++ ex.getStackTrace().nn.mkString("\n ", "\n ", "") + else "\n\n Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace." + + protected def context: String = ex.optTrace match + case Some(trace) => + s"\n\nThe error occurred while trying to ${ + trace.map((prefix, sym, suffix) => i"$prefix$sym$suffix").mkString("\n which required to ") + }$debugInfo" + case None => + "\n\n Run with -explain-cyclic for more details." +end CyclicMsg + abstract class ReferenceMsg(errorId: ErrorMessageID)(using Context) extends Message(errorId): def kind = MessageKind.Reference @@ -1249,9 +1266,9 @@ class UnreducibleApplication(tycon: Type)(using Context) extends TypeMsg(Unreduc |Such applications are equivalent to existential types, which are not |supported in Scala 3.""" -class OverloadedOrRecursiveMethodNeedsResultType(cycleSym: Symbol)(using Context) +class OverloadedOrRecursiveMethodNeedsResultType(val ex: CyclicReference)(using Context) extends CyclicMsg(OverloadedOrRecursiveMethodNeedsResultTypeID) { - def msg(using Context) = i"""Overloaded or recursive $cycleSym needs return type""" + def msg(using Context) = i"""Overloaded or recursive $cycleSym needs return type$context""" def explain(using Context) = i"""Case 1: $cycleSym is overloaded |If there are multiple methods named $cycleSym and at least one definition of @@ -1263,29 +1280,29 @@ extends CyclicMsg(OverloadedOrRecursiveMethodNeedsResultTypeID) { |""" } -class RecursiveValueNeedsResultType(cycleSym: Symbol)(using Context) +class RecursiveValueNeedsResultType(val ex: CyclicReference)(using Context) extends CyclicMsg(RecursiveValueNeedsResultTypeID) { - def msg(using Context) = i"""Recursive $cycleSym needs type""" + def msg(using Context) = i"""Recursive $cycleSym needs type$context""" def explain(using Context) = i"""The definition of $cycleSym is recursive and you need to specify its type. |""" } -class CyclicReferenceInvolving(denot: SymDenotation)(using Context) +class CyclicReferenceInvolving(val ex: CyclicReference)(using Context) extends CyclicMsg(CyclicReferenceInvolvingID) { def msg(using Context) = - val where = if denot.exists then s" involving $denot" else "" - i"Cyclic reference$where" + val where = if ex.denot.exists then s" involving ${ex.denot}" else "" + i"Cyclic reference$where$context" def explain(using Context) = - i"""|$denot is declared as part of a cycle which makes it impossible for the - |compiler to decide upon ${denot.name}'s type. - |To avoid this error, try giving ${denot.name} an explicit type. + i"""|${ex.denot} is declared as part of a cycle which makes it impossible for the + |compiler to decide upon ${ex.denot.name}'s type. + |To avoid this error, try giving ${ex.denot.name} an explicit type. |""" } -class CyclicReferenceInvolvingImplicit(cycleSym: Symbol)(using Context) +class CyclicReferenceInvolvingImplicit(val ex: CyclicReference)(using Context) extends CyclicMsg(CyclicReferenceInvolvingImplicitID) { - def msg(using Context) = i"""Cyclic reference involving implicit $cycleSym""" + def msg(using Context) = i"""Cyclic reference involving implicit $cycleSym$context""" def explain(using Context) = i"""|$cycleSym is declared as part of a cycle which makes it impossible for the |compiler to decide upon ${cycleSym.name}'s type. @@ -2340,9 +2357,9 @@ class TypeTestAlwaysDiverges(scrutTp: Type, testTp: Type)(using Context) extends } // Relative of CyclicReferenceInvolvingImplicit and RecursiveValueNeedsResultType -class TermMemberNeedsResultTypeForImplicitSearch(cycleSym: Symbol)(using Context) +class TermMemberNeedsResultTypeForImplicitSearch(val ex: CyclicReference)(using Context) extends CyclicMsg(TermMemberNeedsNeedsResultTypeForImplicitSearchID) { - def msg(using Context) = i"""$cycleSym needs result type because its right-hand side attempts implicit search""" + def msg(using Context) = i"""$cycleSym needs result type because its right-hand side attempts implicit search$context""" def explain(using Context) = i"""|The right hand-side of $cycleSym's definition requires an implicit search at the highlighted position. |To avoid this error, give `$cycleSym` an explicit type. @@ -2553,8 +2570,9 @@ class UnknownNamedEnclosingClassOrObject(name: TypeName)(using Context) """ } -class IllegalCyclicTypeReference(sym: Symbol, where: String, lastChecked: Type)(using Context) +class IllegalCyclicTypeReference(val ex: CyclicReference, sym: Symbol, where: String, lastChecked: Type)(using Context) extends CyclicMsg(IllegalCyclicTypeReferenceID) { + override def context = "" def msg(using Context) = val lastCheckedStr = try lastChecked.show diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 3e5d65070a80..6d7db37d9aba 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -391,7 +391,7 @@ object Checking { catch { case ex: CyclicReference => if (reportErrors) - errorType(IllegalCyclicTypeReference(sym, checker.where, checker.lastChecked), sym.srcPos) + errorType(IllegalCyclicTypeReference(ex, sym, checker.where, checker.lastChecked), sym.srcPos) else info } } diff --git a/tests/neg-macros/i14772.check b/tests/neg-macros/i14772.check index 42f78b76754c..8decde2fc7fe 100644 --- a/tests/neg-macros/i14772.check +++ b/tests/neg-macros/i14772.check @@ -1,6 +1,11 @@ --- [E044] Cyclic Error: tests/neg-macros/i14772.scala:7:7 -------------------------------------------------------------- -7 | foo(a) // error +-- [E044] Cyclic Error: tests/neg-macros/i14772.scala:8:7 -------------------------------------------------------------- +8 | foo(a) // error | ^ | Overloaded or recursive method impl needs return type | + | The error occurred while trying to complete the info of method $anonfun + | which required to complete the info of method impl + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. + | | longer explanation available when compiling with `-explain` diff --git a/tests/neg-macros/i14772.scala b/tests/neg-macros/i14772.scala index a0cb3c5e857e..6437f5e87769 100644 --- a/tests/neg-macros/i14772.scala +++ b/tests/neg-macros/i14772.scala @@ -1,3 +1,4 @@ +//> using options -explain-cyclic import scala.quoted.* object A { diff --git a/tests/neg-macros/i16582.check b/tests/neg-macros/i16582.check index c06fe0d9829f..478534d20976 100644 --- a/tests/neg-macros/i16582.check +++ b/tests/neg-macros/i16582.check @@ -1,10 +1,16 @@ --- Error: tests/neg-macros/i16582/Test_2.scala:5:27 -------------------------------------------------------------------- -5 | val o2 = ownerDoesNotWork(2) // error +-- Error: tests/neg-macros/i16582/Test_2.scala:6:27 -------------------------------------------------------------------- +6 | val o2 = ownerDoesNotWork(2) // error | ^^^^^^^^^^^^^^^^^^^ | Exception occurred while executing macro expansion. | dotty.tools.dotc.core.CyclicReference: Recursive value o2 needs type | + | The error occurred while trying to complete the info of method test + | which required to complete the info of value o2 + | which required to complete the info of value o2 + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. + | | See full stack trace using -Ydebug |--------------------------------------------------------------------------------------------------------------------- |Inline stack trace diff --git a/tests/neg-macros/i16582/Test_2.scala b/tests/neg-macros/i16582/Test_2.scala index 7cfd65febd00..3b87f18f75c2 100644 --- a/tests/neg-macros/i16582/Test_2.scala +++ b/tests/neg-macros/i16582/Test_2.scala @@ -1,3 +1,4 @@ +//> using options -explain-cyclic def test= val o1 = ownerWorks(1) println(o1) diff --git a/tests/neg/cyclic.check b/tests/neg/cyclic.check new file mode 100644 index 000000000000..82c585c1c443 --- /dev/null +++ b/tests/neg/cyclic.check @@ -0,0 +1,14 @@ +-- [E044] Cyclic Error: tests/neg/cyclic.scala:6:12 -------------------------------------------------------------------- +6 | def i() = f() // error + | ^ + | Overloaded or recursive method f needs return type + | + | The error occurred while trying to complete the info of method f + | which required to complete the info of method g + | which required to complete the info of method h + | which required to complete the info of method i + | which required to complete the info of method f + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg/cyclic.scala b/tests/neg/cyclic.scala new file mode 100644 index 000000000000..e9ffbc164ea6 --- /dev/null +++ b/tests/neg/cyclic.scala @@ -0,0 +1,6 @@ +//> using options -explain-cyclic +object O: + def f() = g() + def g() = h() + def h() = i() + def i() = f() // error diff --git a/tests/neg/i10870.check b/tests/neg/i10870.check index 857eb128b19f..c8f9c500b95b 100644 --- a/tests/neg/i10870.check +++ b/tests/neg/i10870.check @@ -5,3 +5,5 @@ | Extension methods were tried, but the search failed with: | | Overloaded or recursive method x needs return type + | + | Run with -explain-cyclic for more details. diff --git a/tests/neg/i11994.check b/tests/neg/i11994.check index 24d18257ed9f..93ba04af3a1c 100644 --- a/tests/neg/i11994.check +++ b/tests/neg/i11994.check @@ -1,14 +1,26 @@ --- [E008] Not Found Error: tests/neg/i11994.scala:1:28 ----------------------------------------------------------------- -1 |implicit def foo[T <: Tuple.meow]: Unit = ??? // error +-- [E008] Not Found Error: tests/neg/i11994.scala:2:28 ----------------------------------------------------------------- +2 |implicit def foo[T <: Tuple.meow]: Unit = ??? // error | ^^^^^^^^^^ | type meow is not a member of object Tuple. | Extension methods were tried, but the search failed with: | | Cyclic reference involving method foo --- [E008] Not Found Error: tests/neg/i11994.scala:2:18 ----------------------------------------------------------------- -2 |given [T <: Tuple.meow]: Unit = ??? // error + | + | The error occurred while trying to complete the info of method foo + | which required to complete the info of type T + | which required to complete the info of method foo + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. +-- [E008] Not Found Error: tests/neg/i11994.scala:3:18 ----------------------------------------------------------------- +3 |given [T <: Tuple.meow]: Unit = ??? // error | ^^^^^^^^^^ | type meow is not a member of object Tuple. | Extension methods were tried, but the search failed with: | | Cyclic reference involving method given_Unit + | + | The error occurred while trying to complete the info of given instance given_Unit + | which required to complete the info of type T + | which required to complete the info of given instance given_Unit + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. diff --git a/tests/neg/i11994.scala b/tests/neg/i11994.scala index 373de300dd42..70468535f3ab 100644 --- a/tests/neg/i11994.scala +++ b/tests/neg/i11994.scala @@ -1,2 +1,3 @@ +//> using options -explain-cyclic implicit def foo[T <: Tuple.meow]: Unit = ??? // error given [T <: Tuple.meow]: Unit = ??? // error From 7240327109d386c336aa3c19b530f973ecd58e71 Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Wed, 10 Jan 2024 15:34:45 +0100 Subject: [PATCH 056/220] chore: Backport changes from Metals This includes: - https://github.com/scalameta/metals/pull/5956 - https://github.com/scalameta/metals/pull/5979 - https://github.com/scalameta/metals/pull/5994 - https://github.com/scalameta/metals/pull/5995 - https://github.com/scalameta/metals/pull/5998 - https://github.com/scalameta/metals/pull/5999 - https://github.com/scalameta/metals/pull/6000 --- .../tools/dotc/interactive/Interactive.scala | 6 +- .../tools/pc/CompilerSearchVisitor.scala | 1 + .../tools/pc/completions/CompletionPos.scala | 22 +- .../tools/pc/completions/Completions.scala | 29 ++- .../completions/InterpolatorCompletions.scala | 15 +- .../pc/completions/NamedArgCompletions.scala | 21 +- .../tests/completion/CompletionArgSuite.scala | 20 +- .../completion/CompletionKeywordSuite.scala | 50 +++-- .../completion/CompletionPatternSuite.scala | 5 +- .../completion/CompletionSnippetSuite.scala | 12 +- .../pc/tests/completion/CompletionSuite.scala | 146 ++++++++++++- .../highlight/DocumentHighlightSuite.scala | 203 +++++++++++++++++- .../tools/pc/tests/hover/HoverTermSuite.scala | 182 ++++++++++++++++ .../pc/tests/tokens/SemanticTokensSuite.scala | 24 ++- .../tools/pc/utils/MockSymbolSearch.scala | 2 +- project/Build.scala | 2 +- 16 files changed, 673 insertions(+), 67 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala index 3f3e5e25f66e..c181c340d66d 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala @@ -282,12 +282,10 @@ object Interactive { case nested :: encl :: rest => val outer = contextOfPath(encl :: rest) try encl match { - case tree @ PackageDef(pkg, stats) => - assert(tree.symbol.exists) + case tree @ PackageDef(pkg, stats) if tree.symbol.exists => if (nested `eq` pkg) outer else contextOfStat(stats, nested, pkg.symbol.moduleClass, outer.packageContext(tree, tree.symbol)) - case tree: DefDef => - assert(tree.symbol.exists) + case tree: DefDef if tree.symbol.exists => val localCtx = outer.localContext(tree, tree.symbol).setNewScope for params <- tree.paramss; param <- params do localCtx.enter(param.symbol) // Note: this overapproximates visibility a bit, since value parameters are only visible diff --git a/presentation-compiler/src/main/dotty/tools/pc/CompilerSearchVisitor.scala b/presentation-compiler/src/main/dotty/tools/pc/CompilerSearchVisitor.scala index d20537f0239e..231960ec5116 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/CompilerSearchVisitor.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/CompilerSearchVisitor.scala @@ -58,6 +58,7 @@ class CompilerSearchVisitor( .filter(denot => denot.exists) .map(_.symbol) .filter(isAccessible) + .filter(!_.is(Flags.Given)) } loop(next, tl) case Nil => owners diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionPos.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionPos.scala index a0cf6bafcf46..415bef2cff25 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionPos.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionPos.scala @@ -15,6 +15,7 @@ import dotty.tools.dotc.util.Spans import dotty.tools.pc.utils.MtagsEnrichments.* import org.eclipse.lsp4j as l +import scala.annotation.tailrec enum CompletionKind: case Empty, Scope, Members @@ -55,8 +56,10 @@ object CompletionPos: val prevIsDot = if start - 1 >= 0 then text.charAt(start - 1) == '.' else false val kind = - if query.nn.isEmpty() && !prevIsDot then CompletionKind.Empty - else if prevIsDot then CompletionKind.Members + if prevIsDot then CompletionKind.Members + else if isImportOrExportSelect(cursorPos, treePath) then + CompletionKind.Members + else if query.nn.isEmpty then CompletionKind.Empty else CompletionKind.Scope CompletionPos(kind, start, end, query.nn, cursorPos, uri) @@ -84,6 +87,21 @@ object CompletionPos: (i, tabIndented) end inferIndent + private def isImportOrExportSelect( + pos: SourcePosition, + path: List[Tree], + )(using Context): Boolean = + @tailrec + def loop(enclosing: List[Tree]): Boolean = + enclosing match + case head :: tl if !head.sourcePos.contains(pos) => loop(tl) + case (tree: (Import | Export)) :: _ => + tree.selectors.exists(_.imported.sourcePos.contains(pos)) + case _ => false + + loop(path) + + /** * Returns the start offset of the identifier starting as the given offset position. */ diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala index 118a9edae816..178d4a638745 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala @@ -72,8 +72,8 @@ class Completions( case _ :: (withcursor @ Select(fun, name)) :: (appl: GenericApply) :: _ if appl.fun == withcursor && name.decoded == Cursor.value => false - case (_: Import) :: _ => false - case _ :: (_: Import) :: _ => false + case (_: (Import | Export)) :: _ => false + case _ :: (_: (Import | Export)) :: _ => false case (_: Ident) :: (_: SeqLiteral) :: _ => false case _ => true @@ -140,7 +140,8 @@ class Completions( val application = CompletionApplication.fromPath(path) val ordering = completionOrdering(application) - val values = application.postProcess(all.sorted(ordering)) + val sorted = all.sorted(ordering) + val values = application.postProcess(sorted) (values, result) end completions @@ -441,6 +442,10 @@ class Completions( true, ) + case (tree: (Import | Export)) :: _ + if tree.selectors.exists(_.renamed.sourcePos.contains(pos)) => + (List.empty, true) + // From Scala 3.1.3-RC3 (as far as I know), path contains // `Literal(Constant(null))` on head for an incomplete program, in this case, just ignore the head. case Literal(Constant(null)) :: tl => @@ -791,7 +796,8 @@ class Completions( val fuzzyCache = mutable.Map.empty[CompletionValue, Int] def compareLocalSymbols(s1: Symbol, s2: Symbol): Int = - if s1.isLocal && s2.isLocal then + if s1.isLocal && s2.isLocal && s1.sourcePos.exists && s2.sourcePos.exists + then val firstIsAfter = s1.srcPos.isAfter(s2.srcPos) if firstIsAfter then -1 else 1 else 0 @@ -833,6 +839,16 @@ class Completions( priority(o1) - priority(o2) end compareInApplyParams + def prioritizeKeywords(o1: CompletionValue, o2: CompletionValue): Int = + def priority(v: CompletionValue): Int = + v match + case _: CompletionValue.CaseKeyword => 0 + case _: CompletionValue.NamedArg => 1 + case _: CompletionValue.Keyword => 2 + case _ => 3 + + priority(o1) - priority(o2) + end prioritizeKeywords /** * Some completion values should be shown first such as CaseKeyword and * NamedArg @@ -909,7 +925,10 @@ class Completions( case _ => val byApplyParams = compareInApplyParams(o1, o2) if byApplyParams != 0 then byApplyParams - else compareByRelevance(o1, o2) + else + val keywords = prioritizeKeywords(o1, o2) + if keywords != 0 then keywords + else compareByRelevance(o1, o2) end compare end Completions diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/InterpolatorCompletions.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/InterpolatorCompletions.scala index 1d063bc6d873..768f68a66300 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/InterpolatorCompletions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/InterpolatorCompletions.scala @@ -83,14 +83,13 @@ object InterpolatorCompletions: case _: Select => true case _ => false } => - val allLiterals = parent match - case SeqLiteral(elems, _) => - elems - case _ => Nil - expr.elems.zip(allLiterals.tail).collectFirst { - case (i: (Ident | Select), literal) if literal == lit => - i - } + parent match + case SeqLiteral(elems, _) if elems.size > 0 => + expr.elems.zip(elems.tail).collectFirst { + case (i: (Ident | Select), literal) if literal == lit => + i + } + case _ => None end interpolatorMemberArg /** diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/NamedArgCompletions.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/NamedArgCompletions.scala index e4ae4070edb9..d1f6b01f758e 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/NamedArgCompletions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/NamedArgCompletions.scala @@ -17,6 +17,7 @@ import dotty.tools.dotc.core.Names.Name import dotty.tools.dotc.core.StdNames.* import dotty.tools.dotc.core.SymDenotations.NoDenotation import dotty.tools.dotc.core.Symbols +import dotty.tools.dotc.core.Symbols.defn import dotty.tools.dotc.core.Symbols.NoSymbol import dotty.tools.dotc.core.Symbols.Symbol import dotty.tools.dotc.core.Types.AndType @@ -309,15 +310,17 @@ object NamedArgCompletions: val completionSymbols = indexedContext.scopeSymbols def matchingTypesInScope(paramType: Type): List[String] = - completionSymbols - .collect { - case sym - if sym.info <:< paramType && sym.isTerm && !sym.info.isErroneous && !sym.info.isNullType && !sym.info.isNothingType && !sym - .is(Flags.Method) && !sym.is(Flags.Synthetic) => - sym.decodedName - } - .filter(name => name != "Nil" && name != "None") - .sorted + if paramType != defn.AnyType then + completionSymbols + .collect { + case sym + if sym.info <:< paramType && sym.isTerm && !sym.info.isErroneous && !sym.info.isNullType && !sym.info.isNothingType && !sym + .is(Flags.Method) && !sym.is(Flags.Synthetic) => + sym.decodedName + } + .filter(name => name != "Nil" && name != "None") + .sorted + else Nil def findDefaultValue(param: ParamSymbol): String = val matchingType = matchingTypesInScope(param.info) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionArgSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionArgSuite.scala index 16d54cc124ca..61239b535e1c 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionArgSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionArgSuite.scala @@ -1047,7 +1047,7 @@ class CompletionArgSuite extends BaseCompletionSuite: | bbb = 123, | aa@@ | ) - |} + |} |""".stripMargin, """|aaa = : Int |""".stripMargin, @@ -1063,7 +1063,7 @@ class CompletionArgSuite extends BaseCompletionSuite: | ccc = 123, | aa@@ | ) - |} + |} |""".stripMargin, """|aaa = : Int |""".stripMargin, @@ -1079,7 +1079,7 @@ class CompletionArgSuite extends BaseCompletionSuite: | ccc = 123, | aa@@ | ) - |} + |} |""".stripMargin, """|aaa = : Int |""".stripMargin, @@ -1105,4 +1105,18 @@ class CompletionArgSuite extends BaseCompletionSuite: """|str = : String | """.stripMargin, topLines = Some(1), + ) + + @Test def `comparison` = + check( + """package a + |object w { + | abstract class T(x: Int) { + | def met(x: Int): Unit = { + | println(x@@) + | } + | }} + |""".stripMargin, + """x: Int + |x = : Any""".stripMargin, ) \ No newline at end of file diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionKeywordSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionKeywordSuite.scala index 583b138a255b..ec4fedf50f68 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionKeywordSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionKeywordSuite.scala @@ -38,7 +38,8 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | // tr@@ |} |""".stripMargin, - "", + """|transient scala (commit: '') + |transparentTrait - scala.annotation (commit: '')""".stripMargin, includeCommitCharacter = true ) @@ -57,7 +58,8 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | **/ |} |""".stripMargin, - "", + """|transient scala (commit: '') + |transparentTrait - scala.annotation (commit: '')""".stripMargin, includeCommitCharacter = true ) @@ -151,6 +153,8 @@ class CompletionKeywordSuite extends BaseCompletionSuite: """|value: Int |val |var + |varargs(): varargs + |varargs - scala.annotation |""".stripMargin ) @@ -167,6 +171,8 @@ class CompletionKeywordSuite extends BaseCompletionSuite: |""".stripMargin, """|val |var + |varargs(): varargs + |varargs - scala.annotation |""".stripMargin ) @@ -181,9 +187,10 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | } |} |""".stripMargin, - """|given (commit: '') - |""".stripMargin, - includeCommitCharacter = true + """given (commit: '') + |""".stripMargin, + includeCommitCharacter = true, + topLines = Some(5) ) @Test def `val-arg` = @@ -198,8 +205,8 @@ class CompletionKeywordSuite extends BaseCompletionSuite: |} |""".stripMargin, """|value: Int - |""".stripMargin, - topLines = Some(1) + |varargs(): varargs + |varargs - scala.annotation""".stripMargin ) @Test def `val-trailing-space` = @@ -406,7 +413,13 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | protected de@@ |} """.stripMargin, - "def" + """|def + |deprecated scala + |deprecatedInheritance scala + |deprecatedName scala + |deprecatedOverriding scala + |""".stripMargin, + topLines = Some(5) ) @Test def `protected-val` = @@ -418,9 +431,10 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | protected va@@ |} """.stripMargin, - """val - |var - |""".stripMargin + """|val + |var + |varargs - scala.annotation + |""".stripMargin ) @Test def `topLevel` = @@ -458,8 +472,13 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | def hello(u@@) |}""".stripMargin, """|using (commit: '') + |unsafeExceptions scala (commit: '') + |unchecked scala (commit: '') + |unsafe - scala.caps (commit: '') + |unsafeNulls - scala.runtime.stdLibPatches.language (commit: '') |""".stripMargin, - includeCommitCharacter = true + includeCommitCharacter = true, + topLines = Some(5) ) @Test def `not-using` = @@ -467,7 +486,12 @@ class CompletionKeywordSuite extends BaseCompletionSuite: """|object A{ | def hello(a: String, u@@) |}""".stripMargin, - "" + """|unsafeExceptions scala + |unchecked scala + |unsafe - scala.caps + |unsafeNulls - scala.runtime.stdLibPatches.language + |unused - scala.annotation """.stripMargin, + topLines = Some(5) ) @Test def `extends-class` = diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionPatternSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionPatternSuite.scala index 6d2261bbfe66..619ba523de0a 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionPatternSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionPatternSuite.scala @@ -54,7 +54,10 @@ class CompletionPatternSuite extends BaseCompletionSuite: | case ma@@ | } |}""".stripMargin, - "" + """|main scala + |macros - scala.languageFeature.experimental + |macroImpl - scala.reflect.macros.internal + |""".stripMargin ) @Test def `bind2` = diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSnippetSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSnippetSuite.scala index 586b70d54006..46e0fe7b1976 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSnippetSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSnippetSuite.scala @@ -323,7 +323,8 @@ class CompletionSnippetSuite extends BaseCompletionSuite: |Widget($0) - (age: Int): Widget |Widget($0) - (name: String, age: Int): Widget |""".stripMargin, - includeDetail = true + includeDetail = true, + topLines = Some(4) ) @Test def `no-apply` = @@ -335,8 +336,13 @@ class CompletionSnippetSuite extends BaseCompletionSuite: | Wi@@ |} |""".stripMargin, - "Widget - example", - includeDetail = true + """|Widget - example + |Window - java.awt + |WindowPeer - java.awt.peer + |WithFilter - scala.collection + |""".stripMargin, + includeDetail = true, + topLines = Some(4) ) // https://github.com/scalameta/metals/issues/4004 diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala index 055363830a1b..5bc04e89c678 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala @@ -618,9 +618,6 @@ class CompletionSuite extends BaseCompletionSuite: """|Some(value) scala |Some scala |Some[A](value: A): Some[A] - |SomeToExpr(x: Some[T])(using Quotes): Expr[Some[T]] - |SomeToExpr[T: Type: ToExpr]: SomeToExpr[T] - |SomeFromExpr[T](using Type[T], FromExpr[T]): SomeFromExpr[T] |""".stripMargin ) @@ -633,9 +630,6 @@ class CompletionSuite extends BaseCompletionSuite: |""".stripMargin, """|Some scala |Some[A](value: A): Some[A] - |SomeToExpr(x: Some[T])(using Quotes): Expr[Some[T]] - |SomeToExpr[T: Type: ToExpr]: SomeToExpr[T] - |SomeFromExpr[T](using Type[T], FromExpr[T]): SomeFromExpr[T] |""".stripMargin ) @@ -1329,6 +1323,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension (x: Fo@@) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1349,6 +1353,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension [A <: Fo@@] |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1369,6 +1383,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension (using Fo@@) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1380,6 +1404,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension (x: Int)(using Fo@@) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1390,6 +1424,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension (using Fo@@)(x: Int)(using Foo) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1400,6 +1444,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension (using Foo)(x: Int)(using Fo@@) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1410,6 +1464,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension [A](x: Fo@@) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1420,6 +1484,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension [A](using Fo@@)(x: Int) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1430,6 +1504,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension [A](using Foo)(x: Fo@@) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1440,6 +1524,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension [A](using Foo)(x: Fo@@)(using Foo) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1545,3 +1639,43 @@ class CompletionSuite extends BaseCompletionSuite: assertSingleItem = false ) + + @Test def `multi-export` = + check( + """export scala.collection.{AbstractMap, Set@@} + |""".stripMargin, + """Set scala.collection + |SetOps scala.collection + |""".stripMargin + ) + + @Test def `multi-imports` = + check( + """import scala.collection.{AbstractMap, Set@@} + |""".stripMargin, + """Set scala.collection + |SetOps scala.collection + |""".stripMargin, + ) + + + @Test def `multi-imports-empty-query` = + check( + """import scala.collection.{AbstractMap, @@} + |""".stripMargin, + """GenIterable scala.collection + |GenMap scala.collection + |GenSeq scala.collection + |GenSet scala.collection + |GenTraversable scala.collection + |""".stripMargin, + topLines = Some(5) + ) + + + @Test def `import-rename` = + check( + """import scala.collection.{AbstractMap => Set@@} + |""".stripMargin, + "" + ) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/highlight/DocumentHighlightSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/highlight/DocumentHighlightSuite.scala index 1dc2a7b156db..5d9893f6a1c1 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/highlight/DocumentHighlightSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/highlight/DocumentHighlightSuite.scala @@ -1186,7 +1186,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |""".stripMargin, ) - @Test def `constructor` = + @Test def `constructor` = check( """ |object Main { @@ -1195,7 +1195,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor1` = + @Test def `constructor1` = check( """ |object Main { @@ -1204,7 +1204,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor2` = + @Test def `constructor2` = check( """ |object Main { @@ -1214,7 +1214,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor3` = + @Test def `constructor3` = check( """ |object Main { @@ -1224,7 +1224,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor4` = + @Test def `constructor4` = check( """ |object Main { @@ -1234,7 +1234,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor5` = + @Test def `constructor5` = check( """ |object Main { @@ -1246,7 +1246,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor6` = + @Test def `constructor6` = check( """ |class <>[T](a: T) @@ -1256,7 +1256,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor7` = + @Test def `constructor7` = check( """ |object Bar { @@ -1268,7 +1268,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor8` = + @Test def `constructor8` = check( """ |object Bar { @@ -1279,3 +1279,188 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: | val x = Bar.<>[Int](2) |}""".stripMargin ) + + @Test def `i5630` = + check( + """|class MyIntOut(val value: Int) + |object MyIntOut: + | extension (i: MyIntOut) def <> = i.value % 2 == 1 + | + |val a = MyIntOut(1) + |val m = a.<> + |""".stripMargin + ) + + @Test def `i5630-2` = + check( + """|class MyIntOut(val value: Int) + |object MyIntOut: + | extension (i: MyIntOut) def <>(u: Int) = i.value % 2 == 1 + | + |val a = MyIntOut(1).<>(3) + |""".stripMargin + ) + + @Test def `i5630-infix` = + check( + """|class MyIntOut(val value: Int) + |object MyIntOut: + | extension (i: MyIntOut) def <<++>>(u: Int) = i.value + u + | + |val a = MyIntOut(1) <<+@@+>> 3 + |""".stripMargin + ) + + @Test def `i5921-1` = + check( + """|object Logarithms: + | opaque type Logarithm = Double + | extension [K](vmap: Logarithm) + | def <>(k: Logarithm): Logarithm = ??? + | + |object Test: + | val in: Logarithms.Logarithm = ??? + | in.<>(in) + |""".stripMargin + ) + + @Test def `i5921-2` = + check( + """|object Logarithms: + | opaque type Logarithm = Double + | extension [K](vmap: Logarithm) + | def <>(k: Logarithm): Logarithm = ??? + | + |object Test: + | val in: Logarithms.Logarithm = ??? + | in.<>(in) + |""".stripMargin + ) + + @Test def `i5921-3` = + check( + """|object Logarithms: + | opaque type Logarithm = Double + | extension [K](vmap: Logarithm) + | def <>(k: Logarithm): Logarithm = ??? + | (2.0).<>(1.0) + |""".stripMargin + ) + + @Test def `i5921-4` = + check( + """|object Logarithms: + | opaque type Logarithm = Double + | extension [K](vmap: Logarithm) + | def <>(k: Logarithm): Logarithm = ??? + | (2.0).<>(1.0) + |""".stripMargin + ) + + @Test def `i5977` = + check( + """ + |sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def <>[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Int](_.<>("str")) + | usage[Int](_.<>[String]("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>[String]("str")) + |} + |""".stripMargin + ) + + @Test def `i5977-1` = + check( + """ + |sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def <>[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Int](_.<>("str")) + | usage[Int](_.<>[String]("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>[String]("str")) + |} + |""".stripMargin + ) + + @Test def `i5977-2` = + check( + """ + |sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def <>[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Int](_.<>("str")) + | usage[Int](_.<>[String]("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>[String]("str")) + |} + |""".stripMargin + ) + + @Test def `i5977-3` = + check( + """ + |sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def <>[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Int](_.<>("str")) + | usage[Int](_.<>[String]("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>[String]("str")) + |} + |""".stripMargin + ) + + @Test def `i5977-4` = + check( + """ + |sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def <>[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Int](_.<>("str")) + | usage[Int](_.<>[String]("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>[String]("str")) + |} + |""".stripMargin + ) + + +end DocumentHighlightSuite diff --git a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala index 7ce81464fbd6..cf4682bd9a11 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala @@ -412,3 +412,185 @@ class HoverTermSuite extends BaseHoverSuite: |""".stripMargin, "def this(): tailrec".hover ) + + @Test def `i5630` = + check( + """class MyIntOut(val value: Int) + |object MyIntOut: + | extension (i: MyIntOut) def uneven = i.value % 2 == 1 + | + |val a = MyIntOut(1).un@@even + |""".stripMargin, + """extension (i: MyIntOut) def uneven: Boolean + |""".stripMargin.hover + ) + + @Test def `i5921` = + check( + """object Logarithms: + | trait Logarithm + | extension [K](vmap: Logarithm) + | def multiply(k: Logarithm): Logarithm = ??? + | + |object Test: + | val in: Logarithms.Logarithm = ??? + | in.multi@@ply(in) + |""".stripMargin, + "extension [K](vmap: Logarithm) def multiply(k: Logarithm): Logarithm".hover + ) + + @Test def `i5976` = + check( + """sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def noTypeArg: A + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Option[Int]](_.typeArg[Some[Int]].value.noTyp@@eArg.typeArg[Int]) + |} + |""".stripMargin, + """**Expression type**: + |```scala + |Int + |``` + |**Symbol signature**: + |```scala + |extension [A](self: A) def noTypeArg: A + |``` + |""".stripMargin + ) + + @Test def `i5976-1` = + check( + """sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def noTypeArg: A + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Option[Int]](_.type@@Arg[Some[Int]].value.noTypeArg.typeArg[Int]) + |} + |""".stripMargin, + """**Expression type**: + |```scala + |Some[Int] + |``` + |**Symbol signature**: + |```scala + |extension [A](self: A) def typeArg[B <: A]: B + |``` + |""".stripMargin + ) + + @Test def `i5977` = + check( + """sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def inferredTypeArg[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Option[Int]](_.infer@@redTypeArg("str")) + |} + |""".stripMargin, + """**Expression type**: + |```scala + |String + |``` + |**Symbol signature**: + |```scala + |extension [A](self: A) def inferredTypeArg[C](value: C): C + |``` + |""".stripMargin + ) + + @Test def `i5977-1` = + check( + """sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def inferredTypeArg[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Option[Int]](_.infer@@redTypeArg[String]("str")) + |} + |""".stripMargin, + """**Expression type**: + |```scala + |String + |``` + |**Symbol signature**: + |```scala + |extension [A](self: A) def inferredTypeArg[C](value: C): C + |``` + |""".stripMargin + ) + + @Test def `i5977-2` = + check( + """sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def inferredTypeArg[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Option[Int]](_.typeArg[Some[Int]].value.infer@@redTypeArg("str")) + |} + |""".stripMargin, + """**Expression type**: + |```scala + |String + |``` + |**Symbol signature**: + |```scala + |extension [A](self: A) def inferredTypeArg[C](value: C): C + |``` + |""".stripMargin + ) + + @Test def `i5977-3` = + check( + """sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def inferredTypeArg[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Option[Int]](_.typeArg[Some[Int]].value.infer@@redTypeArg[String]("str")) + |} + |""".stripMargin, + """**Expression type**: + |```scala + |String + |``` + |**Symbol signature**: + |```scala + |extension [A](self: A) def inferredTypeArg[C](value: C): C + |``` + |""".stripMargin + ) \ No newline at end of file diff --git a/presentation-compiler/test/dotty/tools/pc/tests/tokens/SemanticTokensSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/tokens/SemanticTokensSuite.scala index e18e37188141..fd90a8dfaca0 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/tokens/SemanticTokensSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/tokens/SemanticTokensSuite.scala @@ -285,7 +285,7 @@ class SemanticTokensSuite extends BaseSemanticTokensSuite: |}""".stripMargin ) - @Test def `predef1` = + @Test def `predef1` = check( """ |object <
>/*class*/ { @@ -296,7 +296,7 @@ class SemanticTokensSuite extends BaseSemanticTokensSuite: |""".stripMargin ) - @Test def `val-object` = + @Test def `val-object` = check( """ |case class <>/*class*/(<>/*variable,declaration,readonly*/: <>/*class,abstract*/) @@ -411,4 +411,24 @@ class SemanticTokensSuite extends BaseSemanticTokensSuite: | } | val <>/*variable,definition,readonly*/ = <>/*class*/(123, 456) |}""".stripMargin + ) + + @Test def `i5977` = + check( + """ + |sealed trait <>/*interface,abstract*/ { + | extension [<>/*typeParameter,definition,abstract*/] (<>/*parameter,declaration,readonly*/: <>/*typeParameter,abstract*/) { + | def <>/*method,declaration*/[<>/*typeParameter,definition,abstract*/]: <>/*typeParameter,abstract*/ + | def <>/*method,declaration*/[<>/*typeParameter,definition,abstract*/](<>/*parameter,declaration,readonly*/: <>/*typeParameter,abstract*/): <>/*typeParameter,abstract*/ + |} + | + |object <>/*class*/ { + | def <>/*method,definition*/[<>/*typeParameter,definition,abstract*/](<>/*parameter,declaration,readonly*/: <>/*interface,abstract*/ ?=> <>/*typeParameter,abstract*/ => <>/*class,abstract*/): <>/*class,abstract*/ = <>/*method*/ + | + | <>/*method*/[<>/*class,abstract*/](<<_>>/*parameter,readonly*/.<>/*method*/("str")) + | <>/*method*/[<>/*class,abstract*/](<<_>>/*parameter,readonly*/.<>/*method*/[<>/*type*/]("str")) + | <>/*method*/[<
diff --git a/library/src/scala/runtime/stdLibPatches/language.scala b/library/src/scala/runtime/stdLibPatches/language.scala index d74bb1376912..70d5f2d41907 100644 --- a/library/src/scala/runtime/stdLibPatches/language.scala +++ b/library/src/scala/runtime/stdLibPatches/language.scala @@ -13,7 +13,7 @@ object language: * code should not rely on them. * * Programmers are encouraged to try out experimental features and - * [[https://github.com/lampepfl/dotty/issues report any bugs or API inconsistencies]] + * [[https://github.com/scala/scala3/issues report any bugs or API inconsistencies]] * they encounter so they can be improved in future releases. * * @group experimental diff --git a/presentation-compiler/src/main/dotty/tools/pc/HoverProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/HoverProvider.scala index a36ce83e6aa0..6f39b4871a06 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/HoverProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/HoverProvider.scala @@ -109,7 +109,7 @@ object HoverProvider: val exprTpw = tpe.widenTermRefExpr.metalsDealias val hoverString = tpw match - // https://github.com/lampepfl/dotty/issues/8891 + // https://github.com/scala/scala3/issues/8891 case tpw: ImportType => printer.hoverSymbol(symbol, symbol.paramRef) case _ => diff --git a/presentation-compiler/src/main/dotty/tools/pc/MetalsInteractive.scala b/presentation-compiler/src/main/dotty/tools/pc/MetalsInteractive.scala index 2c2897e401a1..381e0eaec6a5 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/MetalsInteractive.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/MetalsInteractive.scala @@ -220,7 +220,7 @@ object MetalsInteractive: then List((head.symbol, head.typeOpt)) /* Type tree for List(1) has an Int type variable, which has span * but doesn't exist in code. - * https://github.com/lampepfl/dotty/issues/15937 + * https://github.com/scala/scala3/issues/15937 */ else if head.isInstanceOf[TypeTree] then enclosingSymbolsWithExpressionType(tail, pos, indexed) diff --git a/presentation-compiler/src/main/dotty/tools/pc/PcCollector.scala b/presentation-compiler/src/main/dotty/tools/pc/PcCollector.scala index 310edd60d87e..60def237badb 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/PcCollector.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/PcCollector.scala @@ -57,13 +57,13 @@ abstract class PcCollector[T]( .pathTo(driver.openedTrees(uri), pos)(using driver.currentCtx) .dropWhile(t => // NamedArg anyway doesn't have symbol t.symbol == NoSymbol && !t.isInstanceOf[NamedArg] || - // same issue https://github.com/lampepfl/dotty/issues/15937 as below + // same issue https://github.com/scala/scala3/issues/15937 as below t.isInstanceOf[TypeTree] ) val path = rawPath match // For type it will sometimes go into the wrong tree since TypeTree also contains the same span - // https://github.com/lampepfl/dotty/issues/15937 + // https://github.com/scala/scala3/issues/15937 case TypeApply(sel: Select, _) :: tail if sel.span.contains(pos.span) => Interactive.pathTo(sel, pos.span) ::: rawPath case _ => rawPath @@ -583,7 +583,7 @@ abstract class PcCollector[T]( t } - // NOTE: Connected to https://github.com/lampepfl/dotty/issues/16771 + // NOTE: Connected to https://github.com/scala/scala3/issues/16771 // `sel.nameSpan` is calculated incorrectly in (1 + 2).toString // See test DocumentHighlightSuite.select-parentheses private def selectNameSpan(sel: Select): Span = diff --git a/presentation-compiler/src/main/dotty/tools/pc/SemanticdbSymbols.scala b/presentation-compiler/src/main/dotty/tools/pc/SemanticdbSymbols.scala index da8add9df327..d298a88fc655 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/SemanticdbSymbols.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/SemanticdbSymbols.scala @@ -118,8 +118,8 @@ object SemanticdbSymbols: b.toString /** - * Taken from https://github.com/lampepfl/dotty/blob/2db43dae1480825227eb30d291b0dd0f0494e0f6/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala#L293 - * In future might be replaced by usage of compiler implementation after merging https://github.com/lampepfl/dotty/pull/12885 + * Taken from https://github.com/scala/scala3/blob/2db43dae1480825227eb30d291b0dd0f0494e0f6/compiler/src/dotty/tools/dotc/semanticdb/ExtractSemanticDB.scala#L293 + * In future might be replaced by usage of compiler implementation after merging https://github.com/scala/scala3/pull/12885 */ private def addSymName(b: StringBuilder, sym: Symbol)(using Context): Unit = diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala index 9d46a460850a..710e91750362 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala @@ -157,7 +157,7 @@ class CompletionProvider( // For overloaded signatures we get multiple symbols, so we need // to recalculate the description - // related issue https://github.com/lampepfl/dotty/issues/11941 + // related issue https://github.com/scala/scala3/issues/11941 lazy val kind: CompletionItemKind = completion.completionItemKind val description = completion.description(printer) val label = completion.labelWithDescription(printer) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala index 8f47582e4806..68e9f7728a87 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala @@ -888,7 +888,7 @@ class CompletionSuite extends BaseCompletionSuite: topLines = Some(2) ) - // issues with scala 3 https://github.com/lampepfl/dotty/pull/13515 + // issues with scala 3 https://github.com/scala/scala3/pull/13515 @Test def ordering4 = check( s"""|class Main { diff --git a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala index bd044b55528a..82fd0c657e67 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala @@ -112,7 +112,7 @@ class HoverTermSuite extends BaseHoverSuite: | } |} |""".stripMargin, - // https://github.com/lampepfl/dotty/issues/8835 + // https://github.com/scala/scala3/issues/8835 """|object num: a.Xtension |""".stripMargin.hover ) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTypeSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTypeSuite.scala index 269dc25069a5..c6e2590f8f29 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTypeSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTypeSuite.scala @@ -41,7 +41,7 @@ class HoverTypeSuite extends BaseHoverSuite: ) // We should produce a shorter type but: - // https://github.com/lampepfl/dotty/issues/11683 + // https://github.com/scala/scala3/issues/11683 @Test def `enums` = check( """| @@ -125,7 +125,7 @@ class HoverTypeSuite extends BaseHoverSuite: * As user can actually supply params to them by hand when * invoking the extension method, we always show them next to the * method itself. - * https://github.com/lampepfl/dotty/issues/13123 + * https://github.com/scala/scala3/issues/13123 */ @Test def `extension-methods-complex` = check( diff --git a/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpSuite.scala index 01d5e03b6c1e..c1b51b127fd6 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpSuite.scala @@ -191,7 +191,7 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: |""".stripMargin ) - // https://github.com/lampepfl/dotty/issues/15244 + // https://github.com/scala/scala3/issues/15244 @Test def `vararg` = check( """ diff --git a/project/scripts/bootstrappedOnlyCmdTests b/project/scripts/bootstrappedOnlyCmdTests index 8a0f5cf78f2f..4e18e3a1d4a4 100755 --- a/project/scripts/bootstrappedOnlyCmdTests +++ b/project/scripts/bootstrappedOnlyCmdTests @@ -113,7 +113,7 @@ scala_version=${versionProps[2]} echo "testing -sourcepath with incremental compile: inlining changed inline def into a def" # Here we will test that a changed inline method symbol loaded from the sourcepath (-sourcepath compiler option) # will have its `defTree` correctly set when its method body is required for inlining. -# So far I have not found a way to replicate issue https://github.com/lampepfl/dotty/issues/13994 +# So far I have not found a way to replicate issue https://github.com/scala/scala3/issues/13994 # with sbt scripted tests, if a way is found, move this test there. cwd=$(pwd) sbt_test_command="++${scala_version}!;clean;prepareSources;compile;copyChanges;compile" @@ -126,7 +126,7 @@ echo "testing -sourcepath with incremental compile: hashing reference to changed # Here we will test that a changed inline method symbol loaded from the sourcepath (-sourcepath compiler option) # will have its `defTree` correctly set when its method body is hashed by extractAPI, when referenced from another # inline method. -# So far I have not found a way to replicate https://github.com/lampepfl/dotty/pull/12931#discussion_r753212124 +# So far I have not found a way to replicate https://github.com/scala/scala3/pull/12931#discussion_r753212124 # with sbt scripted tests, if a way is found, move this test there. cwd=$(pwd) sbt_test_dir="$cwd/tests/cmdTest-sbt-tests/sourcepath-with-inline-api-hash" diff --git a/sbt-bridge/src/dotty/tools/xsbt/CompilerBridgeDriver.java b/sbt-bridge/src/dotty/tools/xsbt/CompilerBridgeDriver.java index 2d54d4e83404..20256d9e17cc 100644 --- a/sbt-bridge/src/dotty/tools/xsbt/CompilerBridgeDriver.java +++ b/sbt-bridge/src/dotty/tools/xsbt/CompilerBridgeDriver.java @@ -79,7 +79,7 @@ private static void reportMissingFile(DelegatingReporter reporter, SourceFile so underline + "\n" + " Falling back to placeholder for the given source file (of class " + sourceFile.getClass().getName() + ")\n" + " This is likely a bug in incremental compilation for the Scala 3 compiler.\n" + - " Please report it to the Scala 3 maintainers at https://github.com/lampepfl/dotty/issues."; + " Please report it to the Scala 3 maintainers at https://github.com/scala/scala3/issues."; reporter.reportBasicWarning(message); } diff --git a/sbt-bridge/src/xsbt/CachedCompilerImpl.java b/sbt-bridge/src/xsbt/CachedCompilerImpl.java index 8b7779f9c9cb..c9d4c50485ed 100644 --- a/sbt-bridge/src/xsbt/CachedCompilerImpl.java +++ b/sbt-bridge/src/xsbt/CachedCompilerImpl.java @@ -18,7 +18,7 @@ import dotty.tools.dotc.sbt.interfaces.IncrementalCallback; // deprecation warnings are suppressed because scala3-sbt-bridge must stay compatible with Zinc 1.3 -// see https://github.com/lampepfl/dotty/issues/10816 +// see https://github.com/scala/scala3/issues/10816 @SuppressWarnings("deprecation") public class CachedCompilerImpl implements CachedCompiler { private final String[] args; diff --git a/sbt-test/sbt-bridge/zinc-13-compat/test b/sbt-test/sbt-bridge/zinc-13-compat/test index f7b3295e155c..aecadb2f539d 100644 --- a/sbt-test/sbt-bridge/zinc-13-compat/test +++ b/sbt-test/sbt-bridge/zinc-13-compat/test @@ -1,3 +1,3 @@ # this little app test that scala3-sbt-bridge is compatible with Zinc 1.3 -# this is necessary to maintain the compatibility with Bloop (see https://github.com/lampepfl/dotty/issues/10816) +# this is necessary to maintain the compatibility with Bloop (see https://github.com/scala/scala3/issues/10816) > run diff --git a/sbt-test/sbt-dotty/scaladoc/src/main/scala/MultiversalEquality.scala b/sbt-test/sbt-dotty/scaladoc/src/main/scala/MultiversalEquality.scala index a4089e75de19..b8ebaf5565df 100644 --- a/sbt-test/sbt-dotty/scaladoc/src/main/scala/MultiversalEquality.scala +++ b/sbt-test/sbt-dotty/scaladoc/src/main/scala/MultiversalEquality.scala @@ -4,7 +4,7 @@ import scala.language.strictEquality /** * Multiversal Equality: https://dotty.epfl.ch/docs/reference/contextual/multiversal-equality.html - * scala.Eq definition: https://github.com/lampepfl/dotty/blob/master/library/src/scala/CanEqual.scala + * scala.Eq definition: https://github.com/scala/scala3/blob/master/library/src/scala/CanEqual.scala */ object MultiversalEquality { diff --git a/sbt-test/sbt-dotty/tasty-inspector-cache/inspector/src/main/scala/main.scala b/sbt-test/sbt-dotty/tasty-inspector-cache/inspector/src/main/scala/main.scala index 8335a016578f..b17747aa3ccf 100644 --- a/sbt-test/sbt-dotty/tasty-inspector-cache/inspector/src/main/scala/main.scala +++ b/sbt-test/sbt-dotty/tasty-inspector-cache/inspector/src/main/scala/main.scala @@ -2,7 +2,7 @@ import scala.quoted.Quotes import scala.quoted.quotes import scala.tasty.inspector as ins -// Test for https://github.com/lampepfl/dotty/issues/13919 +// Test for https://github.com/scala/scala3/issues/13919 class MyInspector extends ins.Inspector: def inspect(using Quotes)(tastys: List[ins.Tasty[quotes.type]]): Unit = import quotes.reflect._ diff --git a/sbt-test/source-dependencies/malformed-class-name-with-dollar/test b/sbt-test/source-dependencies/malformed-class-name-with-dollar/test index cf2dc1898f3e..bc71a440925e 100644 --- a/sbt-test/source-dependencies/malformed-class-name-with-dollar/test +++ b/sbt-test/source-dependencies/malformed-class-name-with-dollar/test @@ -1,5 +1,5 @@ > compile $ copy-file changes/A.scala A.scala -# It seems that https://github.com/lampepfl/dotty/pull/10784 break incremental compilation here +# It seems that https://github.com/scala/scala3/pull/10784 break incremental compilation here > clean > compile diff --git a/scaladoc-testcases/src/tests/nonScala3Parent.scala b/scaladoc-testcases/src/tests/nonScala3Parent.scala index 91183d25b583..c5a29b2d6132 100644 --- a/scaladoc-testcases/src/tests/nonScala3Parent.scala +++ b/scaladoc-testcases/src/tests/nonScala3Parent.scala @@ -4,7 +4,7 @@ package nonScala3Parent import javax.swing.JPanel import javax.swing.JFrame -// https://github.com/lampepfl/dotty/issues/15927 +// https://github.com/scala/scala3/issues/15927 trait Foo1 extends Numeric[Any] trait Foo2 extends JPanel diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala index 35cf1cb6eec3..373a26dd0297 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala @@ -298,7 +298,7 @@ trait TypesSupport: } case tpe => - val msg = s"Encountered unsupported type. Report this problem to https://github.com/lampepfl/dotty/.\n" + + val msg = s"Encountered unsupported type. Report this problem to https://github.com/scala/scala3/.\n" + s"${tpe.show(using Printer.TypeReprStructure)}" throw MatchError(msg) diff --git a/scaladoc/test/dotty/tools/scaladoc/ScaladocTest.scala b/scaladoc/test/dotty/tools/scaladoc/ScaladocTest.scala index 540364ec10bf..0c8211865928 100644 --- a/scaladoc/test/dotty/tools/scaladoc/ScaladocTest.scala +++ b/scaladoc/test/dotty/tools/scaladoc/ScaladocTest.scala @@ -27,7 +27,7 @@ abstract class ScaladocTest(val name: String): tastyFiles = tastyFiles(name), output = getTempDir().getRoot, projectVersion = Some("1.0"), - sourceLinks = List("github://lampepfl/dotty/master") + sourceLinks = List("github://scala/scala3/master") ) @Test diff --git a/tests/explicit-nulls/pos/nn2.scala b/tests/explicit-nulls/pos/nn2.scala index a39618b97f22..6c2c67396899 100644 --- a/tests/explicit-nulls/pos/nn2.scala +++ b/tests/explicit-nulls/pos/nn2.scala @@ -1,5 +1,5 @@ // Test that is fixed when explicit nulls are enabled. -// https://github.com/lampepfl/dotty/issues/6247 +// https://github.com/scala/scala3/issues/6247 class Foo { val x1: String|Null = null diff --git a/tests/init/pos/i9795.scala b/tests/init/pos/i9795.scala index 33c13b2eb592..0968dfeb2589 100644 --- a/tests/init/pos/i9795.scala +++ b/tests/init/pos/i9795.scala @@ -2,6 +2,6 @@ class A: // Safe initialization check only allows capturing `this` either through primary constructor or synthetic `apply` // `Some` case class comes from Scala 2 stdlib, which is not visible, hence the warning // For reference: - // https://github.com/lampepfl/dotty/pull/12711 - // https://github.com/lampepfl/dotty/pull/14283 + // https://github.com/scala/scala3/pull/12711 + // https://github.com/scala/scala3/pull/14283 val some = Some(this) diff --git a/tests/neg/i11118.scala b/tests/neg/i11118.scala index 23d9b2b604b6..a94bfce47640 100644 --- a/tests/neg/i11118.scala +++ b/tests/neg/i11118.scala @@ -1,2 +1,2 @@ -// https://github.com/lampepfl/dotty/issues/11118 +// https://github.com/scala/scala3/issues/11118 val (a,b) = (1,2,3) // error // warning diff --git a/tests/neg/i4060.scala b/tests/neg/i4060.scala index ba641d633d3c..bd16ed867966 100644 --- a/tests/neg/i4060.scala +++ b/tests/neg/i4060.scala @@ -1,6 +1,6 @@ //> using options -language:experimental.erasedDefinitions -// See https://github.com/lampepfl/dotty/issues/4060#issuecomment-445808377 +// See https://github.com/scala/scala3/issues/4060#issuecomment-445808377 object App { trait A { type L >: Any} diff --git a/tests/pos-macros/i9361.scala b/tests/pos-macros/i9361.scala index 18efd203d885..abd711bbfcaa 100644 --- a/tests/pos-macros/i9361.scala +++ b/tests/pos-macros/i9361.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/9361 +// https://github.com/scala/scala3/issues/9361 import scala.quoted._ diff --git a/tests/pos-with-compiler-cc/backend/jvm/BCodeHelpers.scala b/tests/pos-with-compiler-cc/backend/jvm/BCodeHelpers.scala index 2454bca9d653..5ad6a99f6055 100644 --- a/tests/pos-with-compiler-cc/backend/jvm/BCodeHelpers.scala +++ b/tests/pos-with-compiler-cc/backend/jvm/BCodeHelpers.scala @@ -833,7 +833,7 @@ trait BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { case tp => report.warning( s"an unexpected type representation reached the compiler backend while compiling ${ctx.compilationUnit}: $tp. " + - "If possible, please file a bug on https://github.com/lampepfl/dotty/issues") + "If possible, please file a bug on https://github.com/scala/scala3/issues") tp match { case tp: ThisType if tp.cls == defn.ArrayClass => ObjectRef.asInstanceOf[ct.bTypes.ClassBType] // was introduced in 9b17332f11 to fix SI-999, but this code is not reached in its test, or any other test @@ -874,7 +874,7 @@ trait BCodeHelpers extends BCodeIdiomatic with BytecodeWriters { report.error( em"""|compiler bug: created invalid generic signature for $sym in ${sym.denot.owner.showFullName} |signature: $sig - |if this is reproducible, please report bug at https://github.com/lampepfl/dotty/issues + |if this is reproducible, please report bug at https://github.com/scala/scala3/issues """, sym.sourcePos) throw ex } diff --git a/tests/pos-with-compiler-cc/backend/jvm/BCodeSkelBuilder.scala b/tests/pos-with-compiler-cc/backend/jvm/BCodeSkelBuilder.scala index 1d8a9c579cb9..125ee26b0528 100644 --- a/tests/pos-with-compiler-cc/backend/jvm/BCodeSkelBuilder.scala +++ b/tests/pos-with-compiler-cc/backend/jvm/BCodeSkelBuilder.scala @@ -131,7 +131,7 @@ trait BCodeSkelBuilder extends BCodeHelpers { // Should we do this transformation earlier, say in Constructors? Or would that just cause // pain for scala-{js, native}? // - // @sjrd (https://github.com/lampepfl/dotty/pull/9181#discussion_r457458205): + // @sjrd (https://github.com/scala/scala3/pull/9181#discussion_r457458205): // moving that before the back-end would make things significantly more complicated for // Scala.js and Native. Both have a first-class concept of ModuleClass, and encode the // singleton pattern of MODULE$ in a completely different way. In the Scala.js IR, there @@ -142,7 +142,7 @@ trait BCodeSkelBuilder extends BCodeHelpers { // TODO: remove `!f.name.is(LazyBitMapName)` once we change lazy val encoding - // https://github.com/lampepfl/dotty/issues/7140 + // https://github.com/scala/scala3/issues/7140 // // Lazy val encoding assumes bitmap fields are non-static // diff --git a/tests/pos-with-compiler-cc/backend/jvm/DottyBackendInterface.scala b/tests/pos-with-compiler-cc/backend/jvm/DottyBackendInterface.scala index a70d671f9c63..6ce434015b8c 100644 --- a/tests/pos-with-compiler-cc/backend/jvm/DottyBackendInterface.scala +++ b/tests/pos-with-compiler-cc/backend/jvm/DottyBackendInterface.scala @@ -126,7 +126,7 @@ object DottyBackendInterface { * See also `genPlainClass` in `BCodeSkelBuilder.scala`. * * TODO: remove the special handing of `LazyBitMapName` once we swtich to - * the new lazy val encoding: https://github.com/lampepfl/dotty/issues/7140 + * the new lazy val encoding: https://github.com/scala/scala3/issues/7140 */ def isStaticModuleField(using Context): Boolean = sym.owner.isStaticModuleClass && sym.isField && !sym.name.is(LazyBitMapName) diff --git a/tests/pos/erasure-array.scala b/tests/pos/erasure-array.scala index 63240e9801f0..83dc2a423306 100644 --- a/tests/pos/erasure-array.scala +++ b/tests/pos/erasure-array.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/1065 +// https://github.com/scala/scala3/issues/1065 package hello object world { diff --git a/tests/pos/i10242.scala b/tests/pos/i10242.scala index 10883633971e..b4a9700e1634 100644 --- a/tests/pos/i10242.scala +++ b/tests/pos/i10242.scala @@ -1,6 +1,6 @@ //> using options -source:3.3 -// https://github.com/lampepfl/dotty/issues/10242 +// https://github.com/scala/scala3/issues/10242 type Foo[A, B <: A] = A type Bar[A] = A match { diff --git a/tests/pos/i11681.scala b/tests/pos/i11681.scala index 587285911610..3374cbf9a4af 100644 --- a/tests/pos/i11681.scala +++ b/tests/pos/i11681.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/11681 +// https://github.com/scala/scala3/issues/11681 import scala.collection.Factory diff --git a/tests/pos/i12663.scala b/tests/pos/i12663.scala index befbc65316cb..dc446acb6bdf 100644 --- a/tests/pos/i12663.scala +++ b/tests/pos/i12663.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/12663 +// https://github.com/scala/scala3/issues/12663 final class HookComponentBuilder[Ctx, CtxFn[_]] { def asd[A](f: Ctx => A): A = ??? diff --git a/tests/pos/i12679.scala b/tests/pos/i12679.scala index fed62c72dd42..3fb14a8a91ed 100644 --- a/tests/pos/i12679.scala +++ b/tests/pos/i12679.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/12679 +// https://github.com/scala/scala3/issues/12679 object Example: def foo[F[_]](qux: String, quux: String = ""): F[Unit] = ??? diff --git a/tests/pos/i14096.scala b/tests/pos/i14096.scala index 59365231b121..49f80332483a 100644 --- a/tests/pos/i14096.scala +++ b/tests/pos/i14096.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/14096 +// https://github.com/scala/scala3/issues/14096 object Test: object Forte: def test[T](i: Int, config: String = ""): Int = 1 diff --git a/tests/pos/i14271.scala b/tests/pos/i14271.scala index 8f46940afd09..d29cf306617a 100644 --- a/tests/pos/i14271.scala +++ b/tests/pos/i14271.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/14271 +// https://github.com/scala/scala3/issues/14271 class Bound[T] class MyClass[T <: Bound[T]] diff --git a/tests/pos/i14278.scala b/tests/pos/i14278.scala index ebc9376fbad5..09feb75a0c6f 100644 --- a/tests/pos/i14278.scala +++ b/tests/pos/i14278.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/14278 +// https://github.com/scala/scala3/issues/14278 class Foo extension (foo: Foo) diff --git a/tests/pos/i14642.scala b/tests/pos/i14642.scala index b69da7d8d6d7..f380c404bd03 100644 --- a/tests/pos/i14642.scala +++ b/tests/pos/i14642.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/14642 +// https://github.com/scala/scala3/issues/14642 case object A case class B() case class C() diff --git a/tests/pos/i14830.scala b/tests/pos/i14830.scala index 592a47c1a53c..6664bd44ea4a 100644 --- a/tests/pos/i14830.scala +++ b/tests/pos/i14830.scala @@ -1,5 +1,5 @@ -// https://github.com/lampepfl/dotty/issues/14830 +// https://github.com/scala/scala3/issues/14830 val a: Comparable[String] = "Fred" val b: { def length: Int } = "Fred" val c: Comparable[String] & { def length: Int } = "Fred" diff --git a/tests/pos/i15546.scala b/tests/pos/i15546.scala index 19c7f15b24f1..86303e283baa 100644 --- a/tests/pos/i15546.scala +++ b/tests/pos/i15546.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/15546 +// https://github.com/scala/scala3/issues/15546 trait Foo[F[_]] diff --git a/tests/pos/i5700.scala b/tests/pos/i5700.scala index 69892dea16f4..89e8ca025c64 100644 --- a/tests/pos/i5700.scala +++ b/tests/pos/i5700.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/5700 +// https://github.com/scala/scala3/issues/5700 object noRecursionLimit: type M = { type T[+A]; type Ev >: T[Any] <: T[Nothing] } val M: M = ().asInstanceOf[M] diff --git a/tests/pos/i7414.scala b/tests/pos/i7414.scala index fd85ed2a2265..2c65b6cce466 100644 --- a/tests/pos/i7414.scala +++ b/tests/pos/i7414.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/7414 +// https://github.com/scala/scala3/issues/7414 object DepTest { trait Trait { diff --git a/tests/pos/i7445a.scala b/tests/pos/i7445a.scala index 2b54166de3f0..c23a5ebd12b9 100644 --- a/tests/pos/i7445a.scala +++ b/tests/pos/i7445a.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/7445 +// https://github.com/scala/scala3/issues/7445 object Main { type O1[A] = { diff --git a/tests/pos/i7445b.scala b/tests/pos/i7445b.scala index 1d49479ef0a5..0f6859fdb5c3 100644 --- a/tests/pos/i7445b.scala +++ b/tests/pos/i7445b.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/7445 +// https://github.com/scala/scala3/issues/7445 type O1[A] = { type OutInner[Ts] <: Tuple = Ts match { diff --git a/tests/pos/i7653.scala b/tests/pos/i7653.scala index 8511b6eef69b..61c75634d10e 100644 --- a/tests/pos/i7653.scala +++ b/tests/pos/i7653.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/7653 +// https://github.com/scala/scala3/issues/7653 object options2 { type Option[T] = { diff --git a/tests/pos/i7790.scala b/tests/pos/i7790.scala index 0a0e2d2ce347..d2dfc5c892a4 100644 --- a/tests/pos/i7790.scala +++ b/tests/pos/i7790.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/7790 +// https://github.com/scala/scala3/issues/7790 trait Foo: given Int = 10 def map(f: Int ?=> Int) = f diff --git a/tests/pos/i7807.scala b/tests/pos/i7807.scala index df8a41ddcf8d..118ad77c58c4 100644 --- a/tests/pos/i7807.scala +++ b/tests/pos/i7807.scala @@ -11,6 +11,6 @@ object Test: val m: n.type match { case 0 => 1 case 1 => 0 } = flip(n) - // The following do not work, see discussion in https://github.com/lampepfl/dotty/pull/7835/files/6e60814e69be5c8d60265d4ce4bc1758863c23d8#r361741296: + // The following do not work, see discussion in https://github.com/scala/scala3/pull/7835/files/6e60814e69be5c8d60265d4ce4bc1758863c23d8#r361741296: // flip(m) // flip(flip(n)) diff --git a/tests/pos/i8300.scala b/tests/pos/i8300.scala index f106b24dbd1c..f4634f7cd520 100644 --- a/tests/pos/i8300.scala +++ b/tests/pos/i8300.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/8300 +// https://github.com/scala/scala3/issues/8300 type Bar[X] = X match { case List[a] => List[Tuple1[a]] diff --git a/tests/pos/kind-projector.scala b/tests/pos/kind-projector.scala index ff787d0111e2..4d6ec8c932a9 100644 --- a/tests/pos/kind-projector.scala +++ b/tests/pos/kind-projector.scala @@ -53,7 +53,7 @@ class BackticksAreFine6 extends FooPlus[BazPlus[Int => `-*`, `-*`, Int]] class BackticksAreFine7 extends Foo[λ[`-x` => BazPlus[x => `-*`, Int, x]]] class BackticksAreFine8 extends Foo[λ[`x` => BazPlus[x => `*`, Int, x]]] -// https://github.com/lampepfl/dotty/issues/13141 +// https://github.com/scala/scala3/issues/13141 // i13141 object A { class X { type Blah = Int } diff --git a/tests/run-macros/f-interpolator-tests.scala b/tests/run-macros/f-interpolator-tests.scala index 8c59ae19a187..e10301ad3115 100755 --- a/tests/run-macros/f-interpolator-tests.scala +++ b/tests/run-macros/f-interpolator-tests.scala @@ -2,7 +2,7 @@ * * The tests are sorted by argument category as the arguments are on https://docs.oracle.com/javase/6/docs/api/java/util/Formatter.html#detail * - * Some tests come from https://github.com/lampepfl/dotty/pull/3894/files + * Some tests come from https://github.com/scala/scala3/pull/3894/files */ object Test { def main(args: Array[String]) = { diff --git a/tests/run/i11583.scala b/tests/run/i11583.scala index 87701ac95310..fd4d63faa084 100644 --- a/tests/run/i11583.scala +++ b/tests/run/i11583.scala @@ -5,7 +5,7 @@ class Context: class Env: type Extra -// TODO: enable after https://github.com/lampepfl/dotty/issues/11700 is fixed +// TODO: enable after https://github.com/scala/scala3/issues/11700 is fixed // extension [Ctx <: Context](using ctx: Ctx)(tpe: ctx.Type)(using env: Env) // /** essentially: `extension (s: String) def &&:(b: Boolean)(i: Int)` // * but exercises the RefinedPrinter and safety of reordering parameters diff --git a/tests/run/i11706.scala b/tests/run/i11706.scala index 276ee408d266..f87f5697c35d 100644 --- a/tests/run/i11706.scala +++ b/tests/run/i11706.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/11706 +// https://github.com/scala/scala3/issues/11706 import scala.compiletime.erasedValue object Obj: diff --git a/tests/run/i12032.scala b/tests/run/i12032.scala index 52358332e2c8..867a485e8222 100644 --- a/tests/run/i12032.scala +++ b/tests/run/i12032.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/12032 +// https://github.com/scala/scala3/issues/12032 class Foo(val strings: Seq[String]) extends FooLowPriority trait FooLowPriority { self: Foo => diff --git a/tests/run/i13216.scala b/tests/run/i13216.scala index 174d0f200f31..59943672eac1 100644 --- a/tests/run/i13216.scala +++ b/tests/run/i13216.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/13216 +// https://github.com/scala/scala3/issues/13216 import scala.annotation.targetName class C(s: String) extends AnyVal { diff --git a/tests/run/i13334.scala b/tests/run/i13334.scala index 2ee0987c13cc..4443114443e0 100644 --- a/tests/run/i13334.scala +++ b/tests/run/i13334.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/13334 +// https://github.com/scala/scala3/issues/13334 trait DFC given DFC = new DFC {} diff --git a/tests/run/i13691b.scala b/tests/run/i13691b.scala index 1da726827467..eef09c38d431 100644 --- a/tests/run/i13691b.scala +++ b/tests/run/i13691b.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/13691 +// https://github.com/scala/scala3/issues/13691 import language.experimental.saferExceptions trait Decoder[+T]: diff --git a/tests/run/i14582.scala b/tests/run/i14582.scala index bce33aa170b2..1f4d26dccf8d 100644 --- a/tests/run/i14582.scala +++ b/tests/run/i14582.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/14582 +// https://github.com/scala/scala3/issues/14582 @main def Test() = val map = Map( "a" -> 1, diff --git a/tests/run/i15913.scala b/tests/run/i15913.scala index f3e98a3bfd6a..f3853e2f8cfe 100644 --- a/tests/run/i15913.scala +++ b/tests/run/i15913.scala @@ -1,4 +1,4 @@ -// https://github.com/lampepfl/dotty/issues/15913 +// https://github.com/lampepfl/scala/scala3/15913 class injector[F] diff --git a/tests/run/i4192/TestCases.scala b/tests/run/i4192/TestCases.scala index 33b4e458ebe7..7935b57d7fc2 100644 --- a/tests/run/i4192/TestCases.scala +++ b/tests/run/i4192/TestCases.scala @@ -62,7 +62,7 @@ class A { topLevel => new AA object AB { - val nestedOnce = this // self alias cannot be used uniformly here: https://github.com/lampepfl/dotty/issues/11648 + val nestedOnce = this // self alias cannot be used uniformly here: https://github.com/scala/scala3/issues/11648 checkMember(this, topLevel) diff --git a/tests/run/i4496b.scala b/tests/run/i4496b.scala index a6ed5b105e59..54459d15a8af 100644 --- a/tests/run/i4496b.scala +++ b/tests/run/i4496b.scala @@ -102,7 +102,7 @@ object Test { assert(consume(v) == 10) assert(consumeInl(v) == 10) assert(v.a == 10) - // Pending, per https://github.com/lampepfl/dotty/issues/4528. + // Pending, per https://github.com/scala/scala3/issues/4528. // v.a = 11 // assert(consume(v) == 11) // assert(consumeInl(v) == 11) diff --git a/tests/semanticdb/expect/Advanced.expect.scala b/tests/semanticdb/expect/Advanced.expect.scala index d36fcd611eef..0078bde9a078 100644 --- a/tests/semanticdb/expect/Advanced.expect.scala +++ b/tests/semanticdb/expect/Advanced.expect.scala @@ -43,7 +43,7 @@ object Test/*<-advanced::Test.*/ { } } - // see: https://github.com/lampepfl/dotty/pull/14608#discussion_r835642563 + // see: https://github.com/scala/scala3/pull/14608#discussion_r835642563 lazy val foo/*<-advanced::Test.foo.*/: (reflect.Selectable/*->scala::reflect::Selectable#*/ { type A/*<-local16*/ = Int/*->scala::Int#*/ }) &/*->scala::`&`#*/ (reflect.Selectable/*->scala::reflect::Selectable#*/ { type A/*<-local17*/ = Int/*->scala::Int#*/; val a/*<-local18*/: A/*->local17*/ }) = ???/*->scala::Predef.`???`().*/ def bar/*<-advanced::Test.bar().*/: foo/*->advanced::Test.foo.*/.A/*->local17*/ = foo/*->advanced::Test.foo.*/.a/*->scala::reflect::Selectable#selectDynamic().*/ } diff --git a/tests/semanticdb/expect/Advanced.scala b/tests/semanticdb/expect/Advanced.scala index 8e0d2f3a1692..dffd122aa798 100644 --- a/tests/semanticdb/expect/Advanced.scala +++ b/tests/semanticdb/expect/Advanced.scala @@ -43,7 +43,7 @@ object Test { } } - // see: https://github.com/lampepfl/dotty/pull/14608#discussion_r835642563 + // see: https://github.com/scala/scala3/pull/14608#discussion_r835642563 lazy val foo: (reflect.Selectable { type A = Int }) & (reflect.Selectable { type A = Int; val a: A }) = ??? def bar: foo.A = foo.a } From 7aa17c5f227c92f9c95cedee1801b68b143374e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Rochala?= <48657087+rochala@users.noreply.github.com> Date: Tue, 5 Mar 2024 14:36:11 +0100 Subject: [PATCH 216/220] Adjust owner in `Interactive.contextOfPath` causing crash in `ImplicitSearch` (#19875) `Interactive` provided us with the method `contextOfPath` which should return enclosing ctx for given position. It was working fine until given loop detection was improved some time ago. It started crashing as the context owner was set to original context owner, instead of the real owner. This PR changes this and sets context to its outer context owner. Fixes https://github.com/scalameta/metals/issues/6193 --- .../dotty/tools/dotc/interactive/Interactive.scala | 6 +++--- .../tools/languageserver/CompletionTest.scala | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala index 928a9be6103b..a03ae502f2f1 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala @@ -297,14 +297,14 @@ object Interactive { else outer case tree @ Block(stats, expr) => - val localCtx = outer.fresh.setNewScope + val localCtx = outer.localContext(tree, outer.owner).setNewScope stats.foreach { case stat: MemberDef => localCtx.enter(stat.symbol) case _ => } - contextOfStat(stats, nested, ctx.owner, localCtx) + contextOfStat(stats, nested, localCtx.owner, localCtx) case tree @ CaseDef(pat, _, _) => - val localCtx = outer.fresh.setNewScope + val localCtx = outer.localContext(tree, outer.owner).setNewScope pat.foreachSubTree { case bind: Bind => localCtx.enter(bind.symbol) case _ => diff --git a/language-server/test/dotty/tools/languageserver/CompletionTest.scala b/language-server/test/dotty/tools/languageserver/CompletionTest.scala index 4c54637b367f..f3794c6f3468 100644 --- a/language-server/test/dotty/tools/languageserver/CompletionTest.scala +++ b/language-server/test/dotty/tools/languageserver/CompletionTest.scala @@ -35,6 +35,20 @@ class CompletionTest { .completion(("Conversion", Class, "Conversion")) } + @Test def implicitSearchCrash: Unit = + code""" + |object Test: + | trait Foo: + | def test(): String + | given Int = ??? + | given (using ev: Int): Conversion[String, Foo] = ??? + | + | val test = { + | "".tes$m1 + | 1 + | }""" + .completion(("test", Method, "(): String")) + @Test def completionFromScalaPackageObject: Unit = { code"class Foo { val foo: BigD${m1} }" .completion( From 3cb5d709df3bc6dddcaa22f2a17af10fae935485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Marks?= Date: Tue, 12 Mar 2024 17:27:15 +0100 Subject: [PATCH 217/220] Add changelog for 3.4.1-RC2 --- changelogs/3.4.1-RC2.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 changelogs/3.4.1-RC2.md diff --git a/changelogs/3.4.1-RC2.md b/changelogs/3.4.1-RC2.md new file mode 100644 index 000000000000..7267d2339c35 --- /dev/null +++ b/changelogs/3.4.1-RC2.md @@ -0,0 +1,18 @@ +# Backported fixes + +- Adjust owner in Interactive.contextOfPath causing crash in ImplicitSearch [#19875](https://github.com/lampepfl/dotty/pull/19875) +- Add GADT symbols when typing typing-ahead lambda bodies[#19644](https://github.com/lampepfl/dotty/pull/19644) + +# Contributors + +Thank you to all the contributors who made this release possible 🎉 + +According to `git shortlog -sn --no-merges 3.4.1-RC1..3.4.1-RC2` these are: + +``` + 4 Hamza REMMAL + 2 Dale Wijnand + 2 Paweł Marks + 1 Jędrzej Rochala + +``` From 4465edadd19f7f8f4ac693736c173fd0293869ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Marks?= Date: Tue, 12 Mar 2024 17:28:38 +0100 Subject: [PATCH 218/220] Release 3.4.1-RC2 --- project/Build.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index 49e9e5163cd8..9166d3a5ce23 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -83,9 +83,9 @@ object DottyJSPlugin extends AutoPlugin { object Build { import ScaladocConfigs._ - val referenceVersion = "3.4.0" + val referenceVersion = "3.4.1-RC1" - val baseVersion = "3.4.1-RC1" + val baseVersion = "3.4.1-RC2" // Versions used by the vscode extension to create a new project // This should be the latest published releases. From 5c4967f76a82a9b0aed1b5d29ed0ea6324a09f9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Marks?= Date: Wed, 27 Mar 2024 13:51:03 +0100 Subject: [PATCH 219/220] Add changelog for 3.4.1 --- changelogs/3.4.1.md | 192 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 changelogs/3.4.1.md diff --git a/changelogs/3.4.1.md b/changelogs/3.4.1.md new file mode 100644 index 000000000000..920c78f61e8f --- /dev/null +++ b/changelogs/3.4.1.md @@ -0,0 +1,192 @@ +# Highlights of the release + +- Add support for `@deprecatedInheritance` [#19082](https://github.com/lampepfl/dotty/pull/19082) +- Avoid generating given definitions that loop [#19282](https://github.com/lampepfl/dotty/pull/19282) + +# Other changes and fixes + +## Coverage + +- Correctly prettify names in coverage info [#18542](https://github.com/lampepfl/dotty/pull/18542) + +## Desugaring + +- Make apply proxies work with overloaded ctors [#19464](https://github.com/lampepfl/dotty/pull/19464) +- Fix possible crash in Desugar [#19567](https://github.com/lampepfl/dotty/pull/19567) + +## Documentation + +- Update `private[this]` deprecation warning and documentation [#19393](https://github.com/lampepfl/dotty/pull/19393) + +## Erasure + +- Make eraseInfo work for classes with EmptyScopes [#19550](https://github.com/lampepfl/dotty/pull/19550) + +## Exports + +- Do not propagate `@tailrec` to exported methods [#19509](https://github.com/lampepfl/dotty/pull/19509) +- Fix retained flags in exports [#19636](https://github.com/lampepfl/dotty/pull/19636) + +## GADTs + +- Only cache base types when gadt state is empty [#19562](https://github.com/lampepfl/dotty/pull/19562) +- Add GADT symbols when typing typing-ahead lambda bodies[#19644](https://github.com/lampepfl/dotty/pull/19644) + +## Implicits + +- Run CheckStatic after UncacheGivenAliases [#19318](https://github.com/lampepfl/dotty/pull/19318) +- Add tests to verify that crash is fixed elsewhere. Fixes #19328 [#19329](https://github.com/lampepfl/dotty/pull/19329) +- Don't search for implicit conversions to NoType [#19563](https://github.com/lampepfl/dotty/pull/19563) +- Instantiate argument type vars before implicit search [#19096](https://github.com/lampepfl/dotty/pull/19096) +- Adjust owner in Interactive.contextOfPath causing crash in ImplicitSearch [#19875](https://github.com/lampepfl/dotty/pull/19875) + +## Java Interop + +- Classfile reader: handle JDK 9+ constant types in constant pool [#19533](https://github.com/lampepfl/dotty/pull/19533) + +## Linting + +- Make fatal warnings not fail compilation early & aggregate warns [#19245](https://github.com/lampepfl/dotty/pull/19245) + +## Macro Annotations + +- Check and enter missing symbols in MacroAnnotations only for definitions [#19579](https://github.com/lampepfl/dotty/pull/19579) + +## Match Types + +- Normalize MatchAlias in unrollTupleTypes [#19565](https://github.com/lampepfl/dotty/pull/19565) +- Fix #19445: Remove too-strict test in match type matching. [#19511](https://github.com/lampepfl/dotty/pull/19511) + +## Opaque Types + +- Fix problems with cycle checks [#19453](https://github.com/lampepfl/dotty/pull/19453) + +## Parser + +- Fix(#18265): crash on extension method without type nor RHS [#18743](https://github.com/lampepfl/dotty/pull/18743) +- Warn when @volatile is used on vals [#19462](https://github.com/lampepfl/dotty/pull/19462) +- Fix(#16459) xml parse regression [#19531](https://github.com/lampepfl/dotty/pull/19531) + +## Pattern Matching + +- Fix false unreachable due to opaqueness [#19368](https://github.com/lampepfl/dotty/pull/19368) +- Improve recursive decompose prefix fix [#19375](https://github.com/lampepfl/dotty/pull/19375) +- Allow constraining a parameter to Nothing [#19397](https://github.com/lampepfl/dotty/pull/19397) +- Add a test case, proving i15661 is fixed [#19432](https://github.com/lampepfl/dotty/pull/19432) + +## Presentation Compiler + +- Improvement: Support completions for implicit classes [#19314](https://github.com/lampepfl/dotty/pull/19314) +- Chore: Backport changes from Metals [#19410](https://github.com/lampepfl/dotty/pull/19410) +- Fix goto-def on exported forwarders [#19494](https://github.com/lampepfl/dotty/pull/19494) +- Backport pc changes from metals [#19617](https://github.com/lampepfl/dotty/pull/19617) +- Chore: Backport changes from Metals [#19592](https://github.com/lampepfl/dotty/pull/19592) +- Use comma counting for all signature help types [#19520](https://github.com/lampepfl/dotty/pull/19520) +- Make PC more resilient to crashes [#19488](https://github.com/lampepfl/dotty/pull/19488) +- Make order of renames and missing imports deterministic [#19468](https://github.com/lampepfl/dotty/pull/19468) +- Chore: backport changes from metals [#19452](https://github.com/lampepfl/dotty/pull/19452) +- Improve signature help by more stable position calculation + better named arg support [#19214](https://github.com/lampepfl/dotty/pull/19214) +- Instantiate Type Vars in completion labels of extension methods [#18914](https://github.com/lampepfl/dotty/pull/18914) + +## Quotes + +- Only evaluate transparent inline unapply once [#19380](https://github.com/lampepfl/dotty/pull/19380) +- Update `staging.Compiler.make` documentation [#19428](https://github.com/lampepfl/dotty/pull/19428) +- Error instead of StaleSymbol crash for certain cyclic macro dependencies [#19549](https://github.com/lampepfl/dotty/pull/19549) +- Refine handling of StaleSymbol type errors [#19605](https://github.com/lampepfl/dotty/pull/19605) +- Fix module symbol recovery from `NoClassDefFoundError` [#19645](https://github.com/lampepfl/dotty/pull/19645) +- Fix HOAS pattern example and error message [#19655](https://github.com/lampepfl/dotty/pull/19655) +- Set the correct type when copying reflect Inlined trees [#19409](https://github.com/lampepfl/dotty/pull/19409) + +## Reporting + +- Don't explain erroneous bounds [#19338](https://github.com/lampepfl/dotty/pull/19338) +- Better error diagnostics for cyclic references [#19408](https://github.com/lampepfl/dotty/pull/19408) +- Properly identify empty bounds in error message [#19310](https://github.com/lampepfl/dotty/pull/19310) + +## Scala-JS + +- Fix #19528: Actually remove Dynamic from interfaces of native JS classes. [#19536](https://github.com/lampepfl/dotty/pull/19536) +- Consider static and non-static methods as non-double def [#19400](https://github.com/lampepfl/dotty/pull/19400) + +## Scaladoc + +- Scaladoc - add option for dynamic side menu [#19337](https://github.com/lampepfl/dotty/pull/19337) +- Scaladoc: Fix "case case Foo" in enum's cases [#19519](https://github.com/lampepfl/dotty/pull/19519) +- Fix(#19377): show inherited abstract members in dedicated section [#19552](https://github.com/lampepfl/dotty/pull/19552) +- Jsoup: 1.14.3 → 1.17.2 [#19564](https://github.com/lampepfl/dotty/pull/19564) +- Extend copyright into 2024 [#19367](https://github.com/lampepfl/dotty/pull/19367) + +## Tooling + +- Prioritize TASTy files over classfiles on classpath aggregation [#19431](https://github.com/lampepfl/dotty/pull/19431) + +## Transform + +- Fix purity check for val inside of object [#19598](https://github.com/lampepfl/dotty/pull/19598) +- Drop special treatment of function types in overloading resolution [#19654](https://github.com/lampepfl/dotty/pull/19654) +- Add checks for the consistency of the parents in TreeChecker [#18935](https://github.com/lampepfl/dotty/pull/18935) + +## Type Inference + +- More careful type variable instance improvements [#19659](https://github.com/lampepfl/dotty/pull/19659) + +## Typer + +- Reject wildcard types in using clauses [#19459](https://github.com/lampepfl/dotty/pull/19459) +- Don't leave underspecified SAM types in the code [#19461](https://github.com/lampepfl/dotty/pull/19461) +- Also compute base classes of wildcardTypes [#19465](https://github.com/lampepfl/dotty/pull/19465) +- Fix(#15784): ident rule for pat match was too strict [#19501](https://github.com/lampepfl/dotty/pull/19501) +- Heal occurrences of => T between ElimByName and Erasure [#19558](https://github.com/lampepfl/dotty/pull/19558) +- Fix(#i18645): overload ext method body in braces didn't compile [#19651](https://github.com/lampepfl/dotty/pull/19651) +- Fix #19202: Passing NotNullInfos to a mutable field of a Completer [#19463](https://github.com/lampepfl/dotty/pull/19463) +- Fix Java record problems (#19578) and (#19386) [#19583](https://github.com/lampepfl/dotty/pull/19583) +- Improve when deprecation warnings are emitted [#19621](https://github.com/lampepfl/dotty/pull/19621) +- Space: Replace showType & make Space Showable [#19370](https://github.com/lampepfl/dotty/pull/19370) + + +# Contributors + +Thank you to all the contributors who made this release possible 🎉 + +According to `git shortlog -sn --no-merges 3.4.0..3.4.1` these are: + +``` + 53 Martin Odersky + 53 Nicolas Stucki + 22 Dale Wijnand + 11 Szymon Rodziewicz + 11 i10416 + 8 Hamza REMMAL + 7 Paweł Marks + 7 noti0na1 + 6 Yilin Wei + 5 Jędrzej Rochala + 3 Eugene Flesselle + 3 Seth Tisue + 2 Florian3k + 2 Hamza Remmal + 2 Jan Chyb + 2 Katarzyna Marek + 2 Sébastien Doeraene + 2 Tomasz Godzik + 2 dependabot[bot] + 1 Bersier + 1 Fabián Heredia Montiel + 1 Jakub Ciesluk + 1 Jakub Cieśluk + 1 Kacper Korban + 1 Kenji Yoshida + 1 Mehdi Alaoui + 1 Nikita Gazarov + 1 Oron Port + 1 Pascal Weisenburger + 1 Philippus Baalman + 1 Quentin Bernet + 1 Som Snytt + 1 Wojciech Mazur + 1 Yichen Xu + 1 aherlihy + 1 rochala + +``` From 3ffe3223f3dc82aa8e0cc65d7666ba39ed074091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Marks?= Date: Wed, 27 Mar 2024 14:16:10 +0100 Subject: [PATCH 220/220] Release 3.4.1 --- project/Build.scala | 4 ++-- tasty/src/dotty/tools/tasty/TastyFormat.scala | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index 9166d3a5ce23..b8bcbde97e7b 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -83,9 +83,9 @@ object DottyJSPlugin extends AutoPlugin { object Build { import ScaladocConfigs._ - val referenceVersion = "3.4.1-RC1" + val referenceVersion = "3.4.0" - val baseVersion = "3.4.1-RC2" + val baseVersion = "3.4.1" // Versions used by the vscode extension to create a new project // This should be the latest published releases. diff --git a/tasty/src/dotty/tools/tasty/TastyFormat.scala b/tasty/src/dotty/tools/tasty/TastyFormat.scala index e17c98234691..b5ca6f45f594 100644 --- a/tasty/src/dotty/tools/tasty/TastyFormat.scala +++ b/tasty/src/dotty/tools/tasty/TastyFormat.scala @@ -318,7 +318,7 @@ object TastyFormat { * compatibility, but remains backwards compatible, with all * preceding `MinorVersion`. */ - final val MinorVersion: Int = 5 + final val MinorVersion: Int = 4 /** Natural Number. The `ExperimentalVersion` allows for * experimentation with changes to TASTy without committing @@ -334,7 +334,7 @@ object TastyFormat { * is able to read final TASTy documents if the file's * `MinorVersion` is strictly less than the current value. */ - final val ExperimentalVersion: Int = 1 + final val ExperimentalVersion: Int = 0 /**This method implements a binary relation (`<:<`) between two TASTy versions. *