From 77aa36303a041a696cd50a9e7893677a5bc1027b Mon Sep 17 00:00:00 2001 From: i10416 Date: Wed, 24 Jan 2024 07:00:19 +0900 Subject: [PATCH 001/277] fix(#16458): regression in xml syntax parsing xLiteral mistakenly assumed that the element just after `<` is always non-special element, but it is not true. It could be xCharData, comment, xProcInstr. --- .../dotc/parsing/xml/MarkupParserCommon.scala | 8 ++++ .../dotc/parsing/xml/MarkupParsers.scala | 15 ++++++-- tests/pos/i16458.scala | 37 +++++++++++++++++++ 3 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 tests/pos/i16458.scala diff --git a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParserCommon.scala b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParserCommon.scala index 803470fe85a5..906d104041b2 100644 --- a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParserCommon.scala +++ b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParserCommon.scala @@ -202,6 +202,14 @@ private[dotty] trait MarkupParserCommon { /** skip optional space S? */ def xSpaceOpt(): Unit = while (isSpace(ch) && !eof) nextch() + /** skip optional space S? and return the number of consumed characters */ + def xSpaceOptN(): Int = + var i = 0 + while (isSpace(ch) && !eof) do + nextch() + i += 1 + i + /** scan [3] S ::= (#x20 | #x9 | #xD | #xA)+ */ def xSpace(): Unit = if (isSpace(ch)) { nextch(); xSpaceOpt() } diff --git a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala index 22ef15b6f497..2a8ae5c64a5b 100644 --- a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala @@ -371,10 +371,17 @@ object MarkupParsers { // parse more XML? if (charComingAfter(xSpaceOpt()) == '<') { while { - xSpaceOpt() - nextch() - ts.append(element) - charComingAfter(xSpaceOpt()) == '<' + if xSpaceOptN() == 0 then + nextch() + if content_LT(ts) then // Is `` valid xml? + xToken("/>") + charComingAfter(xSpaceOpt()) == '<' + else + // this is surely not a special node as any special node + // should start with `<{special symbol}` without space. + nextch() + ts.append(element) + charComingAfter(xSpaceOpt()) == '<' } do () handle.makeXMLseq(Span(start, curOffset, start), ts) } diff --git a/tests/pos/i16458.scala b/tests/pos/i16458.scala new file mode 100644 index 000000000000..fe4c90dcb41c --- /dev/null +++ b/tests/pos/i16458.scala @@ -0,0 +1,37 @@ +def x =
FooBar
+ +package scala.xml { + type MetaData = AnyRef + + trait NamespaceBinding + object TopScope extends NamespaceBinding + object Null + abstract class Node { + def label: String + def child: Seq[Node] + override def toString = label + child.mkString + } + class Comment(commentText: String) extends Node{ + def label = commentText + def child = Nil + } + class Elem(prefix: String, val label: String, attributes1: MetaData, scope: NamespaceBinding, minimizeEmpty: Boolean, val child: Node*) extends Node + class NodeBuffer extends Seq[Node] { + val nodes = scala.collection.mutable.ArrayBuffer.empty[Node] + def &+(o: Any): NodeBuffer = + o match { + case n: Node => nodes.addOne(n) ; this + case t: Text => nodes.addOne(Atom(t)) ; this + } + // Members declared in scala.collection.IterableOnce + def iterator: Iterator[scala.xml.Node] = nodes.iterator + // Members declared in scala.collection.SeqOps + def apply(i: Int): scala.xml.Node = nodes(i) + def length: Int = nodes.length + } + case class Text(text: String) + case class Atom(t: Text) extends Node { + def label = t.text + def child = Nil + } +} \ No newline at end of file From 27046feabeb0f3682c0fc734c9d4e49e7d082a0f Mon Sep 17 00:00:00 2001 From: i10416 Date: Wed, 24 Jan 2024 12:58:26 +0900 Subject: [PATCH 002/277] improve: just use content_LT to fix 16458 Just replacing element with content_LT, it works. See https://github.com/lampepfl/dotty/pull/19522#issuecomment-1907084802 --- .../dotc/parsing/xml/MarkupParserCommon.scala | 8 -------- .../tools/dotc/parsing/xml/MarkupParsers.scala | 15 ++++----------- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParserCommon.scala b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParserCommon.scala index 906d104041b2..803470fe85a5 100644 --- a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParserCommon.scala +++ b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParserCommon.scala @@ -202,14 +202,6 @@ private[dotty] trait MarkupParserCommon { /** skip optional space S? */ def xSpaceOpt(): Unit = while (isSpace(ch) && !eof) nextch() - /** skip optional space S? and return the number of consumed characters */ - def xSpaceOptN(): Int = - var i = 0 - while (isSpace(ch) && !eof) do - nextch() - i += 1 - i - /** scan [3] S ::= (#x20 | #x9 | #xD | #xA)+ */ def xSpace(): Unit = if (isSpace(ch)) { nextch(); xSpaceOpt() } diff --git a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala index 2a8ae5c64a5b..06e8645b82c0 100644 --- a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala @@ -371,17 +371,10 @@ object MarkupParsers { // parse more XML? if (charComingAfter(xSpaceOpt()) == '<') { while { - if xSpaceOptN() == 0 then - nextch() - if content_LT(ts) then // Is `` valid xml? - xToken("/>") - charComingAfter(xSpaceOpt()) == '<' - else - // this is surely not a special node as any special node - // should start with `<{special symbol}` without space. - nextch() - ts.append(element) - charComingAfter(xSpaceOpt()) == '<' + xSpaceOpt() + nextch() + content_LT(ts) + charComingAfter(xSpaceOpt()) == '<' } do () handle.makeXMLseq(Span(start, curOffset, start), ts) } From 9de9d57930b391b8f064f3630af5122d0941c949 Mon Sep 17 00:00:00 2001 From: i10416 Date: Wed, 24 Jan 2024 14:21:55 +0900 Subject: [PATCH 003/277] tidy: use run test instead of compile test To check parsing properly, it is better to run a test and assert parse result. --- tests/{pos => run}/i16458.scala | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) rename tests/{pos => run}/i16458.scala (70%) diff --git a/tests/pos/i16458.scala b/tests/run/i16458.scala similarity index 70% rename from tests/pos/i16458.scala rename to tests/run/i16458.scala index fe4c90dcb41c..1c4b0365e45e 100644 --- a/tests/pos/i16458.scala +++ b/tests/run/i16458.scala @@ -1,4 +1,21 @@ -def x =
FooBar
+ +object Test { + import scala.xml.* + def main(args: Array[String]): Unit = { + val xml =
FooBar
+ assert( + xml match + case Seq(elm: Elem, comment: Comment) if + elm.label == "div" && + elm.child(0) == Atom(Text("FooBar")) && + comment.label == " /.modal-content " + => true + case _ => false + , + xml + ) + } +} package scala.xml { type MetaData = AnyRef @@ -16,7 +33,7 @@ package scala.xml { def child = Nil } class Elem(prefix: String, val label: String, attributes1: MetaData, scope: NamespaceBinding, minimizeEmpty: Boolean, val child: Node*) extends Node - class NodeBuffer extends Seq[Node] { + class NodeBuffer extends Seq[Node] { val nodes = scala.collection.mutable.ArrayBuffer.empty[Node] def &+(o: Any): NodeBuffer = o match { From 16ecedd956ac1da38931293cb410c45f419b5e5e Mon Sep 17 00:00:00 2001 From: EnzeXing Date: Mon, 5 Feb 2024 01:14:30 -0500 Subject: [PATCH 004/277] Add supports for type cast and filtering type for field and method owners --- .../tools/dotc/transform/init/Objects.scala | 31 ++++++++++++++----- .../tools/dotc/transform/init/Util.scala | 7 +++++ tests/init-global/neg/TypeCast.scala | 18 +++++++++++ tests/init-global/pos/i18882.scala | 15 +++++++++ 4 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 tests/init-global/neg/TypeCast.scala create mode 100644 tests/init-global/pos/i18882.scala diff --git a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala index 763b71619de8..8e8eda4fac30 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala @@ -599,6 +599,22 @@ object Objects: case _ => a + def filterType(tpe: Type)(using Context): Value = + val baseClasses = tpe.baseClasses + if baseClasses.isEmpty then a + else filterClass(baseClasses.head) + + def filterClass(sym: Symbol)(using Context): Value = + if !sym.isClass then a + else + val klass = sym.asClass + a match + case Cold => Cold + case ref: Ref if ref.klass.isSubClass(klass) => ref + case ref: Ref => Bottom + case ValueSet(values) => values.map(v => v.filterClass(klass)).join + case _ => a // TODO: could be more precise for OfArray; possibly add class information for Fun + extension (value: Ref | Cold.type) def widenRefOrCold(height : Int)(using Context) : Ref | Cold.type = value.widen(height).asInstanceOf[ThisValue] @@ -617,7 +633,7 @@ object Objects: * @param needResolve Whether the target of the call needs resolution? */ def call(value: Value, meth: Symbol, args: List[ArgInfo], receiver: Type, superType: Type, needResolve: Boolean = true): Contextual[Value] = log("call " + meth.show + ", this = " + value.show + ", args = " + args.map(_.value.show), printer, (_: Value).show) { - value match + value.filterClass(meth.owner) match case Cold => report.warning("Using cold alias. " + Trace.show, Trace.position) Bottom @@ -733,7 +749,6 @@ object Objects: * @param args Arguments of the constructor call (all parameter blocks flatten to a list). */ def callConstructor(value: Value, ctor: Symbol, args: List[ArgInfo]): Contextual[Value] = log("call " + ctor.show + ", args = " + args.map(_.value.show), printer, (_: Value).show) { - value match case ref: Ref => if ctor.hasSource then @@ -768,7 +783,7 @@ object Objects: * @param needResolve Whether the target of the selection needs resolution? */ def select(value: Value, field: Symbol, receiver: Type, needResolve: Boolean = true): Contextual[Value] = log("select " + field.show + ", this = " + value.show, printer, (_: Value).show) { - value match + value.filterClass(field.owner) match case Cold => report.warning("Using cold alias", Trace.position) Bottom @@ -839,12 +854,12 @@ object Objects: * @param rhsTyp The type of the right-hand side. */ def assign(lhs: Value, field: Symbol, rhs: Value, rhsTyp: Type): Contextual[Value] = log("Assign" + field.show + " of " + lhs.show + ", rhs = " + rhs.show, printer, (_: Value).show) { - lhs match + lhs.filterClass(field.owner) match case fun: Fun => report.warning("[Internal error] unexpected tree in assignment, fun = " + fun.code.show + Trace.show, Trace.position) case arr: OfArray => - report.warning("[Internal error] unexpected tree in assignment, array = " + arr.show + Trace.show, Trace.position) + report.warning("[Internal error] unexpected tree in assignment, array = " + arr.show + s", owner = ${field.owner}\n" + Trace.show, Trace.position) case Cold => report.warning("Assigning to cold aliases is forbidden. " + Trace.show, Trace.position) @@ -876,8 +891,7 @@ object Objects: * @param args The arguments passsed to the constructor. */ def instantiate(outer: Value, klass: ClassSymbol, ctor: Symbol, args: List[ArgInfo]): Contextual[Value] = log("instantiating " + klass.show + ", outer = " + outer + ", args = " + args.map(_.value.show), printer, (_: Value).show) { - outer match - + outer.filterClass(klass.owner) match case _ : Fun | _: OfArray => report.warning("[Internal error] unexpected outer in instantiating a class, outer = " + outer.show + ", class = " + klass.show + ", " + Trace.show, Trace.position) Bottom @@ -1091,6 +1105,9 @@ object Objects: instantiate(outer, cls, ctor, args) } + case TypeCast(elem, tpe) => + eval(elem, thisV, klass).filterType(tpe) + case Apply(ref, arg :: Nil) if ref.symbol == defn.InitRegionMethod => val regions2 = Regions.extend(expr.sourcePos) if Regions.exists(expr.sourcePos) then diff --git a/compiler/src/dotty/tools/dotc/transform/init/Util.scala b/compiler/src/dotty/tools/dotc/transform/init/Util.scala index 70390028e84f..1114a9efc218 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Util.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Util.scala @@ -78,6 +78,13 @@ object Util: case _ => None + object TypeCast: + def unapply(tree: Tree)(using Context): Option[(Tree, Type)] = + tree match + case TypeApply(Select(qual, _), typeArg) if tree.symbol.isTypeCast => + Some(qual, typeArg.head.tpe) + case _ => None + def resolve(cls: ClassSymbol, sym: Symbol)(using Context): Symbol = log("resove " + cls + ", " + sym, printer, (_: Symbol).show): if sym.isEffectivelyFinal then sym else sym.matchingMember(cls.appliedRef) diff --git a/tests/init-global/neg/TypeCast.scala b/tests/init-global/neg/TypeCast.scala new file mode 100644 index 000000000000..55447e9df4e2 --- /dev/null +++ b/tests/init-global/neg/TypeCast.scala @@ -0,0 +1,18 @@ +object A { + val f: Int = 10 + def m() = f +} +object B { + val f: Int = g() + def g(): Int = f // error +} +object C { + val a: A.type | B.type = if ??? then A else B + def cast[T](a: Any): T = a.asInstanceOf[T] + val c: A.type = cast[A.type](a) // abstraction for c is {A, B} + val d = c.f // treat as c.asInstanceOf[owner of f].f + val e = c.m() // treat as c.asInstanceOf[owner of f].m() + val c2: B.type = cast[B.type](a) + val g = c2.f // no error here +} + diff --git a/tests/init-global/pos/i18882.scala b/tests/init-global/pos/i18882.scala new file mode 100644 index 000000000000..0a1ea5309a58 --- /dev/null +++ b/tests/init-global/pos/i18882.scala @@ -0,0 +1,15 @@ +class A: + var a = 20 + +class B: + var b = 20 + +object O: + val o: A | B = new A + if o.isInstanceOf[A] then + o.asInstanceOf[A].a += 1 + else + o.asInstanceOf[B].b += 1 // o.asInstanceOf[B] is treated as bottom + o match + case o: A => o.a += 1 + case o: B => o.b += 1 From f091c4e5c81502a3226d2d1e352fbe6642246ea7 Mon Sep 17 00:00:00 2001 From: EnzeXing Date: Mon, 5 Feb 2024 01:21:35 -0500 Subject: [PATCH 005/277] fix error messages --- compiler/src/dotty/tools/dotc/transform/init/Objects.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala index 8e8eda4fac30..6ecd7441829d 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala @@ -859,7 +859,7 @@ object Objects: report.warning("[Internal error] unexpected tree in assignment, fun = " + fun.code.show + Trace.show, Trace.position) case arr: OfArray => - report.warning("[Internal error] unexpected tree in assignment, array = " + arr.show + s", owner = ${field.owner}\n" + Trace.show, Trace.position) + report.warning("[Internal error] unexpected tree in assignment, array = " + arr.show + Trace.show, Trace.position) case Cold => report.warning("Assigning to cold aliases is forbidden. " + Trace.show, Trace.position) From e2b52290d8847a63a995154c3f9cb1d3d8c5cb76 Mon Sep 17 00:00:00 2001 From: Eugene Flesselle Date: Sun, 4 Feb 2024 15:37:56 +0100 Subject: [PATCH 006/277] Fix untupling of functions in for comprehensions --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 7 ++++--- tests/pos/i19576.scala | 6 ++++++ 2 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 tests/pos/i19576.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 7727c125d1e4..5648f651d8e9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1621,15 +1621,16 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer case untpd.Annotated(scrut1, _) => isParamRef(scrut1) case untpd.Ident(id) => id == params.head.name fnBody match - case untpd.Match(scrut, untpd.CaseDef(untpd.Tuple(elems), untpd.EmptyTree, rhs) :: Nil) + case untpd.Match(scrut, cases @ untpd.CaseDef(untpd.Tuple(elems), untpd.EmptyTree, rhs) :: Nil) if scrut.span.isSynthetic && isParamRef(scrut) && elems.hasSameLengthAs(protoFormals) => // If `pt` is N-ary function type, convert synthetic lambda // x$1 => x$1 match case (a1, ..., aN) => e // to // (a1, ..., aN) => e val params1 = desugar.patternsToParams(elems) - if params1.hasSameLengthAs(elems) then - desugared = cpy.Function(tree)(params1, rhs) + desugared = if params1.hasSameLengthAs(elems) + then cpy.Function(tree)(params1, rhs) + else desugar.makeCaseLambda(cases, desugar.MatchCheck.IrrefutablePatDef, protoFormals.length) case _ => if desugared.isEmpty then diff --git a/tests/pos/i19576.scala b/tests/pos/i19576.scala new file mode 100644 index 000000000000..030107b3c63c --- /dev/null +++ b/tests/pos/i19576.scala @@ -0,0 +1,6 @@ + +object Test: + val z = Seq(0 -> 1, 2 -> 3).lazyZip(Seq("A", "B")) + for case ((beg, end), c) <- z yield c // Ok: a withFilter is inserted before map + for (range, c) <- z yield c // Ok: exact shape + for ((beg, end), c) <- z yield c // Error before changes: Wrong number of parameters, expected 2 From e6765088a4041e2541b2a60a7d20ad8636030d2b Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Tue, 6 Feb 2024 14:00:36 +0800 Subject: [PATCH 007/277] Disallow covariant `cap`s in the lower bound of type members --- .../dotty/tools/dotc/cc/CheckCaptures.scala | 7 +++++++ .../neg-custom-args/captures/i19330-alt.scala | 14 +++++++++++++ .../captures/i19330-alt2.scala | 13 ++++++++++++ tests/neg-custom-args/captures/i19330.scala | 21 +++++++++++++++++++ 4 files changed, 55 insertions(+) create mode 100644 tests/neg-custom-args/captures/i19330-alt.scala create mode 100644 tests/neg-custom-args/captures/i19330-alt2.scala create mode 100644 tests/neg-custom-args/captures/i19330.scala diff --git a/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala b/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala index 4564bed6db01..419e6454369c 100644 --- a/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala +++ b/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala @@ -168,6 +168,13 @@ object CheckCaptures: if !seen.contains(t) then seen += t traverseChildren(t) + + // Check the lower bound of path dependent types. + // See issue #19330. + val isTypeParam = t.prefix eq NoPrefix + t.info match + case TypeBounds(lo, hi) if !isTypeParam => traverse(lo) + case _ => case AnnotatedType(_, ann) if ann.symbol == defn.UncheckedCapturesAnnot => () case t => diff --git a/tests/neg-custom-args/captures/i19330-alt.scala b/tests/neg-custom-args/captures/i19330-alt.scala new file mode 100644 index 000000000000..8e6488cb9ccc --- /dev/null +++ b/tests/neg-custom-args/captures/i19330-alt.scala @@ -0,0 +1,14 @@ +import language.experimental.captureChecking + +trait Logger +def usingLogger[T](op: Logger^ => T): T = ??? + +def foo[T >: () => Logger^](): T = + val leaked = usingLogger[T]: l => // ok + val t: () => Logger^ = () => l + t: T + leaked + +def test(): Unit = + val bad: () => Logger^ = foo[() => Logger^] // error + val leaked: Logger^ = bad() // leaked scoped capability! diff --git a/tests/neg-custom-args/captures/i19330-alt2.scala b/tests/neg-custom-args/captures/i19330-alt2.scala new file mode 100644 index 000000000000..b49dce4b71ef --- /dev/null +++ b/tests/neg-custom-args/captures/i19330-alt2.scala @@ -0,0 +1,13 @@ +import language.experimental.captureChecking + +trait Logger +def usingLogger[T](op: Logger^ => T): T = ??? + +trait Foo: + type T >: () => Logger^ + + def foo: this.T = + val leaked = usingLogger[T]: l => // error + val t: () => Logger^ = () => l + t: T + leaked diff --git a/tests/neg-custom-args/captures/i19330.scala b/tests/neg-custom-args/captures/i19330.scala new file mode 100644 index 000000000000..8acb0dd8f66b --- /dev/null +++ b/tests/neg-custom-args/captures/i19330.scala @@ -0,0 +1,21 @@ +import language.experimental.captureChecking + +trait Logger +def usingLogger[T](op: Logger^ => T): T = ??? + +trait Foo: + type T >: () => Logger^ + +class Bar extends Foo: + type T = () => Logger^ + +def foo(x: Foo): x.T = + val leaked = usingLogger[x.T]: l => // error + val t: () => Logger^ = () => l + t: x.T + leaked + +def test(): Unit = + val bar = new Bar + val bad: bar.T = foo(bar) + val leaked: Logger^ = bad() // leaked scoped capability! From 784497d86e83a3ed436d97695b0c56f4fd7e2965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Tue, 6 Feb 2024 10:27:44 +0100 Subject: [PATCH 008/277] Fix #19607: Allow to instantiate *wildcard* type captures to TypeBounds. When matching in a match type, if we encounter a `TypeBounds` scrutinee and we have a wildcard capture on the right, we used to pick the `hi` bound "because anything between between `lo` and `hi` would work". It turns out that *nothing* between `lo` and `hi` works when the type constructor is invariant. Instead, we must be keep the type bounds, and instantiate the wildcard capture to a wildcard type argument. This is fine because a wildcard capture can never be referred to in the body of the case. However, previously this could never happen in successful cases, and we therefore used the presence of a `TypeBounds` in the `instances` as the canonical signal for "fail as not specific". We now use a separate `noInstances` list to be that signal. This change departs from the letter of the spec but not from its spirit. As evidenced by the wording, the spec always *intended* for "the pick" to one that would always succeed. We wrongly assumed `hi` was always working. --- .../dotty/tools/dotc/core/TypeComparer.scala | 41 +++++++++++-------- tests/pos/i19607.scala | 12 ++++++ 2 files changed, 35 insertions(+), 18 deletions(-) create mode 100644 tests/pos/i19607.scala diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index b04978357508..43b88734e669 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -3410,29 +3410,38 @@ class TrackingTypeComparer(initctx: Context) extends TypeComparer(initctx) { // Actual matching logic val instances = Array.fill[Type](spec.captureCount)(NoType) + val noInstances = mutable.ListBuffer.empty[(TypeName, TypeBounds)] def rec(pattern: MatchTypeCasePattern, scrut: Type, variance: Int, scrutIsWidenedAbstract: Boolean): Boolean = pattern match - case MatchTypeCasePattern.Capture(num, isWildcard) => + case MatchTypeCasePattern.Capture(num, /* isWildcard = */ true) => + // instantiate the wildcard in a way that the subtype test always succeeds + instances(num) = variance match + case 1 => scrut.hiBound // actually important if we are not in a class type constructor + case -1 => scrut.loBound + case 0 => scrut + !instances(num).isError + + case MatchTypeCasePattern.Capture(num, /* isWildcard = */ false) => + def failNotSpecific(bounds: TypeBounds): TypeBounds = + noInstances += spec.origMatchCase.paramNames(num) -> bounds + bounds + instances(num) = scrut match case scrut: TypeBounds => - if isWildcard then - // anything will do, as long as it conforms to the bounds for the subsequent `scrut <:< instantiatedPat` test - scrut.hi - else if scrutIsWidenedAbstract then - // always keep the TypeBounds so that we can report the correct NoInstances - scrut + if scrutIsWidenedAbstract then + failNotSpecific(scrut) else variance match case 1 => scrut.hi case -1 => scrut.lo - case 0 => scrut + case 0 => failNotSpecific(scrut) case _ => - if !isWildcard && scrutIsWidenedAbstract && variance != 0 then - // force a TypeBounds to report the correct NoInstances + if scrutIsWidenedAbstract && variance != 0 then + // fail as not specific // the Nothing and Any bounds are used so that they are not displayed; not for themselves in particular - if variance > 0 then TypeBounds(defn.NothingType, scrut) - else TypeBounds(scrut, defn.AnyType) + if variance > 0 then failNotSpecific(TypeBounds(defn.NothingType, scrut)) + else failNotSpecific(TypeBounds(scrut, defn.AnyType)) else scrut !instances(num).isError @@ -3508,12 +3517,8 @@ class TrackingTypeComparer(initctx: Context) extends TypeComparer(initctx) { MatchResult.Stuck if rec(spec.pattern, scrut, variance = 1, scrutIsWidenedAbstract = false) then - if instances.exists(_.isInstanceOf[TypeBounds]) then - MatchResult.NoInstance { - constrainedCaseLambda.paramNames.zip(instances).collect { - case (name, bounds: TypeBounds) => (name, bounds) - } - } + if noInstances.nonEmpty then + MatchResult.NoInstance(noInstances.toList) else val defn.MatchCase(instantiatedPat, reduced) = instantiateParamsSpec(instances, constrainedCaseLambda)(constrainedCaseLambda.resultType): @unchecked diff --git a/tests/pos/i19607.scala b/tests/pos/i19607.scala new file mode 100644 index 000000000000..c4f65e978701 --- /dev/null +++ b/tests/pos/i19607.scala @@ -0,0 +1,12 @@ +trait Foo +trait Bar[T] + +type MatchType[T] = T match + case Bar[?] => Nothing + case _ => T + +object Test: + def foo(b: Bar[? >: Foo]): Unit = + summon[MatchType[b.type] =:= Nothing] + summon[MatchType[Bar[? >: Foo]] =:= Nothing] +end Test From eff34242744052452f2e983757d15e522b950aee Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 6 Feb 2024 16:54:40 +0000 Subject: [PATCH 009/277] Short-circuit isCheckable with classSymbol A mutually recursive, and ever-growing type pair like ExprMap and EM (in the test case) would blow up isCheckable. Let's use the classSymbol instead. --- .../dotty/tools/dotc/transform/patmat/Space.scala | 4 ++-- tests/pos/i19433.scala | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 tests/pos/i19433.scala diff --git a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala index 9bf852084cfe..b7d60f57c757 100644 --- a/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +++ b/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala @@ -773,7 +773,7 @@ object SpaceEngine { } private def exhaustivityCheckable(sel: Tree)(using Context): Boolean = { - val seen = collection.mutable.Set.empty[Type] + val seen = collection.mutable.Set.empty[Symbol] // Possible to check everything, but be compatible with scalac by default def isCheckable(tp: Type): Boolean = @@ -789,7 +789,7 @@ object SpaceEngine { tpw.isRef(defn.BooleanClass) || classSym.isAllOf(JavaEnum) || classSym.is(Case) && { - if seen.add(tpw) then productSelectorTypes(tpw, sel.srcPos).exists(isCheckable(_)) + if seen.add(classSym) then productSelectorTypes(tpw, sel.srcPos).exists(isCheckable(_)) else true // recursive case class: return true and other members can still fail the check } diff --git a/tests/pos/i19433.scala b/tests/pos/i19433.scala new file mode 100644 index 000000000000..a16aeb75f2d5 --- /dev/null +++ b/tests/pos/i19433.scala @@ -0,0 +1,12 @@ +// minimised from github.com/Adam-Vandervorst/CZ2 + +import scala.collection.mutable + +private trait EMImpl[V, F[_]] + +case class EM[V2](apps: ExprMap[ExprMap[V2]]) extends EMImpl[V2, EM]: + def collect[W](pf: PartialFunction[V2, W]): Unit = + val apps1 = apps.collect(_.collect(pf)) + +case class ExprMap[V](var em: EM[V] = null) extends EMImpl[V, ExprMap]: + def collect[W](pf: PartialFunction[V, W]): ExprMap[W] = ??? // was: StackOverflow in isCheckable From cc1e37ea1b0060d26b1360e1917e9576bd44c8d3 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Wed, 7 Feb 2024 22:24:17 +0000 Subject: [PATCH 010/277] Add GADT symbols when typing typing-ahead lambda bodies --- .../src/dotty/tools/dotc/typer/Namer.scala | 8 ++++++- tests/pos/i19570.min1.scala | 23 ++++++++++++++++++ tests/pos/i19570.min2.scala | 24 +++++++++++++++++++ tests/pos/i19570.orig.scala | 14 +++++++++++ 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i19570.min1.scala create mode 100644 tests/pos/i19570.min2.scala create mode 100644 tests/pos/i19570.orig.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 819b43fcec2c..e5e05e02a7d7 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -1733,8 +1733,14 @@ class Namer { typer: Typer => val tpe = (paramss: @unchecked) match case TypeSymbols(tparams) :: TermSymbols(vparams) :: Nil => tpFun(tparams, vparams) case TermSymbols(vparams) :: Nil => tpFun(Nil, vparams) + val rhsCtx = (paramss: @unchecked) match + case TypeSymbols(tparams) :: TermSymbols(_) :: Nil => + val rhsCtx = ctx.fresh.setFreshGADTBounds + rhsCtx.gadtState.addToConstraint(tparams) + rhsCtx + case TermSymbols(_) :: Nil => ctx if (isFullyDefined(tpe, ForceDegree.none)) tpe - else typedAheadExpr(mdef.rhs, tpe).tpe + else typedAheadExpr(mdef.rhs, tpe)(using rhsCtx).tpe case TypedSplice(tpt: TypeTree) if !isFullyDefined(tpt.tpe, ForceDegree.none) => mdef match { diff --git a/tests/pos/i19570.min1.scala b/tests/pos/i19570.min1.scala new file mode 100644 index 000000000000..2cbc852641d3 --- /dev/null +++ b/tests/pos/i19570.min1.scala @@ -0,0 +1,23 @@ +enum Op[A]: + case Dup[T]() extends Op[(T, T)] + +def foo[R](f: [A] => Op[A] => R): R = ??? + +def test = + foo([A] => (o: Op[A]) => o match + case o: Op.Dup[u] => + summon[A =:= (u, u)] // Error: Cannot prove that A =:= (u, u) + () + ) + foo[Unit]([A] => (o: Op[A]) => o match + case o: Op.Dup[u] => + summon[A =:= (u, u)] // Ok + () + ) + foo({ + val f1 = [B] => (o: Op[B]) => o match + case o: Op.Dup[u] => + summon[B =:= (u, u)] // Also ok + () + f1 + }) diff --git a/tests/pos/i19570.min2.scala b/tests/pos/i19570.min2.scala new file mode 100644 index 000000000000..b1450d7e2d1a --- /dev/null +++ b/tests/pos/i19570.min2.scala @@ -0,0 +1,24 @@ +sealed trait Op[A, B] { def giveA: A; def giveB: B } +final case class Dup[T](x: T) extends Op[T, (T, T)] { def giveA: T = x; def giveB: (T, T) = (x, x) } + +class Test: + def foo[R](f: [A, B] => (o: Op[A, B]) => R): R = ??? + + def m1: Unit = + foo([A, B] => (o: Op[A, B]) => o match + case o: Dup[t] => + var a1: t = o.giveA + var a2: A = o.giveA + a1 = a2 + a2 = a1 + + var b1: (t, t) = o.giveB + var b2: B = o.giveB + b1 = b2 + b2 = b1 + + summon[A =:= t] // ERROR: Cannot prove that A =:= t. + summon[B =:= (t, t)] // ERROR: Cannot prove that B =:= (t, t). + + () + ) diff --git a/tests/pos/i19570.orig.scala b/tests/pos/i19570.orig.scala new file mode 100644 index 000000000000..6e574f52be91 --- /dev/null +++ b/tests/pos/i19570.orig.scala @@ -0,0 +1,14 @@ +enum Op[A, B]: + case Dup[T]() extends Op[T, (T, T)] + +def foo[R](f: [A, B] => (o: Op[A, B]) => R): R = + f(Op.Dup()) + +def test = + foo([A, B] => (o: Op[A, B]) => { + o match + case o: Op.Dup[t] => + summon[A =:= t] // ERROR: Cannot prove that A =:= t. + summon[B =:= (t, t)] // ERROR: Cannot prove that B =:= (t, t). + 42 + }) From 5cf670741afaa6eb9bc670f6693fbb82fc5b4c01 Mon Sep 17 00:00:00 2001 From: i10416 Date: Fri, 9 Feb 2024 17:13:47 +0900 Subject: [PATCH 011/277] fix(#i18645): overload ext method body in braces didn't compile `tryWithImplicitOnQualifier` returned without attempting `tryInsertImplicitOnQualifier`, which prevented the compiler from finding overloaded method, because `hasInnerErrors` in `ProtoTypes` picked up the inner error propagated back from outer error. When compiling `x.pprint(()=> { 123 })` before this commit, in `hasInnerErrors`, `t` contains two sub trees; `Block(stmt, expr)` and `stmt`. The span of the former matches the span of `t`, but that of the latter does not, which caused `hasInnerErrors` to return `true`, but the error from the latter is duplicated with the error of parent tree `t`. --- .../src/dotty/tools/dotc/typer/ProtoTypes.scala | 4 +++- tests/pos/i18645.scala | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i18645.scala diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index 6b72f3a8b56e..9d5c1352b106 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -407,7 +407,9 @@ object ProtoTypes { case closureDef(mdef) => hasInnerErrors(mdef.rhs) case _ => t.existsSubTree { t1 => - if t1.typeOpt.isError && t1.span.toSynthetic != t.span.toSynthetic then + if t1.typeOpt.isError + && t.span.toSynthetic != t1.span.toSynthetic + && t.typeOpt != t1.typeOpt then typr.println(i"error subtree $t1 of $t with ${t1.typeOpt}, spans = ${t1.span}, ${t.span}") true else diff --git a/tests/pos/i18645.scala b/tests/pos/i18645.scala new file mode 100644 index 000000000000..599396b678af --- /dev/null +++ b/tests/pos/i18645.scala @@ -0,0 +1,16 @@ +trait Printable { + def pprint(v: () => String): Unit = { + println(v()) + } +} + +extension (ctx: Printable) + def pprint(f: () => Int): Unit = { + ctx.pprint(() => f().toString) + } + +val x = new Printable {} + +def test = + x.pprint(() => ( 234 )) + x.pprint(() => { 123 }) \ No newline at end of file From 5036105f76fac5d9bf15afb61a30dca435b6dbc6 Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 7 Feb 2024 11:31:45 +0100 Subject: [PATCH 012/277] New footprint calculation scheme The old one clearly did not work. It either never worked or was disabled by the changes to matchtype reduction. I now changed it to a more straightforward scheme that computes the footprint directly instead of relying on TypeComparer to produce the right trace. --- .../src/dotty/tools/dotc/core/Types.scala | 44 ++++++++- tests/pos/bad-footprint.scala | 99 +++++++++++++++++++ 2 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 tests/pos/bad-footprint.scala diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index b151dcdf8270..a7aed3893948 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -5009,6 +5009,8 @@ object Types extends TypeUtils { case ex: Throwable => handleRecursive("normalizing", s"${scrutinee.show} match ..." , ex) + private def thisMatchType = this + def reduced(using Context): Type = { def contextInfo(tp: Type): Type = tp match { @@ -5027,12 +5029,44 @@ object Types extends TypeUtils { reductionContext = util.HashMap() for (tp <- footprint) reductionContext(tp) = contextInfo(tp) - typr.println(i"footprint for $this $hashCode: ${footprint.toList.map(x => (x, contextInfo(x)))}%, %") + matchTypes.println(i"footprint for $this $hashCode: ${footprint.toList.map(x => (x, contextInfo(x)))}%, %") def isUpToDate: Boolean = - reductionContext.keysIterator.forall { tp => + reductionContext.keysIterator.forall: tp => reductionContext(tp) `eq` contextInfo(tp) - } + + def computeFootprint(): Unit = + new TypeTraverser: + var footprint: Set[Type] = Set() + var deep: Boolean = true + val seen = util.HashSet[Type]() + def traverse(tp: Type) = + if !seen.contains(tp) then + seen += tp + tp match + case tp: NamedType => + if tp.symbol.is(TypeParam) then footprint += tp + traverseChildren(tp) + case _: AppliedType | _: RefinedType => + if deep then traverseChildren(tp) + case TypeBounds(lo, hi) => + traverse(hi) + case tp: TypeVar => + footprint += tp + traverse(tp.underlying) + case tp: TypeParamRef => + footprint += tp + case _ => + traverseChildren(tp) + end traverse + + traverse(scrutinee) + deep = false + cases.foreach(traverse) + reductionContext = util.HashMap() + for tp <- footprint do + reductionContext(tp) = contextInfo(tp) + matchTypes.println(i"footprint for $thisMatchType $hashCode: ${footprint.toList.map(x => (x, contextInfo(x)))}%, %") record("MatchType.reduce called") if !Config.cacheMatchReduced @@ -5044,19 +5078,21 @@ object Types extends TypeUtils { if (myReduced != null) record("MatchType.reduce cache miss") myReduced = trace(i"reduce match type $this $hashCode", matchTypes, show = true)(withMode(Mode.Type) { + computeFootprint() def matchCases(cmp: TrackingTypeComparer): Type = val saved = ctx.typerState.snapshot() try cmp.matchCases(scrutinee.normalized, cases.map(MatchTypeCaseSpec.analyze(_))) catch case ex: Throwable => handleRecursive("reduce type ", i"$scrutinee match ...", ex) finally - updateReductionContext(cmp.footprint) + //updateReductionContext(cmp.footprint) ctx.typerState.resetTo(saved) // this drops caseLambdas in constraint and undoes any typevar // instantiations during matchtype reduction TypeComparer.tracked(matchCases) }) + //else println(i"no change for $this $hashCode / $myReduced") myReduced.nn } diff --git a/tests/pos/bad-footprint.scala b/tests/pos/bad-footprint.scala new file mode 100644 index 000000000000..4e34267ce9a0 --- /dev/null +++ b/tests/pos/bad-footprint.scala @@ -0,0 +1,99 @@ + +object NamedTuple: + + opaque type AnyNamedTuple = Any + opaque type NamedTuple[N <: Tuple, +V <: Tuple] >: V <: AnyNamedTuple = V + + export NamedTupleDecomposition.{Names, DropNames} + + /** The type of the named tuple `X` mapped with the type-level function `F`. + * If `X = (n1 : T1, ..., ni : Ti)` then `Map[X, F] = `(n1 : F[T1], ..., ni : F[Ti])`. + */ + type Map[X <: AnyNamedTuple, F[_ <: Tuple.Union[DropNames[X]]]] = + NamedTuple[Names[X], Tuple.Map[DropNames[X], F]] + +end NamedTuple + +object NamedTupleDecomposition: + import NamedTuple.* + + /** The names of a named tuple, represented as a tuple of literal string values. */ + type Names[X <: AnyNamedTuple] <: Tuple = X match + case NamedTuple[n, _] => n + + /** The value types of a named tuple represented as a regular tuple. */ + type DropNames[NT <: AnyNamedTuple] <: Tuple = NT match + case NamedTuple[_, x] => x +end NamedTupleDecomposition + +class Expr[Result] + +object Expr: + import NamedTuple.{NamedTuple, AnyNamedTuple} + + type Of[A] = Expr[A] + + type StripExpr[E] = E match + case Expr.Of[b] => b + + case class Ref[A]($name: String = "") extends Expr.Of[A] + + case class Join[A <: AnyNamedTuple](a: A) + extends Expr.Of[NamedTuple.Map[A, StripExpr]] +end Expr + +trait Query[A] + +object Query: + // Extension methods to support for-expression syntax for queries + extension [R](x: Query[R]) + def map[B](f: Expr.Ref[R] => Expr.Of[B]): Query[B] = ??? + +case class City(zipCode: Int, name: String, population: Int) + +object Test: + import Expr.StripExpr + import NamedTuple.{NamedTuple, AnyNamedTuple} + + val cities: Query[City] = ??? + val q6 = + cities.map: city => + val x: NamedTuple[ + ("name", "zipCode"), + (Expr.Of[String], Expr.Of[Int])] = ??? + Expr.Join(x) + +/* Was error: + +-- [E007] Type Mismatch Error: bad-footprint.scala:60:16 ----------------------- +60 | cities.map: city => + | ^ + |Found: Expr.Ref[City] => + | Expr[ + | NamedTuple.NamedTuple[(("name" : String), ("zipCode" : String)), (String, + | Int)] + | ] + |Required: Expr.Ref[City] => + | Expr[ + | NamedTuple.NamedTuple[ + | NamedTupleDecomposition.Names[ + | NamedTuple.NamedTuple[(("name" : String), ("zipCode" : String)), ( + | Expr[String], Expr[Int])] + | ], + | Tuple.Map[ + | NamedTupleDecomposition.DropNames[ + | NamedTuple.NamedTuple[(("name" : String), ("zipCode" : String)), ( + | Expr[String], Expr[Int])] + | ], + | Expr.StripExpr] + | ] + | ] +61 | val x: NamedTuple[ +62 | ("name", "zipCode"), +63 | (Expr.Of[String], Expr.Of[Int])] = ??? +64 | Expr.Join(x) + | + | longer explanation available when compiling with `-explain` +1 error found + +*/ \ No newline at end of file From d6ba9b2d1d3b574561fe0d180f3252e5532d27fe Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 7 Feb 2024 13:30:46 +0100 Subject: [PATCH 013/277] Drop old footprint calculation # Conflicts: # compiler/src/dotty/tools/dotc/core/Types.scala --- .../dotty/tools/dotc/core/TypeComparer.scala | 48 +++++-------------- .../src/dotty/tools/dotc/core/Types.scala | 39 +++++++-------- 2 files changed, 30 insertions(+), 57 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index b04978357508..99d8bb2238d5 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -3054,7 +3054,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling end provablyDisjointTypeArgs protected def explainingTypeComparer(short: Boolean) = ExplainingTypeComparer(comparerContext, short) - protected def trackingTypeComparer = TrackingTypeComparer(comparerContext) + protected def matchReducer = MatchReducer(comparerContext) private def inSubComparer[T, Cmp <: TypeComparer](comparer: Cmp)(op: Cmp => T): T = val saved = myInstance @@ -3068,8 +3068,8 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling inSubComparer(cmp)(op) cmp.lastTrace(header) - def tracked[T](op: TrackingTypeComparer => T)(using Context): T = - inSubComparer(trackingTypeComparer)(op) + def reduceMatchWith[T](op: MatchReducer => T)(using Context): T = + inSubComparer(matchReducer)(op) } object TypeComparer { @@ -3236,14 +3236,14 @@ object TypeComparer { def explained[T](op: ExplainingTypeComparer => T, header: String = "Subtype trace:", short: Boolean = false)(using Context): String = comparing(_.explained(op, header, short)) - def tracked[T](op: TrackingTypeComparer => T)(using Context): T = - comparing(_.tracked(op)) + def reduceMatchWith[T](op: MatchReducer => T)(using Context): T = + comparing(_.reduceMatchWith(op)) def subCaptures(refs1: CaptureSet, refs2: CaptureSet, frozen: Boolean)(using Context): CaptureSet.CompareResult = comparing(_.subCaptures(refs1, refs2, frozen)) } -object TrackingTypeComparer: +object MatchReducer: import printing.*, Texts.* enum MatchResult extends Showable: case Reduced(tp: Type) @@ -3259,38 +3259,16 @@ object TrackingTypeComparer: case Stuck => "Stuck" case NoInstance(fails) => "NoInstance(" ~ Text(fails.map(p.toText(_) ~ p.toText(_)), ", ") ~ ")" -class TrackingTypeComparer(initctx: Context) extends TypeComparer(initctx) { - import TrackingTypeComparer.* +/** A type comparer for reducing match types. + * TODO: Not sure this needs to be a type comparer. Can we make it a + * separate class? + */ +class MatchReducer(initctx: Context) extends TypeComparer(initctx) { + import MatchReducer.* init(initctx) - override def trackingTypeComparer = this - - val footprint: mutable.Set[Type] = mutable.Set[Type]() - - override def bounds(param: TypeParamRef)(using Context): TypeBounds = { - if (param.binder `ne` caseLambda) footprint += param - super.bounds(param) - } - - override def addOneBound(param: TypeParamRef, bound: Type, isUpper: Boolean)(using Context): Boolean = { - if (param.binder `ne` caseLambda) footprint += param - super.addOneBound(param, bound, isUpper) - } - - override def gadtBounds(sym: Symbol)(using Context): TypeBounds | Null = { - if (sym.exists) footprint += sym.typeRef - super.gadtBounds(sym) - } - - override def gadtAddBound(sym: Symbol, b: Type, isUpper: Boolean): Boolean = - if (sym.exists) footprint += sym.typeRef - super.gadtAddBound(sym, b, isUpper) - - override def typeVarInstance(tvar: TypeVar)(using Context): Type = { - footprint += tvar - super.typeVarInstance(tvar) - } + override def matchReducer = this def matchCases(scrut: Type, cases: List[MatchTypeCaseSpec])(using Context): Type = { // a reference for the type parameters poisoned during matching diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index a7aed3893948..78e22b7b76b9 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -5025,17 +5025,11 @@ object Types extends TypeUtils { tp.underlying } - def updateReductionContext(footprint: collection.Set[Type]): Unit = - reductionContext = util.HashMap() - for (tp <- footprint) - reductionContext(tp) = contextInfo(tp) - matchTypes.println(i"footprint for $this $hashCode: ${footprint.toList.map(x => (x, contextInfo(x)))}%, %") - def isUpToDate: Boolean = reductionContext.keysIterator.forall: tp => reductionContext(tp) `eq` contextInfo(tp) - def computeFootprint(): Unit = + def setReductionContext(): Unit = new TypeTraverser: var footprint: Set[Type] = Set() var deep: Boolean = true @@ -5067,6 +5061,7 @@ object Types extends TypeUtils { for tp <- footprint do reductionContext(tp) = contextInfo(tp) matchTypes.println(i"footprint for $thisMatchType $hashCode: ${footprint.toList.map(x => (x, contextInfo(x)))}%, %") + end setReductionContext record("MatchType.reduce called") if !Config.cacheMatchReduced @@ -5077,21 +5072,21 @@ object Types extends TypeUtils { record("MatchType.reduce computed") if (myReduced != null) record("MatchType.reduce cache miss") myReduced = - trace(i"reduce match type $this $hashCode", matchTypes, show = true)(withMode(Mode.Type) { - computeFootprint() - def matchCases(cmp: TrackingTypeComparer): Type = - val saved = ctx.typerState.snapshot() - try cmp.matchCases(scrutinee.normalized, cases.map(MatchTypeCaseSpec.analyze(_))) - catch case ex: Throwable => - handleRecursive("reduce type ", i"$scrutinee match ...", ex) - finally - //updateReductionContext(cmp.footprint) - ctx.typerState.resetTo(saved) - // this drops caseLambdas in constraint and undoes any typevar - // instantiations during matchtype reduction - - TypeComparer.tracked(matchCases) - }) + trace(i"reduce match type $this $hashCode", matchTypes, show = true): + withMode(Mode.Type): + setReductionContext() + def matchCases(cmp: MatchReducer): Type = + val saved = ctx.typerState.snapshot() + try + cmp.matchCases(scrutinee.normalized, cases.map(MatchTypeCaseSpec.analyze(_))) + catch case ex: Throwable => + handleRecursive("reduce type ", i"$scrutinee match ...", ex) + finally + ctx.typerState.resetTo(saved) + // this drops caseLambdas in constraint and undoes any typevar + // instantiations during matchtype reduction + TypeComparer.reduceMatchWith(matchCases) + //else println(i"no change for $this $hashCode / $myReduced") myReduced.nn } From 5e0dfba9374f4d20a68fc1f849ded694bb6a5ee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Costa?= Date: Sun, 11 Feb 2024 18:11:07 +0000 Subject: [PATCH 014/277] Update scala-js-dom --- project/Build.scala | 4 ++-- .../content-contributors/ContentContributors.scala | 13 +++++++------ .../main/src/searchbar/SearchbarComponent.scala | 8 ++++---- .../searchbar/engine/InkuireJSSearchEngine.scala | 1 - .../src/versions-dropdown/DropdownHandler.scala | 7 ++++--- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index 720aa329bbdd..4eab6f86faa7 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1688,7 +1688,7 @@ object Build { lazy val `scaladoc-js-common` = project.in(file("scaladoc-js/common")). enablePlugins(DottyJSPlugin). dependsOn(`scala3-library-bootstrappedJS`). - settings(libraryDependencies += ("org.scala-js" %%% "scalajs-dom" % "1.1.0").cross(CrossVersion.for3Use2_13)) + settings(libraryDependencies += ("org.scala-js" %%% "scalajs-dom" % "2.8.0")) lazy val `scaladoc-js-main` = project.in(file("scaladoc-js/main")). enablePlugins(DottyJSPlugin). @@ -1704,7 +1704,7 @@ object Build { settings( Test / fork := false, scalaJSUseMainModuleInitializer := true, - libraryDependencies += ("org.scala-js" %%% "scalajs-dom" % "1.1.0").cross(CrossVersion.for3Use2_13) + libraryDependencies += ("org.scala-js" %%% "scalajs-dom" % "2.8.0") ) def generateDocumentation(configTask: Def.Initialize[Task[GenerationConfig]]) = diff --git a/scaladoc-js/contributors/src/content-contributors/ContentContributors.scala b/scaladoc-js/contributors/src/content-contributors/ContentContributors.scala index 2e10e4fae0fa..1db7973b3129 100644 --- a/scaladoc-js/contributors/src/content-contributors/ContentContributors.scala +++ b/scaladoc-js/contributors/src/content-contributors/ContentContributors.scala @@ -5,9 +5,10 @@ import org.scalajs.dom.ext._ import scala.util.matching.Regex._ import scala.util.matching._ -import org.scalajs.dom.ext.Ajax -import scala.scalajs.js.JSON +import org.scalajs.dom._ import scala.scalajs.js +import scala.scalajs.js.JSON +import scala.scalajs.js.Thenable.Implicits.thenable2future import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future @@ -55,8 +56,8 @@ class ContentContributors: def linkForFilename(filename: String) = githubContributorsUrl() + s"/commits?path=$filename" def getAuthorsForFilename(filename: String): Future[List[FullAuthor]] = { val link = linkForFilename(filename) - Ajax.get(link).map(_.responseText).flatMap { json => - val res = JSON.parse(json).asInstanceOf[Commits] + fetch(link).flatMap(_.json()).flatMap { json => + val res = json.asInstanceOf[Commits] val authors = res.map { commit => commit.author match case null => @@ -79,8 +80,8 @@ class ContentContributors: } } def findRename(link: String, filename: String): Future[Option[String]] = { - Ajax.get(link).map(_.responseText).map { json => - val res = JSON.parse(json).asInstanceOf[CommitDescription] + fetch(link).flatMap(_.json()).map { json => + val res = json.asInstanceOf[CommitDescription] val files = res.files files .find(_.filename == filename) diff --git a/scaladoc-js/main/src/searchbar/SearchbarComponent.scala b/scaladoc-js/main/src/searchbar/SearchbarComponent.scala index 010129eb9f59..02473ecccd55 100644 --- a/scaladoc-js/main/src/searchbar/SearchbarComponent.scala +++ b/scaladoc-js/main/src/searchbar/SearchbarComponent.scala @@ -148,7 +148,7 @@ class SearchbarComponent(engine: PageSearchEngine, inkuireEngine: InkuireJSSearc val htmlEntries = results.map(result => result.pageEntry.toHTML(result.indices)) val loadMoreElement = createLoadMoreElement - def loadMoreResults(entries: List[raw.HTMLElement]): Unit = { + def loadMoreResults(entries: List[HTMLElement]): Unit = { loadMoreElement.onclick = (event: Event) => { entries.take(resultsChunkSize).foreach(_.classList.remove("hidden")) val nextElems = entries.drop(resultsChunkSize) @@ -192,7 +192,7 @@ class SearchbarComponent(engine: PageSearchEngine, inkuireEngine: InkuireJSSearc } } - def createLoadingAnimation: raw.HTMLElement = + def createLoadingAnimation: HTMLElement = div(cls := "loading-wrapper")( div(cls := "loading") ) @@ -346,7 +346,7 @@ class SearchbarComponent(engine: PageSearchEngine, inkuireEngine: InkuireJSSearc val selectedElement = resultsDiv.querySelector("[selected]") if selectedElement != null then { selectedElement.removeAttribute("selected") - def recur(elem: raw.Element): raw.Element = { + def recur(elem: Element): Element = { val prev = elem.previousElementSibling if prev == null then null else { @@ -366,7 +366,7 @@ class SearchbarComponent(engine: PageSearchEngine, inkuireEngine: InkuireJSSearc } private def handleArrowDown() = { val selectedElement = resultsDiv.querySelector("[selected]") - def recur(elem: raw.Element): raw.Element = { + def recur(elem: Element): Element = { val next = elem.nextElementSibling if next == null then null else { diff --git a/scaladoc-js/main/src/searchbar/engine/InkuireJSSearchEngine.scala b/scaladoc-js/main/src/searchbar/engine/InkuireJSSearchEngine.scala index 2dde7178e3f7..75cf6f43a907 100644 --- a/scaladoc-js/main/src/searchbar/engine/InkuireJSSearchEngine.scala +++ b/scaladoc-js/main/src/searchbar/engine/InkuireJSSearchEngine.scala @@ -2,7 +2,6 @@ package dotty.tools.scaladoc import scala.io.Source import dotty.tools.scaladoc.PageEntry -import org.scalajs.dom.webworkers.Worker import org.scalajs.dom._ import scala.scalajs.js.{ JSON, Dynamic } import scala.collection.mutable.ListBuffer diff --git a/scaladoc-js/main/src/versions-dropdown/DropdownHandler.scala b/scaladoc-js/main/src/versions-dropdown/DropdownHandler.scala index 465ee44d1ad4..3551b207a246 100644 --- a/scaladoc-js/main/src/versions-dropdown/DropdownHandler.scala +++ b/scaladoc-js/main/src/versions-dropdown/DropdownHandler.scala @@ -7,9 +7,10 @@ import scala.util.{Success,Failure} import org.scalajs.dom._ import org.scalajs.dom.ext._ import scala.scalajs.js.annotation.JSExportTopLevel -import org.scalajs.dom.ext.Ajax +import org.scalajs.dom._ import scala.scalajs.js import scala.scalajs.js.JSON +import scala.scalajs.js.Thenable.Implicits.thenable2future import utils.HTML._ @@ -33,7 +34,7 @@ class DropdownHandler: btn.classList.add("disabled") btn.classList.add("hidden") - private def getURLContent(url: String): Future[String] = Ajax.get(url).map(_.responseText) + private def getURLContent(url: String): Future[String] = fetch(url).flatMap(_.text()) window.sessionStorage.getItem(KEY) match case null => // If no key, returns null @@ -68,7 +69,7 @@ end DropdownHandler def dropdownHandler(e: Event) = e.stopPropagation() if document.getElementById("version-dropdown").getElementsByTagName("a").size > 0 && - window.getSelection.toString.length == 0 then + window.getSelection().toString.length == 0 then document.getElementById("version-dropdown").classList.toggle("expanded") document.getElementById("dropdown-trigger").classList.toggle("selected") From e6b8e75d80597ab02ea2513ce11d37cf9c6bce01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Costa?= Date: Sun, 11 Feb 2024 18:11:34 +0000 Subject: [PATCH 015/277] Load search bar if defined in the query param --- .../main/src/searchbar/SearchbarComponent.scala | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/scaladoc-js/main/src/searchbar/SearchbarComponent.scala b/scaladoc-js/main/src/searchbar/SearchbarComponent.scala index 02473ecccd55..842b1cb44c23 100644 --- a/scaladoc-js/main/src/searchbar/SearchbarComponent.scala +++ b/scaladoc-js/main/src/searchbar/SearchbarComponent.scala @@ -17,6 +17,9 @@ import java.net.URI class SearchbarComponent(engine: PageSearchEngine, inkuireEngine: InkuireJSSearchEngine, parser: QueryParser): val initialChunkSize = 5 val resultsChunkSize = 20 + + val querySearch = Option(URLSearchParams(window.location.search).get("search")).filter(_.nonEmpty) + def pathToRoot() = window.document.documentElement.getAttribute("data-pathToRoot") extension (p: PageEntry) def toHTML(boldChars: Set[Int]) = @@ -262,7 +265,8 @@ class SearchbarComponent(engine: PageSearchEngine, inkuireEngine: InkuireJSSearc document.body.addEventListener("keydown", (e: KeyboardEvent) => handleGlobalKeyDown(e)) private val inputElem: html.Input = - input(cls := "scaladoc-searchbar-input", `type` := "search", `placeholder`:= "Find anything").tap { element => + val initialValue = querySearch.getOrElse("") + input(cls := "scaladoc-searchbar-input", `type` := "search", `placeholder`:= "Find anything", value := initialValue).tap { element => element.addEventListener("input", { e => clearTimeout(timeoutHandle) val inputValue = e.target.asInstanceOf[html.Input].value @@ -453,3 +457,7 @@ class SearchbarComponent(engine: PageSearchEngine, inkuireEngine: InkuireJSSearc } inputElem.dispatchEvent(new Event("input")) + if (querySearch.isDefined && !document.body.contains(rootDiv)) { + document.body.appendChild(rootDiv) + inputElem.focus() + } From e06b8318f000a727c9c054801ed8d465a6ee5c29 Mon Sep 17 00:00:00 2001 From: odersky Date: Sun, 11 Feb 2024 20:10:52 +0100 Subject: [PATCH 016/277] Update syntax.md 1. Add missing soft modifiers 2. Port changes from multiple type parameter sections to reference. Now that multiple type parameter sections are merged, this is the official syntax. This also covers extension method declarations. Fixes #19667 Fixes #19668 --- docs/_docs/internals/syntax.md | 42 +++++++++++++++++++++++----------- docs/_docs/reference/syntax.md | 20 ++++++++-------- 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/docs/_docs/internals/syntax.md b/docs/_docs/internals/syntax.md index aa8cd15f00a0..ede6144afca3 100644 --- a/docs/_docs/internals/syntax.md +++ b/docs/_docs/internals/syntax.md @@ -20,6 +20,8 @@ productions map to AST nodes. The following description of Scala tokens uses literal characters `‘c’` when referring to the ASCII fragment `\u0000` – `\u007F`. +Informal descriptions are typeset as `“some comment”`. + ## Lexical Syntax The lexical syntax of Scala is given by the following grammar in EBNF form: @@ -99,7 +101,10 @@ semi ::= ‘;’ | nl {nl} ## Optional Braces -The lexical analyzer also inserts `indent` and `outdent` tokens that represent regions of indented code [at certain points](../reference/other-new-features/indentation.md) +The principle of optional braces is that any keyword that can be followed by `{` can also be followed by an indented block, without needing an intervening `:`. +(Allowing an optional `:` would be counterproductive since it would introduce several ways to do the same thing.) + +The lexical analyzer inserts `indent` and `outdent` tokens that represent regions of indented code [at certain points](./other-new-features/indentation.md). In the context-free productions below we use the notation `<<< ts >>>` to indicate a token sequence `ts` that is either enclosed in a pair of braces `{ ts }` or that constitutes an indented region `indent ts outdent`. Analogously, the @@ -181,7 +186,7 @@ FunTypeArgs ::= InfixType | ‘(’ [ FunArgTypes ] ‘)’ | FunParamClause FunParamClause ::= ‘(’ TypedFunParam {‘,’ TypedFunParam } ‘)’ -TypedFunParam ::= [`erased`] id ‘:’ Type +TypedFunParam ::= [`erased`] id ‘:’ IntoType MatchType ::= InfixType `match` <<< TypeCaseClauses >>> InfixType ::= RefinedType {id [nl] RefinedType} InfixOp(t1, op, t2) RefinedType ::= AnnotType {[nl] Refinement} RefinedTypeTree(t, ds) @@ -201,14 +206,17 @@ SimpleType1 ::= id Singleton ::= SimpleRef | SimpleLiteral | Singleton ‘.’ id -FunArgType ::= [`erased`] Type - | [`erased`] ‘=>’ Type PrefixOp(=>, t) +FunArgType ::= IntoType + | ‘=>’ IntoType PrefixOp(=>, t) FunArgTypes ::= FunArgType { ‘,’ FunArgType } ParamType ::= [‘=>’] ParamValueType -ParamValueType ::= [‘into’] ExactParamType Into(t) -ExactParamType ::= ParamValueType [‘*’] PostfixOp(t, "*") +ParamValueType ::= IntoType [‘*’] PostfixOp(t, "*") +IntoType ::= [‘into’] IntoTargetType Into(t) + | ‘(’ ‘into’ IntoTargetType ‘)’ +IntoTargetType ::= Type + | FunTypeArgs (‘=>’ | ‘?=>’) IntoType TypeArgs ::= ‘[’ Types ‘]’ ts -Refinement ::= :<<< [RefineDef] {semi [RefineDef]} >>> ds +Refinement ::= :<<< [RefineDef] {semi [RefineDcl]} >>> ds TypeBounds ::= [‘>:’ Type] [‘<:’ Type] TypeBoundsTree(lo, hi) TypeParamBounds ::= TypeBounds {‘:’ Type} ContextBounds(typeBounds, tps) Types ::= Type {‘,’ Type} @@ -223,7 +231,7 @@ BlockResult ::= FunParams (‘=>’ | ‘?=>’) Block | HkTypeParamClause ‘=>’ Block | Expr1 FunParams ::= Bindings - | [`erased`] id + | id | ‘_’ Expr1 ::= [‘inline’] ‘if’ ‘(’ Expr ‘)’ {nl} Expr [[semi] ‘else’ Expr] If(Parens(cond), thenp, elsep?) | [‘inline’] ‘if’ Expr ‘then’ Expr [[semi] ‘else’ Expr] If(cond, thenp, elsep?) @@ -272,7 +280,7 @@ ColonArgument ::= colon [LambdaStart] LambdaStart ::= FunParams (‘=>’ | ‘?=>’) | HkTypeParamClause ‘=>’ Quoted ::= ‘'’ ‘{’ Block ‘}’ - | ‘'’ ‘[’ Type ‘]’ + | ‘'’ ‘[’ TypeBlock ‘]’ ExprSplice ::= spliceId -- if inside quoted block | ‘$’ ‘{’ Block ‘}’ -- unless inside quoted pattern | ‘$’ ‘{’ Pattern ‘}’ -- when inside quoted pattern @@ -294,6 +302,8 @@ BlockStat ::= Import | Extension | Expr1 | EndMarker +TypeBlock ::= {TypeBlockStat semi} Type +TypeBlockStat ::= ‘type’ {nl} TypeDcl ForExpr ::= ‘for’ ‘(’ Enumerators0 ‘)’ {nl} [‘do‘ | ‘yield’] Expr ForYield(enums, expr) / ForDo(enums, expr) | ‘for’ ‘{’ Enumerators0 ‘}’ {nl} [‘do‘ | ‘yield’] Expr @@ -376,8 +386,8 @@ Param ::= id ‘:’ ParamType [‘=’ Expr] ### Bindings and Imports ```ebnf -Bindings ::= ‘(’[`erased`] [Binding {‘,’ [`erased`] Binding}] ‘)’ -Binding ::= (id | ‘_’) [‘:’ Type] ValDef(_, id, tpe, EmptyTree) +Bindings ::= ‘(’ [Binding {‘,’ Binding}] ‘)’ +Binding ::= [`erased`] (id | ‘_’) [‘:’ Type] ValDef(_, id, tpe, EmptyTree) Modifier ::= LocalModifier | AccessModifier @@ -390,6 +400,10 @@ LocalModifier ::= ‘abstract’ | ‘implicit’ | ‘lazy’ | ‘inline’ + | ‘transparent’ + | ‘infix’ + | ‘erased’ + AccessModifier ::= (‘private’ | ‘protected’) [AccessQualifier] AccessQualifier ::= ‘[’ id ‘]’ @@ -414,9 +428,11 @@ EndMarkerTag ::= id | ‘if’ | ‘while’ | ‘for’ | ‘match’ | ### Definitions ```ebnf -RefineDef ::= ‘val’ ValDef - | ‘def’ DefDef +RefineDcl ::= ‘val’ ValDcl + | ‘def’ DefDcl | ‘type’ {nl} TypeDef +ValDcl ::= ids ‘:’ Type +DefDcl ::= DefSig ‘:’ Type Def ::= ‘val’ PatDef | ‘var’ PatDef diff --git a/docs/_docs/reference/syntax.md b/docs/_docs/reference/syntax.md index bf2c27d57863..be51d1f3db1a 100644 --- a/docs/_docs/reference/syntax.md +++ b/docs/_docs/reference/syntax.md @@ -383,6 +383,8 @@ LocalModifier ::= ‘abstract’ | ‘implicit’ | ‘lazy’ | ‘inline’ + | ‘transparent’ + | ‘infix’ AccessModifier ::= (‘private’ | ‘protected’) [AccessQualifier] AccessQualifier ::= ‘[’ id ‘]’ @@ -409,24 +411,22 @@ EndMarkerTag ::= id | ‘if’ | ‘while’ | ‘for’ | ‘match’ | ``` RefineDcl ::= ‘val’ ValDcl | ‘def’ DefDcl - | ‘type’ {nl} TypeDcl -Dcl ::= RefineDcl - | ‘var’ VarDcl + | ‘type’ {nl} TypeDef ValDcl ::= ids ‘:’ Type -VarDcl ::= ids ‘:’ Type DefDcl ::= DefSig ‘:’ Type -DefSig ::= id [DefTypeParamClause] [TypelessClauses] [DefImplicitClause] -TypeDcl ::= id [TypeParamClause] {FunParamClause} TypeBounds Def ::= ‘val’ PatDef | ‘var’ PatDef | ‘def’ DefDef | ‘type’ {nl} TypeDcl | TmplDef -PatDef ::= ids [‘:’ Type] ‘=’ Expr - | Pattern2 [‘:’ Type] ‘=’ Expr -DefDef ::= DefSig [‘:’ Type] ‘=’ Expr - | ‘this’ TypelessClauses [DefImplicitClause] ‘=’ ConstrExpr +PatDef ::= ids [‘:’ Type] [‘=’ Expr] + | Pattern2 [‘:’ Type] [‘=’ Expr] PatDef(_, pats, tpe?, expr) +DefDef ::= DefSig [‘:’ Type] [‘=’ Expr] DefDef(_, name, paramss, tpe, expr) + | ‘this’ TypelessClauses [DefImplicitClause] ‘=’ ConstrExpr DefDef(_, , vparamss, EmptyTree, expr | Block) +DefSig ::= id [DefParamClauses] [DefImplicitClause] +TypeDef ::= id [TypeParamClause] {FunParamClause} TypeBounds TypeDefTree(_, name, tparams, bound + [‘=’ Type] TmplDef ::= ([‘case’] ‘class’ | ‘trait’) ClassDef | [‘case’] ‘object’ ObjectDef From 6a9bea8138bb2c307d61571cd0b9120ddfa8c404 Mon Sep 17 00:00:00 2001 From: odersky Date: Sun, 11 Feb 2024 21:28:09 +0100 Subject: [PATCH 017/277] Align Parser with syntax - Change doc comments to match described syntax - Refactor `typ` method to make it clear it matches the syntax --- .../dotty/tools/dotc/parsing/Parsers.scala | 174 +++++++++--------- .../dotty/tools/dotc/transform/Recheck.scala | 3 +- docs/_docs/internals/syntax.md | 10 +- 3 files changed, 90 insertions(+), 97 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 6892dfdd94ca..13e30fc04890 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1532,13 +1532,15 @@ object Parsers { * PolyFunType ::= HKTypeParamClause '=>' Type * | HKTypeParamClause ‘->’ [CaptureSet] Type -- under pureFunctions * FunTypeArgs ::= InfixType - * | `(' [ [ ‘['erased'] FunArgType {`,' FunArgType } ] `)' - * | '(' [ ‘['erased'] TypedFunParam {',' TypedFunParam } ')' + * | `(' [ FunArgType {`,' FunArgType } ] `)' + * | '(' [ TypedFunParam {',' TypedFunParam } ')' + * MatchType ::= InfixType `match` <<< TypeCaseClauses >>> */ def typ(): Tree = val start = in.offset var imods = Modifiers() var erasedArgs: ListBuffer[Boolean] = ListBuffer() + def functionRest(params: List[Tree]): Tree = val paramSpan = Span(start, in.lastOffset) atSpan(start, in.offset) { @@ -1567,7 +1569,8 @@ object Parsers { else accept(ARROW) - val resultType = if isPure then capturesAndResult(typ) else typ() + val resultType = + if isPure then capturesAndResult(typ) else typ() if token == TLARROW then for case ValDef(_, tpt, _) <- params do if isByNameType(tpt) then @@ -1585,98 +1588,93 @@ object Parsers { Function(params, resultType) } - var isValParamList = false + def typeRest(t: Tree) = in.token match + case ARROW | CTXARROW => + erasedArgs.addOne(false) + functionRest(t :: Nil) + case MATCH => + matchType(t) + case FORSOME => + syntaxError(ExistentialTypesNoLongerSupported()) + t + case _ if isPureArrow => + erasedArgs.addOne(false) + functionRest(t :: Nil) + case _ => + if erasedArgs.contains(true) && !t.isInstanceOf[FunctionWithMods] then + syntaxError(ErasedTypesCanOnlyBeFunctionTypes(), implicitKwPos(start)) + t - val t = - if (in.token == LPAREN) { + var isValParamList = false + if in.token == LPAREN then + in.nextToken() + if in.token == RPAREN then in.nextToken() - if (in.token == RPAREN) { - in.nextToken() - functionRest(Nil) - } - else { - val paramStart = in.offset - def addErased() = - erasedArgs.addOne(isErasedKw) - if isErasedKw then { in.skipToken(); } - addErased() - val ts = in.currentRegion.withCommasExpected { + functionRest(Nil) + else + val paramStart = in.offset + def addErased() = + erasedArgs.addOne(isErasedKw) + if isErasedKw then in.skipToken() + addErased() + val args = + in.currentRegion.withCommasExpected: funArgType() match case Ident(name) if name != tpnme.WILDCARD && in.isColon => isValParamList = true - def funParam(start: Offset, mods: Modifiers) = { - atSpan(start) { + def funParam(start: Offset, mods: Modifiers) = + atSpan(start): addErased() typedFunParam(in.offset, ident(), imods) - } - } commaSeparatedRest( typedFunParam(paramStart, name.toTermName, imods), () => funParam(in.offset, imods)) case t => - def funParam() = { - addErased() - funArgType() - } - commaSeparatedRest(t, funParam) - } - accept(RPAREN) - if isValParamList || in.isArrow || isPureArrow then - functionRest(ts) - else { - val ts1 = ts.mapConserve { t => - if isByNameType(t) then - syntaxError(ByNameParameterNotSupported(t), t.span) - stripByNameType(t) - else - t - } - val tuple = atSpan(start) { makeTupleOrParens(ts1) } - infixTypeRest( - refinedTypeRest( - withTypeRest( - annotTypeRest( - simpleTypeRest(tuple))))) - } - } - } - else if (in.token == LBRACKET) { - val start = in.offset - val tparams = typeParamClause(ParamOwner.TypeParam) - if (in.token == TLARROW) - atSpan(start, in.skipToken())(LambdaTypeTree(tparams, toplevelTyp())) - else if (in.token == ARROW || isPureArrow(nme.PUREARROW)) { - val arrowOffset = in.skipToken() - val body = toplevelTyp() - atSpan(start, arrowOffset) { - getFunction(body) match { - case Some(f) => - PolyFunction(tparams, body) - case None => - syntaxError(em"Implementation restriction: polymorphic function types must have a value parameter", arrowOffset) - Ident(nme.ERROR.toTypeName) - } - } - } - else { accept(TLARROW); typ() } - } - else if (in.token == INDENT) enclosed(INDENT, typ()) - else infixType() - - in.token match - case ARROW | CTXARROW => - erasedArgs.addOne(false) - functionRest(t :: Nil) - case MATCH => matchType(t) - case FORSOME => syntaxError(ExistentialTypesNoLongerSupported()); t - case _ => - if isPureArrow then - erasedArgs.addOne(false) - functionRest(t :: Nil) + def funArg() = + addErased() + funArgType() + commaSeparatedRest(t, funArg) + accept(RPAREN) + if isValParamList || in.isArrow || isPureArrow then + functionRest(args) else - if (erasedArgs.contains(true) && !t.isInstanceOf[FunctionWithMods]) - syntaxError(ErasedTypesCanOnlyBeFunctionTypes(), implicitKwPos(start)) - t + val args1 = args.mapConserve: t => + if isByNameType(t) then + syntaxError(ByNameParameterNotSupported(t), t.span) + stripByNameType(t) + else + t + val tuple = atSpan(start): + makeTupleOrParens(args1) + typeRest: + infixTypeRest: + refinedTypeRest: + withTypeRest: + annotTypeRest: + simpleTypeRest(tuple) + else if in.token == LBRACKET then + val start = in.offset + val tparams = typeParamClause(ParamOwner.TypeParam) + if in.token == TLARROW then + atSpan(start, in.skipToken()): + LambdaTypeTree(tparams, toplevelTyp()) + else if in.token == ARROW || isPureArrow(nme.PUREARROW) then + val arrowOffset = in.skipToken() + val body = toplevelTyp() + atSpan(start, arrowOffset): + getFunction(body) match + case Some(f) => + PolyFunction(tparams, body) + case None => + syntaxError(em"Implementation restriction: polymorphic function types must have a value parameter", arrowOffset) + Ident(nme.ERROR.toTypeName) + else + accept(TLARROW) + typ() + else if in.token == INDENT then + enclosed(INDENT, typ()) + else + typeRest(infixType()) end typ private def makeKindProjectorTypeDef(name: TypeName): TypeDef = { @@ -1713,7 +1711,7 @@ object Parsers { private def implicitKwPos(start: Int): Span = Span(start, start + nme.IMPLICITkw.asSimpleName.length) - /** TypedFunParam ::= id ':' Type */ + /** TypedFunParam ::= [`erased`] id ':' Type */ def typedFunParam(start: Offset, name: TermName, mods: Modifiers = EmptyModifiers): ValDef = atSpan(start) { acceptColon() @@ -2068,7 +2066,7 @@ object Parsers { */ def paramType(): Tree = paramTypeOf(paramValueType) - /** ParamValueType ::= [`into`] Type [`*'] + /** ParamValueType ::= Type [`*'] */ def paramValueType(): Tree = { val t = maybeInto(toplevelTyp) @@ -2425,7 +2423,7 @@ object Parsers { Match(t, inBracesOrIndented(caseClauses(() => caseClause()))) } - /** `match' `{' TypeCaseClauses `}' + /** `match' <<< TypeCaseClauses >>> */ def matchType(t: Tree): MatchTypeTree = atSpan(startOffset(t), accept(MATCH)) { @@ -2435,7 +2433,7 @@ object Parsers { /** FunParams ::= Bindings * | id * | `_' - * Bindings ::= `(' [[‘erased’] Binding {`,' Binding}] `)' + * Bindings ::= `(' [Binding {`,' Binding}] `)' */ def funParams(mods: Modifiers, location: Location): List[Tree] = if in.token == LPAREN then @@ -3173,7 +3171,7 @@ object Parsers { * | AccessModifier * | override * | opaque - * LocalModifier ::= abstract | final | sealed | open | implicit | lazy | erased | inline | transparent + * LocalModifier ::= abstract | final | sealed | open | implicit | lazy | inline | transparent | infix | erased */ def modifiers(allowed: BitSet = modifierTokens, start: Modifiers = Modifiers()): Modifiers = { @tailrec diff --git a/compiler/src/dotty/tools/dotc/transform/Recheck.scala b/compiler/src/dotty/tools/dotc/transform/Recheck.scala index 3d7b81a606ab..44d5caba631a 100644 --- a/compiler/src/dotty/tools/dotc/transform/Recheck.scala +++ b/compiler/src/dotty/tools/dotc/transform/Recheck.scala @@ -9,14 +9,13 @@ import ast.* import Names.Name import Phases.Phase import DenotTransformers.{DenotTransformer, IdentityDenotTransformer, SymTransformer} -import NamerOps.{methodType, linkConstructorParams} +import NamerOps.linkConstructorParams import NullOpsDecorator.stripNull import typer.ErrorReporting.err import typer.ProtoTypes.* import typer.TypeAssigner.seqLitType import typer.ConstFold import typer.ErrorReporting.{Addenda, NothingToAdd} -import NamerOps.methodType import config.Printers.recheckr import util.Property import StdNames.nme diff --git a/docs/_docs/internals/syntax.md b/docs/_docs/internals/syntax.md index ede6144afca3..06d35dfe4a4a 100644 --- a/docs/_docs/internals/syntax.md +++ b/docs/_docs/internals/syntax.md @@ -186,7 +186,7 @@ FunTypeArgs ::= InfixType | ‘(’ [ FunArgTypes ] ‘)’ | FunParamClause FunParamClause ::= ‘(’ TypedFunParam {‘,’ TypedFunParam } ‘)’ -TypedFunParam ::= [`erased`] id ‘:’ IntoType +TypedFunParam ::= [`erased`] id ‘:’ Type MatchType ::= InfixType `match` <<< TypeCaseClauses >>> InfixType ::= RefinedType {id [nl] RefinedType} InfixOp(t1, op, t2) RefinedType ::= AnnotType {[nl] Refinement} RefinedTypeTree(t, ds) @@ -206,15 +206,11 @@ SimpleType1 ::= id Singleton ::= SimpleRef | SimpleLiteral | Singleton ‘.’ id -FunArgType ::= IntoType - | ‘=>’ IntoType PrefixOp(=>, t) +FunArgType ::= Type + | ‘=>’ Type PrefixOp(=>, t) FunArgTypes ::= FunArgType { ‘,’ FunArgType } ParamType ::= [‘=>’] ParamValueType ParamValueType ::= IntoType [‘*’] PostfixOp(t, "*") -IntoType ::= [‘into’] IntoTargetType Into(t) - | ‘(’ ‘into’ IntoTargetType ‘)’ -IntoTargetType ::= Type - | FunTypeArgs (‘=>’ | ‘?=>’) IntoType TypeArgs ::= ‘[’ Types ‘]’ ts Refinement ::= :<<< [RefineDef] {semi [RefineDcl]} >>> ds TypeBounds ::= [‘>:’ Type] [‘<:’ Type] TypeBoundsTree(lo, hi) From 6159045fd1d6fe4d1c330ec8dccd6a21b3d2adf0 Mon Sep 17 00:00:00 2001 From: odersky Date: Sun, 11 Feb 2024 21:40:49 +0100 Subject: [PATCH 018/277] Simplify erased parameter syntax erased is not always a modifier on the parameter name. The syntax `erased Type` is dropped. There's not really a need for this syntactic inconsistency. --- .../dotty/tools/dotc/parsing/Parsers.scala | 2 +- tests/neg/lambda-infer.scala | 4 ++-- .../polymorphic-erased-functions-types.check | 20 +++++++++---------- .../polymorphic-erased-functions-types.scala | 4 ++-- tests/run/erased-lambdas.scala | 8 ++++---- tests/run/polymorphic-erased-functions.scala | 4 ++-- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 13e30fc04890..fdd2f50af718 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1631,7 +1631,7 @@ object Parsers { () => funParam(in.offset, imods)) case t => def funArg() = - addErased() + erasedArgs.addOne(false) funArgType() commaSeparatedRest(t, funArg) accept(RPAREN) diff --git a/tests/neg/lambda-infer.scala b/tests/neg/lambda-infer.scala index 90f40aa05e86..6c3db90cb893 100644 --- a/tests/neg/lambda-infer.scala +++ b/tests/neg/lambda-infer.scala @@ -1,6 +1,6 @@ //> using options -language:experimental.erasedDefinitions -type F = (Int, erased Int) => Int +type F = (x: Int, erased y: Int) => Int erased class A @@ -14,7 +14,7 @@ erased class A use { (x, y) => x } // error: Expected F got (Int, Int) => Int - def singleParam(f: (erased Int) => Int) = f(5) + def singleParam(f: (erased x: Int) => Int) = f(5) singleParam(x => 5) // error: Expected (erased Int) => Int got Int => Int singleParam((erased x) => 5) // ok diff --git a/tests/neg/polymorphic-erased-functions-types.check b/tests/neg/polymorphic-erased-functions-types.check index 39d2720023cf..78a0ab37b1ab 100644 --- a/tests/neg/polymorphic-erased-functions-types.check +++ b/tests/neg/polymorphic-erased-functions-types.check @@ -5,11 +5,11 @@ | Required: [T] => (x$1: T) => Unit | | longer explanation available when compiling with `-explain` --- [E007] Type Mismatch Error: tests/neg/polymorphic-erased-functions-types.scala:4:37 --------------------------------- -4 |def t1b: [T] => (erased T) => Unit = [T] => (t: T) => () // error - | ^^^^^^^^^^^^^^^^^^^ - | Found: [T] => (t: T) => Unit - | Required: [T] => (erased x$1: T) => Unit +-- [E007] Type Mismatch Error: tests/neg/polymorphic-erased-functions-types.scala:4:40 --------------------------------- +4 |def t1b: [T] => (erased t: T) => Unit = [T] => (t: T) => () // error + | ^^^^^^^^^^^^^^^^^^^ + | Found: [T] => (t: T) => Unit + | Required: [T] => (erased t: T) => Unit | | longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg/polymorphic-erased-functions-types.scala:6:36 --------------------------------- @@ -19,10 +19,10 @@ | Required: [T, U] => (x$1: T, x$2: U) => Unit | | longer explanation available when compiling with `-explain` --- [E007] Type Mismatch Error: tests/neg/polymorphic-erased-functions-types.scala:7:43 --------------------------------- -7 |def t2b: [T, U] => (T, erased U) => Unit = [T, U] => (t: T, u: U) => () // error - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | Found: [T, U] => (t: T, u: U) => Unit - | Required: [T, U] => (x$1: T, erased x$2: U) => Unit +-- [E007] Type Mismatch Error: tests/neg/polymorphic-erased-functions-types.scala:7:49 --------------------------------- +7 |def t2b: [T, U] => (t: T, erased u: U) => Unit = [T, U] => (t: T, u: U) => () // error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | Found: [T, U] => (t: T, u: U) => Unit + | Required: [T, U] => (t: T, erased u: U) => Unit | | longer explanation available when compiling with `-explain` diff --git a/tests/neg/polymorphic-erased-functions-types.scala b/tests/neg/polymorphic-erased-functions-types.scala index d453c4602bad..c49a5c05c74e 100644 --- a/tests/neg/polymorphic-erased-functions-types.scala +++ b/tests/neg/polymorphic-erased-functions-types.scala @@ -1,7 +1,7 @@ import language.experimental.erasedDefinitions def t1a: [T] => T => Unit = [T] => (erased t: T) => () // error -def t1b: [T] => (erased T) => Unit = [T] => (t: T) => () // error +def t1b: [T] => (erased t: T) => Unit = [T] => (t: T) => () // error def t2a: [T, U] => (T, U) => Unit = [T, U] => (t: T, erased u: U) => () // error -def t2b: [T, U] => (T, erased U) => Unit = [T, U] => (t: T, u: U) => () // error +def t2b: [T, U] => (t: T, erased u: U) => Unit = [T, U] => (t: T, u: U) => () // error diff --git a/tests/run/erased-lambdas.scala b/tests/run/erased-lambdas.scala index 9c107e0fa0d4..e6be086bec8c 100644 --- a/tests/run/erased-lambdas.scala +++ b/tests/run/erased-lambdas.scala @@ -3,8 +3,8 @@ // lambdas should parse and work -type F = (erased Int, String) => String -type S = (Int, erased String) => Int +type F = (erased x: Int, y: String) => String +type S = (x: Int, erased y: String) => Int def useF(f: F) = f(5, "a") def useS(f: S) = f(5, "a") @@ -16,7 +16,7 @@ val fsExpl = (x: Int, erased y: String) => x // contextual lambdas should work -type FC = (Int, erased String) ?=> Int +type FC = (x: Int, erased y: String) ?=> Int def useCtx(f: FC) = f(using 5, "a") @@ -25,7 +25,7 @@ val fCvExpl = (x: Int, erased y: String) ?=> x // nested lambdas should work -val nested: Int => (String, erased Int) => FC = a => (_, erased _) => (c, erased d) ?=> a + c +val nested: Int => (x: String, erased y: Int) => FC = a => (_, erased _) => (c, erased d) ?=> a + c @main def Test() = assert("a" == useF(ff)) diff --git a/tests/run/polymorphic-erased-functions.scala b/tests/run/polymorphic-erased-functions.scala index 4086423d8c6a..40fd548a67af 100644 --- a/tests/run/polymorphic-erased-functions.scala +++ b/tests/run/polymorphic-erased-functions.scala @@ -3,8 +3,8 @@ import language.experimental.erasedDefinitions object Test extends App { // Types - type F1 = [T] => (erased T) => Int - type F2 = [T, U] => (T, erased U) => T + type F1 = [T] => (erased x: T) => Int + type F2 = [T, U] => (t: T, erased u: U) => T // Terms val t1 = [T] => (erased t: T) => 3 From 3f95ea7cc1b5bf6d1f500e584634f4ef74391e99 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 13 Feb 2024 13:20:30 +0100 Subject: [PATCH 019/277] Remove dead code in Checking Remove `checkTraitInheritance` in class `Checking`. Note that we have an identical method in `object Checking` which is only used by post-typer. --- .../src/dotty/tools/dotc/typer/Checking.scala | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 5fc63f4575e3..eadca79cd78b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -1250,30 +1250,6 @@ trait Checking { def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(using Context): Unit = Checking.checkDerivedValueClass(clazz, stats) - /** Given a parent `parent` of a class `cls`, if `parent` is a trait check that - * the superclass of `cls` derived from the superclass of `parent`. - * - * An exception is made if `cls` extends `Any`, and `parent` is `java.io.Serializable` - * or `java.lang.Comparable`. These two classes are treated by Scala as universal - * traits. E.g. the following is OK: - * - * ... extends Any with java.io.Serializable - * - * The standard library relies on this idiom. - */ - def checkTraitInheritance(parent: Symbol, cls: ClassSymbol, pos: SrcPos)(using Context): Unit = - parent match { - case parent: ClassSymbol if parent.is(Trait) => - val psuper = parent.superClass - val csuper = cls.superClass - val ok = csuper.derivesFrom(psuper) || - parent.is(JavaDefined) && csuper == defn.AnyClass && - (parent == defn.JavaSerializableClass || parent == defn.ComparableClass) - if (!ok) - report.error(em"illegal trait inheritance: super$csuper does not derive from $parent's super$psuper", pos) - case _ => - } - /** Check that case classes are not inherited by case classes. */ def checkCaseInheritance(parent: Symbol, caseCls: ClassSymbol, pos: SrcPos)(using Context): Unit = @@ -1650,7 +1626,6 @@ trait NoChecking extends ReChecking { override def checkParentCall(call: Tree, caller: ClassSymbol)(using Context): Unit = () override def checkSimpleKinded(tpt: Tree)(using Context): Tree = tpt override def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(using Context): Unit = () - override def checkTraitInheritance(parentSym: Symbol, cls: ClassSymbol, pos: SrcPos)(using Context): Unit = () override def checkCaseInheritance(parentSym: Symbol, caseCls: ClassSymbol, pos: SrcPos)(using Context): Unit = () override def checkNoForwardDependencies(vparams: List[ValDef])(using Context): Unit = () override def checkMembersOK(tp: Type, pos: SrcPos)(using Context): Type = tp From 720e1fd705e18370a3b95e534bb3a302c8f14cbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Marks?= Date: Tue, 13 Feb 2024 17:03:45 +0100 Subject: [PATCH 020/277] Set version developed on main as 3.4.2 --- project/Build.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Build.scala b/project/Build.scala index 720aa329bbdd..356d8bd0e7b9 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -85,7 +85,7 @@ object Build { val referenceVersion = "3.3.1" - val baseVersion = "3.4.1-RC1" + val baseVersion = "3.4.2-RC1" // Versions used by the vscode extension to create a new project // This should be the latest published releases. From 0f81c2f2eb2c23d656bda8f0d5e7cfc2b098a17c Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Wed, 14 Feb 2024 00:07:38 +0800 Subject: [PATCH 021/277] Ignore orphan parameters inside a retains annotation during Ycheck --- .../tools/dotc/transform/TreeChecker.scala | 20 ++++++++++++++++++- tests/pos-custom-args/captures/i19661.scala | 8 ++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tests/pos-custom-args/captures/i19661.scala diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index d847d14603a2..3039c692e33c 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -23,6 +23,7 @@ import collection.mutable import ProtoTypes.* import staging.StagingLevel import inlines.Inlines.inInlineMethod +import cc.{isRetainsLike, CaptureAnnotation} import dotty.tools.backend.jvm.DottyBackendInterface.symExtensions @@ -162,6 +163,13 @@ object TreeChecker { */ def checkNoOrphans(tp0: Type, tree: untpd.Tree = untpd.EmptyTree)(using Context): Type = new TypeMap() { val definedBinders = new java.util.IdentityHashMap[Type, Any] + private var inRetainingAnnot = false + + def insideRetainingAnnot[T](op: => T): T = + val saved = inRetainingAnnot + inRetainingAnnot = true + try op finally inRetainingAnnot = saved + def apply(tp: Type): Type = { tp match { case tp: BindingType => @@ -169,10 +177,20 @@ object TreeChecker { mapOver(tp) definedBinders.remove(tp) case tp: ParamRef => - assert(definedBinders.get(tp.binder) != null, s"orphan param: ${tp.show}, hash of binder = ${System.identityHashCode(tp.binder)}, tree = ${tree.show}, type = $tp0") + val isValidRef = + definedBinders.get(tp.binder) != null + || inRetainingAnnot + // Inside a normal @retains annotation, the captured references could be ill-formed. See issue #19661. + // But this is ok since capture checking does not rely on them. + assert(isValidRef, s"orphan param: ${tp.show}, hash of binder = ${System.identityHashCode(tp.binder)}, tree = ${tree.show}, type = $tp0") case tp: TypeVar => assert(tp.isInstantiated, s"Uninstantiated type variable: ${tp.show}, tree = ${tree.show}") apply(tp.underlying) + case tp @ AnnotatedType(underlying, annot) if annot.symbol.isRetainsLike && !annot.isInstanceOf[CaptureAnnotation] => + val underlying1 = this(underlying) + val annot1 = insideRetainingAnnot: + annot.mapWith(this) + derivedAnnotatedType(tp, underlying1, annot1) case _ => mapOver(tp) } diff --git a/tests/pos-custom-args/captures/i19661.scala b/tests/pos-custom-args/captures/i19661.scala new file mode 100644 index 000000000000..9e882fba0a87 --- /dev/null +++ b/tests/pos-custom-args/captures/i19661.scala @@ -0,0 +1,8 @@ +import language.experimental.captureChecking + +trait MySet[A]: + def collect[B](pf: PartialFunction[A, B]^): MySet[B]^{this, pf} + +class Test: + def f(xs: MySet[Int]) = xs collect { case x => x } + def g(xs: MySet[Int]): MySet[Int] = f(xs) From 32723c5811a88a5ccad9c2ead16dcbb0610f80ab Mon Sep 17 00:00:00 2001 From: odersky Date: Tue, 13 Feb 2024 22:30:18 +0100 Subject: [PATCH 022/277] Address review comments --- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 4 ++-- docs/_docs/internals/syntax.md | 9 ++++----- docs/_docs/reference/syntax.md | 11 +++++++---- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index fdd2f50af718..fbb4e1319948 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1539,7 +1539,7 @@ object Parsers { def typ(): Tree = val start = in.offset var imods = Modifiers() - var erasedArgs: ListBuffer[Boolean] = ListBuffer() + val erasedArgs: ListBuffer[Boolean] = ListBuffer() def functionRest(params: List[Tree]): Tree = val paramSpan = Span(start, in.lastOffset) @@ -3324,7 +3324,7 @@ object Parsers { /** ClsTermParamClause ::= ‘(’ ClsParams ‘)’ | UsingClsTermParamClause * UsingClsTermParamClause::= ‘(’ ‘using’ [‘erased’] (ClsParams | ContextTypes) ‘)’ * ClsParams ::= ClsParam {‘,’ ClsParam} - * ClsParam ::= {Annotation} + * ClsParam ::= {Annotation} [{Modifier} (‘val’ | ‘var’)] Param * * TypelessClause ::= DefTermParamClause * | UsingParamClause diff --git a/docs/_docs/internals/syntax.md b/docs/_docs/internals/syntax.md index 06d35dfe4a4a..005ff174cd12 100644 --- a/docs/_docs/internals/syntax.md +++ b/docs/_docs/internals/syntax.md @@ -210,9 +210,9 @@ FunArgType ::= Type | ‘=>’ Type PrefixOp(=>, t) FunArgTypes ::= FunArgType { ‘,’ FunArgType } ParamType ::= [‘=>’] ParamValueType -ParamValueType ::= IntoType [‘*’] PostfixOp(t, "*") +ParamValueType ::= Type [‘*’] PostfixOp(t, "*") TypeArgs ::= ‘[’ Types ‘]’ ts -Refinement ::= :<<< [RefineDef] {semi [RefineDcl]} >>> ds +Refinement ::= :<<< [RefineDcl] {semi [RefineDcl]} >>> ds TypeBounds ::= [‘>:’ Type] [‘<:’ Type] TypeBoundsTree(lo, hi) TypeParamBounds ::= TypeBounds {‘:’ Type} ContextBounds(typeBounds, tps) Types ::= Type {‘,’ Type} @@ -299,7 +299,7 @@ BlockStat ::= Import | Expr1 | EndMarker TypeBlock ::= {TypeBlockStat semi} Type -TypeBlockStat ::= ‘type’ {nl} TypeDcl +TypeBlockStat ::= ‘type’ {nl} TypeDef ForExpr ::= ‘for’ ‘(’ Enumerators0 ‘)’ {nl} [‘do‘ | ‘yield’] Expr ForYield(enums, expr) / ForDo(enums, expr) | ‘for’ ‘{’ Enumerators0 ‘}’ {nl} [‘do‘ | ‘yield’] Expr @@ -359,7 +359,7 @@ ClsParamClause ::= [nl] ‘(’ ClsParams ‘)’ | [nl] ‘(’ ‘using’ (ClsParams | FunArgTypes) ‘)’ ClsParams ::= ClsParam {‘,’ ClsParam} ClsParam ::= {Annotation} ValDef(mods, id, tpe, expr) -- point of mods on val/var - [{Modifier} (‘val’ | ‘var’) | ‘inline’] Param + [{Modifier} (‘val’ | ‘var’)] Param DefParamClauses ::= DefParamClause { DefParamClause } -- and two DefTypeParamClause cannot be adjacent DefParamClause ::= DefTypeParamClause @@ -473,7 +473,6 @@ TemplateBody ::= :<<< [SelfType] TemplateStat {semi TemplateStat} >>> TemplateStat ::= Import | Export | {Annotation [nl]} {Modifier} Def - | {Annotation [nl]} {Modifier} Dcl | Extension | Expr1 | EndMarker diff --git a/docs/_docs/reference/syntax.md b/docs/_docs/reference/syntax.md index be51d1f3db1a..1980bc4e0ab2 100644 --- a/docs/_docs/reference/syntax.md +++ b/docs/_docs/reference/syntax.md @@ -294,7 +294,7 @@ BlockStat ::= Import | Expr1 | EndMarker TypeBlock ::= {TypeBlockStat semi} Type -TypeBlockStat ::= ‘type’ {nl} TypeDcl +TypeBlockStat ::= ‘type’ {nl} TypeDef ForExpr ::= ‘for’ ‘(’ Enumerators0 ‘)’ {nl} [‘do‘ | ‘yield’] Expr | ‘for’ ‘{’ Enumerators0 ‘}’ {nl} [‘do‘ | ‘yield’] Expr @@ -350,8 +350,12 @@ ClsParamClauses ::= {ClsParamClause} [[nl] ‘(’ [‘implicit’] ClsParams ClsParamClause ::= [nl] ‘(’ ClsParams ‘)’ | [nl] ‘(’ ‘using’ (ClsParams | FunArgTypes) ‘)’ ClsParams ::= ClsParam {‘,’ ClsParam} -ClsParam ::= {Annotation} [{Modifier} (‘val’ | ‘var’) | ‘inline’] Param +ClsParam ::= {Annotation} [{Modifier} (‘val’ | ‘var’)] Param +DefParamClauses ::= DefParamClause { DefParamClause } -- and two DefTypeParamClause cannot be adjacent +DefParamClause ::= DefTypeParamClause + | DefTermParamClause + | UsingParamClause TypelessClauses ::= TypelessClause {TypelessClause} TypelessClause ::= DefTermParamClause | UsingParamClause @@ -418,7 +422,7 @@ DefDcl ::= DefSig ‘:’ Type Def ::= ‘val’ PatDef | ‘var’ PatDef | ‘def’ DefDef - | ‘type’ {nl} TypeDcl + | ‘type’ {nl} TypeDef | TmplDef PatDef ::= ids [‘:’ Type] [‘=’ Expr] | Pattern2 [‘:’ Type] [‘=’ Expr] PatDef(_, pats, tpe?, expr) @@ -458,7 +462,6 @@ TemplateBody ::= :<<< [SelfType] TemplateStat {semi TemplateStat} >>> TemplateStat ::= Import | Export | {Annotation [nl]} {Modifier} Def - | {Annotation [nl]} {Modifier} Dcl | Extension | Expr1 | EndMarker From f2f505194687d2bfe2de6d9688ff79518360f12d Mon Sep 17 00:00:00 2001 From: odersky Date: Tue, 13 Feb 2024 22:59:07 +0100 Subject: [PATCH 023/277] Update docs/_docs/internals/syntax.md Co-authored-by: Eugene Flesselle --- docs/_docs/internals/syntax.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_docs/internals/syntax.md b/docs/_docs/internals/syntax.md index 005ff174cd12..cfa77c6ff965 100644 --- a/docs/_docs/internals/syntax.md +++ b/docs/_docs/internals/syntax.md @@ -104,7 +104,7 @@ semi ::= ‘;’ | nl {nl} The principle of optional braces is that any keyword that can be followed by `{` can also be followed by an indented block, without needing an intervening `:`. (Allowing an optional `:` would be counterproductive since it would introduce several ways to do the same thing.) -The lexical analyzer inserts `indent` and `outdent` tokens that represent regions of indented code [at certain points](./other-new-features/indentation.md). +The lexical analyzer inserts `indent` and `outdent` tokens that represent regions of indented code [at certain points](../reference/other-new-features/indentation.md). In the context-free productions below we use the notation `<<< ts >>>` to indicate a token sequence `ts` that is either enclosed in a pair of braces `{ ts }` or that constitutes an indented region `indent ts outdent`. Analogously, the From cc698957a9f5004bd7328989fb68305e001a87e8 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 14 Feb 2024 10:10:34 +0100 Subject: [PATCH 024/277] Improve -Xprint-suspension message --- compiler/src/dotty/tools/dotc/Run.scala | 2 +- tests/neg-macros/annot-suspend-cycle.check | 2 +- tests/neg-macros/macros-in-same-project-4.check | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala index 4e0b7d09e95f..d18a2ddc7db0 100644 --- a/compiler/src/dotty/tools/dotc/Run.scala +++ b/compiler/src/dotty/tools/dotc/Run.scala @@ -141,7 +141,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint |""" val enableXprintSuspensionHint = if ctx.settings.XprintSuspension.value then "" - else "\n\nCompiling with -Xprint-suspension gives more information." + else "\n\nCompile with -Xprint-suspension for information." report.error(em"""Cyclic macro dependencies $where |Compilation stopped since no further progress can be made. | diff --git a/tests/neg-macros/annot-suspend-cycle.check b/tests/neg-macros/annot-suspend-cycle.check index e3ecea7345fd..437398f1d668 100644 --- a/tests/neg-macros/annot-suspend-cycle.check +++ b/tests/neg-macros/annot-suspend-cycle.check @@ -9,4 +9,4 @@ Compilation stopped since no further progress can be made. To fix this, place macros in one set of files and their callers in another. -Compiling with -Xprint-suspension gives more information. +Compile with -Xprint-suspension for information. diff --git a/tests/neg-macros/macros-in-same-project-4.check b/tests/neg-macros/macros-in-same-project-4.check index 79c78fd0fb7f..f027f57637f4 100644 --- a/tests/neg-macros/macros-in-same-project-4.check +++ b/tests/neg-macros/macros-in-same-project-4.check @@ -3,4 +3,4 @@ Compilation stopped since no further progress can be made. To fix this, place macros in one set of files and their callers in another. -Compiling with -Xprint-suspension gives more information. +Compile with -Xprint-suspension for information. From 2c324360cf395c21539674445b418f056ff4cc41 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 14 Feb 2024 10:11:15 +0100 Subject: [PATCH 025/277] Add regression test Closes #19526 --- tests/neg-macros/i19526.check | 6 ++++++ tests/neg-macros/i19526/Macro.scala | 15 +++++++++++++++ tests/neg-macros/i19526/Test.scala | 14 ++++++++++++++ tests/pos-macros/i19526b/Macro.scala | 15 +++++++++++++++ tests/pos-macros/i19526b/Test.scala | 16 ++++++++++++++++ 5 files changed, 66 insertions(+) create mode 100644 tests/neg-macros/i19526.check create mode 100644 tests/neg-macros/i19526/Macro.scala create mode 100644 tests/neg-macros/i19526/Test.scala create mode 100644 tests/pos-macros/i19526b/Macro.scala create mode 100644 tests/pos-macros/i19526b/Test.scala diff --git a/tests/neg-macros/i19526.check b/tests/neg-macros/i19526.check new file mode 100644 index 000000000000..2ad0a7aa2199 --- /dev/null +++ b/tests/neg-macros/i19526.check @@ -0,0 +1,6 @@ +Cyclic macro dependencies in tests/neg-macros/i19526/Test.scala. +Compilation stopped since no further progress can be made. + +To fix this, place macros in one set of files and their callers in another. + +Compile with -Xprint-suspension for information. diff --git a/tests/neg-macros/i19526/Macro.scala b/tests/neg-macros/i19526/Macro.scala new file mode 100644 index 000000000000..e6861c1986ef --- /dev/null +++ b/tests/neg-macros/i19526/Macro.scala @@ -0,0 +1,15 @@ +package crash.test + +import scala.language.dynamics + +import scala.quoted.* + +object Export extends Dynamic: + inline def applyDynamic(name: "apply")(inline args: Any*): Stack = ${ + applyDynamicImpl('args) + } + + def applyDynamicImpl(args: Expr[Seq[Any]])(using Quotes): Expr[Stack] = + import quotes.reflect.* + + '{ Stack("", Vector.empty) } diff --git a/tests/neg-macros/i19526/Test.scala b/tests/neg-macros/i19526/Test.scala new file mode 100644 index 000000000000..45ae51b664dd --- /dev/null +++ b/tests/neg-macros/i19526/Test.scala @@ -0,0 +1,14 @@ +package crash.test + +case class Stack private[crash] ( + exports: String, + dependsOn: Vector[Int] +) + +trait StackFactory: + val exports: Export.type = Export + + def apply(dependsOn: Int*): Stack = + Export().copy(dependsOn = dependsOn.toVector) + +// nopos-error diff --git a/tests/pos-macros/i19526b/Macro.scala b/tests/pos-macros/i19526b/Macro.scala new file mode 100644 index 000000000000..e6861c1986ef --- /dev/null +++ b/tests/pos-macros/i19526b/Macro.scala @@ -0,0 +1,15 @@ +package crash.test + +import scala.language.dynamics + +import scala.quoted.* + +object Export extends Dynamic: + inline def applyDynamic(name: "apply")(inline args: Any*): Stack = ${ + applyDynamicImpl('args) + } + + def applyDynamicImpl(args: Expr[Seq[Any]])(using Quotes): Expr[Stack] = + import quotes.reflect.* + + '{ Stack("", Vector.empty) } diff --git a/tests/pos-macros/i19526b/Test.scala b/tests/pos-macros/i19526b/Test.scala new file mode 100644 index 000000000000..1cc037298e01 --- /dev/null +++ b/tests/pos-macros/i19526b/Test.scala @@ -0,0 +1,16 @@ +package crash.test + +case class Stack private[crash] ( + exports: String, + dependsOn: Vector[Int] +) + +object Stack: + @annotation.publicInBinary + private[crash] def apply(exports: String, dependsOn: Vector[Int]): Stack = new Stack(exports, dependsOn) + +trait StackFactory: + val exports: Export.type = Export + + def apply(dependsOn: Int*): Stack = + Export().copy(dependsOn = dependsOn.toVector) From 5eb08456537801c51db79caf5adb318418a103a9 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Wed, 14 Feb 2024 15:29:55 +0100 Subject: [PATCH 026/277] Java TASTy: use new threadsafe writer implementation Also fix bug where Jar entries for -Yjava-tasty-output have backslash on Windows. --- .../dotty/tools/dotc/transform/Pickler.scala | 28 +- .../dotty/tools/io/ClassfileWriterOps.scala | 50 ---- compiler/src/dotty/tools/io/FileWriters.scala | 254 ++++++++++++++++++ 3 files changed, 274 insertions(+), 58 deletions(-) delete mode 100644 compiler/src/dotty/tools/io/ClassfileWriterOps.scala create mode 100644 compiler/src/dotty/tools/io/FileWriters.scala diff --git a/compiler/src/dotty/tools/dotc/transform/Pickler.scala b/compiler/src/dotty/tools/dotc/transform/Pickler.scala index 0be66828d58c..27b5d53e25dc 100644 --- a/compiler/src/dotty/tools/dotc/transform/Pickler.scala +++ b/compiler/src/dotty/tools/dotc/transform/Pickler.scala @@ -9,7 +9,7 @@ import tasty.* import config.Printers.{noPrinter, pickling} import config.Feature import java.io.PrintStream -import io.ClassfileWriterOps +import io.FileWriters.TastyWriter import StdNames.{str, nme} import Periods.* import Phases.* @@ -19,8 +19,9 @@ import reporting.{ThrowingReporter, Profile, Message} import collection.mutable import util.concurrent.{Executor, Future} import compiletime.uninitialized -import dotty.tools.io.JarArchive +import dotty.tools.io.{JarArchive, AbstractFile} import dotty.tools.dotc.printing.OutlinePrinter +import scala.annotation.constructorOnly object Pickler { val name: String = "pickler" @@ -32,8 +33,17 @@ object Pickler { */ inline val ParallelPickling = true - class EarlyFileWriter(writer: ClassfileWriterOps): - export writer.{writeTasty, close} + class EarlyFileWriter private (writer: TastyWriter, origin: AbstractFile): + def this(dest: AbstractFile)(using @constructorOnly ctx: Context) = this(TastyWriter(dest), dest) + + export writer.writeTasty + + def close(): Unit = + writer.close() + origin match { + case jar: JarArchive => jar.close() // also close the file system + case _ => + } } /** This phase pickles trees */ @@ -184,7 +194,7 @@ class Pickler extends Phase { override def runOn(units: List[CompilationUnit])(using Context): List[CompilationUnit] = { val sigWriter: Option[Pickler.EarlyFileWriter] = ctx.settings.YjavaTastyOutput.value match case jar: JarArchive if jar.exists => - Some(Pickler.EarlyFileWriter(ClassfileWriterOps(jar))) + Some(Pickler.EarlyFileWriter(jar)) case _ => None val units0 = @@ -225,9 +235,11 @@ class Pickler extends Phase { (cls, pickled) <- unit.pickled if cls.isDefinedInCurrentRun do - val binaryName = cls.binaryClassName.replace('.', java.io.File.separatorChar).nn - val binaryClassName = if (cls.is(Module)) binaryName.stripSuffix(str.MODULE_SUFFIX).nn else binaryName - writer.writeTasty(binaryClassName, pickled()) + val binaryClassName = cls.binaryClassName + val internalName = + if (cls.is(Module)) binaryClassName.stripSuffix(str.MODULE_SUFFIX).nn + else binaryClassName + val _ = writer.writeTasty(internalName, pickled()) count += 1 finally writer.close() diff --git a/compiler/src/dotty/tools/io/ClassfileWriterOps.scala b/compiler/src/dotty/tools/io/ClassfileWriterOps.scala deleted file mode 100644 index c2107ded6f51..000000000000 --- a/compiler/src/dotty/tools/io/ClassfileWriterOps.scala +++ /dev/null @@ -1,50 +0,0 @@ -package dotty.tools.io - -import dotty.tools.io.* -import dotty.tools.dotc.core.Decorators.* -import dotty.tools.dotc.core.Contexts.* -import dotty.tools.dotc.report -import scala.language.unsafeNulls -import scala.annotation.constructorOnly - - -/** Experimental usage - writes bytes to JarArchives */ -class ClassfileWriterOps(outputDir: JarArchive)(using @constructorOnly ictx: Context) { - - type InternalName = String - - // if non-null, classfiles are written to a jar instead of the output directory - private val jarWriter: JarWriter | Null = - val localCtx = ictx - outputDir.underlyingSource.map { source => - if outputDir.isEmpty then - new Jar(source.file).jarWriter() - else inContext(localCtx) { - // Writing to non-empty JAR might be an undefined behaviour, e.g. in case if other files where - // created using `AbstractFile.bufferedOutputStream`instead of JarWriter - report.warning(em"Tried to write to non-empty JAR: $source") - null - } - }.getOrElse( - inContext(localCtx) { - report.warning(em"tried to create a file writer for $outputDir, but it had no underlying source.") - null - } - ) - - def writeTasty(className: InternalName, bytes: Array[Byte]): Unit = - writeToJar(className, bytes, ".tasty") - - private def writeToJar(className: InternalName, bytes: Array[Byte], suffix: String): Unit = { - if (jarWriter == null) return - val path = className + suffix - val out = jarWriter.newOutputStream(path) - try out.write(bytes, 0, bytes.length) - finally out.flush() - } - - def close(): Unit = { - if (jarWriter != null) jarWriter.close() - outputDir.close() - } -} diff --git a/compiler/src/dotty/tools/io/FileWriters.scala b/compiler/src/dotty/tools/io/FileWriters.scala new file mode 100644 index 000000000000..4f03194fa4ce --- /dev/null +++ b/compiler/src/dotty/tools/io/FileWriters.scala @@ -0,0 +1,254 @@ +package dotty.tools.io + +import dotty.tools.dotc.core.Contexts.* +import dotty.tools.dotc.core.Decorators.em +import dotty.tools.dotc.report +import dotty.tools.io.AbstractFile +import dotty.tools.io.JarArchive +import dotty.tools.io.PlainFile + +import java.io.BufferedOutputStream +import java.io.DataOutputStream +import java.io.FileOutputStream +import java.io.IOException +import java.nio.ByteBuffer +import java.nio.channels.ClosedByInterruptException +import java.nio.channels.FileChannel +import java.nio.file.FileAlreadyExistsException +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.StandardOpenOption +import java.nio.file.attribute.FileAttribute +import java.util +import java.util.concurrent.ConcurrentHashMap +import java.util.zip.CRC32 +import java.util.zip.Deflater +import java.util.zip.ZipEntry +import java.util.zip.ZipOutputStream +import scala.language.unsafeNulls + +/** Copied from `dotty.tools.backend.jvm.ClassfileWriters` but no `PostProcessorFrontendAccess` needed */ +object FileWriters { + type InternalName = String + type NullableFile = AbstractFile | Null + + /** + * The interface to writing classfiles. GeneratedClassHandler calls these methods to generate the + * directory and files that are created, and eventually calls `close` when the writing is complete. + * + * The companion object is responsible for constructing a appropriate and optimal implementation for + * the supplied settings. + * + * Operations are threadsafe. + */ + sealed trait TastyWriter { + /** + * Write a `.tasty` file. + * + * @param name the internal name of the class, e.g. "scala.Option" + */ + def writeTasty(name: InternalName, bytes: Array[Byte])(using Context): NullableFile + + /** + * Close the writer. Behavior is undefined after a call to `close`. + */ + def close(): Unit + + protected def classToRelativePath(className: InternalName): String = + className.replace('.', '/').nn + ".tasty" + } + + object TastyWriter { + + def apply(output: AbstractFile)(using Context): TastyWriter = { + + // In Scala 2 depenening on cardinality of distinct output dirs MultiClassWriter could have been used + // In Dotty we always use single output directory + val basicTastyWriter = new SingleTastyWriter( + FileWriter(output, None) + ) + + basicTastyWriter + } + + private final class SingleTastyWriter(underlying: FileWriter) extends TastyWriter { + + override def writeTasty(className: InternalName, bytes: Array[Byte])(using Context): NullableFile = { + underlying.writeFile(classToRelativePath(className), bytes) + } + + override def close(): Unit = underlying.close() + } + + } + + sealed trait FileWriter { + def writeFile(relativePath: String, bytes: Array[Byte])(using Context): NullableFile + def close(): Unit + } + + object FileWriter { + def apply(file: AbstractFile, jarManifestMainClass: Option[String])(using Context): FileWriter = + if (file.isInstanceOf[JarArchive]) { + val jarCompressionLevel = ctx.settings.YjarCompressionLevel.value + // Writing to non-empty JAR might be an undefined behaviour, e.g. in case if other files where + // created using `AbstractFile.bufferedOutputStream`instead of JarWritter + val jarFile = file.underlyingSource.getOrElse{ + throw new IllegalStateException("No underlying source for jar") + } + assert(file.isEmpty, s"Unsafe writing to non-empty JAR: $jarFile") + new JarEntryWriter(jarFile, jarManifestMainClass, jarCompressionLevel) + } + else if (file.isVirtual) new VirtualFileWriter(file) + else if (file.isDirectory) new DirEntryWriter(file.file.toPath.nn) + else throw new IllegalStateException(s"don't know how to handle an output of $file [${file.getClass}]") + } + + private final class JarEntryWriter(file: AbstractFile, mainClass: Option[String], compressionLevel: Int) extends FileWriter { + //keep these imports local - avoid confusion with scala naming + import java.util.jar.Attributes.Name.{MANIFEST_VERSION, MAIN_CLASS} + import java.util.jar.{JarOutputStream, Manifest} + + val storeOnly = compressionLevel == Deflater.NO_COMPRESSION + + val jarWriter: JarOutputStream = { + import scala.util.Properties.* + val manifest = new Manifest + val attrs = manifest.getMainAttributes.nn + attrs.put(MANIFEST_VERSION, "1.0") + attrs.put(ScalaCompilerVersion, versionNumberString) + mainClass.foreach(c => attrs.put(MAIN_CLASS, c)) + + val jar = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(file.file), 64000), manifest) + jar.setLevel(compressionLevel) + if (storeOnly) jar.setMethod(ZipOutputStream.STORED) + jar + } + + lazy val crc = new CRC32 + + override def writeFile(relativePath: String, bytes: Array[Byte])(using Context): NullableFile = this.synchronized { + val entry = new ZipEntry(relativePath) + if (storeOnly) { + // When using compression method `STORED`, the ZIP spec requires the CRC and compressed/ + // uncompressed sizes to be written before the data. The JarOutputStream could compute the + // values while writing the data, but not patch them into the stream after the fact. So we + // need to pre-compute them here. The compressed size is taken from size. + // https://stackoverflow.com/questions/1206970/how-to-create-uncompressed-zip-archive-in-java/5868403 + // With compression method `DEFLATED` JarOutputStream computes and sets the values. + entry.setSize(bytes.length) + crc.reset() + crc.update(bytes) + entry.setCrc(crc.getValue) + } + jarWriter.putNextEntry(entry) + try jarWriter.write(bytes, 0, bytes.length) + finally jarWriter.flush() + null + } + + override def close(): Unit = this.synchronized(jarWriter.close()) + } + + private final class DirEntryWriter(base: Path) extends FileWriter { + val builtPaths = new ConcurrentHashMap[Path, java.lang.Boolean]() + val noAttributes = Array.empty[FileAttribute[?]] + private val isWindows = scala.util.Properties.isWin + + private def checkName(component: Path)(using Context): Unit = if (isWindows) { + val specials = raw"(?i)CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9]".r + val name = component.toString + def warnSpecial(): Unit = report.warning(em"path component is special Windows device: ${name}") + specials.findPrefixOf(name).foreach(prefix => if (prefix.length == name.length || name(prefix.length) == '.') warnSpecial()) + } + + def ensureDirForPath(baseDir: Path, filePath: Path)(using Context): Unit = { + import java.lang.Boolean.TRUE + val parent = filePath.getParent + if (!builtPaths.containsKey(parent)) { + parent.iterator.forEachRemaining(checkName) + try Files.createDirectories(parent, noAttributes*) + catch { + case e: FileAlreadyExistsException => + // `createDirectories` reports this exception if `parent` is an existing symlink to a directory + // but that's fine for us (and common enough, `scalac -d /tmp` on mac targets symlink). + if (!Files.isDirectory(parent)) + throw new FileConflictException(s"Can't create directory $parent; there is an existing (non-directory) file in its path", e) + } + builtPaths.put(baseDir, TRUE) + var current = parent + while ((current ne null) && (null ne builtPaths.put(current, TRUE))) { + current = current.getParent + } + } + checkName(filePath.getFileName()) + } + + // the common case is that we are are creating a new file, and on MS Windows the create and truncate is expensive + // because there is not an options in the windows API that corresponds to this so the truncate is applied as a separate call + // even if the file is new. + // as this is rare, its best to always try to create a new file, and it that fails, then open with truncate if that fails + + private val fastOpenOptions = util.EnumSet.of(StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE) + private val fallbackOpenOptions = util.EnumSet.of(StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING) + + override def writeFile(relativePath: String, bytes: Array[Byte])(using Context): NullableFile = { + val path = base.resolve(relativePath) + try { + ensureDirForPath(base, path) + val os = if (isWindows) { + try FileChannel.open(path, fastOpenOptions) + catch { + case _: FileAlreadyExistsException => FileChannel.open(path, fallbackOpenOptions) + } + } else FileChannel.open(path, fallbackOpenOptions) + + try os.write(ByteBuffer.wrap(bytes), 0L) + catch { + case ex: ClosedByInterruptException => + try Files.deleteIfExists(path) // don't leave a empty of half-written classfile around after an interrupt + catch { case _: Throwable => () } + throw ex + } + os.close() + } catch { + case e: FileConflictException => + report.error(em"error writing ${path.toString}: ${e.getMessage}") + case e: java.nio.file.FileSystemException => + if (ctx.settings.Ydebug.value) e.printStackTrace() + report.error(em"error writing ${path.toString}: ${e.getClass.getName} ${e.getMessage}") + } + AbstractFile.getFile(path) + } + + override def close(): Unit = () + } + + private final class VirtualFileWriter(base: AbstractFile) extends FileWriter { + private def getFile(base: AbstractFile, path: String): AbstractFile = { + def ensureDirectory(dir: AbstractFile): AbstractFile = + if (dir.isDirectory) dir + else throw new FileConflictException(s"${base.path}/${path}: ${dir.path} is not a directory") + val components = path.split('/') + var dir = base + for (i <- 0 until components.length - 1) dir = ensureDirectory(dir) subdirectoryNamed components(i).toString + ensureDirectory(dir) fileNamed components.last.toString + } + + private def writeBytes(outFile: AbstractFile, bytes: Array[Byte]): Unit = { + val out = new DataOutputStream(outFile.bufferedOutput) + try out.write(bytes, 0, bytes.length) + finally out.close() + } + + override def writeFile(relativePath: String, bytes: Array[Byte])(using Context):NullableFile = { + val outFile = getFile(base, relativePath) + writeBytes(outFile, bytes) + outFile + } + override def close(): Unit = () + } + + /** Can't output a file due to the state of the file system. */ + class FileConflictException(msg: String, cause: Throwable = null) extends IOException(msg, cause) +} From 465bf6500f862cb810b0db37ac79328bcb2aec04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Marks?= Date: Wed, 14 Feb 2024 08:34:42 -0800 Subject: [PATCH 027/277] Revert "Implement SIP-42 - Support for binary integer literals" --- .../dotty/tools/dotc/parsing/Scanners.scala | 2 +- .../other-new-features/binary-literals.md | 19 ----- docs/_spec/01-lexical-syntax.md | 5 +- docs/sidebar.yml | 1 - .../referenceReplacements/sidebar.yml | 1 - tests/neg/binaryLiterals.scala | 8 --- tests/run/binaryLiterals.scala | 72 ------------------- 7 files changed, 3 insertions(+), 105 deletions(-) delete mode 100644 docs/_docs/reference/other-new-features/binary-literals.md delete mode 100644 tests/neg/binaryLiterals.scala delete mode 100644 tests/run/binaryLiterals.scala diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index 3f9e8ca6532e..ea43706e9fdb 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -884,7 +884,7 @@ object Scanners { nextChar() ch match { case 'x' | 'X' => base = 16 ; nextChar() - case 'b' | 'B' => base = 2 ; nextChar() + //case 'b' | 'B' => base = 2 ; nextChar() case _ => base = 10 ; putChar('0') } if (base != 10 && !isNumberSeparator(ch) && digit2int(ch, base) < 0) diff --git a/docs/_docs/reference/other-new-features/binary-literals.md b/docs/_docs/reference/other-new-features/binary-literals.md deleted file mode 100644 index ba19fdd3d7f7..000000000000 --- a/docs/_docs/reference/other-new-features/binary-literals.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: doc-page -title: "Binary Integer Literals" -nightlyOf: https://docs.scala-lang.org/scala3/reference/changed-features/binary-integer-literals.html ---- - -A new syntax for integer literals has been added, it is now possible to do the following: -```scala -val bitmask = 0b0010_0000 // equivalent to 32, 0x20 -``` - -Binary integer literals behave similarly to hex integer literals (`0x...`), for example: -* Both `0b...` and `0B...` are allowed -* `0b`/`0B` on its own is disallowed, possible alternatives: `0`, `0b0`, `0B0` -* Only `0` and `1` are allowed after the b (`b`/`B`) -* Underscores `_` are allowed anywhere between digits, and are ignored: `0b__1 == 0b1` - - -Note: This change has been backported to Scala 2.13.13, it is therefore not technically a changed feature diff --git a/docs/_spec/01-lexical-syntax.md b/docs/_spec/01-lexical-syntax.md index e1686204116e..7dfcea87bd2d 100644 --- a/docs/_spec/01-lexical-syntax.md +++ b/docs/_spec/01-lexical-syntax.md @@ -332,10 +332,9 @@ Literal ::= [‘-’] integerLiteral ### Integer Literals ```ebnf -integerLiteral ::= (decimalNumeral | hexNumeral | binaryNumeral) [‘L’ | ‘l’] +integerLiteral ::= (decimalNumeral | hexNumeral) [‘L’ | ‘l’] decimalNumeral ::= ‘0’ | digit [{digit | ‘_’} digit] hexNumeral ::= ‘0’ (‘x’ | ‘X’) hexDigit [{hexDigit | ‘_’} hexDigit] -binaryNumeral ::= ‘0’ (‘b’ | ‘B’) binaryDigit [{binaryDigit | ‘_’} binaryDigit] ``` Values of type `Int` are all integer numbers between $-2\^{31}$ and $2\^{31}-1$, inclusive. @@ -358,7 +357,7 @@ The numeric ranges given by these types are: The digits of a numeric literal may be separated by arbitrarily many underscores for purposes of legibility. > ```scala -> 0 21_000 0x7F -42L 0xFFFF_FFFF 0b0100_0010 +> 0 21_000 0x7F -42L 0xFFFF_FFFF > ``` ### Floating Point Literals diff --git a/docs/sidebar.yml b/docs/sidebar.yml index 16678e682dd6..65d7ac2f9ee4 100644 --- a/docs/sidebar.yml +++ b/docs/sidebar.yml @@ -81,7 +81,6 @@ subsection: - page: reference/other-new-features/safe-initialization.md - page: reference/other-new-features/type-test.md - page: reference/other-new-features/experimental-defs.md - - page: reference/other-new-features/binary-literals.md - title: Other Changed Features directory: changed-features index: reference/changed-features/changed-features.md diff --git a/project/resources/referenceReplacements/sidebar.yml b/project/resources/referenceReplacements/sidebar.yml index 240085b681f2..de0f3d7bec2c 100644 --- a/project/resources/referenceReplacements/sidebar.yml +++ b/project/resources/referenceReplacements/sidebar.yml @@ -77,7 +77,6 @@ subsection: - page: reference/other-new-features/safe-initialization.md - page: reference/other-new-features/type-test.md - page: reference/other-new-features/experimental-defs.md - - page: reference/other-new-features/binary-literals.md - title: Other Changed Features directory: changed-features index: reference/changed-features/changed-features.md diff --git a/tests/neg/binaryLiterals.scala b/tests/neg/binaryLiterals.scala deleted file mode 100644 index 5d5f0b4986fc..000000000000 --- a/tests/neg/binaryLiterals.scala +++ /dev/null @@ -1,8 +0,0 @@ - -object Test: - val x = 0b1__0000_0000_0000_0000__0000_0000_0000_0000 // error: number too large - val X = 0B1__0000_0000_0000_0000__0000_0000_0000_0000 // error: number too large - val y = 0b1__0000_0000_0000_0000__0000_0000_0000_0000__0000_0000_0000_0000__0000_0000_0000_0000L // error: number too large - val Y = 0B1__0000_0000_0000_0000__0000_0000_0000_0000__0000_0000_0000_0000__0000_0000_0000_0000L // error: number too large - 0b // error: invalid literal number - 0b2 // error: invalid literal number diff --git a/tests/run/binaryLiterals.scala b/tests/run/binaryLiterals.scala deleted file mode 100644 index 5ac8c7b6f8bc..000000000000 --- a/tests/run/binaryLiterals.scala +++ /dev/null @@ -1,72 +0,0 @@ -@main -def Test = - val kenobi = 0b1 - - assert(kenobi == 1) - - assert(0B0000 == 0) - assert(0B0001 == 1) - assert(0B0010 == 2) - assert(0B0100 == 4) - assert(0B1000 == 8) - - assert(0b0000 == 0) - assert(0b0001 == 1) - assert(0b0010 == 2) - assert(0b0100 == 4) - assert(0b1000 == 8) - - assert(0b0001_0000 == 16) - assert(0b0010_0000 == 32) - assert(0b0100_0000 == 64) - assert(0b1000_0000 == 128) - - assert(0b0001_0000_0000 == 256) - assert(0b0010_0000_0000 == 512) - assert(0b0100_0000_0000 == 1024) - assert(0b1000_0000_0000 == 2048) - - assert(0b0001_0000_0000_0000 == 4096) - assert(0b0010_0000_0000_0000 == 8192) - assert(0b0100_0000_0000_0000 == 16384) - assert(0b1000_0000_0000_0000 == 32768) - - assert(0b0001__0000_0000_0000_0000 == 65536) - assert(0b0010__0000_0000_0000_0000 == 131072) - assert(0b0100__0000_0000_0000_0000 == 262144) - assert(0b1000__0000_0000_0000_0000 == 524288) - - assert(0b0001_0000__0000_0000_0000_0000 == 1048576) - assert(0b0010_0000__0000_0000_0000_0000 == 2097152) - assert(0b0100_0000__0000_0000_0000_0000 == 4194304) - assert(0b1000_0000__0000_0000_0000_0000 == 8388608) - - assert(0b0001_0000_0000__0000_0000_0000_0000 == 16777216) - assert(0b0010_0000_0000__0000_0000_0000_0000 == 33554432) - assert(0b0100_0000_0000__0000_0000_0000_0000 == 67108864) - assert(0b1000_0000_0000__0000_0000_0000_0000 == 134217728) - - assert(0b0001_0000_0000_0000__0000_0000_0000_0000 == 268435456) - assert(0b0010_0000_0000_0000__0000_0000_0000_0000 == 536870912) - assert(0b0100_0000_0000_0000__0000_0000_0000_0000 == 1073741824) - assert(0b1000_0000_0000_0000__0000_0000_0000_0000L == 2147483648L) - - assert(0b1000_0000_0000_0000__0000_0000_0000_0000 == -2147483648) // Signed ! - assert(0b1111_1111_1111_1111__1111_1111_1111_1111 == -1) - - // Randomly generated using https://numbergenerator.org/random-32-bit-binary-number#!numbers=10&length=32&addfilters= - // Converted to signed decimal using https://onlinetoolz.net/unsigned-signed#base=2&bits=32 - assert(0b0110_1000_1100_0101_0010_1100_0100_0011 == 1757752387) - assert(0b1111_0101_0100_1011_0101_1000_0011_0110 == -179611594) - assert(0b0000_0011_0000_1010_1010_0011_0000_0000 == 51028736) - assert(0b0101_0010_1111_1001_0100_0101_1101_1011 == 1392068059) - assert(0b1001_0000_1111_1001_1011_1101_1100_1111 == -1862681137) - - assert(0B0000_0111_1110_1100_0111_1100_1000_0010 == 132938882) - assert(0B0000_1011_0111_1011_0001_1010_1010_1000 == 192617128) - assert(0B1100_1100_1000_1010_1111_0111_0100_1101 == -863307955) - assert(0B1000_0000_0001_0010_0001_1001_0101_1110 == -2146297506) - assert(0B1110_0000_0110_1100_0111_0110_1100_1111 == -529762609) - - assert(0b0010_1001_0101_1001__1010_0100_1000_1010__1001_1000_0011_0111__1100_1011_0111_0101L == 2979593543648529269L) - assert(0b1101_1110_0100_1000__0010_1101_1010_0010__0111_1000_1111_1001__1010_1001_0101_1000L == -2429641823128802984L) From 314d26f80af2d81222751a14be21833053137126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Marks?= Date: Thu, 15 Feb 2024 13:24:30 +0100 Subject: [PATCH 028/277] Update package-objects.md Package objects are not deprecated in Scala 3.3.1 yet. [Cherry-picked bb5be18e11b412bc7fe39d76f0b4785297f49b86][modified] --- docs/_docs/reference/dropped-features/package-objects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_docs/reference/dropped-features/package-objects.md b/docs/_docs/reference/dropped-features/package-objects.md index 469ec6ac5134..9fe5bbd2de41 100644 --- a/docs/_docs/reference/dropped-features/package-objects.md +++ b/docs/_docs/reference/dropped-features/package-objects.md @@ -11,7 +11,7 @@ package object p { def b = ... } ``` -will be dropped. They are still available, but will be deprecated and removed afterwards. +will be dropped. They are still available, but will be deprecated and removed at some point in the future. Package objects are no longer needed since all kinds of definitions can now be written at the top-level. Example: ```scala From 34e5b5d8a27d6095c8029afd760b6fb9679208c5 Mon Sep 17 00:00:00 2001 From: Bersier Date: Tue, 2 Jan 2024 05:46:47 -0500 Subject: [PATCH 029/277] Update context-functions.md Mainly fixed indentation [Cherry-picked 20d0d59b8a59214ea33fb304f262b492803cc4e7] --- .../reference/contextual/context-functions.md | 124 ++++++++++-------- 1 file changed, 67 insertions(+), 57 deletions(-) diff --git a/docs/_docs/reference/contextual/context-functions.md b/docs/_docs/reference/contextual/context-functions.md index 0ad3c8757782..0d174583f230 100644 --- a/docs/_docs/reference/contextual/context-functions.md +++ b/docs/_docs/reference/contextual/context-functions.md @@ -8,27 +8,29 @@ _Context functions_ are functions with (only) context parameters. Their types are _context function types_. Here is an example of a context function type: ```scala +import scala.concurrent.ExecutionContext + type Executable[T] = ExecutionContext ?=> T ``` Context functions are written using `?=>` as the "arrow" sign. They are applied to synthesized arguments, in the same way methods with context parameters are applied. For instance: ```scala - given ec: ExecutionContext = ... +given ec: ExecutionContext = ... - def f(x: Int): ExecutionContext ?=> Int = ... +def f(x: Int): ExecutionContext ?=> Int = ... - // could be written as follows with the type alias from above - // def f(x: Int): Executable[Int] = ... +// could be written as follows with the type alias from above +// def f(x: Int): Executable[Int] = ... - f(2)(using ec) // explicit argument - f(2) // argument is inferred +f(2)(using ec) // explicit argument +f(2) // argument is inferred ``` Conversely, if the expected type of an expression `E` is a context function type `(T_1, ..., T_n) ?=> U` and `E` is not already an context function literal, `E` is converted to a context function literal by rewriting it to ```scala - (x_1: T1, ..., x_n: Tn) ?=> E +(x_1: T1, ..., x_n: Tn) ?=> E ``` where the names `x_1`, ..., `x_n` are arbitrary. This expansion is performed before the expression `E` is typechecked, which means that `x_1`, ..., `x_n` @@ -38,14 +40,14 @@ Like their types, context function literals are written using `?=>` as the arrow For example, continuing with the previous definitions, ```scala - def g(arg: Executable[Int]) = ... +def g(arg: Executable[Int]) = ... - g(22) // is expanded to g((ev: ExecutionContext) ?=> 22) +g(22) // is expanded to g((ev: ExecutionContext) ?=> 22) - g(f(2)) // is expanded to g((ev: ExecutionContext) ?=> f(2)(using ev)) +g(f(2)) // is expanded to g((ev: ExecutionContext) ?=> f(2)(using ev)) - g((ctx: ExecutionContext) ?=> f(3)) // is expanded to g((ctx: ExecutionContext) ?=> f(3)(using ctx)) - g((ctx: ExecutionContext) ?=> f(3)(using ctx)) // is left as it is +g((ctx: ExecutionContext) ?=> f(3)) // is expanded to g((ctx: ExecutionContext) ?=> f(3)(using ctx)) +g((ctx: ExecutionContext) ?=> f(3)(using ctx)) // is left as it is ``` ## Example: Builder Pattern @@ -54,63 +56,65 @@ Context function types have considerable expressive power. For instance, here is how they can support the "builder pattern", where the aim is to construct tables like this: ```scala - table { - row { - cell("top left") - cell("top right") - } - row { - cell("bottom left") - cell("bottom right") - } +table { + row { + cell("top left") + cell("top right") + } + row { + cell("bottom left") + cell("bottom right") } +} ``` The idea is to define classes for `Table` and `Row` that allow the addition of elements via `add`: ```scala - class Table: - val rows = new ArrayBuffer[Row] - def add(r: Row): Unit = rows += r - override def toString = rows.mkString("Table(", ", ", ")") +import scala.collection.mutable.ArrayBuffer + +class Table: + val rows = new ArrayBuffer[Row] + def add(r: Row): Unit = rows += r + override def toString = rows.mkString("Table(", ", ", ")") - class Row: - val cells = new ArrayBuffer[Cell] - def add(c: Cell): Unit = cells += c - override def toString = cells.mkString("Row(", ", ", ")") +class Row: + val cells = new ArrayBuffer[Cell] + def add(c: Cell): Unit = cells += c + override def toString = cells.mkString("Row(", ", ", ")") - case class Cell(elem: String) +case class Cell(elem: String) ``` Then, the `table`, `row` and `cell` constructor methods can be defined with context function types as parameters to avoid the plumbing boilerplate that would otherwise be necessary. ```scala - def table(init: Table ?=> Unit) = - given t: Table = Table() - init - t - - def row(init: Row ?=> Unit)(using t: Table) = - given r: Row = Row() - init - t.add(r) - - def cell(str: String)(using r: Row) = - r.add(new Cell(str)) +def table(init: Table ?=> Unit) = + given t: Table = Table() + init + t + +def row(init: Row ?=> Unit)(using t: Table) = + given r: Row = Row() + init + t.add(r) + +def cell(str: String)(using r: Row) = + r.add(new Cell(str)) ``` With that setup, the table construction code above compiles and expands to: ```scala - table { ($t: Table) ?=> - - row { ($r: Row) ?=> - cell("top left")(using $r) - cell("top right")(using $r) - }(using $t) - - row { ($r: Row) ?=> - cell("bottom left")(using $r) - cell("bottom right")(using $r) - }(using $t) - } +table { ($t: Table) ?=> + + row { ($r: Row) ?=> + cell("top left")(using $r) + cell("top right")(using $r) + }(using $t) + + row { ($r: Row) ?=> + cell("bottom left")(using $r) + cell("bottom right")(using $r) + }(using $t) +} ``` ## Example: Postconditions @@ -131,12 +135,18 @@ import PostConditions.{ensuring, result} val s = List(1, 2, 3).sum.ensuring(result == 6) ``` -**Explanations**: We use a context function type `WrappedResult[T] ?=> Boolean` +### Explanation + +We use a context function type `WrappedResult[T] ?=> Boolean` as the type of the condition of `ensuring`. An argument to `ensuring` such as `(result == 6)` will therefore have a given of type `WrappedResult[T]` in -scope to pass along to the `result` method. `WrappedResult` is a fresh type, to make sure +scope to pass along to the `result` method. + +`WrappedResult` is a fresh type, to make sure that we do not get unwanted givens in scope (this is good practice in all cases -where context parameters are involved). Since `WrappedResult` is an opaque type alias, its +where context parameters are involved). + +Since `WrappedResult` is an opaque type alias, its values need not be boxed, and since `ensuring` is added as an extension method, its argument does not need boxing either. Hence, the implementation of `ensuring` is close in efficiency to the best possible code one could write by hand: From 4d204695f547c981e364b0e4c8a1f749c739a5a4 Mon Sep 17 00:00:00 2001 From: Bersier Date: Thu, 28 Dec 2023 11:21:51 -0500 Subject: [PATCH 030/277] Update wildcards.md The documentation gives incorrect Scala versions for the transitions. [Cherry-picked 074128b9f2d6bce066e7137042b19dd401353ecc] --- .../reference/changed-features/wildcards.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/_docs/reference/changed-features/wildcards.md b/docs/_docs/reference/changed-features/wildcards.md index 0d3e13c3d7e0..ac7235770e36 100644 --- a/docs/_docs/reference/changed-features/wildcards.md +++ b/docs/_docs/reference/changed-features/wildcards.md @@ -4,7 +4,7 @@ title: Wildcard Arguments in Types nightlyOf: https://docs.scala-lang.org/scala3/reference/changed-features/wildcards.html --- -The syntax of wildcard arguments in types has changed from `_` to `?`. Example: +The syntax of wildcard arguments in types is changing from `_` to `?`. Example: ```scala List[?] Map[? <: AnyRef, ? >: Null] @@ -14,8 +14,8 @@ Map[? <: AnyRef, ? >: Null] We would like to use the underscore syntax `_` to stand for an anonymous type parameter, aligning it with its meaning in value parameter lists. So, just as `f(_)` is a shorthand for the lambda `x => f(x)`, in the future `C[_]` will be a shorthand -for the type lambda `[X] =>> C[X]`. This makes higher-kinded types easier to use. It also removes the wart that, used as a type -parameter, `F[_]` means `F` is a type constructor whereas used as a type, `F[_]` means it is a wildcard (i.e. existential) type. +for the type lambda `[X] =>> C[X]`. This will make higher-kinded types easier to use. It will also remove the wart that, used as a type +parameter, `F[_]` means `F` is a type constructor, whereas used as a type, `F[_]` means it is a wildcard (i.e. existential) type. In the future, `F[_]` will mean the same thing, no matter where it is used. We pick `?` as a replacement syntax for wildcard types, since it aligns with @@ -28,11 +28,11 @@ compiler plugin still uses the reverse convention, with `?` meaning parameter pl A step-by-step migration is made possible with the following measures: - 1. In Scala 3.0, both `_` and `?` are legal names for wildcards. - 2. In Scala 3.1, `_` is deprecated in favor of `?` as a name for a wildcard. A `-rewrite` option is + 1. In earlier versions of Scala 3, both `_` and `?` are legal names for wildcards. + 2. In Scala 3.4, `_` will be deprecated in favor of `?` as a name for wildcards. A `-rewrite` option is available to rewrite one to the other. - 3. In Scala 3.2, the meaning of `_` changes from wildcard to placeholder for type parameter. - 4. The Scala 3.1 behavior is already available today under the `-source future` setting. + 3. At some later point in the future, the meaning of `_` will change from wildcard to placeholder for type parameters. + 4. Some deprecation warnings are already available under the `-source future` setting. To smooth the transition for codebases that use kind-projector, we adopt the following measures under the command line option `-Ykind-projector`: @@ -42,7 +42,7 @@ option `-Ykind-projector`: available to rewrite one to the other. 3. In Scala 3.3, `*` is removed again, and all type parameter placeholders will be expressed with `_`. -These rules make it possible to cross build between Scala 2 using the kind projector plugin and Scala 3.0 - 3.2 using the compiler option `-Ykind-projector`. +These rules make it possible to cross-build between Scala 2 using the kind projector plugin and Scala 3.0 - 3.2 using the compiler option `-Ykind-projector`. There is also a migration path for users that want a one-time transition to syntax with `_` as a type parameter placeholder. With option `-Ykind-projector:underscores` Scala 3 will regard `_` as a type parameter placeholder, leaving `?` as the only syntax for wildcards. From a4064bedb2188865c69d63bd1a5c075b76a16ae1 Mon Sep 17 00:00:00 2001 From: Stephane Bersier Date: Mon, 29 Jan 2024 05:45:20 -0500 Subject: [PATCH 031/277] Update derivation.md Attempted small grammar improvements [Cherry-picked ec4299464bdbabad83892b442cc9533d2a4cf6a7] --- docs/_docs/reference/contextual/derivation.md | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/_docs/reference/contextual/derivation.md b/docs/_docs/reference/contextual/derivation.md index 66d0cf3fdf38..5157bb57699c 100644 --- a/docs/_docs/reference/contextual/derivation.md +++ b/docs/_docs/reference/contextual/derivation.md @@ -104,7 +104,7 @@ given TC[DerivingType] = TC.derived // simplified form of: given TC[ [A_1, ..., A_K] =>> DerivingType[A_1, ..., A_K] ] = TC.derived ``` -If `DerivingType` takes less arguments than `F` (`N < K`), we use only the rightmost parameters from the type lambda: +If `DerivingType` takes fewer arguments than `F` (`N < K`), we use only the rightmost parameters from the type lambda: ```scala given TC[ [A_1, ..., A_K] =>> DerivingType[A_(K-N+1), ..., A_K] ] = TC.derived @@ -112,7 +112,7 @@ given TC[ [A_1, ..., A_K] =>> DerivingType[A_(K-N+1), ..., A_K] ] = TC.derived given TC[ [A_1, ..., A_K] =>> DerivingType ] = TC.derived ``` -If `F` takes less arguments than `DerivingType` (`K < N`), we fill in the remaining leftmost slots with type parameters of the given: +If `F` takes fewer arguments than `DerivingType` (`K < N`), we fill in the remaining leftmost slots with type parameters of the given: ```scala given [T_1, ... T_(N-K)]: TC[[A_1, ..., A_K] =>> DerivingType[T_1, ... T_(N-K), A_1, ..., A_K]] = TC.derived ``` @@ -158,7 +158,7 @@ of the `Mirror` type class available. ## `Mirror` `scala.deriving.Mirror` type class instances provide information at the type level about the components and labelling of the type. -They also provide minimal term level infrastructure to allow higher level libraries to provide comprehensive +They also provide minimal term-level infrastructure to allow higher-level libraries to provide comprehensive derivation support. Instances of the `Mirror` type class are generated automatically by the compiler @@ -269,14 +269,14 @@ No given instance of type deriving.Mirror.Of[A] was found for parameter x of met Note the following properties of `Mirror` types, + Properties are encoded using types rather than terms. This means that they have no runtime footprint unless used and - also that they are a compile time feature for use with Scala 3's metaprogramming facilities. + also that they are a compile-time feature for use with Scala 3's metaprogramming facilities. + There is no restriction against the mirrored type being a local or inner class. + The kinds of `MirroredType` and `MirroredElemTypes` match the kind of the data type the mirror is an instance for. This allows `Mirror`s to support ADTs of all kinds. + There is no distinct representation type for sums or products (ie. there is no `HList` or `Coproduct` type as in Scala 2 versions of Shapeless). Instead the collection of child types of a data type is represented by an ordinary, possibly parameterized, tuple type. Scala 3's metaprogramming facilities can be used to work with these tuple types - as-is, and higher level libraries can be built on top of them. + as-is, and higher-level libraries can be built on top of them. + For both product and sum types, the elements of `MirroredElemTypes` are arranged in definition order (i.e. `Branch[T]` precedes `Leaf[T]` in `MirroredElemTypes` for `Tree` because `Branch` is defined before `Leaf` in the source file). This means that `Mirror.Sum` differs in this respect from Shapeless's generic representation for ADTs in Scala 2, @@ -303,16 +303,16 @@ has a context `Mirror` parameter, or not at all (e.g. they might use some comple instance using Scala 3 macros or runtime reflection). We expect that (direct or indirect) `Mirror` based implementations will be the most common and that is what this document emphasises. -Type class authors will most likely use higher level derivation or generic programming libraries to implement -`derived` methods. An example of how a `derived` method might be implemented using _only_ the low level facilities +Type class authors will most likely use higher-level derivation or generic programming libraries to implement +`derived` methods. An example of how a `derived` method might be implemented using _only_ the low-level facilities described above and Scala 3's general metaprogramming features is provided below. It is not anticipated that type class authors would normally implement a `derived` method in this way, however this walkthrough can be taken as a guide for -authors of the higher level derivation libraries that we expect typical type class authors will use (for a fully +authors of the higher-level derivation libraries that we expect typical type class authors will use (for a fully worked out example of such a library, see [Shapeless 3](https://github.com/milessabin/shapeless/tree/shapeless-3)). -## How to write a type class `derived` method using low level mechanisms +## How to write a type class `derived` method using low-level mechanisms -The low-level method we will use to implement a type class `derived` method in this example exploits three new type-level constructs in Scala 3: inline methods, inline matches, and implicit searches via `summonInline` or `summonFrom`. +The low-level technique we will use to implement a type class `derived` method in this example exploits three new type-level constructs in Scala 3: inline methods, inline matches, and implicit searches via `summonInline` or `summonFrom`. Given this definition of the `Eq` type class, ```scala @@ -335,13 +335,13 @@ inline def derived[T](using m: Mirror.Of[T]): Eq[T] = ``` Note that `derived` is defined as an `inline def`. -This means that the method will be inlined at all call sites (for instance the compiler generated instance definitions in the companion objects of ADTs which have a `deriving Eq` clause). +This means that the method will be inlined at all call sites (for instance the compiler-generated instance definitions in the companion objects of ADTs which have a `deriving Eq` clause). > Inlining of complex code is potentially expensive if overused (meaning slower compile times) so we should be careful to limit how many times `derived` is called for the same type. -> For example, when computing an instance for a sum type, it may be necessary to call `derived` recursively to compute an instance for a one of its child cases. +> For example, when computing an instance for a sum type, it may be necessary to call `derived` recursively to compute an instance for each one of its child cases. > That child case may in turn be a product type, that declares a field referring back to the parent sum type. > To compute the instance for this field, we should not call `derived` recursively, but instead summon from the context. -> Typically the found given instance will be the root given instance that initially called `derived`. +> Typically, the found given instance will be the root given instance that initially called `derived`. The body of `derived` (1) first materializes the `Eq` instances for all the child types of type the instance is being derived for. This is either all the branches of a sum type or all the fields of a product type. @@ -380,7 +380,7 @@ def eqSum[T](s: Mirror.SumOf[T], elems: => List[Eq[?]]): Eq[T] = (s.ordinal(y) == ordx) && check(x, y, elems(ordx)) // (4) ``` -In the product case, `eqProduct` we test the runtime values of the arguments to `eqv` for equality as products based on the `Eq` instances for the fields of the data type (5), +In the product case, `eqProduct`, we test the runtime values of the arguments to `eqv` for equality as products based on the `Eq` instances for the fields of the data type (5), ```scala import scala.deriving.Mirror @@ -486,7 +486,7 @@ Alternative approaches can be taken to the way that `derived` methods can be def inlined variants using Scala 3 macros, whilst being more involved for type class authors to write than the example above, can produce code for type classes like `Eq` which eliminate all the abstraction artefacts (eg. the `Lists` of child instances in the above) and generate code which is indistinguishable from what a programmer might write by hand. -As a third example, using a higher level library such as Shapeless the type class author could define an equivalent +As a third example, using a higher-level library such as Shapeless, the type class author could define an equivalent `derived` method as, ```scala @@ -508,7 +508,7 @@ inline def derived[A](using gen: K0.Generic[A]): Eq[A] = The framework described here enables all three of these approaches without mandating any of them. For a brief discussion on how to use macros to write a type class `derived` -method please read more at [How to write a type class `derived` method using macros](./derivation-macro.md). +method, please read more at [How to write a type class `derived` method using macros](./derivation-macro.md). ## Syntax @@ -539,22 +539,22 @@ This type class derivation framework is intentionally very small and low-level. infrastructure in compiler-generated `Mirror` instances, + type members encoding properties of the mirrored types. -+ a minimal value level mechanism for working generically with terms of the mirrored types. ++ a minimal value-level mechanism for working generically with terms of the mirrored types. The `Mirror` infrastructure can be seen as an extension of the existing `Product` infrastructure for case classes: -typically `Mirror` types will be implemented by the ADTs companion object, hence the type members and the `ordinal` or +typically, `Mirror` types will be implemented by the ADTs companion object, hence the type members and the `ordinal` or `fromProduct` methods will be members of that object. The primary motivation for this design decision, and the decision to encode properties via types rather than terms was to keep the bytecode and runtime footprint of the feature small enough to make it possible to provide `Mirror` instances _unconditionally_. -Whilst `Mirrors` encode properties precisely via type members, the value level `ordinal` and `fromProduct` are +Whilst `Mirrors` encode properties precisely via type members, the value-level `ordinal` and `fromProduct` are somewhat weakly typed (because they are defined in terms of `MirroredMonoType`) just like the members of `Product`. This means that code for generic type classes has to ensure that type exploration and value selection proceed in lockstep and it has to assert this conformance in some places using casts. If generic type classes are correctly written these casts will never fail. -As mentioned, however, the compiler-provided mechanism is intentionally very low level and it is anticipated that -higher level type class derivation and generic programming libraries will build on this and Scala 3's other +As mentioned, however, the compiler-provided mechanism is intentionally very low-level and it is anticipated that +higher-level type class derivation and generic programming libraries will build on this and Scala 3's other metaprogramming facilities to hide these low-level details from type class authors and general users. Type class derivation in the style of both Shapeless and Magnolia are possible (a prototype of Shapeless 3, which combines aspects of both Shapeless 2 and Magnolia has been developed alongside this language feature) as is a more aggressively From 825a453966597b0330afc466ef792e41746e7207 Mon Sep 17 00:00:00 2001 From: Stephane Bersier Date: Mon, 29 Jan 2024 06:45:44 -0500 Subject: [PATCH 032/277] Update derivation.md Added missing import [Cherry-picked 1627f0586de8d95ab938e02a483435f2e9faf279] --- docs/_docs/reference/contextual/derivation.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/_docs/reference/contextual/derivation.md b/docs/_docs/reference/contextual/derivation.md index 5157bb57699c..ed0e005c1bd4 100644 --- a/docs/_docs/reference/contextual/derivation.md +++ b/docs/_docs/reference/contextual/derivation.md @@ -396,8 +396,9 @@ Both `eqSum` and `eqProduct` have a by-name parameter `elems`, because the argum Pulling this all together we have the following complete implementation, ```scala +import scala.collection.AbstractIterable +import scala.compiletime.{erasedValue, error, summonInline} import scala.deriving.* -import scala.compiletime.{error, erasedValue, summonInline} inline def summonInstances[T, Elems <: Tuple]: List[Eq[?]] = inline erasedValue[Elems] match From 5f85033f200473c0191e4b7f4e782d62b160f415 Mon Sep 17 00:00:00 2001 From: Aleksander Boruch-Gruszecki Date: Wed, 14 Feb 2024 19:59:51 +0100 Subject: [PATCH 033/277] Fix the capture checking documentation The syntax on the official Scala page was outdated. Also, new docs nudge people to use the latest version of Scala, which allow trying capture checking out on a stable compiler version. [Cherry-picked 97138fbb6eff1fa2206f48de8f20ec3a42805779] --- docs/_docs/reference/experimental/cc.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/_docs/reference/experimental/cc.md b/docs/_docs/reference/experimental/cc.md index b1b2fa8e80cc..5bdf91f628ec 100644 --- a/docs/_docs/reference/experimental/cc.md +++ b/docs/_docs/reference/experimental/cc.md @@ -8,7 +8,8 @@ Capture checking is a research project that modifies the Scala type system to tr ```scala import language.experimental.captureChecking ``` -At present, capture checking is still highly experimental and unstable. +At present, capture checking is still highly experimental and unstable, and it evolves quickly. +Before trying it out, make sure you have the latest version of Scala. To get an idea what capture checking can do, let's start with a small example: ```scala From a8bc72a070b5874f7936791866a71405d50d9739 Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Fri, 16 Feb 2024 01:23:09 +0800 Subject: [PATCH 034/277] Improve variable naming --- compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala b/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala index 419e6454369c..3af076693dc0 100644 --- a/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala +++ b/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala @@ -171,9 +171,9 @@ object CheckCaptures: // Check the lower bound of path dependent types. // See issue #19330. - val isTypeParam = t.prefix eq NoPrefix + val isMember = t.prefix eq NoPrefix t.info match - case TypeBounds(lo, hi) if !isTypeParam => traverse(lo) + case TypeBounds(lo, _) if !isMember => traverse(lo) case _ => case AnnotatedType(_, ann) if ann.symbol == defn.UncheckedCapturesAnnot => () From 920bf44d4288c61625655e0a417729988b13c68b Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Fri, 16 Feb 2024 01:25:12 +0800 Subject: [PATCH 035/277] Cleanup dead code --- .../dotty/tools/dotc/cc/CheckCaptures.scala | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala b/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala index 3af076693dc0..b88c46a70a4e 100644 --- a/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala +++ b/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala @@ -142,26 +142,6 @@ object CheckCaptures: private val seen = new EqHashSet[TypeRef] - /** Check that there is at least one method containing carrier and defined - * in the scope of tparam. E.g. this is OK: - * def f[T] = { ... var x: T ... } - * So is this: - * class C[T] { def f() = { class D { var x: T }}} - * But this is not OK: - * class C[T] { object o { var x: T }} - */ - extension (tparam: Symbol) def isParametricIn(carrier: Symbol): Boolean = - carrier.exists && { - val encl = carrier.owner.enclosingMethodOrClass - if encl.isClass then tparam.isParametricIn(encl) - else - def recur(encl: Symbol): Boolean = - if tparam.owner == encl then true - else if encl.isStatic || !encl.exists then false - else recur(encl.owner.enclosingMethodOrClass) - recur(encl) - } - def traverse(t: Type) = t.dealiasKeepAnnots match case t: TypeRef => From d539d8919650b5f3c5d5f5b123c50c8832ffeffd Mon Sep 17 00:00:00 2001 From: odersky Date: Thu, 15 Feb 2024 18:36:34 +0100 Subject: [PATCH 036/277] Apply suggestions from code review --- compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala b/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala index b88c46a70a4e..de584797f154 100644 --- a/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala +++ b/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala @@ -151,9 +151,9 @@ object CheckCaptures: // Check the lower bound of path dependent types. // See issue #19330. - val isMember = t.prefix eq NoPrefix + val isMember = t.prefix ne NoPrefix t.info match - case TypeBounds(lo, _) if !isMember => traverse(lo) + case TypeBounds(lo, _) if isMember => traverse(lo) case _ => case AnnotatedType(_, ann) if ann.symbol == defn.UncheckedCapturesAnnot => () From 3c453ab98a83ea5fc224245e08f6d6d0d45817c9 Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Thu, 15 Feb 2024 17:54:24 +0100 Subject: [PATCH 037/277] Switch to Java 17 in the CI --- .github/workflows/ci.yaml | 55 +++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index eb29d98632f6..ca22eae666a4 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -47,7 +47,7 @@ jobs: test_non_bootstrapped: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2021-03-22 + image: lampepfl/dotty:2023-11-07 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -65,8 +65,8 @@ jobs: && github.repository == 'lampepfl/dotty' )" steps: - - name: Set JDK 16 as default - run: echo "/usr/lib/jvm/java-16-openjdk-amd64/bin" >> $GITHUB_PATH + - name: Set JDK 17 as default + run: echo "/usr/lib/jvm/java-17-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true @@ -96,7 +96,7 @@ jobs: test: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2021-03-22 + image: lampepfl/dotty:2023-11-07 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -116,8 +116,8 @@ jobs: )" steps: - - name: Set JDK 16 as default - run: echo "/usr/lib/jvm/java-16-openjdk-amd64/bin" >> $GITHUB_PATH + - name: Set JDK 17 as default + run: echo "/usr/lib/jvm/java-17-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true @@ -153,7 +153,7 @@ jobs: test_scala2_library_tasty: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2021-03-22 + image: lampepfl/dotty:2023-11-07 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -170,8 +170,8 @@ jobs: )" steps: - - name: Set JDK 16 as default - run: echo "/usr/lib/jvm/java-16-openjdk-amd64/bin" >> $GITHUB_PATH + - name: Set JDK 17 as default + run: echo "/usr/lib/jvm/java-17-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true @@ -271,7 +271,7 @@ jobs: name: MiMa runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2021-03-22 + image: lampepfl/dotty:2023-11-07 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -290,6 +290,9 @@ jobs: && github.repository == 'lampepfl/dotty' )" steps: + - name: Set JDK 17 as default + run: echo "/usr/lib/jvm/java-17-openjdk-amd64/bin" >> $GITHUB_PATH + - name: Reset existing repo run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true @@ -317,7 +320,7 @@ jobs: community_build_a: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2021-03-22 + image: lampepfl/dotty:2023-11-07 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -338,6 +341,8 @@ jobs: )" steps: + - name: Set JDK 8 as default + run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true @@ -355,6 +360,7 @@ jobs: - name: Test run: | + git config --global --add safe.directory /__w/dotty/dotty git submodule sync git submodule update --init --recursive --jobs 7 ./project/scripts/sbt "community-build/testOnly dotty.communitybuild.CommunityBuildTestA" @@ -366,7 +372,7 @@ jobs: community_build_b: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2021-03-22 + image: lampepfl/dotty:2023-11-07 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -387,6 +393,8 @@ jobs: )" steps: + - name: Set JDK 8 as default + run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true @@ -404,6 +412,7 @@ jobs: - name: Test run: | + git config --global --add safe.directory /__w/dotty/dotty git submodule sync git submodule update --init --recursive --jobs 7 ./project/scripts/sbt "community-build/testOnly dotty.communitybuild.CommunityBuildTestB" @@ -415,7 +424,7 @@ jobs: community_build_c: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2020-11-19 + image: lampepfl/dotty:2023-11-07 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -436,6 +445,8 @@ jobs: )" steps: + - name: Set JDK 8 as default + run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true @@ -453,6 +464,7 @@ jobs: - name: Test run: | + git config --global --add safe.directory /__w/dotty/dotty git submodule sync git submodule update --init --recursive --jobs 7 ./project/scripts/sbt "community-build/testOnly dotty.communitybuild.CommunityBuildTestC" @@ -464,7 +476,7 @@ jobs: test_sbt: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2021-03-22 + image: lampepfl/dotty:2023-11-07 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -483,6 +495,9 @@ jobs: )" steps: + - name: Set JDK 17 as default + run: echo "/usr/lib/jvm/java-17-openjdk-amd64/bin" >> $GITHUB_PATH + - name: Reset existing repo run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true @@ -504,7 +519,7 @@ jobs: test_java8: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2021-03-22 + image: lampepfl/dotty:2023-11-07 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -558,7 +573,7 @@ jobs: publish_nightly: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2021-03-22 + image: lampepfl/dotty:2023-11-07 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -574,6 +589,8 @@ jobs: SONATYPE_USER: ${{ secrets.SONATYPE_USER_ORGSCALALANG }} steps: + - name: Set JDK 17 as default + run: echo "/usr/lib/jvm/java-17-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true @@ -609,7 +626,7 @@ jobs: nightly_documentation: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2021-03-22 + image: lampepfl/dotty:2023-11-07 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -660,7 +677,7 @@ jobs: contents: write # for actions/create-release to create a release runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2021-03-22 + image: lampepfl/dotty:2023-11-07 options: --cpu-shares 4096 volumes: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt @@ -748,7 +765,7 @@ jobs: open_issue_on_failure: runs-on: [self-hosted, Linux] container: - image: lampepfl/dotty:2021-03-22 + image: lampepfl/dotty:2023-11-07 needs: [nightly_documentation, test_windows_full] # The `failure()` expression is true iff at least one of the dependencies # of this job (including transitive dependencies) has failed. From b0b6ec52768699c1394558ef57f50114c91c113c Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 16 Feb 2024 09:02:24 +0100 Subject: [PATCH 038/277] Add patch for undefined behavior with `object $` Add an ad-hoc patch to make it possible to use the broken `object $` definitions in https://github.com/com-lihaoyi/Ammonite/blob/main/amm/interp/api/src/main/scala/ammonite/Stubs.scala. This is a temporary patch while these definitions get deprecated. There is not guarantee that the semantics of these objects are correct. There is also no way to adapt the spec to allow there definition without breaking the language. For example consider `object $` and `object $$`, how would we know if the `$$.class` is the class of `$$` or the module class of `$`. We need to know this before we read the file. --- compiler/src/dotty/tools/dotc/classpath/FileUtils.scala | 4 ++++ tests/pos/i19702/Macro_1.scala | 9 +++++++++ tests/pos/i19702/Test_2.scala | 4 ++++ 3 files changed, 17 insertions(+) create mode 100644 tests/pos/i19702/Macro_1.scala create mode 100644 tests/pos/i19702/Test_2.scala diff --git a/compiler/src/dotty/tools/dotc/classpath/FileUtils.scala b/compiler/src/dotty/tools/dotc/classpath/FileUtils.scala index 8c31faa43186..b8cb9a2155dc 100644 --- a/compiler/src/dotty/tools/dotc/classpath/FileUtils.scala +++ b/compiler/src/dotty/tools/dotc/classpath/FileUtils.scala @@ -114,6 +114,10 @@ object FileUtils { if classOrModuleName.endsWith("$") && classOrModuleName != "Null$" // scala.runtime.Null$ && classOrModuleName != "Nothing$" // scala.runtime.Nothing$ + // Special case for `object $` in Amonite. + // This is an ad-hoc workaround for Amonite `object $`. See issue #19702 + // This definition is not valid Scala. + && classOrModuleName != "$" then classOrModuleName.stripSuffix("$") else classOrModuleName className + SUFFIX_TASTY diff --git a/tests/pos/i19702/Macro_1.scala b/tests/pos/i19702/Macro_1.scala new file mode 100644 index 000000000000..79aab856dfda --- /dev/null +++ b/tests/pos/i19702/Macro_1.scala @@ -0,0 +1,9 @@ +package test + +// IMPORTANT: this object has undefined behavior due to its illegal use of a $ in an identifier +// This test is only to check that the ad-hoc workaround for Amonite `object $` is working. +// If at some point it becomes impossible to support this test, we can drop it. +// Ideally Amonite will have deprecated the `object $` by then. +object $ { + def test(): Int = 1 +} diff --git a/tests/pos/i19702/Test_2.scala b/tests/pos/i19702/Test_2.scala new file mode 100644 index 000000000000..c8bcd4287e0d --- /dev/null +++ b/tests/pos/i19702/Test_2.scala @@ -0,0 +1,4 @@ +@main def hello = + test.$.test() + + println("?") From 0a2d995c9ac88ac045fd0f08cbddfd01f81f7150 Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 6 Jan 2024 13:12:56 +0100 Subject: [PATCH 039/277] Also reduce term projections We already reduce `R { type A = T } # A` to `T` in most situations when we create types. We now also reduce `R { val x: S } # x` to `S` if `S` is a singleton type. This will simplify types as we go to more term-dependent typing. As a concrete benefit, it will avoid several test-pickling failures due to pickling differences when using dependent types. --- .../src/dotty/tools/dotc/core/Types.scala | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 78e22b7b76b9..5dede9080ecc 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1645,6 +1645,8 @@ object Types extends TypeUtils { pre.refinedInfo match { case tp: AliasingBounds => if (pre.refinedName ne name) loop(pre.parent) else tp.alias + case tp: SingletonType => + if pre.refinedName ne name then loop(pre.parent) else tp case _ => loop(pre.parent) } @@ -2676,7 +2678,7 @@ object Types extends TypeUtils { * refinement type `T { X = U; ... }` */ def reduceProjection(using Context): Type = - if (isType) { + if (isType || true) { val reduced = prefix.lookupRefined(name) if (reduced.exists) reduced else this } @@ -2765,14 +2767,14 @@ object Types extends TypeUtils { * (S | T)#A --> S#A | T#A */ def derivedSelect(prefix: Type)(using Context): Type = - if (prefix eq this.prefix) this - else if (prefix.isExactlyNothing) prefix + if prefix eq this.prefix then this + else if prefix.isExactlyNothing then prefix else { + val res = + if (isType && currentValidSymbol.isAllOf(ClassTypeParam)) argForParam(prefix) + else prefix.lookupRefined(name) + if (res.exists) return res if (isType) { - val res = - if (currentValidSymbol.isAllOf(ClassTypeParam)) argForParam(prefix) - else prefix.lookupRefined(name) - if (res.exists) return res if (Config.splitProjections) prefix match { case prefix: AndType => @@ -6563,7 +6565,7 @@ object Types extends TypeUtils { record(s"foldOver $getClass") record(s"foldOver total") tp match { - case tp: TypeRef => + case tp: NamedType => if stopBecauseStaticOrLocal(tp) then x else val tp1 = tp.prefix.lookupRefined(tp.name) @@ -6592,8 +6594,8 @@ object Types extends TypeUtils { variance = saved this(y, restpe) - case tp: TermRef => - if stopBecauseStaticOrLocal(tp) then x else applyToPrefix(x, tp) + //case tp: TermRef => + // if stopBecauseStaticOrLocal(tp) then x else applyToPrefix(x, tp) case tp: TypeVar => this(x, tp.underlying) From daa29e6c5750b93baa602b48eba555a88ac5ba0f Mon Sep 17 00:00:00 2001 From: odersky Date: Fri, 16 Feb 2024 19:41:20 +0100 Subject: [PATCH 040/277] Simplifty code, addressing review comments --- compiler/src/dotty/tools/dotc/core/Types.scala | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 5dede9080ecc..2b1f6394acdc 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2678,11 +2678,8 @@ object Types extends TypeUtils { * refinement type `T { X = U; ... }` */ def reduceProjection(using Context): Type = - if (isType || true) { - val reduced = prefix.lookupRefined(name) - if (reduced.exists) reduced else this - } - else this + val reduced = prefix.lookupRefined(name) + if reduced.exists then reduced else this /** Guard against cycles that can arise if given `op` * follows info. The problematic cases are a type alias to itself or @@ -6594,9 +6591,6 @@ object Types extends TypeUtils { variance = saved this(y, restpe) - //case tp: TermRef => - // if stopBecauseStaticOrLocal(tp) then x else applyToPrefix(x, tp) - case tp: TypeVar => this(x, tp.underlying) From 300f2cc9a3ec981e00faedc7b03c7c3bcd3905f0 Mon Sep 17 00:00:00 2001 From: Olga Mazhara Date: Sat, 17 Feb 2024 13:26:01 +0100 Subject: [PATCH 041/277] Fix #19402: improved parsing of given paramiters with absence of using keyword --- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 2 +- tests/neg/i19402.scala | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 tests/neg/i19402.scala diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index fbb4e1319948..50380e5b14d3 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -4012,7 +4012,7 @@ object Parsers { val tparams = typeParamClauseOpt(ParamOwner.Given) newLineOpt() val vparamss = - if in.token == LPAREN && in.lookahead.isIdent(nme.using) + if in.token == LPAREN && (in.lookahead.isIdent(nme.using) || name != EmptyTermName) then termParamClauses(ParamOwner.Given) else Nil newLinesOpt() diff --git a/tests/neg/i19402.scala b/tests/neg/i19402.scala new file mode 100644 index 000000000000..dd5a4903027c --- /dev/null +++ b/tests/neg/i19402.scala @@ -0,0 +1,11 @@ +object Test: + + class Bar(foo: Foo) + + class Foo + + given (Foo) = ??? + given (using a: Int): Int = ??? + given [T](using a: T): T = ??? + given bar(foo: Foo): Bar = Bar(foo) // error: using is expected + \ No newline at end of file From c79bd93b72e1de2eda7f794aa8ee34f26af8bf1b Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 17 Feb 2024 15:56:35 +0100 Subject: [PATCH 042/277] Prefer extensions over conversions for member selection Fixes #19715 --- .../dotty/tools/dotc/typer/Implicits.scala | 59 ++++++++++--------- tests/pos/i19715.scala | 15 +++++ 2 files changed, 45 insertions(+), 29 deletions(-) create mode 100644 tests/pos/i19715.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index c3bf2dd822c9..0a26ea697a6a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -1308,35 +1308,36 @@ trait Implicits: case alt1: SearchSuccess => var diff = compareAlternatives(alt1, alt2) assert(diff <= 0) // diff > 0 candidates should already have been eliminated in `rank` - if diff == 0 && alt1.isExtension && alt2.isExtension then - // Fall back: if both results are extension method applications, - // compare the extension methods instead of their wrappers. - def stripExtension(alt: SearchSuccess) = methPart(stripApply(alt.tree)).tpe - (stripExtension(alt1), stripExtension(alt2)) match - case (ref1: TermRef, ref2: TermRef) => - // ref1 and ref2 might refer to type variables owned by - // alt1.tstate and alt2.tstate respectively, to compare the - // alternatives correctly we need a TyperState that includes - // constraints from both sides, see - // tests/*/extension-specificity2.scala for test cases. - val constraintsIn1 = alt1.tstate.constraint ne ctx.typerState.constraint - val constraintsIn2 = alt2.tstate.constraint ne ctx.typerState.constraint - def exploreState(alt: SearchSuccess): TyperState = - alt.tstate.fresh(committable = false) - val comparisonState = - if constraintsIn1 && constraintsIn2 then - exploreState(alt1).mergeConstraintWith(alt2.tstate) - else if constraintsIn1 then - exploreState(alt1) - else if constraintsIn2 then - exploreState(alt2) - else - ctx.typerState - - diff = inContext(ctx.withTyperState(comparisonState)) { - compare(ref1, ref2) - } - case _ => + if diff == 0 && alt2.isExtension then + if alt1.isExtension then + // Fall back: if both results are extension method applications, + // compare the extension methods instead of their wrappers. + def stripExtension(alt: SearchSuccess) = methPart(stripApply(alt.tree)).tpe + (stripExtension(alt1), stripExtension(alt2)) match + case (ref1: TermRef, ref2: TermRef) => + // ref1 and ref2 might refer to type variables owned by + // alt1.tstate and alt2.tstate respectively, to compare the + // alternatives correctly we need a TyperState that includes + // constraints from both sides, see + // tests/*/extension-specificity2.scala for test cases. + val constraintsIn1 = alt1.tstate.constraint ne ctx.typerState.constraint + val constraintsIn2 = alt2.tstate.constraint ne ctx.typerState.constraint + def exploreState(alt: SearchSuccess): TyperState = + alt.tstate.fresh(committable = false) + val comparisonState = + if constraintsIn1 && constraintsIn2 then + exploreState(alt1).mergeConstraintWith(alt2.tstate) + else if constraintsIn1 then + exploreState(alt1) + else if constraintsIn2 then + exploreState(alt2) + else + ctx.typerState + + diff = inContext(ctx.withTyperState(comparisonState)): + compare(ref1, ref2) + else // alt1 is a conversion, prefer extension alt2 over it + diff = -1 if diff < 0 then alt2 else if diff > 0 then alt1 else SearchFailure(new AmbiguousImplicits(alt1, alt2, pt, argument), span) diff --git a/tests/pos/i19715.scala b/tests/pos/i19715.scala new file mode 100644 index 000000000000..91aeda5c1698 --- /dev/null +++ b/tests/pos/i19715.scala @@ -0,0 +1,15 @@ +class Tup(): + def app(n: Int): String = "a" + +class NT(t: Tup): + def toTup = t +object NT: + extension (x: NT) + def app(n: Int): Boolean = true + given Conversion[NT, Tup] = _.toTup + +def test = + val nt = new NT(Tup()) + val x = nt.app(3) + val _: Boolean = x + From 586ac06ac6c62fe9dff59275156659b7becca565 Mon Sep 17 00:00:00 2001 From: Yilin Wei Date: Sat, 17 Feb 2024 17:00:56 +0000 Subject: [PATCH 043/277] Update local `Dockerfile` to be in line with github workflows --- docs/_spec/Dockerfile | 6 ++++-- docs/_spec/Gemfile | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/_spec/Dockerfile b/docs/_spec/Dockerfile index 6f0c349da396..28dc664e87c9 100644 --- a/docs/_spec/Dockerfile +++ b/docs/_spec/Dockerfile @@ -7,9 +7,11 @@ RUN apt-get install -y curl \ && apt-get install -y nodejs \ && curl -L https://www.npmjs.com/install.sh | sh -RUN gem update --system +RUN gem install "rubygems-update:<3.5" --no-document +RUN update_rubygems + RUN gem install sass-embedded -v 1.58.0 -RUN gem install bundler:1.17.2 jekyll +RUN gem install bundler:2.3.5 WORKDIR /srv/jekyll diff --git a/docs/_spec/Gemfile b/docs/_spec/Gemfile index bc45dc84db8c..ec15529ceb37 100644 --- a/docs/_spec/Gemfile +++ b/docs/_spec/Gemfile @@ -1,5 +1,6 @@ # To build the spec on Travis CI source "https://rubygems.org" +ruby "~> 2.7" gem "jekyll", "3.6.3" gem "webrick" From e6b726b04e101d69cbb1e5975fa417a8a29c43ed Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 17 Feb 2024 18:36:29 +0100 Subject: [PATCH 044/277] Tweak parameter accessor scheme To qualify as a super-parameter alias, a parameter of a subclass has to be passed to the primary constructor of the superclass. Fixes #19711 --- .../tools/dotc/transform/PostTyper.scala | 3 +- tests/run/i19711.scala | 29 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/run/i19711.scala diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index 63f6af2beb86..4ce41ca21bfe 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -116,7 +116,8 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase => * This info is used in phase ParamForwarding */ private def forwardParamAccessors(impl: Template)(using Context): Unit = impl.parents match - case superCall @ Apply(fn, superArgs) :: _ if superArgs.nonEmpty => + case superCall @ Apply(fn, superArgs) :: _ + if superArgs.nonEmpty && fn.symbol.isPrimaryConstructor => fn.tpe.widen match case MethodType(superParamNames) => for case stat: ValDef <- impl.body do diff --git a/tests/run/i19711.scala b/tests/run/i19711.scala new file mode 100644 index 000000000000..a9ef03b398e2 --- /dev/null +++ b/tests/run/i19711.scala @@ -0,0 +1,29 @@ +class Foo(val s: Any): + def this(s: String) = + this(0) +class Bar(s: String) extends Foo(s): + def foo = s + +class Foo2(val s: Any) +class Bar2(s: String) extends Foo2(s): + def foo = s + +case class Config(_config: String) + +abstract class Foo3(val config: Config) { + def this(config: String) = { + this(Config(config)) + } +} + +class Bar3(config: String) extends Foo3(config) { + def foo(): Unit = { + config.getClass() + } +} + + +@main def Test = + Bar("").foo + Bar2("").foo + Bar3("").foo() From bafaa343d47ba6e7432bb185b4147d672caeb778 Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Sat, 17 Feb 2024 20:13:25 +0100 Subject: [PATCH 045/277] Add dotty to the safe directories in nightly_documentation --- .github/workflows/ci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ca22eae666a4..0827308f138a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -662,6 +662,7 @@ jobs: - name: Generate Website run: | + git config --global --add safe.directory /__w/dotty/dotty ./project/scripts/genDocs -doc-snapshot - name: Deploy Website to dotty-website From 9f7bf728d03e830bfb5cc74fa52b51a636ec4bfa Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Sat, 17 Feb 2024 21:37:08 +0100 Subject: [PATCH 046/277] Address actions/runner#2033 --- .github/workflows/ci.yaml | 57 +++++++++++++++++++++++++--------- .github/workflows/releases.yml | 4 ++- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0827308f138a..444d30c38776 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -68,8 +68,11 @@ jobs: - name: Set JDK 17 as default run: echo "/usr/lib/jvm/java-17-openjdk-amd64/bin" >> $GITHUB_PATH + ## Workaround for https://github.com/actions/runner/issues/2033 (See https://github.com/lampepfl/dotty/pull/19720) - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/dotty/dotty + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -120,7 +123,9 @@ jobs: run: echo "/usr/lib/jvm/java-17-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/dotty/dotty + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -174,7 +179,9 @@ jobs: run: echo "/usr/lib/jvm/java-17-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/dotty/dotty + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -211,8 +218,10 @@ jobs: steps: - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true shell: cmd + run: | + git config --global --add safe.directory /__w/dotty/dotty + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true - name: Git Checkout uses: actions/checkout@v4 @@ -253,8 +262,10 @@ jobs: steps: - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true shell: cmd + run: | + git config --global --add safe.directory /__w/dotty/dotty + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true - name: Git Checkout uses: actions/checkout@v4 @@ -294,7 +305,9 @@ jobs: run: echo "/usr/lib/jvm/java-17-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/dotty/dotty + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -344,7 +357,9 @@ jobs: - name: Set JDK 8 as default run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/dotty/dotty + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -396,7 +411,9 @@ jobs: - name: Set JDK 8 as default run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/dotty/dotty + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -448,7 +465,9 @@ jobs: - name: Set JDK 8 as default run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/dotty/dotty + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -499,7 +518,9 @@ jobs: run: echo "/usr/lib/jvm/java-17-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/dotty/dotty + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -546,7 +567,9 @@ jobs: run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/dotty/dotty + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -592,7 +615,9 @@ jobs: - name: Set JDK 17 as default run: echo "/usr/lib/jvm/java-17-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/dotty/dotty + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -646,7 +671,9 @@ jobs: steps: - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/dotty/dotty + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -697,7 +724,9 @@ jobs: steps: - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/dotty/dotty + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index f2cd0706cfe7..dde8b0372d52 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -18,7 +18,9 @@ jobs: steps: - name: Reset existing repo - run: git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + run: | + git config --global --add safe.directory /__w/dotty/dotty + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true - name: Cleanup run: .github/workflows/cleanup.sh From 1a2b7186c8d6bc11561eb6b1787288fa69ba3b91 Mon Sep 17 00:00:00 2001 From: aherlihy Date: Thu, 8 Feb 2024 16:50:08 +0100 Subject: [PATCH 047/277] update documentation for running scalajs tests with update checkfiles --- docs/_docs/contributing/testing.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/_docs/contributing/testing.md b/docs/_docs/contributing/testing.md index 3f3e5421b9bd..6c9ea7616e0b 100644 --- a/docs/_docs/contributing/testing.md +++ b/docs/_docs/contributing/testing.md @@ -141,6 +141,11 @@ checkfiles with the test outputs. $ sbt > testCompilation --update-checkfiles ``` +Or for ScalaJS +```bash +$ sbt +> sjsCompilerTests/testOnly -- -Ddotty.tests.updateCheckfiles=TRUE +``` Use `--help` to see all the options ```bash From 00b6fb43bcec049f1ad89a3a8c22b9bf88c3858b Mon Sep 17 00:00:00 2001 From: aherlihy Date: Tue, 6 Feb 2024 18:14:23 +0100 Subject: [PATCH 048/277] Add explanation for NotClassType error message Fixes #14175 --- .../dotty/tools/dotc/reporting/messages.scala | 6 +++++- .../jsconstructorof-error-in-prepjsinterop.check | 16 ++++++++++++++++ ...jsconstructortag-error-in-prepjsinterop.check | 16 ++++++++++++++++ tests/neg/classOf.check | 6 ++++++ tests/neg/i13808.check | 4 ++++ 5 files changed, 47 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index c230e3b4d6d7..0367698b9bbe 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -2775,7 +2775,11 @@ extends SyntaxMsg(TargetNameOnTopLevelClassID): class NotClassType(tp: Type)(using Context) extends TypeMsg(NotClassTypeID), ShowMatchTrace(tp): def msg(using Context) = i"$tp is not a class type" - def explain(using Context) = "" + def explain(using Context) = + i"""A class type includes classes and traits in a specific order. Defining a class, even an anonymous class, + |requires specifying a linearization order for the traits it extends. For example, `A & B` is not a class type + |because it doesn't specify which trait takes precedence, A or B. For more information about class types, please see the Scala Language Specification. + |Class types also can't have refinements.""" class NotConstant(suffix: String, tp: Type)(using Context) extends TypeMsg(NotConstantID), ShowMatchTrace(tp): diff --git a/tests/neg-scalajs/jsconstructorof-error-in-prepjsinterop.check b/tests/neg-scalajs/jsconstructorof-error-in-prepjsinterop.check index fe55c0caee52..f222ea3b444f 100644 --- a/tests/neg-scalajs/jsconstructorof-error-in-prepjsinterop.check +++ b/tests/neg-scalajs/jsconstructorof-error-in-prepjsinterop.check @@ -20,14 +20,20 @@ 14 | val b = js.constructorOf[NativeJSObject.type] // error | ^^^^^^^^^^^^^^^^^^^ | NativeJSObject.type is not a class type + | + | longer explanation available when compiling with `-explain` -- [E170] Type Error: tests/neg-scalajs/jsconstructorof-error-in-prepjsinterop.scala:16:27 ----------------------------- 16 | val c = js.constructorOf[NativeJSClass with NativeJSTrait] // error | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | NativeJSClass & NativeJSTrait is not a class type + | + | longer explanation available when compiling with `-explain` -- [E170] Type Error: tests/neg-scalajs/jsconstructorof-error-in-prepjsinterop.scala:17:27 ----------------------------- 17 | val d = js.constructorOf[NativeJSClass { def bar: Int }] // error | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | NativeJSClass{def bar: Int} is not a class type + | + | longer explanation available when compiling with `-explain` -- Error: tests/neg-scalajs/jsconstructorof-error-in-prepjsinterop.scala:19:27 ----------------------------------------- 19 | val e = js.constructorOf[JSTrait] // error | ^^^^^^^ @@ -36,19 +42,29 @@ 20 | val f = js.constructorOf[JSObject.type] // error | ^^^^^^^^^^^^^ | JSObject.type is not a class type + | + | longer explanation available when compiling with `-explain` -- [E170] Type Error: tests/neg-scalajs/jsconstructorof-error-in-prepjsinterop.scala:22:27 ----------------------------- 22 | val g = js.constructorOf[JSClass with JSTrait] // error | ^^^^^^^^^^^^^^^^^^^^ | JSClass & JSTrait is not a class type + | + | longer explanation available when compiling with `-explain` -- [E170] Type Error: tests/neg-scalajs/jsconstructorof-error-in-prepjsinterop.scala:23:27 ----------------------------- 23 | val h = js.constructorOf[JSClass { def bar: Int }] // error | ^^^^^^^^^^^^^^^^^^^^^^^^ | JSClass{def bar: Int} is not a class type + | + | longer explanation available when compiling with `-explain` -- [E170] Type Error: tests/neg-scalajs/jsconstructorof-error-in-prepjsinterop.scala:25:42 ----------------------------- 25 | def foo[A <: js.Any] = js.constructorOf[A] // error | ^ | A is not a class type + | + | longer explanation available when compiling with `-explain` -- [E170] Type Error: tests/neg-scalajs/jsconstructorof-error-in-prepjsinterop.scala:26:66 ----------------------------- 26 | def bar[A <: js.Any: scala.reflect.ClassTag] = js.constructorOf[A] // error | ^ | A is not a class type + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.check b/tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.check index df09d5b1953d..1ee2e8445b0a 100644 --- a/tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.check +++ b/tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.check @@ -20,14 +20,20 @@ 14 | val b = js.constructorTag[NativeJSObject.type] // error | ^ | NativeJSObject.type is not a class type + | + | longer explanation available when compiling with `-explain` -- [E170] Type Error: tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.scala:16:61 ---------------------------- 16 | val c = js.constructorTag[NativeJSClass with NativeJSTrait] // error | ^ | NativeJSClass & NativeJSTrait is not a class type + | + | longer explanation available when compiling with `-explain` -- [E170] Type Error: tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.scala:17:59 ---------------------------- 17 | val d = js.constructorTag[NativeJSClass { def bar: Int }] // error | ^ | NativeJSClass{def bar: Int} is not a class type + | + | longer explanation available when compiling with `-explain` -- Error: tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.scala:19:36 ---------------------------------------- 19 | val e = js.constructorTag[JSTrait] // error | ^ @@ -36,19 +42,29 @@ 20 | val f = js.constructorTag[JSObject.type] // error | ^ | JSObject.type is not a class type + | + | longer explanation available when compiling with `-explain` -- [E170] Type Error: tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.scala:22:49 ---------------------------- 22 | val g = js.constructorTag[JSClass with JSTrait] // error | ^ | JSClass & JSTrait is not a class type + | + | longer explanation available when compiling with `-explain` -- [E170] Type Error: tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.scala:23:53 ---------------------------- 23 | val h = js.constructorTag[JSClass { def bar: Int }] // error | ^ | JSClass{def bar: Int} is not a class type + | + | longer explanation available when compiling with `-explain` -- [E170] Type Error: tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.scala:25:45 ---------------------------- 25 | def foo[A <: js.Any] = js.constructorTag[A] // error | ^ | A is not a class type + | + | longer explanation available when compiling with `-explain` -- [E170] Type Error: tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.scala:26:69 ---------------------------- 26 | def bar[A <: js.Any: scala.reflect.ClassTag] = js.constructorTag[A] // error | ^ | A is not a class type + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg/classOf.check b/tests/neg/classOf.check index e3be3ca17026..e6576a60bbff 100644 --- a/tests/neg/classOf.check +++ b/tests/neg/classOf.check @@ -2,13 +2,19 @@ 6 | def f1[T] = classOf[T] // error | ^ | T is not a class type + | + | longer explanation available when compiling with `-explain` -- [E170] Type Error: tests/neg/classOf.scala:7:32 --------------------------------------------------------------------- 7 | def f2[T <: String] = classOf[T] // error | ^ | T is not a class type | | where: T is a type in method f2 with bounds <: String + | + | longer explanation available when compiling with `-explain` -- [E170] Type Error: tests/neg/classOf.scala:9:18 --------------------------------------------------------------------- 9 | val y = classOf[C { type I = String }] // error | ^^^^^^^^^^^^^^^^^^^^^ | Test.C{type I = String} is not a class type + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg/i13808.check b/tests/neg/i13808.check index f3e0ebac7141..e0f6d01c09db 100644 --- a/tests/neg/i13808.check +++ b/tests/neg/i13808.check @@ -2,7 +2,11 @@ 13 |case class Boom[A](value: A) derives OpaqueType, Foo // error // error | ^^^^^^^^^^ | OpaqueTypes.OpaqueType is not a class type + | + | longer explanation available when compiling with `-explain` -- [E170] Type Error: tests/neg/i13808.scala:13:49 --------------------------------------------------------------------- 13 |case class Boom[A](value: A) derives OpaqueType, Foo // error // error | ^^^ | FooModule.Foo is not a class type + | + | longer explanation available when compiling with `-explain` From c3a1959be9d763600b9e0555239a93e5806a4637 Mon Sep 17 00:00:00 2001 From: Hamza Remmal <56235032+hamzaremmal@users.noreply.github.com> Date: Mon, 19 Feb 2024 12:20:46 +0100 Subject: [PATCH 049/277] [regression] Publish nightly releases and releases using Java 8 (#19722) Close #19721 [test_java8] --- .github/workflows/ci.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 444d30c38776..3d94d869a42f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -612,8 +612,8 @@ jobs: SONATYPE_USER: ${{ secrets.SONATYPE_USER_ORGSCALALANG }} steps: - - name: Set JDK 17 as default - run: echo "/usr/lib/jvm/java-17-openjdk-amd64/bin" >> $GITHUB_PATH + - name: Set JDK 8 as default + run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo run: | git config --global --add safe.directory /__w/dotty/dotty @@ -723,6 +723,8 @@ jobs: SONATYPE_USER: ${{ secrets.SONATYPE_USER_ORGSCALALANG }} steps: + - name: Set JDK 8 as default + run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo run: | git config --global --add safe.directory /__w/dotty/dotty From 69170d3260a4f5989b63527192b245e4c57d8c3e Mon Sep 17 00:00:00 2001 From: Matt Bovel Date: Mon, 19 Feb 2024 14:12:12 +0100 Subject: [PATCH 050/277] Add regression test for #19087 (#19726) Fixes #19087 --- tests/neg/19087.check | 20 ++++++++++++++++++++ tests/neg/19087.scala | 15 +++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 tests/neg/19087.check create mode 100644 tests/neg/19087.scala diff --git a/tests/neg/19087.check b/tests/neg/19087.check new file mode 100644 index 000000000000..db6da907205d --- /dev/null +++ b/tests/neg/19087.check @@ -0,0 +1,20 @@ +-- [E103] Syntax Error: tests/neg/19087.scala:4:2 ---------------------------------------------------------------------- +4 | Option.when(state.x == 0) body // error: Illegal start of toplevel definition + | ^^^^^^ + | Illegal start of toplevel definition + | + | longer explanation available when compiling with `-explain` +-- [E040] Syntax Error: tests/neg/19087.scala:15:6 --------------------------------------------------------------------- +15 | bar = 2 // error: ',' or ')' expected + | ^^^ + | ',' or ')' expected, but identifier found +-- [E067] Syntax Error: tests/neg/19087.scala:3:4 ---------------------------------------------------------------------- +3 |def foo[T](state: State)(body: => T): Option[T] // error: only classes can have declared but undefined members + | ^ + | Declaration of method foo not allowed here: only classes can have declared but undefined members +-- [E050] Type Error: tests/neg/19087.scala:13:22 ---------------------------------------------------------------------- +13 | foo(state.copy(x = 5): // Missing ")" // error: method copy in class State does not take more parameters + | ^^^^^^^^^^^^^^^^^ + | method copy in class State does not take more parameters + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg/19087.scala b/tests/neg/19087.scala new file mode 100644 index 000000000000..b52dddcad651 --- /dev/null +++ b/tests/neg/19087.scala @@ -0,0 +1,15 @@ +case class State(x: Int) + +def foo[T](state: State)(body: => T): Option[T] // error: only classes can have declared but undefined members + Option.when(state.x == 0) body // error: Illegal start of toplevel definition + +var bar = 0 +val state = State(0) + +def app: Function1[Int, Unit] = + new Function1[Int, Unit]: + def apply(x: Int): Unit = + foo(state): + foo(state.copy(x = 5): // Missing ")" // error: method copy in class State does not take more parameters + println("a") + bar = 2 // error: ',' or ')' expected From 4e6d1567277c7fa8596d114c3402bc5c104663df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 13:37:02 +0000 Subject: [PATCH 051/277] Bump VirtusLab/scala-cli-setup from 1.1.2 to 1.1.3 Bumps [VirtusLab/scala-cli-setup](https://github.com/virtuslab/scala-cli-setup) from 1.1.2 to 1.1.3. - [Release notes](https://github.com/virtuslab/scala-cli-setup/releases) - [Commits](https://github.com/virtuslab/scala-cli-setup/compare/v1.1.2...v1.1.3) --- updated-dependencies: - dependency-name: VirtusLab/scala-cli-setup dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/lts-backport.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lts-backport.yaml b/.github/workflows/lts-backport.yaml index 090b55b8eaf5..2dbfedbc447b 100644 --- a/.github/workflows/lts-backport.yaml +++ b/.github/workflows/lts-backport.yaml @@ -15,7 +15,7 @@ jobs: with: fetch-depth: 0 - uses: coursier/cache-action@v6 - - uses: VirtusLab/scala-cli-setup@v1.1.2 + - uses: VirtusLab/scala-cli-setup@v1.1.3 - run: scala-cli ./project/scripts/addToBackportingProject.scala -- ${{ github.sha }} env: GRAPHQL_API_TOKEN: ${{ secrets.GRAPHQL_API_TOKEN }} From 837272c45accc395373e351352c4d7a327063f62 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 19 Feb 2024 11:09:36 +0100 Subject: [PATCH 052/277] warn when running console instead of repl --- project/Build.scala | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/project/Build.scala b/project/Build.scala index 356d8bd0e7b9..879d411eabe9 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -2138,6 +2138,16 @@ object Build { // default. addCommandAlias("publishLocal", "scala3-bootstrapped/publishLocal"), repl := (`scala3-compiler-bootstrapped` / repl).value, + (Compile / console) := (Compile / console).dependsOn(Def.task { + import _root_.scala.io.AnsiColor._ + val msg = "`console` uses the reference Scala version. Use `repl` instead." + val f = "═" * (msg.length + 2) + val box = + s"""╔$f╗ + |║ ${BOLD}$msg$RESET ║ + |╚$f╝""".stripMargin + streams.value.log.warn(box) + }).value, ). settings( publish / skip := true From 1e890164b6dcb7d4f84a5df5135f56111ae74925 Mon Sep 17 00:00:00 2001 From: Eugene Flesselle Date: Mon, 19 Feb 2024 17:36:34 +0100 Subject: [PATCH 053/277] Attempt implicit search for old style `implicit` parameters (not only `using` params) --- .../src/dotty/tools/dotc/typer/Applications.scala | 2 +- tests/neg/i19594.check | 8 ++++++++ tests/neg/i19594.scala | 13 +++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 tests/neg/i19594.check create mode 100644 tests/neg/i19594.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 8a1db87a4f92..cf7a9dc71317 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -638,7 +638,7 @@ trait Applications extends Compatibility { defaultArg.tpe.widen match case _: MethodOrPoly if testOnly => matchArgs(args1, formals1, n + 1) case _ => matchArgs(args1, addTyped(treeToArg(defaultArg)), n + 1) - else if methodType.isContextualMethod && ctx.mode.is(Mode.ImplicitsEnabled) then + else if methodType.isImplicitMethod && ctx.mode.is(Mode.ImplicitsEnabled) then matchArgs(args1, addTyped(treeToArg(implicitArg)), n + 1) else missingArg(n) diff --git a/tests/neg/i19594.check b/tests/neg/i19594.check new file mode 100644 index 000000000000..bb9ff3fc68af --- /dev/null +++ b/tests/neg/i19594.check @@ -0,0 +1,8 @@ +-- [E172] Type Error: tests/neg/i19594.scala:12:14 --------------------------------------------------------------------- +12 | assertEquals(true, 1, "values are not the same") // error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | Can you see me?! +-- [E172] Type Error: tests/neg/i19594.scala:13:14 --------------------------------------------------------------------- +13 | assertEquals(true, 1) // error + | ^^^^^^^^^^^^^^^^^^^^^ + | Can you see me?! diff --git a/tests/neg/i19594.scala b/tests/neg/i19594.scala new file mode 100644 index 000000000000..a559da8d9250 --- /dev/null +++ b/tests/neg/i19594.scala @@ -0,0 +1,13 @@ +import scala.annotation.implicitNotFound + +@implicitNotFound("Can you see me?!") +trait Compare[A, B] + +object example extends App: + + // The presence of the below default argument prevents the `implicitNotFound` message from appearing + def assertEquals[A, B](a: A, b: B, clue: => Any = "values are not the same") + (implicit comp: Compare[A, B]): Unit = () + + assertEquals(true, 1, "values are not the same") // error + assertEquals(true, 1) // error From ab447590d61256ba98659727ab05209a67219a42 Mon Sep 17 00:00:00 2001 From: Jakub Ciesluk <323892@uwr.edu.pl> Date: Fri, 16 Feb 2024 14:11:36 +0100 Subject: [PATCH 054/277] bugfix: Choose correct signature is signatureHelp for overloaded methods --- .../dotty/tools/dotc/reporting/messages.scala | 2 +- .../dotty/tools/dotc/util/Signatures.scala | 58 ++++++++++++++----- .../signaturehelp/SignatureHelpSuite.scala | 34 +++++++++++ 3 files changed, 80 insertions(+), 14 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index 0367698b9bbe..484bc88c0983 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -289,7 +289,7 @@ extends NotFoundMsg(MissingIdentID) { } } -class TypeMismatch(found: Type, expected: Type, inTree: Option[untpd.Tree], addenda: => String*)(using Context) +class TypeMismatch(val found: Type, expected: Type, inTree: Option[untpd.Tree], addenda: => String*)(using Context) extends TypeMismatchMsg(found, expected)(TypeMismatchID): def msg(using Context) = diff --git a/compiler/src/dotty/tools/dotc/util/Signatures.scala b/compiler/src/dotty/tools/dotc/util/Signatures.scala index 9131f4f761a2..0bd407261125 100644 --- a/compiler/src/dotty/tools/dotc/util/Signatures.scala +++ b/compiler/src/dotty/tools/dotc/util/Signatures.scala @@ -221,7 +221,7 @@ object Signatures { val funSymbol = fun.symbol val alternatives = if funSymbol.isLocalToBlock then List(funSymbol.denot) else funSymbol.owner.info.member(funSymbol.name).alternatives - val alternativeIndex = alternatives.map(_.symbol).indexOf(funSymbol) max 0 + val alternativeIndex = bestAlternative(alternatives, params, paramssListIndex) (alternativeIndex, alternatives) if alternativeIndex < alternatives.length then @@ -660,24 +660,56 @@ object Signatures { case msg: NoMatchingOverload => msg.alternatives case _ => Nil - val userParamsTypes = params.map(_.tpe) // Assign a score to each alternative (how many parameters are correct so far), and // use that to determine what is the current active signature. + val alternativeIndex = bestAlternative(alternatives, params, paramssIndex) + (alternativeIndex, alternatives) + } + + /** + * Given a list of alternatives, and a list of parameters, returns the index of the best + * alternative, i.e. the alternative that has the most formal parameters matching the given + * arguments and the least number of formal parameters. + * + * @param alternatives The list of alternatives to inspect. + * @param params The parameters that were given at the call site. + * @param paramssIndex Index of paramss we are currently in. + * + * @return The index of the best alternative. + */ + private def bestAlternative(alternatives: List[SingleDenotation], params: List[tpd.Tree], paramssIndex: Int)(using Context): Int = + val userParamsTypes = params.map( + _.tpe match + case e: PreviousErrorType => + /** + * In case: + * def foo(i: Int, s: String): Unit = ??? + * def foo(i: Boolean, s: Int, x: Double): Unit = ??? + * foo(false, @@) + * + * `false` has error type: `Required: Int, Found: Boolean` + */ + e.msg match + case tm: TypeMismatch => + tm.found + case _ => e + case t => t + ) val alternativesScores = alternatives.map { alt => val alreadyCurriedBonus = if (alt.symbol.paramSymss.length > paramssIndex) 1 else 0 - alt.info.stripPoly match - case tpe: MethodType => alreadyCurriedBonus + - userParamsTypes.zip(tpe.paramInfos).takeWhile{ case (t0, t1) => t0 <:< t1 }.size - case _ => 0 + alt.info.stripPoly match + case tpe: MethodType => + val score = alreadyCurriedBonus + + userParamsTypes + .zip(tpe.paramInfos) + .takeWhile { case (t0, t1) =>t0 <:< t1 } + .size + (score, -tpe.paramInfos.length) + case _ => (0, 0) } - - val bestAlternative = - if (alternativesScores.isEmpty) 0 - else alternativesScores.zipWithIndex.maxBy(_._1)._2 - - (bestAlternative, alternatives) - } + if (alternativesScores.isEmpty) 0 + else alternativesScores.zipWithIndex.maxBy(_._1)._2 } 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..ac63ef92aef5 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/signaturehelp/SignatureHelpSuite.scala @@ -1499,3 +1499,37 @@ class SignatureHelpSuite extends BaseSignatureHelpSuite: | ^ |""".stripMargin ) + + @Test def `correct-alternative` = + check( + """ + |object x { + | def foo(i: Int, s: String): Unit = ??? + | def foo(i: Boolean, s: Int, x: Double): Unit = ??? + | + | foo(false, @@) + |} + |""".stripMargin, + """ + |foo(i: Boolean, s: Int, x: Double): Unit + | ^^^^^^ + |foo(i: Int, s: String): Unit + |""".stripMargin + ) + + @Test def `correct-alternative1` = + check( + """ + |object x { + | def foo(i: Boolean, s: String)(b: Int): Unit = ??? + | def foo(i: Boolean, s: Int)(b: String): Unit = ??? + | + | foo(false, 123)(@@) + |} + |""".stripMargin, + """ + |foo(i: Boolean, s: Int)(b: String): Unit + | ^^^^^^^^^ + |foo(i: Boolean, s: String)(b: Int): Unit + |""".stripMargin + ) From 49e325075ec7e316d10fa38c725707adb17d4ab8 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 20 Feb 2024 14:30:44 +0100 Subject: [PATCH 055/277] Refine behavior of `-Yno-experimental` --- compiler/src/dotty/tools/dotc/config/Feature.scala | 2 +- compiler/src/dotty/tools/dotc/config/ScalaSettings.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/Feature.scala b/compiler/src/dotty/tools/dotc/config/Feature.scala index 2798828ad9a7..f2ed58a5c8ca 100644 --- a/compiler/src/dotty/tools/dotc/config/Feature.scala +++ b/compiler/src/dotty/tools/dotc/config/Feature.scala @@ -163,7 +163,7 @@ object Feature: do checkExperimentalFeature(s"feature $setting", NoSourcePosition) def isExperimentalEnabled(using Context): Boolean = - (Properties.experimental || ctx.settings.experimental.value) && !ctx.settings.YnoExperimental.value + (Properties.experimental && !ctx.settings.YnoExperimental.value) || ctx.settings.experimental.value /** Handle language import `import language..` if it is one * of the global imports `pureFunctions` or `captureChecking`. In this case diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 85e6ebef751f..cb6d0bdab424 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -397,7 +397,7 @@ private sealed trait YSettings: val YretainTrees: Setting[Boolean] = BooleanSetting("-Yretain-trees", "Retain trees for top-level classes, accessible from ClassSymbol#tree") val YshowTreeIds: Setting[Boolean] = BooleanSetting("-Yshow-tree-ids", "Uniquely tag all tree nodes in debugging output.") val YfromTastyIgnoreList: Setting[List[String]] = MultiStringSetting("-Yfrom-tasty-ignore-list", "file", "List of `tasty` files in jar files that will not be loaded when using -from-tasty.") - val YnoExperimental: Setting[Boolean] = BooleanSetting("-Yno-experimental", "Disable experimental language features.") + val YnoExperimental: Setting[Boolean] = BooleanSetting("-Yno-experimental", "Disable experimental language features by default in NIGHTLY/SNAPSHOT versions of the compiler.") val YlegacyLazyVals: Setting[Boolean] = BooleanSetting("-Ylegacy-lazy-vals", "Use legacy (pre 3.3.0) implementation of lazy vals.") val YcompileScala2Library: Setting[Boolean] = BooleanSetting("-Ycompile-scala2-library", "Used when compiling the Scala 2 standard library.") val YoutputOnlyTasty: Setting[Boolean] = BooleanSetting("-Youtput-only-tasty", "Used to only generate the TASTy file without the classfiles") From d244a30b67ce6db9e929f3e7e9c0ef4051ac0e5c Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 8 Feb 2024 10:39:23 +0100 Subject: [PATCH 056/277] Inline transparent implicit parameters when typing Unapply trees We needed to delay the inlining of the transparent inline when typing the unapply function application. We used the NoInline mode, but this also stopped the inlining of the arguments of the unapply. To fix this we target more precisely the inlining of the unapply method and not the implicit arguments. To do this we detect the dummy argument that is used type the unapply as an application, before it is transformed into a pattern. Fixes #19623 --- .../dotty/tools/dotc/inlines/Inlines.scala | 12 ++++++ .../dotty/tools/dotc/typer/Applications.scala | 2 +- tests/pos/i19623.scala | 40 +++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i19623.scala diff --git a/compiler/src/dotty/tools/dotc/inlines/Inlines.scala b/compiler/src/dotty/tools/dotc/inlines/Inlines.scala index 230092898051..a97917e28771 100644 --- a/compiler/src/dotty/tools/dotc/inlines/Inlines.scala +++ b/compiler/src/dotty/tools/dotc/inlines/Inlines.scala @@ -5,6 +5,7 @@ package inlines import ast.*, core.* import Flags.*, Symbols.*, Types.*, Decorators.*, Constants.*, Contexts.* import StdNames.{tpnme, nme} +import NameOps.* import typer.* import NameKinds.BodyRetainerName import SymDenotations.SymDenotation @@ -54,6 +55,16 @@ object Inlines: def needsInlining(tree: Tree)(using Context): Boolean = tree match { case Block(_, expr) => needsInlining(expr) case _ => + def isUnapplyExpressionWithDummy: Boolean = + // The first step of typing an `unapply` consists in typing the call + // with a dummy argument (see Applications.typedUnApply). We delay the + // inlining of this call. + def rec(tree: Tree): Boolean = tree match + case Apply(_, ProtoTypes.dummyTreeOfType(_) :: Nil) => true + case Apply(fn, _) => rec(fn) + case _ => false + tree.symbol.name.isUnapplyName && rec(tree) + isInlineable(tree.symbol) && !tree.tpe.widenTermRefExpr.isInstanceOf[MethodOrPoly] && StagingLevel.level == 0 @@ -64,6 +75,7 @@ object Inlines: && !ctx.typer.hasInliningErrors && !ctx.base.stopInlining && !ctx.mode.is(Mode.NoInline) + && !isUnapplyExpressionWithDummy } private def needsTransparentInlining(tree: Tree)(using Context): Boolean = diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 8a1db87a4f92..fd1421d81b61 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -1492,7 +1492,7 @@ trait Applications extends Compatibility { val dummyArg = dummyTreeOfType(ownType) val (newUnapplyFn, unapplyApp) = - val unapplyAppCall = withMode(Mode.NoInline): + val unapplyAppCall = typedExpr(untpd.TypedSplice(Apply(unapplyFn, dummyArg :: Nil))) inlinedUnapplyFnAndApp(dummyArg, unapplyAppCall) diff --git a/tests/pos/i19623.scala b/tests/pos/i19623.scala new file mode 100644 index 000000000000..8ab8cde159a9 --- /dev/null +++ b/tests/pos/i19623.scala @@ -0,0 +1,40 @@ +import scala.compiletime.* +import scala.language.dynamics + +abstract class % extends Selectable + +trait Select { type Out <: % } +trait Selector extends Dynamic { + def selectDynamic[S <: Singleton & String](label: S): Any = ??? + + def unapply[R: RecordLike](record: R)(using + t: Select, + r: RecordLike[t.Out] + ): r.ElemTypes = ??? +} + +trait RecordLike[R] { + type ElemTypes <: Tuple +} + + +@main def Test = { + val r: %{ val name: String; } = ??? + + // originally derived in macro, use dummy instance instead + transparent inline given outputRecordLike[R <: %]: RecordLike[R] = null.asInstanceOf[ + RecordLike[R] { + type ElemTypes = String *: EmptyTuple + } + ] + + type FieldSelector = Select { type Out = % { val name: String } } + given fieldSelector: FieldSelector = ??? + val selector: Selector = ??? + + val works = selector.unapply(r) + val works2 = selector.unapply(r)(using summon, fieldSelector, summon) + r match { + case selector(value) => value // compilation error + } +} From 3e2a88e7288437a32a1595d1c0a2732002007530 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Wed, 14 Feb 2024 17:30:25 +0100 Subject: [PATCH 057/277] reproduce the issue --- tests/run/i19619/InnerClass.java | 67 ++++++++++++++++++++++++ tests/run/i19619/InnerClassGen.java | 80 +++++++++++++++++++++++++++++ tests/run/i19619/RawTypes.java | 18 +++++++ tests/run/i19619/Test.scala | 42 +++++++++++++++ 4 files changed, 207 insertions(+) create mode 100644 tests/run/i19619/InnerClass.java create mode 100644 tests/run/i19619/InnerClassGen.java create mode 100644 tests/run/i19619/RawTypes.java create mode 100644 tests/run/i19619/Test.scala diff --git a/tests/run/i19619/InnerClass.java b/tests/run/i19619/InnerClass.java new file mode 100644 index 000000000000..32bb1642a232 --- /dev/null +++ b/tests/run/i19619/InnerClass.java @@ -0,0 +1,67 @@ +// InnerClass.java + +package lib; + +public class InnerClass { + + public class Inner { + public U innerField; + + public Inner(U innerField) { + this.innerField = innerField; + } + + public U getInnerField() { + return innerField; + } + } + + public class Outer { + + public class Nested { + + public U outerField; + public V innerField; + + public Nested(U outerField, V innerField) { + this.outerField = outerField; + this.innerField = innerField; + } + + public U getOuterField() { + return outerField; + } + + public V getInnerField() { + return innerField; + } + } + } + + public Inner createInner(U innerField) { + return new Inner<>(innerField); + } + + public Outer.Nested createNested(U outerField, V innerField) { + Outer outer = new Outer<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static InnerClass.Inner createInnerStatic(U innerField) { + InnerClass innerClass = new InnerClass(); + return innerClass.new Inner<>(innerField); + } + + public static InnerClass.Outer.Nested createNestedStatic(U outerField, V innerField) { + InnerClass innerClass = new InnerClass(); + InnerClass.Outer outer = innerClass.new Outer<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static void consumeNestedStatic(InnerClass.Outer.Nested nested) { + } + + public static void consumeNestedStatic2(Outer.Nested nested) { + } + +} diff --git a/tests/run/i19619/InnerClassGen.java b/tests/run/i19619/InnerClassGen.java new file mode 100644 index 000000000000..3a691aa0608f --- /dev/null +++ b/tests/run/i19619/InnerClassGen.java @@ -0,0 +1,80 @@ +// InnerClassGen.java + +package lib; + +public class InnerClassGen { + + public class Inner { + public T rootField; + public U innerField; + + public Inner(T rootField, U innerField) { + this.rootField = rootField; + this.innerField = innerField; + } + + public T getRootField() { + return rootField; + } + + public U getInnerField() { + return innerField; + } + } + + public class Outer { + + public class Nested { + public T rootField; + public U outerField; + public V innerField; + + public Nested(T rootField, U outerField, V innerField) { + this.rootField = rootField; + this.outerField = outerField; + this.innerField = innerField; + } + + public T getRootField() { + return rootField; + } + + public U getOuterField() { + return outerField; + } + + public V getInnerField() { + return innerField; + } + } + } + + public static class OuterStatic { + public static class NestedStatic { + } + } + + public Inner createInner(T rootField, U innerField) { + return new Inner<>(rootField, innerField); + } + + public Outer.Nested createNested(T rootField, U outerField, V innerField) { + Outer outer = new Outer<>(); + return outer.new Nested<>(rootField, outerField, innerField); + } + + public static InnerClassGen.Inner createInnerStatic(T rootField, U innerField) { + InnerClassGen innerClassGen = new InnerClassGen<>(); + return innerClassGen.new Inner<>(rootField, innerField); + } + + public static InnerClassGen.Outer.Nested createNestedStatic(T rootField, U outerField, V innerField) { + InnerClassGen innerClassGen = new InnerClassGen<>(); + InnerClassGen.Outer outer = innerClassGen.new Outer<>(); + return outer.new Nested<>(rootField, outerField, innerField); + } + + public static void consumeNestedStatic(InnerClassGen.Outer.Nested nested) { + } + +} diff --git a/tests/run/i19619/RawTypes.java b/tests/run/i19619/RawTypes.java new file mode 100644 index 000000000000..4373a04093eb --- /dev/null +++ b/tests/run/i19619/RawTypes.java @@ -0,0 +1,18 @@ +// RawTypes.java + +package lib; + +public class RawTypes { + + public class C { + public class D { + } + } + + public static void mii_Raw_Raw(RawTypes.C.D d) { + } + + public static void mii_Raw_Raw2(C.D d) { + } + +} diff --git a/tests/run/i19619/Test.scala b/tests/run/i19619/Test.scala new file mode 100644 index 000000000000..7e10950c6cfd --- /dev/null +++ b/tests/run/i19619/Test.scala @@ -0,0 +1,42 @@ +import lib.InnerClass +import lib.InnerClassGen +import lib.RawTypes + +@main def Test = + + locally: + val ici: InnerClass = new InnerClass() + val ici_inner1: ici.Inner[Long] = ici.createInner[Long](47L) // ok, but should error + val ici_inner2: InnerClass#Inner[Long] = ici.createInner[Long](47L) + val ici_inner3: InnerClass#Inner[Long] = InnerClass.createInnerStatic[Long](47L) + + val ici_outer: InnerClass#Outer[Long] = new ici.Outer[Long]() + val ici_nested1: InnerClass#Outer[Long]#Nested[Int] = new ici_outer.Nested[Int](47L, 23) + val ici_nested2: InnerClass#Outer[Long]#Nested[Int] = ici.createNested[Long, Int](47L, 23) + val ici_nested3: InnerClass#Outer[Long]#Nested[Int] = InnerClass.createNestedStatic[Long, Int](47L, 23) + + InnerClass.consumeNestedStatic(ici_nested3) + InnerClass.consumeNestedStatic2(ici_nested3) // error: dotty is inferring static selection when there is no explicit prefix + + locally: + val ici: InnerClassGen[String] = new InnerClassGen() + val ici_inner1: ici.Inner[Long] = ici.createInner[Long]("Hello", 47L) // ok, but should error + val ici_inner2: InnerClassGen[String]#Inner[Long] = ici.createInner[Long]("Hello", 47L) + val ici_inner3: InnerClassGen[String]#Inner[Long] = InnerClassGen.createInnerStatic[String, Long]("Hello", 47L) + + val ici_outer: InnerClassGen[String]#Outer[Long] = new ici.Outer[Long]() + val ici_nested1: InnerClassGen[String]#Outer[Long]#Nested[Int] = new ici_outer.Nested[Int]("Hello", 47L, 23) + val ici_nested2: InnerClassGen[String]#Outer[Long]#Nested[Int] = ici.createNested[Long, Int]("Hello", 47L, 23) + val ici_nested3: InnerClassGen[String]#Outer[Long]#Nested[Int] = InnerClassGen.createNestedStatic[String, Long, Int]("Hello", 47L, 23) + + InnerClassGen.consumeNestedStatic(ici_nested3) + + locally: + val rt: RawTypes = new RawTypes() + val c: RawTypes#C[String] = new rt.C[String]() + + val cd_ii: RawTypes#C[String]#D[String] = new c.D[String]() + val cd_ii_Raw: RawTypes#C[?]#D[?] = cd_ii + + RawTypes.mii_Raw_Raw(cd_ii_Raw) + RawTypes.mii_Raw_Raw2(cd_ii_Raw) // error: dotty is inferring static selection when there is no explicit prefix From b3501a67402e80cac5a87b7cb90d3d93625ae1db Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Fri, 16 Feb 2024 17:36:50 +0100 Subject: [PATCH 058/277] do not look in companion in javaFindMember in typedSelect --- .../src/dotty/tools/dotc/core/ContextOps.scala | 15 ++++++++++++--- .../src/dotty/tools/dotc/typer/TypeAssigner.scala | 5 ++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/ContextOps.scala b/compiler/src/dotty/tools/dotc/core/ContextOps.scala index 920da377f9b4..55fb31fd1916 100644 --- a/compiler/src/dotty/tools/dotc/core/ContextOps.scala +++ b/compiler/src/dotty/tools/dotc/core/ContextOps.scala @@ -34,7 +34,10 @@ object ContextOps: if (elem.name == name) return elem.sym.denot // return self } val pre = ctx.owner.thisType - if ctx.isJava then javaFindMember(name, pre, required, excluded) + if ctx.isJava then + // Note: I didn't verify if there exists a code path that would require `lookInCompanion = true`, + // it is just to preserve the original behavior. + javaFindMember(name, pre, lookInCompanion = true, required, excluded) else pre.findMember(name, pre, required, excluded) } else // we are in the outermost context belonging to a class; self is invisible here. See inClassContext. @@ -43,7 +46,13 @@ object ContextOps: ctx.scope.denotsNamed(name).filterWithFlags(required, excluded).toDenot(NoPrefix) } - final def javaFindMember(name: Name, pre: Type, required: FlagSet = EmptyFlags, excluded: FlagSet = EmptyFlags): Denotation = + /** Look in the prefix with Java semantics. + * @param lookInCompanion If true, try in the companion class of a module as a fallback. + * Note: originally this was used to type Select nodes in Java code, + * but that is no longer the case. + * It is preserved in case it is necessary for denotNamed, but this is unverified. + */ + final def javaFindMember(name: Name, pre: Type, lookInCompanion: Boolean, required: FlagSet = EmptyFlags, excluded: FlagSet = EmptyFlags): Denotation = assert(ctx.isJava) inContext(ctx) { @@ -53,7 +62,7 @@ object ContextOps: val directSearch = pre.findMember(name, pre, required, excluded) // 2. Try to search in companion class if current is an object. - def searchCompanionClass = if preSym.is(Flags.Module) then + def searchCompanionClass = if lookInCompanion && preSym.is(Flags.Module) then preSym.companionClass.thisType.findMember(name, pre, required, excluded) else NoDenotation diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 8bae3a2fb3a7..96c5e57dde0e 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -156,7 +156,10 @@ trait TypeAssigner { val pre = maybeSkolemizePrefix(qualType, name) val mbr = if ctx.isJava then - ctx.javaFindMember(name, pre) + // don't look in the companion class here if qual is a module, + // we use backtracking to instead change the qual to the companion class + // if this fails. + ctx.javaFindMember(name, pre, lookInCompanion = false) else qualType.findMember(name, pre) From 3ab29995e1571c6f19dea41d47b143f4895a8cac Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Fri, 16 Feb 2024 19:11:21 +0100 Subject: [PATCH 059/277] Widen prefix in findRef of class from Java sources. potential TODO: tree's of Raw types from Java are still incorrect once they are serialized to TASTy, however it is debateable if we care to support them. --- .../tools/dotc/core/SymDenotations.scala | 7 ++ .../src/dotty/tools/dotc/typer/Typer.scala | 4 + .../Yjava-tasty-paths/a/InnerClass.java | 65 +++++++++++++++ .../Yjava-tasty-paths/a/InnerClassGen.java | 78 ++++++++++++++++++ .../Yjava-tasty-paths/a/RawTypes.java | 16 ++++ .../Yjava-tasty-paths/a/package.scala | 2 + .../pipelining/Yjava-tasty-paths/b/Test.scala | 50 ++++++++++++ .../pipelining/Yjava-tasty-paths/build.sbt | 31 +++++++ .../project/DottyInjectedPlugin.scala | 12 +++ sbt-test/pipelining/Yjava-tasty-paths/test | 5 ++ tests/neg/i19619/InnerClass.java | 67 ++++++++++++++++ tests/neg/i19619/InnerClassGen.java | 80 +++++++++++++++++++ tests/neg/i19619/Test.scala | 12 +++ tests/run/i19619/Test.scala | 8 +- 14 files changed, 433 insertions(+), 4 deletions(-) create mode 100644 sbt-test/pipelining/Yjava-tasty-paths/a/InnerClass.java create mode 100644 sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassGen.java create mode 100644 sbt-test/pipelining/Yjava-tasty-paths/a/RawTypes.java create mode 100644 sbt-test/pipelining/Yjava-tasty-paths/a/package.scala create mode 100644 sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala create mode 100644 sbt-test/pipelining/Yjava-tasty-paths/build.sbt create mode 100644 sbt-test/pipelining/Yjava-tasty-paths/project/DottyInjectedPlugin.scala create mode 100644 sbt-test/pipelining/Yjava-tasty-paths/test create mode 100644 tests/neg/i19619/InnerClass.java create mode 100644 tests/neg/i19619/InnerClassGen.java create mode 100644 tests/neg/i19619/Test.scala diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 13eb5ce8b5ba..b3fe5757720e 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1512,6 +1512,13 @@ object SymDenotations { def namedType(using Context): NamedType = if (isType) typeRef else termRef + /** Like typeRef, but the prefix is widened. + * + * See tests/neg/i19619/Test.scala + */ + def javaTypeRef(using Context) = + TypeRef(maybeOwner.reachablePrefix.widen, symbol) + /** Like typeRef, but objects in the prefix are represented by their singleton type, * this means we output `pre.O.member` rather than `pre.O$.this.member`. * diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index f1db302e958c..1800754e6650 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -461,6 +461,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer if (isSelfDenot(defDenot)) curOwner.enclosingClass.thisType else if (ctx.isJava && defDenot.symbol.isStatic) { defDenot.symbol.namedType + } + else if (ctx.isJava && defDenot.symbol.isClass) { + // in a java context a raw identifier to a class should have a widened prefix. + defDenot.symbol.javaTypeRef } else { val effectiveOwner = if (curOwner.isTerm && defDenot.symbol.maybeOwner.isType) diff --git a/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClass.java b/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClass.java new file mode 100644 index 000000000000..c23bc54397dd --- /dev/null +++ b/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClass.java @@ -0,0 +1,65 @@ +package a; + +public class InnerClass { + + public class Inner { + public U innerField; + + public Inner(U innerField) { + this.innerField = innerField; + } + + public U getInnerField() { + return innerField; + } + } + + public class Outer { + + public class Nested { + + public U outerField; + public V innerField; + + public Nested(U outerField, V innerField) { + this.outerField = outerField; + this.innerField = innerField; + } + + public U getOuterField() { + return outerField; + } + + public V getInnerField() { + return innerField; + } + } + } + + public Inner createInner(U innerField) { + return new Inner<>(innerField); + } + + public Outer.Nested createNested(U outerField, V innerField) { + Outer outer = new Outer<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static InnerClass.Inner createInnerStatic(U innerField) { + InnerClass innerClass = new InnerClass(); + return innerClass.new Inner<>(innerField); + } + + public static InnerClass.Outer.Nested createNestedStatic(U outerField, V innerField) { + InnerClass innerClass = new InnerClass(); + InnerClass.Outer outer = innerClass.new Outer<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static void consumeNestedStatic(InnerClass.Outer.Nested nested) { + } + + public static void consumeNestedStatic2(Outer.Nested nested) { + } + +} diff --git a/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassGen.java b/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassGen.java new file mode 100644 index 000000000000..4011cf2fc244 --- /dev/null +++ b/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassGen.java @@ -0,0 +1,78 @@ +package a; + +public class InnerClassGen { + + public class Inner { + public T rootField; + public U innerField; + + public Inner(T rootField, U innerField) { + this.rootField = rootField; + this.innerField = innerField; + } + + public T getRootField() { + return rootField; + } + + public U getInnerField() { + return innerField; + } + } + + public class Outer { + + public class Nested { + public T rootField; + public U outerField; + public V innerField; + + public Nested(T rootField, U outerField, V innerField) { + this.rootField = rootField; + this.outerField = outerField; + this.innerField = innerField; + } + + public T getRootField() { + return rootField; + } + + public U getOuterField() { + return outerField; + } + + public V getInnerField() { + return innerField; + } + } + } + + public static class OuterStatic { + public static class NestedStatic { + } + } + + public Inner createInner(T rootField, U innerField) { + return new Inner<>(rootField, innerField); + } + + public Outer.Nested createNested(T rootField, U outerField, V innerField) { + Outer outer = new Outer<>(); + return outer.new Nested<>(rootField, outerField, innerField); + } + + public static InnerClassGen.Inner createInnerStatic(T rootField, U innerField) { + InnerClassGen innerClassGen = new InnerClassGen<>(); + return innerClassGen.new Inner<>(rootField, innerField); + } + + public static InnerClassGen.Outer.Nested createNestedStatic(T rootField, U outerField, V innerField) { + InnerClassGen innerClassGen = new InnerClassGen<>(); + InnerClassGen.Outer outer = innerClassGen.new Outer<>(); + return outer.new Nested<>(rootField, outerField, innerField); + } + + public static void consumeNestedStatic(InnerClassGen.Outer.Nested nested) { + } + +} diff --git a/sbt-test/pipelining/Yjava-tasty-paths/a/RawTypes.java b/sbt-test/pipelining/Yjava-tasty-paths/a/RawTypes.java new file mode 100644 index 000000000000..4f97c45e7f90 --- /dev/null +++ b/sbt-test/pipelining/Yjava-tasty-paths/a/RawTypes.java @@ -0,0 +1,16 @@ +package a; + +public class RawTypes { + + public class C { + public class D { + } + } + + public static void mii_Raw_Raw(RawTypes.C.D d) { + } + + public static void mii_Raw_Raw2(C.D d) { + } + +} diff --git a/sbt-test/pipelining/Yjava-tasty-paths/a/package.scala b/sbt-test/pipelining/Yjava-tasty-paths/a/package.scala new file mode 100644 index 000000000000..93f99e9892fe --- /dev/null +++ b/sbt-test/pipelining/Yjava-tasty-paths/a/package.scala @@ -0,0 +1,2 @@ +// THIS FILE EXISTS SO THAT `A.java` WILL BE COMPILED BY SCALAC +package a diff --git a/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala b/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala new file mode 100644 index 000000000000..4f555d3b8ac9 --- /dev/null +++ b/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala @@ -0,0 +1,50 @@ +package b + +import a.InnerClass +import a.InnerClassGen +import a.RawTypes + +object B { + @main def test = { + locally { + val ici: InnerClass = new InnerClass() + // val ici_inner1: ici.Inner[Long] = ici.createInner[Long](47L) // error + val ici_inner2: InnerClass#Inner[Long] = ici.createInner[Long](47L) + val ici_inner3: InnerClass#Inner[Long] = InnerClass.createInnerStatic[Long](47L) + + val ici_outer: InnerClass#Outer[Long] = new ici.Outer[Long]() + val ici_nested1: InnerClass#Outer[Long]#Nested[Int] = new ici_outer.Nested[Int](47L, 23) + val ici_nested2: InnerClass#Outer[Long]#Nested[Int] = ici.createNested[Long, Int](47L, 23) + val ici_nested3: InnerClass#Outer[Long]#Nested[Int] = InnerClass.createNestedStatic[Long, Int](47L, 23) + + InnerClass.consumeNestedStatic(ici_nested3) + InnerClass.consumeNestedStatic2(ici_nested3) + } + + locally { + val ici: InnerClassGen[String] = new InnerClassGen() + // val ici_inner1: ici.Inner[Long] = ici.createInner[Long]("Hello", 47L) // error + val ici_inner2: InnerClassGen[String]#Inner[Long] = ici.createInner[Long]("Hello", 47L) + val ici_inner3: InnerClassGen[String]#Inner[Long] = InnerClassGen.createInnerStatic[String, Long]("Hello", 47L) + + val ici_outer: InnerClassGen[String]#Outer[Long] = new ici.Outer[Long]() + val ici_nested1: InnerClassGen[String]#Outer[Long]#Nested[Int] = new ici_outer.Nested[Int]("Hello", 47L, 23) + val ici_nested2: InnerClassGen[String]#Outer[Long]#Nested[Int] = ici.createNested[Long, Int]("Hello", 47L, 23) + val ici_nested3: InnerClassGen[String]#Outer[Long]#Nested[Int] = InnerClassGen.createNestedStatic[String, Long, Int]("Hello", 47L, 23) + + InnerClassGen.consumeNestedStatic(ici_nested3) + } + + locally { + val rt: RawTypes = new RawTypes() + val c: RawTypes#C[String] = new rt.C[String]() + + val cd_ii: RawTypes#C[String]#D[String] = new c.D[String]() + val cd_ii_Raw: RawTypes#C[?]#D[?] = cd_ii + + RawTypes.mii_Raw_Raw(cd_ii_Raw) + // RawTypes.mii_Raw_Raw2(cd_ii_Raw) // error: dotty still doesnt rewrite the tree of a raw type to a type with wildcards + } + } + +} diff --git a/sbt-test/pipelining/Yjava-tasty-paths/build.sbt b/sbt-test/pipelining/Yjava-tasty-paths/build.sbt new file mode 100644 index 000000000000..d63d1f9a3f7e --- /dev/null +++ b/sbt-test/pipelining/Yjava-tasty-paths/build.sbt @@ -0,0 +1,31 @@ +lazy val a = project.in(file("a")) + .settings( + scalacOptions += "-Yjava-tasty", // enable pickling of java signatures + scalacOptions ++= Seq("-Yjava-tasty-output", ((ThisBuild / baseDirectory).value / "a-paths-java-tasty.jar").toString), + scalacOptions += "-Ycheck:all", + Compile / classDirectory := ((ThisBuild / baseDirectory).value / "a-paths-classes"), // send classfiles to a different directory + ) + +lazy val b = project.in(file("b")) + .settings( + Compile / unmanagedClasspath := Seq(Attributed.blank((ThisBuild / baseDirectory).value / "a-paths-java-tasty.jar")), + scalacOptions += "-Ycheck:all", + scalacOptions += "-explain-cyclic", + scalacOptions += "-Ydebug-cyclic", + ) + .settings( + fork := true, // we have to fork the JVM if we actually want to run the code with correct failure semantics + Runtime / unmanagedClasspath += Attributed.blank((ThisBuild / baseDirectory).value / "a-paths-classes"), // make sure the java classes are visible at runtime + ) + +// same as b, but adds the real classes to the classpath instead of the tasty jar +lazy val bAlt = project.in(file("b-alt")) + .settings( + Compile / sources := (b / Compile / sources).value, + Compile / unmanagedClasspath := Seq(Attributed.blank((ThisBuild / baseDirectory).value / "a-paths-classes")), + scalacOptions += "-Ycheck:all", + ) + .settings( + fork := true, // we have to fork the JVM if we actually want to run the code with correct failure semantics + Runtime / unmanagedClasspath += Attributed.blank((ThisBuild / baseDirectory).value / "a-paths-classes"), // make sure the java classes are visible at runtime + ) diff --git a/sbt-test/pipelining/Yjava-tasty-paths/project/DottyInjectedPlugin.scala b/sbt-test/pipelining/Yjava-tasty-paths/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..69f15d168bfc --- /dev/null +++ b/sbt-test/pipelining/Yjava-tasty-paths/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +import sbt._ +import Keys._ + +object DottyInjectedPlugin extends AutoPlugin { + override def requires = plugins.JvmPlugin + override def trigger = allRequirements + + override val projectSettings = Seq( + scalaVersion := sys.props("plugin.scalaVersion"), + scalacOptions += "-source:3.0-migration" + ) +} diff --git a/sbt-test/pipelining/Yjava-tasty-paths/test b/sbt-test/pipelining/Yjava-tasty-paths/test new file mode 100644 index 000000000000..101a1b7cd2f1 --- /dev/null +++ b/sbt-test/pipelining/Yjava-tasty-paths/test @@ -0,0 +1,5 @@ +> a/compile +# test depending on variations of Java paths +> b/run +# double check against the real java classes +> bAlt/run diff --git a/tests/neg/i19619/InnerClass.java b/tests/neg/i19619/InnerClass.java new file mode 100644 index 000000000000..32bb1642a232 --- /dev/null +++ b/tests/neg/i19619/InnerClass.java @@ -0,0 +1,67 @@ +// InnerClass.java + +package lib; + +public class InnerClass { + + public class Inner { + public U innerField; + + public Inner(U innerField) { + this.innerField = innerField; + } + + public U getInnerField() { + return innerField; + } + } + + public class Outer { + + public class Nested { + + public U outerField; + public V innerField; + + public Nested(U outerField, V innerField) { + this.outerField = outerField; + this.innerField = innerField; + } + + public U getOuterField() { + return outerField; + } + + public V getInnerField() { + return innerField; + } + } + } + + public Inner createInner(U innerField) { + return new Inner<>(innerField); + } + + public Outer.Nested createNested(U outerField, V innerField) { + Outer outer = new Outer<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static InnerClass.Inner createInnerStatic(U innerField) { + InnerClass innerClass = new InnerClass(); + return innerClass.new Inner<>(innerField); + } + + public static InnerClass.Outer.Nested createNestedStatic(U outerField, V innerField) { + InnerClass innerClass = new InnerClass(); + InnerClass.Outer outer = innerClass.new Outer<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static void consumeNestedStatic(InnerClass.Outer.Nested nested) { + } + + public static void consumeNestedStatic2(Outer.Nested nested) { + } + +} diff --git a/tests/neg/i19619/InnerClassGen.java b/tests/neg/i19619/InnerClassGen.java new file mode 100644 index 000000000000..3a691aa0608f --- /dev/null +++ b/tests/neg/i19619/InnerClassGen.java @@ -0,0 +1,80 @@ +// InnerClassGen.java + +package lib; + +public class InnerClassGen { + + public class Inner { + public T rootField; + public U innerField; + + public Inner(T rootField, U innerField) { + this.rootField = rootField; + this.innerField = innerField; + } + + public T getRootField() { + return rootField; + } + + public U getInnerField() { + return innerField; + } + } + + public class Outer { + + public class Nested { + public T rootField; + public U outerField; + public V innerField; + + public Nested(T rootField, U outerField, V innerField) { + this.rootField = rootField; + this.outerField = outerField; + this.innerField = innerField; + } + + public T getRootField() { + return rootField; + } + + public U getOuterField() { + return outerField; + } + + public V getInnerField() { + return innerField; + } + } + } + + public static class OuterStatic { + public static class NestedStatic { + } + } + + public Inner createInner(T rootField, U innerField) { + return new Inner<>(rootField, innerField); + } + + public Outer.Nested createNested(T rootField, U outerField, V innerField) { + Outer outer = new Outer<>(); + return outer.new Nested<>(rootField, outerField, innerField); + } + + public static InnerClassGen.Inner createInnerStatic(T rootField, U innerField) { + InnerClassGen innerClassGen = new InnerClassGen<>(); + return innerClassGen.new Inner<>(rootField, innerField); + } + + public static InnerClassGen.Outer.Nested createNestedStatic(T rootField, U outerField, V innerField) { + InnerClassGen innerClassGen = new InnerClassGen<>(); + InnerClassGen.Outer outer = innerClassGen.new Outer<>(); + return outer.new Nested<>(rootField, outerField, innerField); + } + + public static void consumeNestedStatic(InnerClassGen.Outer.Nested nested) { + } + +} diff --git a/tests/neg/i19619/Test.scala b/tests/neg/i19619/Test.scala new file mode 100644 index 000000000000..85f9b3e529ac --- /dev/null +++ b/tests/neg/i19619/Test.scala @@ -0,0 +1,12 @@ +import lib.InnerClass +import lib.InnerClassGen + +@main def Test = + + locally: + val ici: InnerClass = new InnerClass() + val ici_inner1: ici.Inner[Long] = ici.createInner[Long](47L) // error + + locally: + val ici: InnerClassGen[String] = new InnerClassGen() + val ici_inner1: ici.Inner[Long] = ici.createInner[Long]("Hello", 47L) // error diff --git a/tests/run/i19619/Test.scala b/tests/run/i19619/Test.scala index 7e10950c6cfd..5d6f4d11c7a1 100644 --- a/tests/run/i19619/Test.scala +++ b/tests/run/i19619/Test.scala @@ -6,7 +6,7 @@ import lib.RawTypes locally: val ici: InnerClass = new InnerClass() - val ici_inner1: ici.Inner[Long] = ici.createInner[Long](47L) // ok, but should error + // val ici_inner1: ici.Inner[Long] = ici.createInner[Long](47L) // error val ici_inner2: InnerClass#Inner[Long] = ici.createInner[Long](47L) val ici_inner3: InnerClass#Inner[Long] = InnerClass.createInnerStatic[Long](47L) @@ -16,11 +16,11 @@ import lib.RawTypes val ici_nested3: InnerClass#Outer[Long]#Nested[Int] = InnerClass.createNestedStatic[Long, Int](47L, 23) InnerClass.consumeNestedStatic(ici_nested3) - InnerClass.consumeNestedStatic2(ici_nested3) // error: dotty is inferring static selection when there is no explicit prefix + InnerClass.consumeNestedStatic2(ici_nested3) locally: val ici: InnerClassGen[String] = new InnerClassGen() - val ici_inner1: ici.Inner[Long] = ici.createInner[Long]("Hello", 47L) // ok, but should error + // val ici_inner1: ici.Inner[Long] = ici.createInner[Long]("Hello", 47L) // error val ici_inner2: InnerClassGen[String]#Inner[Long] = ici.createInner[Long]("Hello", 47L) val ici_inner3: InnerClassGen[String]#Inner[Long] = InnerClassGen.createInnerStatic[String, Long]("Hello", 47L) @@ -39,4 +39,4 @@ import lib.RawTypes val cd_ii_Raw: RawTypes#C[?]#D[?] = cd_ii RawTypes.mii_Raw_Raw(cd_ii_Raw) - RawTypes.mii_Raw_Raw2(cd_ii_Raw) // error: dotty is inferring static selection when there is no explicit prefix + RawTypes.mii_Raw_Raw2(cd_ii_Raw) From e8e295afe3bf1d0452ecf0a515346c5986f33da7 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Tue, 20 Feb 2024 18:23:37 +0100 Subject: [PATCH 060/277] also cook the tree of a java raw type --- .../src/dotty/tools/dotc/typer/Typer.scala | 18 ++++++++++-------- .../pipelining/Yjava-tasty-paths/b/Test.scala | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 1800754e6650..165484091260 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -4275,14 +4275,16 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer val tree1 = if ((pt eq AnyTypeConstructorProto) || tp.typeParamSymbols.isEmpty) tree else { - val tp1 = - if (ctx.isJava) - // Cook raw type - AppliedType(tree.tpe, tp.typeParams.map(Function.const(TypeBounds.empty))) - else - // Eta-expand higher-kinded type - tree.tpe.etaExpand(tp.typeParamSymbols) - tree.withType(tp1) + if (ctx.isJava) + // Cook raw type + val typeArgs = tp.typeParams.map(Function.const(TypeBounds.empty)) + val tree1 = AppliedTypeTree(tree, typeArgs.map(TypeTree(_))) + val tp1 = AppliedType(tree.tpe, typeArgs) + tree1.withType(tp1) + else + // Eta-expand higher-kinded type + val tp1 = tree.tpe.etaExpand(tp.typeParamSymbols) + tree.withType(tp1) } if (ctx.mode.is(Mode.Pattern) || ctx.mode.isQuotedPattern || tree1.tpe <:< pt) tree1 else err.typeMismatch(tree1, pt) diff --git a/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala b/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala index 4f555d3b8ac9..084469e76d8b 100644 --- a/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala +++ b/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala @@ -43,7 +43,7 @@ object B { val cd_ii_Raw: RawTypes#C[?]#D[?] = cd_ii RawTypes.mii_Raw_Raw(cd_ii_Raw) - // RawTypes.mii_Raw_Raw2(cd_ii_Raw) // error: dotty still doesnt rewrite the tree of a raw type to a type with wildcards + RawTypes.mii_Raw_Raw2(cd_ii_Raw) } } From 5212897ed9938ee0908c4bdb3048d5f93797233a Mon Sep 17 00:00:00 2001 From: Robert Stoll Date: Wed, 21 Feb 2024 17:11:34 +0100 Subject: [PATCH 061/277] remove implementation from asInstanceOf it only adds to the confusion about asInstanceOf introducing type checks. See https://contributors.scala-lang.org/t/this-trick-enables-overloading-for-opaque-types/6560/17 and https://contributors.scala-lang.org/t/pre-sip-deprecate-asinstanceof-introduce-unsafeasinstanceof/6568 --- docs/_spec/12-the-scala-standard-library.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/_spec/12-the-scala-standard-library.md b/docs/_spec/12-the-scala-standard-library.md index df8626b5119c..40c136085528 100644 --- a/docs/_spec/12-the-scala-standard-library.md +++ b/docs/_spec/12-the-scala-standard-library.md @@ -68,11 +68,7 @@ abstract class Any { def isInstanceOf[a]: Boolean /** Type cast; needs to be inlined to work as given */ */ - def asInstanceOf[A]: A = this match { - case x: A => x - case _ => if (this eq null) this - else throw new ClassCastException() - } + def asInstanceOf[A]: A } /** The root class of all value types */ From be8abfad5eae7cdf37968cf184b4ec3a03d24777 Mon Sep 17 00:00:00 2001 From: Jakub Ciesluk <323892@uwr.edu.pl> Date: Wed, 21 Feb 2024 17:44:38 +0100 Subject: [PATCH 062/277] improvement: Replace synthetic decorations with inlay hints Backports changes from Metals: https://github.com/scalameta/metals/pull/5983 --- ...vider.scala => PcInlayHintsProvider.scala} | 211 +++--- .../tools/pc/ScalaPresentationCompiler.scala | 10 +- .../pc/printer/ShortenedTypePrinter.scala | 2 + .../tools/pc/utils/MtagsEnrichments.scala | 18 + .../tools/pc/base/BaseInlayHintsSuite.scala | 56 ++ .../base/BaseSyntheticDecorationsSuite.scala | 60 -- .../SyntheticDecorationsSuite.scala | 528 -------------- .../SyntheticDecorationsSuite.scala | 667 ++++++++++++++++++ .../dotty/tools/pc/utils/TestInlayHints.scala | 70 ++ project/Build.scala | 2 +- 10 files changed, 932 insertions(+), 692 deletions(-) rename presentation-compiler/src/main/dotty/tools/pc/{PcSyntheticDecorationProvider.scala => PcInlayHintsProvider.scala} (63%) create mode 100644 presentation-compiler/test/dotty/tools/pc/base/BaseInlayHintsSuite.scala delete mode 100644 presentation-compiler/test/dotty/tools/pc/base/BaseSyntheticDecorationsSuite.scala delete mode 100644 presentation-compiler/test/dotty/tools/pc/tests/decorations/SyntheticDecorationsSuite.scala create mode 100644 presentation-compiler/test/dotty/tools/pc/tests/inlayHints/SyntheticDecorationsSuite.scala create mode 100644 presentation-compiler/test/dotty/tools/pc/utils/TestInlayHints.scala diff --git a/presentation-compiler/src/main/dotty/tools/pc/PcSyntheticDecorationProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/PcInlayHintsProvider.scala similarity index 63% rename from presentation-compiler/src/main/dotty/tools/pc/PcSyntheticDecorationProvider.scala rename to presentation-compiler/src/main/dotty/tools/pc/PcInlayHintsProvider.scala index d810ce5b07cc..3a17d30bc024 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/PcSyntheticDecorationProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/PcInlayHintsProvider.scala @@ -6,18 +6,18 @@ import java.nio.file.Paths import scala.meta.internal.metals.ReportContext import dotty.tools.pc.utils.MtagsEnrichments.* import dotty.tools.pc.printer.ShortenedTypePrinter +import scala.meta.internal.pc.InlayHints +import scala.meta.internal.pc.LabelPart +import scala.meta.internal.pc.LabelPart.* +import scala.meta.pc.InlayHintsParams import scala.meta.pc.SymbolSearch -import scala.meta.pc.SyntheticDecoration -import scala.meta.pc.SyntheticDecorationsParams -import scala.meta.internal.pc.DecorationKind -import scala.meta.internal.pc.Decoration - import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.ast.tpd.* import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Flags import dotty.tools.dotc.core.StdNames.* +import dotty.tools.dotc.core.Symbols.* import dotty.tools.dotc.core.Types.* import dotty.tools.dotc.interactive.Interactive import dotty.tools.dotc.interactive.InteractiveDriver @@ -26,9 +26,13 @@ import dotty.tools.dotc.util.SourcePosition import dotty.tools.dotc.util.Spans.Span import dotty.tools.pc.IndexedContext -final class PcSyntheticDecorationsProvider( +import org.eclipse.lsp4j.InlayHint +import org.eclipse.lsp4j.InlayHintKind +import org.eclipse.{lsp4j as l} + +class PcInlayHintsProvider( driver: InteractiveDriver, - params: SyntheticDecorationsParams, + params: InlayHintsParams, symbolSearch: SymbolSearch, )(using ReportContext): @@ -43,75 +47,81 @@ final class PcSyntheticDecorationsProvider( given InferredType.Text = InferredType.Text(text) given ctx: Context = driver.currentCtx val unit = driver.currentCtx.run.nn.units.head + val pos = driver.sourcePosition(params) - def tpdTree = unit.tpdTree + def provide(): List[InlayHint] = + val deepFolder = DeepFolder[InlayHints](collectDecorations) + Interactive + .pathTo(driver.openedTrees(uri), pos)(using driver.currentCtx) + .headOption + .getOrElse(unit.tpdTree) + .enclosedChildren(pos.span) + .flatMap(tpdTree => deepFolder(InlayHints.empty, tpdTree).result()) - def provide(): List[SyntheticDecoration] = - val deepFolder = DeepFolder[Synthetics](collectDecorations) - deepFolder(Synthetics.empty, tpdTree).result() + private def adjustPos(pos: SourcePosition): SourcePosition = + pos.adjust(text)._1 def collectDecorations( - decorations: Synthetics, + inlayHints: InlayHints, tree: Tree, - ): Synthetics = + ): InlayHints = tree match - case ImplicitConversion(name, range) if params.implicitConversions() => - val adjusted = range.adjust(text)._1 - decorations + case ImplicitConversion(symbol, range) if params.implicitConversions() => + val adjusted = adjustPos(range) + inlayHints .add( - Decoration( - adjusted.startPos.toLsp, - name + "(", - DecorationKind.ImplicitConversion, - ) + adjusted.startPos.toLsp, + labelPart(symbol, symbol.decodedName) :: LabelPart("(") :: Nil, + InlayHintKind.Parameter, ) .add( - Decoration( - adjusted.endPos.toLsp, - ")", - DecorationKind.ImplicitConversion, - ) + adjusted.endPos.toLsp, + LabelPart(")") :: Nil, + InlayHintKind.Parameter, ) - case ImplicitParameters(names, pos, allImplicit) + case ImplicitParameters(symbols, pos, allImplicit) if params.implicitParameters() => + val labelParts = symbols.map(s => List(labelPart(s, s.decodedName))) val label = - if allImplicit then names.mkString("(", ", ", ")") - else names.mkString(", ", ", ", "") - decorations.add( - Decoration( - pos.adjust(text)._1.toLsp, - label, - DecorationKind.ImplicitParameter, - ) + if allImplicit then labelParts.separated("(", ", ", ")") + else labelParts.separated(", ") + inlayHints.add( + adjustPos(pos).toLsp, + label, + InlayHintKind.Parameter, + ) + case ValueOf(label, pos) if params.implicitParameters() => + inlayHints.add( + adjustPos(pos).toLsp, + LabelPart("(") :: LabelPart(label) :: List(LabelPart(")")), + InlayHintKind.Parameter, ) case TypeParameters(tpes, pos, sel) if params.typeParameters() && !syntheticTupleApply(sel) => - val label = tpes.map(toLabel(_, pos)).mkString("[", ", ", "]") - decorations.add( - Decoration( - pos.adjust(text)._1.endPos.toLsp, - label, - DecorationKind.TypeParameter, - ) + val label = tpes.map(toLabelParts(_, pos)).separated("[", ", ", "]") + inlayHints.add( + adjustPos(pos).endPos.toLsp, + label, + InlayHintKind.Type, ) - case InferredType(tpe, pos, defTree) if params.inferredTypes() => - val adjustedPos = pos.adjust(text)._1.endPos - if decorations.containsDef(adjustedPos.start) then decorations + case InferredType(tpe, pos, defTree) + if params.inferredTypes() && !isErrorTpe(tpe) => + val adjustedPos = adjustPos(pos).endPos + if inlayHints.containsDef(adjustedPos.start) then inlayHints else - decorations.add( - Decoration( + inlayHints + .add( adjustedPos.toLsp, - ": " + toLabel(tpe, pos), - DecorationKind.InferredType, - ), - adjustedPos.start, - ) - case _ => decorations + LabelPart(": ") :: toLabelParts(tpe, pos), + InlayHintKind.Type, + ) + .addDefinition(adjustedPos.start) + case _ => inlayHints - private def toLabel( + private def toLabelParts( tpe: Type, pos: SourcePosition, - ): String = + ): List[LabelPart] = val tpdPath = Interactive.pathTo(unit.tpdTree, pos.span) @@ -129,13 +139,15 @@ final class PcSyntheticDecorationsProvider( case AppliedType(tycon, args) => isInScope(tycon) && args.forall(isInScope) case _ => true - if isInScope(tpe) - then tpe + if isInScope(tpe) then tpe else tpe.metalsDealias(using indexedCtx.ctx) val dealiased = optDealias(tpe) - printer.tpe(dealiased) - end toLabel + val tpeStr = printer.tpe(dealiased) + val usedRenames = printer.getUsedRenames + val parts = partsFromType(dealiased, usedRenames) + InlayHints.makeLabelParts(parts, tpeStr) + end toLabelParts private val definitions = IndexedContext(ctx).ctx.definitions private def syntheticTupleApply(tree: Tree): Boolean = @@ -152,7 +164,32 @@ final class PcSyntheticDecorationsProvider( case _ => true else false case _ => false -end PcSyntheticDecorationsProvider + + private def labelPart(symbol: Symbol, label: String) = + if symbol.source == pos.source then + LabelPart( + label, + pos = Some(symbol.sourcePos.toLsp.getStart().nn), + ) + else + LabelPart( + label, + symbol = SemanticdbSymbols.symbolName(symbol), + ) + + private def partsFromType( + tpe: Type, + usedRenames: Map[Symbol, String], + ): List[LabelPart] = + NamedPartsAccumulator(_ => true)(Nil, tpe) + .filter(_.symbol != NoSymbol) + .map { t => + val label = usedRenames.get(t.symbol).getOrElse(t.symbol.decodedName) + labelPart(t.symbol, label) + } + + private def isErrorTpe(tpe: Type): Boolean = tpe.isError +end PcInlayHintsProvider object ImplicitConversion: def unapply(tree: Tree)(using Context) = @@ -170,7 +207,7 @@ object ImplicitConversion: val lastArgPos = args.lastOption.map(_.sourcePos).getOrElse(fun.sourcePos) Some( - fun.symbol.decodedName, + fun.symbol, lastArgPos.withStart(fun.sourcePos.start), ) end ImplicitConversion @@ -183,23 +220,29 @@ object ImplicitParameters: val (implicitArgs, providedArgs) = args.partition(isSyntheticArg) val allImplicit = providedArgs.isEmpty val pos = implicitArgs.head.sourcePos - Some(implicitArgs.map(_.symbol.decodedName), pos, allImplicit) + Some(implicitArgs.map(_.symbol), pos, allImplicit) + case _ => None + + private def isSyntheticArg(tree: Tree)(using Context) = tree match + case tree: Ident => + tree.span.isSynthetic && tree.symbol.isOneOf(Flags.GivenOrImplicit) + case _ => false +end ImplicitParameters + +object ValueOf: + def unapply(tree: Tree)(using Context) = + tree match case Apply(ta @ TypeApply(fun, _), _) if fun.span.isSynthetic && isValueOf(fun) => Some( - List("new " + tpnme.valueOf.decoded.capitalize + "(...)"), + "new " + tpnme.valueOf.decoded.capitalize + "(...)", fun.sourcePos, - true, ) case _ => None private def isValueOf(tree: Tree)(using Context) = val symbol = tree.symbol.maybeOwner symbol.name.decoded == tpnme.valueOf.decoded.capitalize - private def isSyntheticArg(tree: Tree)(using Context) = tree match - case tree: Ident => - tree.span.isSynthetic && tree.symbol.isOneOf(Flags.GivenOrImplicit) - case _ => false -end ImplicitParameters +end ValueOf object TypeParameters: def unapply(tree: Tree)(using Context) = @@ -259,35 +302,7 @@ object InferredType: */ def isValDefBind(text: Text, vd: ValDef)(using Context) = val afterDef = text.drop(vd.nameSpan.end) - val index = afterDef.indexAfterSpacesAndComments + val index = indexAfterSpacesAndComments(afterDef) index >= 0 && index < afterDef.size && afterDef(index) == '@' end InferredType - -case class Synthetics( - decorations: List[Decoration], - definitions: Set[Int], -): - def containsDef(offset: Int) = definitions(offset) - def add(decoration: Decoration, offset: Int) = - copy( - decorations = addDecoration(decoration), - definitions = definitions + offset, - ) - def add(decoration: Decoration) = - copy ( - decorations = addDecoration(decoration) - ) - - // If method has both type parameter and implicit parameter, we want the type parameter decoration to be displayed first, - // but it's added second. This method adds the decoration to the right position in the list. - private def addDecoration(decoration: Decoration): List[Decoration] = - val atSamePos = - decorations.takeWhile(_.range.getStart() == decoration.range.getStart()) - (atSamePos :+ decoration) ++ decorations.drop(atSamePos.size) - - def result(): List[Decoration] = decorations.reverse -end Synthetics - -object Synthetics: - def empty: Synthetics = Synthetics(Nil, Set.empty) diff --git a/presentation-compiler/src/main/dotty/tools/pc/ScalaPresentationCompiler.scala b/presentation-compiler/src/main/dotty/tools/pc/ScalaPresentationCompiler.scala index 87b67015f9e4..f3dc8d1658c4 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/ScalaPresentationCompiler.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/ScalaPresentationCompiler.scala @@ -106,15 +106,15 @@ case class ScalaPresentationCompiler( new PcSemanticTokensProvider(driver, params).provide().asJava } - override def syntheticDecorations( - params: SyntheticDecorationsParams - ): ju.concurrent.CompletableFuture[ju.List[SyntheticDecoration]] = + override def inlayHints( + params: InlayHintsParams + ): ju.concurrent.CompletableFuture[ju.List[l.InlayHint]] = compilerAccess.withInterruptableCompiler(Some(params))( - new ju.ArrayList[SyntheticDecoration](), + new ju.ArrayList[l.InlayHint](), params.token(), ) { access => val driver = access.compiler() - new PcSyntheticDecorationsProvider(driver, params, search) + new PcInlayHintsProvider(driver, params, search) .provide() .asJava } diff --git a/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala b/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala index 3b763523f9e6..ed37e133372b 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala @@ -66,6 +66,8 @@ class ShortenedTypePrinter( private val foundRenames = collection.mutable.LinkedHashMap.empty[Symbol, String] + def getUsedRenames: Map[Symbol, String] = foundRenames.toMap + def getUsedRenamesInfo(using Context): List[String] = foundRenames.map { (from, to) => s"type $to = ${from.showName}" diff --git a/presentation-compiler/src/main/dotty/tools/pc/utils/MtagsEnrichments.scala b/presentation-compiler/src/main/dotty/tools/pc/utils/MtagsEnrichments.scala index d6c8c10f8030..e4385392973f 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/utils/MtagsEnrichments.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/utils/MtagsEnrichments.scala @@ -316,6 +316,24 @@ object MtagsEnrichments extends CommonMtagsEnrichments: .map(source.apply) .contains('.') case _ => false + + def children(using Context): List[Tree] = + val collector = new TreeAccumulator[List[Tree]]: + def apply(x: List[Tree], tree: Tree)(using Context): List[Tree] = + tree :: x + collector + .foldOver(Nil, tree) + .reverse + + /** + * Returns the children of the tree that overlap with the given span. + */ + def enclosedChildren(span: Span)(using Context): List[Tree] = + tree.children + .filter(tree => + tree.sourcePos.exists && tree.span.start <= span.end && tree.span.end >= span.start + ) + end enclosedChildren end extension extension (imp: Import) diff --git a/presentation-compiler/test/dotty/tools/pc/base/BaseInlayHintsSuite.scala b/presentation-compiler/test/dotty/tools/pc/base/BaseInlayHintsSuite.scala new file mode 100644 index 000000000000..94b00ca82aea --- /dev/null +++ b/presentation-compiler/test/dotty/tools/pc/base/BaseInlayHintsSuite.scala @@ -0,0 +1,56 @@ +package dotty.tools.pc.base + +import java.net.URI + +import scala.meta.internal.jdk.CollectionConverters._ +import scala.meta.internal.metals.CompilerInlayHintsParams +import scala.meta.internal.metals.CompilerRangeParams +import scala.language.unsafeNulls + +import dotty.tools.pc.utils.TestInlayHints +import dotty.tools.pc.utils.TextEdits + +import org.eclipse.lsp4j.TextEdit + +class BaseInlayHintsSuite extends BasePCSuite { + + def check( + base: String, + expected: String, + kind: Option[Int] = None, + ): Unit = + def pkgWrap(text: String) = + if (text.contains("package")) text + else s"package test\n$text" + + val withPkg = pkgWrap(base) + val rangeParams = CompilerRangeParams( + URI.create("file:/InlayHints.scala"), + withPkg, + 0, + withPkg.length() + ) + val pcParams = CompilerInlayHintsParams( + rangeParams, + true, + true, + true, + true + ) + + val inlayHints = presentationCompiler + .inlayHints( + pcParams + ) + .get() + .asScala + .toList + + val obtained = TestInlayHints.applyInlayHints(withPkg, inlayHints) + + assertNoDiff( + obtained, + pkgWrap(expected) + ) + +} \ No newline at end of file diff --git a/presentation-compiler/test/dotty/tools/pc/base/BaseSyntheticDecorationsSuite.scala b/presentation-compiler/test/dotty/tools/pc/base/BaseSyntheticDecorationsSuite.scala deleted file mode 100644 index 450a42f26153..000000000000 --- a/presentation-compiler/test/dotty/tools/pc/base/BaseSyntheticDecorationsSuite.scala +++ /dev/null @@ -1,60 +0,0 @@ -package dotty.tools.pc.base - -import java.net.URI - -import scala.meta.internal.jdk.CollectionConverters._ -import scala.meta.internal.metals.CompilerSyntheticDecorationsParams -import scala.meta.internal.metals.CompilerVirtualFileParams -import scala.language.unsafeNulls - -import dotty.tools.pc.utils.TextEdits - -import org.eclipse.lsp4j.TextEdit - -class BaseSyntheticDecorationsSuite extends BasePCSuite { - - def check( - base: String, - expected: String, - kind: Option[Int] = None, - ): Unit = - def pkgWrap(text: String) = - if (text.contains("package")) text - else s"package test\n$text" - - val withPkg = pkgWrap(base) - val vFile = CompilerVirtualFileParams( - URI.create("file:/Decorations.scala"), - withPkg, - ) - - val pcParams = CompilerSyntheticDecorationsParams( - vFile, - true, - true, - true, - true, - ) - - val allDecorations = presentationCompiler - .syntheticDecorations( - pcParams - ) - .get() - .asScala - .toList - - val decorations = kind match { - case Some(k) => allDecorations.filter(_.kind == k) - case _ => allDecorations - } - - val edits = decorations.map(d => new TextEdit(d.range(), d.label())) - val obtained = TextEdits.applyEdits(withPkg, edits) - - assertNoDiff( - obtained, - pkgWrap(expected), - ) - -} \ No newline at end of file diff --git a/presentation-compiler/test/dotty/tools/pc/tests/decorations/SyntheticDecorationsSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/decorations/SyntheticDecorationsSuite.scala deleted file mode 100644 index 49ffb911aaa3..000000000000 --- a/presentation-compiler/test/dotty/tools/pc/tests/decorations/SyntheticDecorationsSuite.scala +++ /dev/null @@ -1,528 +0,0 @@ -package dotty.tools.pc.tests.decorations - -import scala.meta.internal.pc.DecorationKind - -import dotty.tools.pc.base.BaseSyntheticDecorationsSuite - -import org.junit.Test - -class SyntheticDecorationsSuite extends BaseSyntheticDecorationsSuite: - - @Test def `type-params` = - check( - """|object Main { - | def hello[T](t: T) = t - | val x = hello(List(1)) - |} - |""".stripMargin, - """|object Main { - | def hello[T](t: T) = t - | val x = hello[List[Int]](List[Int](1)) - |} - |""".stripMargin, - kind = Some(DecorationKind.TypeParameter) - ) - - @Test def `type-params2` = - check( - """|object Main { - | def hello[T](t: T) = t - | val x = hello(Map((1,"abc"))) - |} - |""".stripMargin, - """|object Main { - | def hello[T](t: T) = t - | val x = hello[Map[Int, String]](Map[Int, String]((1,"abc"))) - |} - |""".stripMargin, - kind = Some(DecorationKind.TypeParameter) - ) - - @Test def `implicit-param` = - check( - """|case class User(name: String) - |object Main { - | implicit val imp: Int = 2 - | def addOne(x: Int)(implicit one: Int) = x + one - | val x = addOne(1) - |} - |""".stripMargin, - """|case class User(name: String) - |object Main { - | implicit val imp: Int = 2 - | def addOne(x: Int)(implicit one: Int) = x + one - | val x = addOne(1)(imp) - |} - |""".stripMargin, - kind = Some(DecorationKind.ImplicitParameter) - ) - - @Test def `implicit-conversion` = - check( - """|case class User(name: String) - |object Main { - | implicit def intToUser(x: Int): User = new User(x.toString) - | val y: User = 1 - |} - |""".stripMargin, - """|case class User(name: String) - |object Main { - | implicit def intToUser(x: Int): User = new User(x.toString) - | val y: User = intToUser(1) - |} - |""".stripMargin, - kind = Some(DecorationKind.ImplicitConversion) - ) - - @Test def `using-param` = - check( - """|case class User(name: String) - |object Main { - | implicit val imp: Int = 2 - | def addOne(x: Int)(using one: Int) = x + one - | val x = addOne(1) - |} - |""".stripMargin, - """|case class User(name: String) - |object Main { - | implicit val imp: Int = 2 - | def addOne(x: Int)(using one: Int) = x + one - | val x = addOne(1)(imp) - |} - |""".stripMargin, - kind = Some(DecorationKind.ImplicitParameter) - ) - - @Test def `given-conversion` = - check( - """|case class User(name: String) - |object Main { - | given intToUser: Conversion[Int, User] = User(_.toString) - | val y: User = 1 - |} - |""".stripMargin, - """|case class User(name: String) - |object Main { - | given intToUser: Conversion[Int, User] = User(_.toString) - | val y: User = intToUser(1) - |} - |""".stripMargin, - kind = Some(DecorationKind.ImplicitConversion) - ) - - @Test def `given-conversion2` = - check( - """|trait Xg: - | def doX: Int - |trait Yg: - | def doY: String - |given (using Xg): Yg with - | def doY = "7" - |""".stripMargin, - """|trait Xg: - | def doX: Int - |trait Yg: - | def doY: String - |given (using Xg): Yg with - | def doY: String = "7" - |""".stripMargin - ) - - @Test def `basic` = - check( - """|object Main { - | val foo = 123 - |} - |""".stripMargin, - """|object Main { - | val foo: Int = 123 - |} - |""".stripMargin - ) - - @Test def `list` = - check( - """|object Main { - | val foo = List[Int](123) - |} - |""".stripMargin, - """|object Main { - | val foo: List[Int] = List[Int](123) - |} - |""".stripMargin - ) - - @Test def `list2` = - check( - """|object O { - | def m = 1 :: List(1) - |} - |""".stripMargin, - """|object O { - | def m: List[Int] = 1 ::[Int] List[Int](1) - |} - |""".stripMargin - ) - - @Test def `two-param` = - check( - """|object Main { - | val foo = Map((1, "abc")) - |} - |""".stripMargin, - """|object Main { - | val foo: Map[Int, String] = Map[Int, String]((1, "abc")) - |} - |""".stripMargin - ) - - @Test def `tuple` = - check( - """|object Main { - | val foo = (123, 456) - |} - |""".stripMargin, - """|object Main { - | val foo: (Int, Int) = (123, 456) - |} - |""".stripMargin - ) - - @Test def `import-needed` = - check( - """|object Main { - | val foo = List[String]("").toBuffer[String] - |} - |""".stripMargin, - """|object Main { - | val foo: Buffer[String] = List[String]("").toBuffer[String] - |} - |""".stripMargin - ) - - @Test def `lambda-type` = - check( - """|object Main { - | val foo = () => 123 - |} - |""".stripMargin, - """|object Main { - | val foo: () => Int = () => 123 - |} - |""".stripMargin - ) - - @Test def `block` = - check( - """|object Main { - | val foo = { val z = 123; z + 2} - |} - |""".stripMargin, - """|object Main { - | val foo: Int = { val z: Int = 123; z + 2} - |} - |""".stripMargin - ) - - @Test def `refined-types` = - check( - """|object O{ - | trait Foo { - | type T - | type G - | } - | - | val c = new Foo { type T = Int; type G = Long} - |} - |""".stripMargin, - """|object O{ - | trait Foo { - | type T - | type G - | } - | - | val c: Foo{type T = Int; type G = Long} = new Foo { type T = Int; type G = Long} - |} - |""".stripMargin - ) - - @Test def `refined-types1` = - check( - """|object O{ - | trait Foo { - | type T - | } - | val c = new Foo { type T = Int } - | val d = c - |} - |""".stripMargin, - """|object O{ - | trait Foo { - | type T - | } - | val c: Foo{type T = Int} = new Foo { type T = Int } - | val d: Foo{type T = Int} = c - |} - |""".stripMargin - ) - - @Test def `refined-types4` = - check( - """|trait Foo extends Selectable { - | type T - |} - | - |val c = new Foo { - | type T = Int - | val x = 0 - | def y = 0 - | var z = 0 - |} - |""".stripMargin, - """|trait Foo extends Selectable { - | type T - |} - | - |val c: Foo{type T = Int; val x: Int; def y: Int; val z: Int; def z_=(x$1: Int): Unit} = new Foo { - | type T = Int - | val x: Int = 0 - | def y: Int = 0 - | var z: Int = 0 - |} - |""".stripMargin - ) - - @Test def `dealias` = - check( - """|class Foo() { - | type T = Int - | def getT: T = 1 - |} - | - |object O { - | val c = new Foo().getT - |} - |""".stripMargin, - """|class Foo() { - | type T = Int - | def getT: T = 1 - |} - | - |object O { - | val c: Int = new Foo().getT - |} - |""".stripMargin - ) - - @Test def `dealias2` = - check( - """|object Foo { - | type T = Int - | def getT: T = 1 - | val c = getT - |} - |""".stripMargin, - """|object Foo { - | type T = Int - | def getT: T = 1 - | val c: T = getT - |} - |""".stripMargin - ) - - @Test def `dealias3` = - check( - """|object Foo: - | opaque type T = Int - | def getT: T = 1 - |val c = Foo.getT - |""".stripMargin, - """|object Foo: - | opaque type T = Int - | def getT: T = 1 - |val c: T = Foo.getT - |""".stripMargin - ) - - @Test def `dealias4` = - check( - """|object O: - | type M = Int - | type W = M => Int - | def get: W = ??? - | - |val m = O.get - |""".stripMargin, - """|object O: - | type M = Int - | type W = M => Int - | def get: W = ??? - | - |val m: Int => Int = O.get - |""".stripMargin - ) - - @Test def `dealias5` = - check( - """|object O: - | opaque type M = Int - | type W = M => Int - | def get: W = ??? - | - |val m = O.get - |""".stripMargin, - """|object O: - | opaque type M = Int - | type W = M => Int - | def get: W = ??? - | - |val m: M => Int = O.get - |""".stripMargin - ) - - @Test def `explicit-tuple` = - check( - """|object Main { - | val x = Tuple2.apply(1, 2) - |} - |""".stripMargin, - """|object Main { - | val x: (Int, Int) = Tuple2.apply[Int, Int](1, 2) - |} - |""".stripMargin - ) - - @Test def `explicit-tuple1` = - check( - """|object Main { - | val x = Tuple2(1, 2) - |} - |""".stripMargin, - """|object Main { - | val x: (Int, Int) = Tuple2[Int, Int](1, 2) - |} - |""".stripMargin - ) - - @Test def `tuple-unapply` = - check( - """|object Main { - | val (fst, snd) = (1, 2) - |} - |""".stripMargin, - """|object Main { - | val (fst: Int, snd: Int) = (1, 2) - |} - |""".stripMargin - ) - - @Test def `list-unapply` = - check( - """|object Main { - | val hd :: tail = List(1, 2) - |} - |""".stripMargin, - """|object Main { - | val hd: Int ::[Int] tail: List[Int] = List[Int](1, 2) - |} - |""".stripMargin - ) - - @Test def `list-match` = - check( - """|object Main { - | val x = List(1, 2) match { - | case hd :: tail => hd - | } - |} - |""".stripMargin, - """|object Main { - | val x: Int = List[Int](1, 2) match { - | case hd: Int ::[Int] tail: List[Int] => hd - | } - |} - |""".stripMargin - ) - - @Test def `case-class-unapply` = - check( - """|object Main { - |case class Foo[A](x: A, y: A) - | val Foo(fst, snd) = Foo(1, 2) - |} - |""".stripMargin, - """|object Main { - |case class Foo[A](x: A, y: A) - | val Foo[Int](fst: Int, snd: Int) = Foo[Int](1, 2) - |} - |""".stripMargin - ) - - @Test def `valueOf` = - check( - """|object O { - | def foo[Total <: Int](implicit total: ValueOf[Total]): Int = total.value - | val m = foo[500] - |} - |""".stripMargin, - """|object O { - | def foo[Total <: Int](implicit total: ValueOf[Total]): Int = total.value - | val m: Int = foo[500](new ValueOf(...)) - |} - |""".stripMargin - ) - - @Test def `case-class1` = - check( - """|object O { - |case class A(x: Int, g: Int)(implicit y: String) - |} - |""".stripMargin, - """|object O { - |case class A(x: Int, g: Int)(implicit y: String) - |} - |""".stripMargin - ) - - @Test def `ord` = - check( - """ - |object Main { - | val ordered = "acb".sorted - |} - |""".stripMargin, - """ - |object Main { - | val ordered: String = augmentString("acb").sorted[Char](Char) - |} - |""".stripMargin - ) - - @Test def `val-def-with-bind` = - check( - """ - |object O { - | val tupleBound @ (one, two) = ("1", "2") - |} - |""".stripMargin, - """ - |object O { - | val tupleBound @ (one: String, two: String) = ("1", "2") - |} - |""".stripMargin - ) - - @Test def `val-def-with-bind-and-comment` = - check( - """ - |object O { - | val tupleBound /* comment */ @ (one, two) = ("1", "2") - |} - |""".stripMargin, - """ - |object O { - | val tupleBound /* comment */ @ (one: String, two: String) = ("1", "2") - |} - |""".stripMargin - ) - diff --git a/presentation-compiler/test/dotty/tools/pc/tests/inlayHints/SyntheticDecorationsSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/inlayHints/SyntheticDecorationsSuite.scala new file mode 100644 index 000000000000..0e32e5cf0682 --- /dev/null +++ b/presentation-compiler/test/dotty/tools/pc/tests/inlayHints/SyntheticDecorationsSuite.scala @@ -0,0 +1,667 @@ +package dotty.tools.pc.tests.inlayHints + +import dotty.tools.pc.base.BaseInlayHintsSuite + +import org.junit.Test +class InlayHintsSuite extends BaseInlayHintsSuite { + + @Test def `local` = + check( + """|object Main { + | def foo() = { + | implicit val imp: Int = 2 + | def addOne(x: Int)(implicit one: Int) = x + one + | val x = addOne(1) + | } + |} + |""".stripMargin, + """|object Main { + | def foo()/*: Unit<>*/ = { + | implicit val imp: Int = 2 + | def addOne(x: Int)(implicit one: Int)/*: Int<>*/ = x + one + | val x/*: Int<>*/ = addOne(1)/*(imp<<(3:17)>>)*/ + | } + |} + |""".stripMargin + ) + + @Test def `type-params` = + check( + """|object Main { + | def hello[T](t: T) = t + | val x = hello(List(1)) + |} + |""".stripMargin, + """|object Main { + | def hello[T](t: T)/*: T<<(2:12)>>*/ = t + | val x/*: List<>[Int<>]*/ = hello/*[List<>[Int<>]]*/(List/*[Int<>]*/(1)) + |} + |""".stripMargin + ) + + @Test def `type-params2` = + check( + """|object Main { + | def hello[T](t: T) = t + | val x = hello(Map((1,"abc"))) + |} + |""".stripMargin, + """|object Main { + | def hello[T](t: T)/*: T<<(2:12)>>*/ = t + | val x/*: Map<>[Int<>, String<>]*/ = hello/*[Map<>[Int<>, String<>]]*/(Map/*[Int<>, String<>]*/((1,"abc"))) + |} + |""".stripMargin, + ) + + @Test def `implicit-param` = + check( + """|case class User(name: String) + |object Main { + | implicit val imp: Int = 2 + | def addOne(x: Int)(implicit one: Int) = x + one + | val x = addOne(1) + |} + |""".stripMargin, + """|case class User(name: String) + |object Main { + | implicit val imp: Int = 2 + | def addOne(x: Int)(implicit one: Int)/*: Int<>*/ = x + one + | val x/*: Int<>*/ = addOne(1)/*(imp<<(3:15)>>)*/ + |} + |""".stripMargin + ) + + @Test def `implicit-conversion` = + check( + """|case class User(name: String) + |object Main { + | implicit def intToUser(x: Int): User = new User(x.toString) + | val y: User = 1 + |} + |""".stripMargin, + """|case class User(name: String) + |object Main { + | implicit def intToUser(x: Int): User = new User(x.toString) + | val y: User = /*intToUser<<(3:15)>>(*/1/*)*/ + |} + |""".stripMargin + ) + + @Test def `using-param` = + check( + """|case class User(name: String) + |object Main { + | implicit val imp: Int = 2 + | def addOne(x: Int)(using one: Int) = x + one + | val x = addOne(1) + |} + |""".stripMargin, + """|case class User(name: String) + |object Main { + | implicit val imp: Int = 2 + | def addOne(x: Int)(using one: Int)/*: Int<>*/ = x + one + | val x/*: Int<>*/ = addOne(1)/*(imp<<(3:15)>>)*/ + |} + |""".stripMargin + ) + + @Test def `given-conversion` = + check( + """|case class User(name: String) + |object Main { + | given intToUser: Conversion[Int, User] = User(_.toString) + | val y: User = 1 + |} + |""".stripMargin, + """|case class User(name: String) + |object Main { + | given intToUser: Conversion[Int, User] = User(_.toString) + | val y: User = /*intToUser<<(3:8)>>(*/1/*)*/ + |} + |""".stripMargin + ) + + @Test def `given-conversion2` = + check( + """|trait Xg: + | def doX: Int + |trait Yg: + | def doY: String + |given (using Xg): Yg with + | def doY = "7" + |""".stripMargin, + """|trait Xg: + | def doX: Int + |trait Yg: + | def doY: String + |given (using Xg): Yg with + | def doY/*: String<>*/ = "7" + |""".stripMargin + ) + + @Test def `basic` = + check( + """|object Main { + | val foo = 123 + |} + |""".stripMargin, + """|object Main { + | val foo/*: Int<>*/ = 123 + |} + |""".stripMargin + ) + + @Test def `list` = + check( + """|object Main { + | val foo = List[Int](123) + |} + |""".stripMargin, + """|object Main { + | val foo/*: List<>[Int<>]*/ = List[Int](123) + |} + |""".stripMargin + ) + + @Test def `list2` = + check( + """|object O { + | def m = 1 :: List(1) + |} + |""".stripMargin, + """|object O { + | def m/*: List<>[Int<>]*/ = 1 ::/*[Int<>]*/ List/*[Int<>]*/(1) + |} + |""".stripMargin + ) + + @Test def `two-param` = + check( + """|object Main { + | val foo = Map((1, "abc")) + |} + |""".stripMargin, + """|object Main { + | val foo/*: Map<>[Int<>, String<>]*/ = Map/*[Int<>, String<>]*/((1, "abc")) + |} + |""".stripMargin, + ) + + @Test def `tuple` = + check( + """|object Main { + | val foo = (123, 456) + |} + |""".stripMargin, + """|object Main { + | val foo/*: (Int<>, Int<>)*/ = (123, 456) + |} + |""".stripMargin + ) + + @Test def `import-needed` = + check( + """|object Main { + | val foo = List[String]("").toBuffer[String] + |} + |""".stripMargin, + """|object Main { + | val foo/*: Buffer<>[String<>]*/ = List[String]("").toBuffer[String] + |} + |""".stripMargin, + ) + + @Test def `lambda-type` = + check( + """|object Main { + | val foo = () => 123 + |} + |""".stripMargin, + """|object Main { + | val foo/*: () => Int<>*/ = () => 123 + |} + |""".stripMargin + ) + + @Test def `block` = + check( + """|object Main { + | val foo = { val z = 123; z + 2} + |} + |""".stripMargin, + """|object Main { + | val foo/*: Int<>*/ = { val z/*: Int<>*/ = 123; z + 2} + |} + |""".stripMargin + ) + + @Test def `refined-types` = + check( + """|object O{ + | trait Foo { + | type T + | type G + | } + | + | val c = new Foo { type T = Int; type G = Long} + |} + |""".stripMargin, + """|object O{ + | trait Foo { + | type T + | type G + | } + | + | val c/*: Foo<<(2:8)>>{type T = Int<>; type G = Long<>}*/ = new Foo { type T = Int; type G = Long} + |} + |""".stripMargin + ) + + @Test def `refined-types2` = + check( + """|object O{ + | trait Foo { + | type T + | } + | val c = new Foo { type T = Int } + | val d = c + |} + |""".stripMargin, + """|object O{ + | trait Foo { + | type T + | } + | val c/*: Foo<<(2:8)>>{type T = Int<>}*/ = new Foo { type T = Int } + | val d/*: Foo<<(2:8)>>{type T = Int<>}*/ = c + |} + |""".stripMargin + ) + + @Test def `refined-types3` = + check( + """|trait Foo extends Selectable { + | type T + |} + | + |val c = new Foo { + | type T = Int + | val x = 0 + | def y = 0 + | var z = 0 + |} + |""".stripMargin, + """|trait Foo extends Selectable { + | type T + |} + | + |val c/*: Foo<<(1:6)>>{type T = Int<>; val x: Int<>; def y: Int<>; val z: Int<>; def z_=(x$1: Int<>): Unit<>}*/ = new Foo { + | type T = Int + | val x/*: Int<>*/ = 0 + | def y/*: Int<>*/ = 0 + | var z/*: Int<>*/ = 0 + |} + |""".stripMargin + ) + + @Test def `dealias` = + check( + """|class Foo() { + | type T = Int + | def getT: T = 1 + |} + | + |object O { + | val c = new Foo().getT + |} + |""".stripMargin, + """|class Foo() { + | type T = Int + | def getT: T = 1 + |} + | + |object O { + | val c/*: Int<>*/ = new Foo().getT + |} + |""".stripMargin + ) + + @Test def `dealias2` = + check( + """|object Foo { + | type T = Int + | def getT: T = 1 + | val c = getT + |} + |""".stripMargin, + """|object Foo { + | type T = Int + | def getT: T = 1 + | val c/*: T<<(2:7)>>*/ = getT + |} + |""".stripMargin + ) + + @Test def `dealias3` = + check( + """|object Foo: + | opaque type T = Int + | def getT: T = 1 + |val c = Foo.getT + |""".stripMargin, + """|object Foo: + | opaque type T = Int + | def getT: T = 1 + |val c/*: T<<(2:14)>>*/ = Foo.getT + |""".stripMargin + ) + + @Test def `dealias4` = + check( + """|object O: + | type M = Int + | type W = M => Int + | def get: W = ??? + | + |val m = O.get + |""".stripMargin, + """|object O: + | type M = Int + | type W = M => Int + | def get: W = ??? + | + |val m/*: Int<> => Int<>*/ = O.get + |""".stripMargin + ) + + @Test def `dealias5` = + check( + """|object O: + | opaque type M = Int + | type W = M => Int + | def get: W = ??? + | + |val m = O.get + |""".stripMargin, + """|object O: + | opaque type M = Int + | type W = M => Int + | def get: W = ??? + | + |val m/*: M<<(2:13)>> => Int<>*/ = O.get + |""".stripMargin + ) + + @Test def `explicit-tuple` = + check( + """|object Main { + | val x = Tuple2.apply(1, 2) + |} + |""".stripMargin, + """|object Main { + | val x/*: (Int<>, Int<>)*/ = Tuple2.apply/*[Int<>, Int<>]*/(1, 2) + |} + |""".stripMargin + ) + + @Test def `explicit-tuple1` = + check( + """|object Main { + | val x = Tuple2(1, 2) + |} + |""".stripMargin, + """|object Main { + | val x/*: (Int<>, Int<>)*/ = Tuple2/*[Int<>, Int<>]*/(1, 2) + |} + |""".stripMargin + ) + + @Test def `tuple-unapply` = + check( + """|object Main { + | val (fst, snd) = (1, 2) + |} + |""".stripMargin, + """|object Main { + | val (fst/*: Int<>*/, snd/*: Int<>*/) = (1, 2) + |} + |""".stripMargin + ) + + @Test def `list-unapply` = + check( + """|object Main { + | val hd :: tail = List(1, 2) + |} + |""".stripMargin, + """|object Main { + | val hd/*: Int<>*/ ::/*[Int<>]*/ tail/*: List<>[Int<>]*/ = List/*[Int<>]*/(1, 2) + |} + |""".stripMargin, + ) + + @Test def `list-match` = + check( + """|object Main { + | val x = List(1, 2) match { + | case hd :: tail => hd + | } + |} + |""".stripMargin, + """|object Main { + | val x/*: Int<>*/ = List/*[Int<>]*/(1, 2) match { + | case hd/*: Int<>*/ ::/*[Int<>]*/ tail/*: List<>[Int<>]*/ => hd + | } + |} + |""".stripMargin, + ) + + @Test def `case-class-unapply` = + check( + """|object Main { + |case class Foo[A](x: A, y: A) + | val Foo(fst, snd) = Foo(1, 2) + |} + |""".stripMargin, + """|object Main { + |case class Foo[A](x: A, y: A) + | val Foo/*[Int<>]*/(fst/*: Int<>*/, snd/*: Int<>*/) = Foo/*[Int<>]*/(1, 2) + |} + |""".stripMargin, + ) + + @Test def `valueOf` = + check( + """|object O { + | def foo[Total <: Int](implicit total: ValueOf[Total]): Int = total.value + | val m = foo[500] + |} + |""".stripMargin, + """|object O { + | def foo[Total <: Int](implicit total: ValueOf[Total]): Int = total.value + | val m/*: Int<>*/ = foo[500]/*(new ValueOf(...))*/ + |} + |""".stripMargin + ) + + @Test def `case-class1` = + check( + """|object O { + |case class A(x: Int, g: Int)(implicit y: String) + |} + |""".stripMargin, + """|object O { + |case class A(x: Int, g: Int)(implicit y: String) + |} + |""".stripMargin + ) + + @Test def `ord` = + check( + """|object Main { + | val ordered = "acb".sorted + |} + |""".stripMargin, + """|object Main { + | val ordered/*: String<>*/ = /*augmentString<>(*/"acb"/*)*/.sorted/*[Char<>]*//*(Char<>)*/ + |} + |""".stripMargin + ) + + @Test def `partial-fun` = + check( + """|object Main { + | List(1).collect { case x => x } + | val x: PartialFunction[Int, Int] = { + | case 1 => 2 + | } + |} + |""".stripMargin, + """|object Main { + | List/*[Int<>]*/(1).collect/*[Int<>]*/ { case x/*: Int<>*/ => x } + | val x: PartialFunction[Int, Int] = { + | case 1 => 2 + | } + |} + |""".stripMargin + ) + + @Test def `val-def-with-bind` = + check( + """|object O { + | val tupleBound @ (one, two) = ("1", "2") + |} + |""".stripMargin, + """|object O { + | val tupleBound @ (one/*: String<>*/, two/*: String<>*/) = ("1", "2") + |} + |""".stripMargin + ) + + @Test def `val-def-with-bind-and-comment` = + check( + """|object O { + | val tupleBound /* comment */ @ (one, two) = ("1", "2") + |} + |""".stripMargin, + """|object O { + | val tupleBound /* comment */ @ (one/*: String<>*/, two/*: String<>*/) = ("1", "2") + |} + |""".stripMargin + ) + + @Test def `complex` = + check( + """|object ScalatestMock { + | class SRF + | implicit val subjectRegistrationFunction: SRF = new SRF() + | class Position + | implicit val here: Position = new Position() + | implicit class StringTestOps(name: String) { + | def should(right: => Unit)(implicit config: SRF): Unit = () + | def in(f: => Unit)(implicit pos: Position): Unit = () + | } + | implicit def instancesString: Eq[String] with Semigroup[String] = ??? + |} + | + |trait Eq[A] + |trait Semigroup[A] + | + |class DemoSpec { + | import ScalatestMock._ + | + | "foo" should { + | "checkThing1" in { + | checkThing1[String] + | } + | "checkThing2" in { + | checkThing2[String] + | } + | } + | + | "bar" should { + | "checkThing1" in { + | checkThing1[String] + | } + | } + | + | def checkThing1[A](implicit ev: Eq[A]) = ??? + | def checkThing2[A](implicit ev: Eq[A], sem: Semigroup[A]) = ??? + |} + |""".stripMargin, + """|object ScalatestMock { + | class SRF + | implicit val subjectRegistrationFunction: SRF = new SRF() + | class Position + | implicit val here: Position = new Position() + | implicit class StringTestOps(name: String) { + | def should(right: => Unit)(implicit config: SRF): Unit = () + | def in(f: => Unit)(implicit pos: Position): Unit = () + | } + | implicit def instancesString: Eq[String] with Semigroup[String] = ??? + |} + | + |trait Eq[A] + |trait Semigroup[A] + | + |class DemoSpec { + | import ScalatestMock._ + | + | /*StringTestOps<<(6:17)>>(*/"foo"/*)*/ should { + | /*StringTestOps<<(6:17)>>(*/"checkThing1"/*)*/ in { + | checkThing1[String]/*(instancesString<<(10:15)>>)*/ + | }/*(here<<(5:15)>>)*/ + | /*StringTestOps<<(6:17)>>(*/"checkThing2"/*)*/ in { + | checkThing2[String]/*(instancesString<<(10:15)>>, instancesString<<(10:15)>>)*/ + | }/*(here<<(5:15)>>)*/ + | }/*(subjectRegistrationFunction<<(3:15)>>)*/ + | + | /*StringTestOps<<(6:17)>>(*/"bar"/*)*/ should { + | /*StringTestOps<<(6:17)>>(*/"checkThing1"/*)*/ in { + | checkThing1[String]/*(instancesString<<(10:15)>>)*/ + | }/*(here<<(5:15)>>)*/ + | }/*(subjectRegistrationFunction<<(3:15)>>)*/ + | + | def checkThing1[A](implicit ev: Eq[A])/*: Nothing<>*/ = ??? + | def checkThing2[A](implicit ev: Eq[A], sem: Semigroup[A])/*: Nothing<>*/ = ??? + |} + |""".stripMargin + ) + + @Test def `import-rename` = + check( + """|import scala.collection.{AbstractMap => AB} + |import scala.collection.{Set => S} + | + |object Main { + | def test(d: S[Int], f: S[Char]): AB[Int, String] = { + | val x = d.map(_.toString) + | val y = f + | ??? + | } + | val x = test(Set(1), Set('a')) + |} + |""".stripMargin, + """|import scala.collection.{AbstractMap => AB} + |import scala.collection.{Set => S} + | + |object Main { + | def test(d: S[Int], f: S[Char]): AB[Int, String] = { + | val x/*: S<>[String<>]*/ = d.map/*[String<>]*/(_.toString) + | val y/*: S<>[Char<>]*/ = f + | ??? + | } + | val x/*: AB<>[Int<>, String<>]*/ = test(Set/*[Int<>]*/(1), Set/*[Char<>]*/('a')) + |} + |""".stripMargin, + ) + + @Test def `error-symbol` = + check( + """|package example + |case class ErrorMessage(error) + |""".stripMargin, + """|package example + |case class ErrorMessage(error) + |""".stripMargin + ) +} \ No newline at end of file diff --git a/presentation-compiler/test/dotty/tools/pc/utils/TestInlayHints.scala b/presentation-compiler/test/dotty/tools/pc/utils/TestInlayHints.scala new file mode 100644 index 000000000000..98ebb0852735 --- /dev/null +++ b/presentation-compiler/test/dotty/tools/pc/utils/TestInlayHints.scala @@ -0,0 +1,70 @@ +package dotty.tools.pc.utils + +import scala.collection.mutable.ListBuffer + +import scala.meta.internal.jdk.CollectionConverters._ +import dotty.tools.pc.utils.MtagsEnrichments.* +import dotty.tools.pc.utils.TextEdits + +import org.eclipse.lsp4j.InlayHint +import org.eclipse.lsp4j.TextEdit +import org.eclipse.{lsp4j => l} + +object TestInlayHints { + + // For not local symbols - semanticdb symbol + // val x = 123 + // | + // v + // val x<<: Int/*scala/predef/Int#*/>> = 123 + // For local symbols - definition position in source + // type T = Int + // val x: T = ??? + // val y = x + // | + // v + // val y<<: T/*(0:5,0:5)*/>> = x + def decorationString(inlayHint: InlayHint): String = { + val buffer = ListBuffer.empty[String] + + val labels = inlayHint.getLabel().nn.asScala match { + case Left(label) => List(label) + case Right(labelParts) => labelParts.asScala.map(_.getValue()).toList + } + val data = + inlayHint.getData().asInstanceOf[Array[Any]] + buffer += "/*" + labels.zip(data).foreach { case (label, data) => + buffer += label.nn + buffer ++= readData(data) + } + buffer += "*/" + buffer.toList.mkString + } + + private def readData(data: Any): List[String] = { + data match { + case data: String if data.isEmpty => Nil + case data: String => List("<<", data, ">>") + case data: l.Position => + val str = s"(${data.getLine()}:${data.getCharacter()})" + List("<<", str, ">>") + } + } + + def applyInlayHints(text: String, inlayHints: List[InlayHint]): String = { + val textEdits = inlayHints.map { hint => + val newText = decorationString(hint) + val range = new l.Range(hint.getPosition(), hint.getPosition()) + new TextEdit( + range, + newText + ) + } + TextEdits.applyEdits(text, textEdits) + } + + def removeInlayHints(text: String): String = + text.replaceAll(raw"\/\*(.*?)\*\/", "").nn + +} \ No newline at end of file diff --git a/project/Build.scala b/project/Build.scala index c01dc4e49efa..a849e37c41fd 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1338,7 +1338,7 @@ object Build { BuildInfoPlugin.buildInfoDefaultSettings lazy val presentationCompilerSettings = { - val mtagsVersion = "1.2.0+67-30f8ab53-SNAPSHOT" + val mtagsVersion = "1.2.2+25-bb9dfbb9-SNAPSHOT" Seq( resolvers ++= Resolver.sonatypeOssRepos("snapshots"), From d37857c1e1a921c865a285a377aa52d52d9152d5 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Wed, 21 Feb 2024 18:02:42 +0100 Subject: [PATCH 063/277] In Java sources, allow a non-stable prefix for a class parent. (If we widen Foo.this.Inner in the parents of a class to AbstractFoo#Inner, i.e. an inherited class Inner prefixed by its owner abstract class AbstractFoo, this is not considered a stable prefix for a class parent type. But in Java this is the correct type so allow it.) --- .../src/dotty/tools/dotc/typer/Namer.scala | 12 +++-- .../Yjava-tasty-paths/a/InnerClassSub.java | 52 ++++++++++++++++++ .../pipelining/Yjava-tasty-paths/b/Test.scala | 18 +++++++ tests/run/i19619/InnerClassSub.java | 54 +++++++++++++++++++ tests/run/i19619/Test.scala | 17 ++++++ 5 files changed, 149 insertions(+), 4 deletions(-) create mode 100644 sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassSub.java create mode 100644 tests/run/i19619/InnerClassSub.java diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 03ff6e168666..7d1134f76d42 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -1542,17 +1542,19 @@ class Namer { typer: Typer => end parentType /** Check parent type tree `parent` for the following well-formedness conditions: - * (1) It must be a class type with a stable prefix (@see checkClassTypeWithStablePrefix) + * (1) It must be a class type with a stable prefix (unless `isJava`) (@see checkClassTypeWithStablePrefix) * (2) If may not derive from itself * (3) The class is not final * (4) If the class is sealed, it is defined in the same compilation unit as the current class + * + * @param isJava If true, the parent type is in Java mode, and we do not require a stable prefix */ - def checkedParentType(parent: untpd.Tree): Type = { + def checkedParentType(parent: untpd.Tree, isJava: Boolean): Type = { val ptype = parentType(parent)(using completerCtx.superCallContext).dealiasKeepAnnots if (cls.isRefinementClass) ptype else { val pt = checkClassType(ptype, parent.srcPos, - traitReq = parent ne parents.head, stablePrefixReq = true) + traitReq = parent ne parents.head, stablePrefixReq = !isJava) if (pt.derivesFrom(cls)) { val addendum = parent match { case Select(qual: Super, _) if Feature.migrateTo3 => @@ -1621,7 +1623,9 @@ class Namer { typer: Typer => val parentTypes = defn.adjustForTuple(cls, cls.typeParams, defn.adjustForBoxedUnit(cls, addUsingTraits( - ensureFirstIsClass(cls, parents.map(checkedParentType(_))) + locally: + val isJava = ctx.isJava + ensureFirstIsClass(cls, parents.map(checkedParentType(_, isJava))) ) ) ) diff --git a/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassSub.java b/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassSub.java new file mode 100644 index 000000000000..6441d71a4b20 --- /dev/null +++ b/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassSub.java @@ -0,0 +1,52 @@ +package a; + +public class InnerClassSub extends InnerClass { + + public class InnerSub extends Inner { + public InnerSub(U innerField) { + super(innerField); + } + } + + public class OuterSub extends Outer { + public OuterSub() { + super(); + } + } + + public Inner createInnerSub(U innerField) { + return new InnerSub<>(innerField); + } + + public Outer.Nested createNestedSub(U outerField, V innerField) { + OuterSub outer = new OuterSub<>(); + return outer.new Nested<>(outerField, innerField); + } + + public InnerClass.Inner createInnerSub2(U innerField) { + return new InnerSub<>(innerField); + } + + public InnerClass.Outer.Nested createNestedSub2(U outerField, V innerField) { + OuterSub outer = new OuterSub<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static InnerClass.Inner createInnerStatic(U innerField) { + InnerClassSub innerClass = new InnerClassSub(); + return innerClass.new Inner<>(innerField); + } + + public static InnerClass.Outer.Nested createNestedStatic(U outerField, V innerField) { + InnerClassSub innerClass = new InnerClassSub(); + InnerClassSub.Outer outer = innerClass.new Outer<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static void consumeNestedStatic(InnerClass.Outer.Nested nested) { + } + + public static void consumeNestedStatic2(Outer.Nested nested) { + } + +} diff --git a/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala b/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala index 084469e76d8b..bad55e361aa7 100644 --- a/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala +++ b/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala @@ -3,6 +3,7 @@ package b import a.InnerClass import a.InnerClassGen import a.RawTypes +import a.InnerClassSub object B { @main def test = { @@ -45,6 +46,23 @@ object B { RawTypes.mii_Raw_Raw(cd_ii_Raw) RawTypes.mii_Raw_Raw2(cd_ii_Raw) } + + locally { + val ici: InnerClassSub = new InnerClassSub() + // val ici_inner1: ici.Inner[Long] = ici.createInner[Long](47L) // error + val ici_inner2: InnerClass#Inner[Long] = ici.createInnerSub[Long](47L) + val ici_inner2_2: InnerClass#Inner[Long] = ici.createInnerSub2[Long](47L) + val ici_inner3: InnerClass#Inner[Long] = InnerClassSub.createInnerStatic[Long](47L) + + val ici_outer: InnerClassSub#Outer[Long] = new ici.Outer[Long]() + val ici_nested1: InnerClassSub#Outer[Long]#Nested[Int] = new ici_outer.Nested[Int](47L, 23) + val ici_nested2: InnerClass#Outer[Long]#Nested[Int] = ici.createNestedSub[Long, Int](47L, 23) + val ici_nested2_2: InnerClass#Outer[Long]#Nested[Int] = ici.createNestedSub2[Long, Int](47L, 23) + val ici_nested3: InnerClass#Outer[Long]#Nested[Int] = InnerClassSub.createNestedStatic[Long, Int](47L, 23) + + InnerClass.consumeNestedStatic(ici_nested3) + InnerClass.consumeNestedStatic2(ici_nested3) + } } } diff --git a/tests/run/i19619/InnerClassSub.java b/tests/run/i19619/InnerClassSub.java new file mode 100644 index 000000000000..5a1d1f4d3857 --- /dev/null +++ b/tests/run/i19619/InnerClassSub.java @@ -0,0 +1,54 @@ +// InnerClass.java + +package lib; + +public class InnerClassSub extends InnerClass { + + public class InnerSub extends Inner { + public InnerSub(U innerField) { + super(innerField); + } + } + + public class OuterSub extends Outer { + public OuterSub() { + super(); + } + } + + public Inner createInnerSub(U innerField) { + return new InnerSub<>(innerField); + } + + public Outer.Nested createNestedSub(U outerField, V innerField) { + OuterSub outer = new OuterSub<>(); + return outer.new Nested<>(outerField, innerField); + } + + public InnerClass.Inner createInnerSub2(U innerField) { + return new InnerSub<>(innerField); + } + + public InnerClass.Outer.Nested createNestedSub2(U outerField, V innerField) { + OuterSub outer = new OuterSub<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static InnerClass.Inner createInnerStatic(U innerField) { + InnerClassSub innerClass = new InnerClassSub(); + return innerClass.new Inner<>(innerField); + } + + public static InnerClass.Outer.Nested createNestedStatic(U outerField, V innerField) { + InnerClassSub innerClass = new InnerClassSub(); + InnerClassSub.Outer outer = innerClass.new Outer<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static void consumeNestedStatic(InnerClass.Outer.Nested nested) { + } + + public static void consumeNestedStatic2(Outer.Nested nested) { + } + +} diff --git a/tests/run/i19619/Test.scala b/tests/run/i19619/Test.scala index 5d6f4d11c7a1..8e8def4994db 100644 --- a/tests/run/i19619/Test.scala +++ b/tests/run/i19619/Test.scala @@ -1,6 +1,7 @@ import lib.InnerClass import lib.InnerClassGen import lib.RawTypes +import lib.InnerClassSub @main def Test = @@ -40,3 +41,19 @@ import lib.RawTypes RawTypes.mii_Raw_Raw(cd_ii_Raw) RawTypes.mii_Raw_Raw2(cd_ii_Raw) + + locally: + val ici: InnerClassSub = new InnerClassSub() + // val ici_inner1: ici.Inner[Long] = ici.createInner[Long](47L) // error + val ici_inner2: InnerClass#Inner[Long] = ici.createInnerSub[Long](47L) + val ici_inner2_2: InnerClass#Inner[Long] = ici.createInnerSub2[Long](47L) + val ici_inner3: InnerClass#Inner[Long] = InnerClassSub.createInnerStatic[Long](47L) + + val ici_outer: InnerClassSub#Outer[Long] = new ici.Outer[Long]() + val ici_nested1: InnerClassSub#Outer[Long]#Nested[Int] = new ici_outer.Nested[Int](47L, 23) + val ici_nested2: InnerClass#Outer[Long]#Nested[Int] = ici.createNestedSub[Long, Int](47L, 23) + val ici_nested2_2: InnerClass#Outer[Long]#Nested[Int] = ici.createNestedSub2[Long, Int](47L, 23) + val ici_nested3: InnerClass#Outer[Long]#Nested[Int] = InnerClassSub.createNestedStatic[Long, Int](47L, 23) + + InnerClass.consumeNestedStatic(ici_nested3) + InnerClass.consumeNestedStatic2(ici_nested3) From faf8547ecd0cdf4c50d7b789e8fba22c6b6efde3 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Thu, 22 Feb 2024 14:30:58 +0100 Subject: [PATCH 064/277] skip test on scala-js --- tests/run/i19619/Test.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/run/i19619/Test.scala b/tests/run/i19619/Test.scala index 8e8def4994db..871e7a490ea0 100644 --- a/tests/run/i19619/Test.scala +++ b/tests/run/i19619/Test.scala @@ -1,3 +1,5 @@ +// scalajs: --skip + import lib.InnerClass import lib.InnerClassGen import lib.RawTypes From 8f2b6cf0dc2d681be6c585572e7cf0680e627d2e Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 22 Feb 2024 13:59:04 +0000 Subject: [PATCH 065/277] Approximate MatchTypes with lub of case bodies, if non-recursive --- .../src/dotty/tools/dotc/core/TypeComparer.scala | 13 ++++++++++++- tests/pos/i19710.scala | 11 +++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i19710.scala diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index b23bfe9fe14b..9373889b37d6 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -1030,6 +1030,17 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling if tp1 ne tp1norm then recur(tp1norm, tp2) else either(recur(tp11, tp2), recur(tp12, tp2)) case tp1: MatchType => + def compareUpper = + val lub1 = tp1.cases.foldLeft(defn.NothingType: Type): (acc, case1) => + if acc.exists then + val rhs = case1.resultType match { case defn.MatchCase(_, body) => body } + val isRecursive = rhs.existsPart(_.isInstanceOf[LazyRef]) + if isRecursive then NoType else lub(acc, rhs) + else acc + if lub1.exists then + recur(lub1, tp2) + else + recur(tp1.underlying, tp2) def compareMatch = tp2 match { case tp2: MatchType => // we allow a small number of scrutinee types to be widened: @@ -1047,7 +1058,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling tp1.cases.corresponds(tp2.cases)(isSubType) case _ => false } - (!caseLambda.exists || canWidenAbstract) && recur(tp1.underlying, tp2) || compareMatch + (!caseLambda.exists || canWidenAbstract) && compareUpper || compareMatch case tp1: AnnotatedType if tp1.isRefining => isNewSubType(tp1.parent) case JavaArrayType(elem1) => diff --git a/tests/pos/i19710.scala b/tests/pos/i19710.scala new file mode 100644 index 000000000000..03fd1e2d80b3 --- /dev/null +++ b/tests/pos/i19710.scala @@ -0,0 +1,11 @@ +import scala.util.NotGiven + +type HasName1 = [n] =>> [x] =>> x match { + case n => true + case _ => false + } +@main def Test = { + summon[HasName1["foo"]["foo"] =:= true] + summon[NotGiven[HasName1["foo"]["bar"] =:= true]] + summon[Tuple.Filter[(1, "foo", 2, "bar"), HasName1["foo"]] =:= Tuple1["foo"]] // error +} From 124f68b9260e99bdb8ad080ddbc3f0b01b6a77e9 Mon Sep 17 00:00:00 2001 From: EnzeXing Date: Thu, 22 Feb 2024 10:05:26 -0500 Subject: [PATCH 066/277] Added tests --- tests/init-global/pos/TypeCast1.scala | 9 +++++++++ tests/init-global/pos/TypeCast2.scala | 9 +++++++++ tests/init-global/pos/TypeCast3.scala | 8 ++++++++ tests/init-global/pos/TypeCast4.scala | 9 +++++++++ 4 files changed, 35 insertions(+) create mode 100644 tests/init-global/pos/TypeCast1.scala create mode 100644 tests/init-global/pos/TypeCast2.scala create mode 100644 tests/init-global/pos/TypeCast3.scala create mode 100644 tests/init-global/pos/TypeCast4.scala diff --git a/tests/init-global/pos/TypeCast1.scala b/tests/init-global/pos/TypeCast1.scala new file mode 100644 index 000000000000..e9881c6f5e4d --- /dev/null +++ b/tests/init-global/pos/TypeCast1.scala @@ -0,0 +1,9 @@ +class A: + class B(val b: Int) + +object O: + val o: A | Array[Int] = new Array[Int](10) + o match + case a: A => new a.B(10) + case arr: Array[Int] => arr(5) + diff --git a/tests/init-global/pos/TypeCast2.scala b/tests/init-global/pos/TypeCast2.scala new file mode 100644 index 000000000000..e18c8ffca5d1 --- /dev/null +++ b/tests/init-global/pos/TypeCast2.scala @@ -0,0 +1,9 @@ +class A: + class B(val b: Int) + +object O: + val o: A | (Int => Int) = (x: Int) => x + 1 + o match + case a: A => new a.B(10) + case f: (_ => _) => f.asInstanceOf[Int => Int](5) + diff --git a/tests/init-global/pos/TypeCast3.scala b/tests/init-global/pos/TypeCast3.scala new file mode 100644 index 000000000000..08197790edd6 --- /dev/null +++ b/tests/init-global/pos/TypeCast3.scala @@ -0,0 +1,8 @@ +class A: + var x: Int = 10 + +object O: + val o: A | (Int => Int) = (x: Int) => x + 1 + o match + case a: A => a.x = 20 + case f: (_ => _) => f.asInstanceOf[Int => Int](5) diff --git a/tests/init-global/pos/TypeCast4.scala b/tests/init-global/pos/TypeCast4.scala new file mode 100644 index 000000000000..8b65bc775cc2 --- /dev/null +++ b/tests/init-global/pos/TypeCast4.scala @@ -0,0 +1,9 @@ +class A: + var x: Int = 10 + +object O: + val o: A | Array[Int] = new Array[Int](10) + o match + case a: A => a.x = 20 + case arr: Array[Int] => arr(5) + From 2c81588e620e0ae62aa6641db4aebf9683bd97d3 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 22 Feb 2024 14:39:47 +0000 Subject: [PATCH 067/277] Extract shared prepareRhsCtx --- .../src/dotty/tools/dotc/typer/Namer.scala | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index e5e05e02a7d7..577907e243d9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -1733,12 +1733,7 @@ class Namer { typer: Typer => val tpe = (paramss: @unchecked) match case TypeSymbols(tparams) :: TermSymbols(vparams) :: Nil => tpFun(tparams, vparams) case TermSymbols(vparams) :: Nil => tpFun(Nil, vparams) - val rhsCtx = (paramss: @unchecked) match - case TypeSymbols(tparams) :: TermSymbols(_) :: Nil => - val rhsCtx = ctx.fresh.setFreshGADTBounds - rhsCtx.gadtState.addToConstraint(tparams) - rhsCtx - case TermSymbols(_) :: Nil => ctx + val rhsCtx = prepareRhsCtx(ctx.fresh, paramss) if (isFullyDefined(tpe, ForceDegree.none)) tpe else typedAheadExpr(mdef.rhs, tpe)(using rhsCtx).tpe @@ -1938,14 +1933,7 @@ class Namer { typer: Typer => var rhsCtx = ctx.fresh.addMode(Mode.InferringReturnType) if sym.isInlineMethod then rhsCtx = rhsCtx.addMode(Mode.InlineableBody) if sym.is(ExtensionMethod) then rhsCtx = rhsCtx.addMode(Mode.InExtensionMethod) - val typeParams = paramss.collect { case TypeSymbols(tparams) => tparams }.flatten - if (typeParams.nonEmpty) { - // we'll be typing an expression from a polymorphic definition's body, - // so we must allow constraining its type parameters - // compare with typedDefDef, see tests/pos/gadt-inference.scala - rhsCtx.setFreshGADTBounds - rhsCtx.gadtState.addToConstraint(typeParams) - } + rhsCtx = prepareRhsCtx(rhsCtx, paramss) def typedAheadRhs(pt: Type) = PrepareInlineable.dropInlineIfError(sym, @@ -1990,4 +1978,15 @@ class Namer { typer: Typer => lhsType orElse WildcardType } end inferredResultType + + /** Prepare a GADT-aware context used to type the RHS of a ValOrDefDef. */ + def prepareRhsCtx(rhsCtx: FreshContext, paramss: List[List[Symbol]])(using Context): FreshContext = + val typeParams = paramss.collect { case TypeSymbols(tparams) => tparams }.flatten + if typeParams.nonEmpty then + // we'll be typing an expression from a polymorphic definition's body, + // so we must allow constraining its type parameters + // compare with typedDefDef, see tests/pos/gadt-inference.scala + rhsCtx.setFreshGADTBounds + rhsCtx.gadtState.addToConstraint(typeParams) + rhsCtx } From 6c6f7d8163efdaf5e274604d839074b11f247be0 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 22 Feb 2024 15:13:28 +0000 Subject: [PATCH 068/277] Make -Xprompt work as desired under -Werror --- .../dotty/tools/dotc/reporting/ConsoleReporter.scala | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/ConsoleReporter.scala b/compiler/src/dotty/tools/dotc/reporting/ConsoleReporter.scala index ce7477f4da70..270c35d0add7 100644 --- a/compiler/src/dotty/tools/dotc/reporting/ConsoleReporter.scala +++ b/compiler/src/dotty/tools/dotc/reporting/ConsoleReporter.scala @@ -4,7 +4,7 @@ package reporting import core.Contexts.* import java.io.{ BufferedReader, PrintWriter } -import Diagnostic.Error +import Diagnostic.* /** * This class implements a Reporter that displays messages on a text console @@ -18,9 +18,11 @@ class ConsoleReporter( override def doReport(dia: Diagnostic)(using Context): Unit = { super.doReport(dia) - dia match - case dia: Error if ctx.settings.Xprompt.value => Reporter.displayPrompt(reader, writer) - case _ => + if ctx.settings.Xprompt.value then + dia match + case _: Error => Reporter.displayPrompt(reader, writer) + case _: Warning if ctx.settings.XfatalWarnings.value => Reporter.displayPrompt(reader, writer) + case _ => } } From 113002bc2b4b064e460f2d88e82a5676fa08fbf2 Mon Sep 17 00:00:00 2001 From: EnzeXing Date: Thu, 22 Feb 2024 11:13:51 -0500 Subject: [PATCH 069/277] Fixing filtering arrays --- .../dotty/tools/dotc/transform/init/Objects.scala | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala index 6ecd7441829d..c76f4658eecb 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala @@ -203,6 +203,7 @@ object Objects: /** * Represents a lambda expression + * @param klass The enclosing class of the anonymous function's creation site */ case class Fun(code: Tree, thisV: ThisValue, klass: ClassSymbol, env: Env.Data) extends ValueElement: def show(using Context) = "Fun(" + code.show + ", " + thisV.show + ", " + klass.show + ")" @@ -600,9 +601,10 @@ object Objects: case _ => a def filterType(tpe: Type)(using Context): Value = + // if tpe is SAMType and a is Fun, allow it val baseClasses = tpe.baseClasses if baseClasses.isEmpty then a - else filterClass(baseClasses.head) + else filterClass(baseClasses.head) // could have called ClassSymbol, but it does not handle OrType and AndType def filterClass(sym: Symbol)(using Context): Value = if !sym.isClass then a @@ -613,7 +615,11 @@ object Objects: case ref: Ref if ref.klass.isSubClass(klass) => ref case ref: Ref => Bottom case ValueSet(values) => values.map(v => v.filterClass(klass)).join - case _ => a // TODO: could be more precise for OfArray; possibly add class information for Fun + case arr: OfArray => if defn.ArrayClass.isSubClass(klass) then arr else Bottom + case fun: Fun => if defn.Function1.isSubClass(klass) then fun else Bottom + // TODO: could be more precise for OfArray; possibly add class information for Fun + // If ArrayClass.isSubClass(klass) keep the array else discard (see Definitions.scala) + // For function, if any superclass is FunctionClass (or a single abstract method interface?), allow it extension (value: Ref | Cold.type) def widenRefOrCold(height : Int)(using Context) : Ref | Cold.type = value.widen(height).asInstanceOf[ThisValue] @@ -859,7 +865,7 @@ object Objects: report.warning("[Internal error] unexpected tree in assignment, fun = " + fun.code.show + Trace.show, Trace.position) case arr: OfArray => - report.warning("[Internal error] unexpected tree in assignment, array = " + arr.show + Trace.show, Trace.position) + report.warning("[Internal error] unexpected tree in assignment, array = " + arr.show + " field = " + field + Trace.show, Trace.position) case Cold => report.warning("Assigning to cold aliases is forbidden. " + Trace.show, Trace.position) @@ -1566,7 +1572,7 @@ object Objects: report.warning("The argument should be a constant integer value", arg) res.widen(1) case _ => - res.widen(1) + res.widen(1) // TODO: changing to widen(2) causes standard library analysis to loop infinitely argInfos += ArgInfo(widened, trace.add(arg.tree), arg.tree) } From 4df6b10d93f7c3232066213b86fde14999d6b9b8 Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Tue, 20 Feb 2024 14:46:42 +0100 Subject: [PATCH 070/277] Add test for overriding a definition with MacroAnnotation without dummy definition --- tests/run-macros/annot-concrete-class.check | 1 + .../annot-concrete-class/Macro_1.scala | 16 ++++++++++++++++ .../run-macros/annot-concrete-class/Test_2.scala | 11 +++++++++++ 3 files changed, 28 insertions(+) create mode 100644 tests/run-macros/annot-concrete-class.check create mode 100644 tests/run-macros/annot-concrete-class/Macro_1.scala create mode 100644 tests/run-macros/annot-concrete-class/Test_2.scala diff --git a/tests/run-macros/annot-concrete-class.check b/tests/run-macros/annot-concrete-class.check new file mode 100644 index 000000000000..694fe5799063 --- /dev/null +++ b/tests/run-macros/annot-concrete-class.check @@ -0,0 +1 @@ +Hello, I was added by a MacroAnnotation and without being defined in the class. diff --git a/tests/run-macros/annot-concrete-class/Macro_1.scala b/tests/run-macros/annot-concrete-class/Macro_1.scala new file mode 100644 index 000000000000..54d1bc7c20ce --- /dev/null +++ b/tests/run-macros/annot-concrete-class/Macro_1.scala @@ -0,0 +1,16 @@ +import scala.annotation.MacroAnnotation +import scala.quoted.* + +class implementAFoo extends MacroAnnotation: + + def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + import quotes.reflect.* + tree match + case ClassDef(name, cstr, parents, self, body) => + val owner = tree.symbol + val sym = Symbol.newMethod(tree.symbol, "foo", ByNameType.apply(TypeRepr.of[String])) + val mtd = DefDef.apply(sym, _ => Some(Literal(StringConstant("Hello, I was added by a MacroAnnotation and without being defined in the class.")))) + List(ClassDef.copy(tree)(name, cstr, parents, self, mtd :: body)) + case _ => report.errorAndAbort(s"@implementAFoo can only be applied to classes that extend AFoo") + +end implementAFoo diff --git a/tests/run-macros/annot-concrete-class/Test_2.scala b/tests/run-macros/annot-concrete-class/Test_2.scala new file mode 100644 index 000000000000..713b0d814813 --- /dev/null +++ b/tests/run-macros/annot-concrete-class/Test_2.scala @@ -0,0 +1,11 @@ + +trait AFoo: + def foo: String + +@implementAFoo +class Foo extends AFoo + +@main def Test = + val foo = new Foo + println(foo.foo) + \ No newline at end of file From 3ad3acba11552e638a91889b8ff48385b624db08 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 23 Feb 2024 08:55:25 +0100 Subject: [PATCH 071/277] Update reference compiler to 3.4.0 --- project/Build.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Build.scala b/project/Build.scala index a849e37c41fd..59ba6cff9006 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -83,7 +83,7 @@ object DottyJSPlugin extends AutoPlugin { object Build { import ScaladocConfigs._ - val referenceVersion = "3.3.1" + val referenceVersion = "3.4.0" val baseVersion = "3.4.2-RC1" From aeb58367fe93cc5a1250dc53614b0e2ebd0b5502 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 23 Feb 2024 08:55:51 +0100 Subject: [PATCH 072/277] Update previous Dotty version for MiMa to 3.4.0 --- project/Build.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Build.scala b/project/Build.scala index 59ba6cff9006..ace0588e9ab3 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -101,7 +101,7 @@ object Build { * set to 3.1.3. If it is going to be 3.1.0, it must be set to the latest * 3.0.x release. */ - val previousDottyVersion = "3.4.0-RC3" + val previousDottyVersion = "3.4.0" /** Version against which we check binary compatibility. */ val ltsDottyVersion = "3.3.0" From 8ae80fe1929a20cb949a6fce74ea54956b997a87 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 23 Feb 2024 08:59:09 +0100 Subject: [PATCH 073/277] Remove `ErasedFunction` This can be removed now that the reference compiler (3.4.0) no longer tries to load the symbol of `ErasedFunction`. Follow up of #18295 --- library/src/scala/runtime/ErasedFunction.scala | 13 ------------- .../stdlibExperimentalDefinitions.scala | 1 - 2 files changed, 14 deletions(-) delete mode 100644 library/src/scala/runtime/ErasedFunction.scala diff --git a/library/src/scala/runtime/ErasedFunction.scala b/library/src/scala/runtime/ErasedFunction.scala deleted file mode 100644 index dbbcc3431cc9..000000000000 --- a/library/src/scala/runtime/ErasedFunction.scala +++ /dev/null @@ -1,13 +0,0 @@ -package scala.runtime - -import scala.annotation.experimental - -/** Marker trait for function types with erased parameters. - * - * This trait will be refined with an `apply` method with erased parameters: - * ErasedFunction { def apply([erased] x_1: P_1, ..., [erased] x_N: P_N): R } - * This type will be erased to FunctionL, where L = N - count(erased). - * - * Note: Now we use `scala.PolyFunction` instead. This will be removed. - */ -@experimental trait ErasedFunction // TODO delete. Cannot be deleted until the reference compiler stops using it. diff --git a/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala b/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala index 111c8c0bada3..888e5c36405d 100644 --- a/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala +++ b/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala @@ -86,7 +86,6 @@ val experimentalDefinitionInLibrary = Set( // New feature: functions with erased parameters. // Need erasedDefinitions enabled. - "scala.runtime.ErasedFunction", // will be removed (now using PolyFunction) "scala.quoted.Quotes.reflectModule.MethodTypeMethods.erasedParams", "scala.quoted.Quotes.reflectModule.MethodTypeMethods.hasErasedParams", "scala.quoted.Quotes.reflectModule.TermParamClauseMethods.erasedArgs", From bc4e1d7adab75ce25ede9471cfafebf5c6f276d3 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 23 Feb 2024 11:02:23 +0100 Subject: [PATCH 074/277] Cleanup repl scripted tests flags --- compiler/test-resources/repl/erased | 1 + compiler/test-resources/repl/erased-implicit | 1 + compiler/test-resources/type-printer/test-definitions | 2 ++ compiler/test/dotty/tools/repl/ReplTest.scala | 2 +- 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/test-resources/repl/erased b/compiler/test-resources/repl/erased index 9a67c1963769..fd9067692dbe 100644 --- a/compiler/test-resources/repl/erased +++ b/compiler/test-resources/repl/erased @@ -1,2 +1,3 @@ +scala> import scala.language.experimental.erasedDefinitions scala> def f(erased a: Int): Int = ??? def f(erased a: Int): Int diff --git a/compiler/test-resources/repl/erased-implicit b/compiler/test-resources/repl/erased-implicit index 5b1ec654c2aa..43624a5a9a08 100644 --- a/compiler/test-resources/repl/erased-implicit +++ b/compiler/test-resources/repl/erased-implicit @@ -1,2 +1,3 @@ +scala> import scala.language.experimental.erasedDefinitions scala> def f(using erased a: Int): Int = ??? def f(using erased a: Int): Int diff --git a/compiler/test-resources/type-printer/test-definitions b/compiler/test-resources/type-printer/test-definitions index ce33846472cf..cdda5f65cb0e 100644 --- a/compiler/test-resources/type-printer/test-definitions +++ b/compiler/test-resources/type-printer/test-definitions @@ -19,5 +19,7 @@ scala> trait E scala> implicit def x: Int = 1 def x: Int +scala> import scala.language.experimental.erasedDefinitions + scala> erased def y: Int = 1 def y: Int diff --git a/compiler/test/dotty/tools/repl/ReplTest.scala b/compiler/test/dotty/tools/repl/ReplTest.scala index 8fbf635c9a17..ae0d0c666a9c 100644 --- a/compiler/test/dotty/tools/repl/ReplTest.scala +++ b/compiler/test/dotty/tools/repl/ReplTest.scala @@ -104,6 +104,6 @@ extends ReplDriver(options, new PrintStream(out, true, StandardCharsets.UTF_8.na } object ReplTest: - val commonOptions = Array("-color:never", "-language:experimental.erasedDefinitions", "-pagewidth", "80") + val commonOptions = Array("-color:never", "-pagewidth", "80") val defaultOptions = commonOptions ++ Array("-classpath", TestConfiguration.basicClasspath) lazy val withStagingOptions = commonOptions ++ Array("-classpath", TestConfiguration.withStagingClasspath) From 2a1d1b363afa61ea41b5149dc459908479088257 Mon Sep 17 00:00:00 2001 From: i10416 Date: Sat, 24 Feb 2024 16:57:21 +0900 Subject: [PATCH 075/277] test: add test for #19762 Add a test to confirm issue#19762 is solved. --- tests/neg/i19762.check | 6 ++++++ tests/neg/i19762.scala | 8 ++++++++ 2 files changed, 14 insertions(+) create mode 100644 tests/neg/i19762.check create mode 100644 tests/neg/i19762.scala diff --git a/tests/neg/i19762.check b/tests/neg/i19762.check new file mode 100644 index 000000000000..93def936e2a0 --- /dev/null +++ b/tests/neg/i19762.check @@ -0,0 +1,6 @@ +-- [E019] Syntax Error: tests/neg/i19762.scala:8:31 -------------------------------------------------------------------- +8 | def combine(x: Int, y: Int)) = x + y // error + | ^ + | Missing return type + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg/i19762.scala b/tests/neg/i19762.scala new file mode 100644 index 000000000000..4966f0d8cb53 --- /dev/null +++ b/tests/neg/i19762.scala @@ -0,0 +1,8 @@ +trait Monoid[A]: + def combine(x: A, y: A): A + def empty: A + +object Monoid: + lazy val addInt: Monoid[Int] = new: + val empty = 0 + def combine(x: Int, y: Int)) = x + y // error \ No newline at end of file From 22d98d6603a66589f63f699d5b0114c578b0483a Mon Sep 17 00:00:00 2001 From: i10416 Date: Sat, 24 Feb 2024 15:13:58 +0900 Subject: [PATCH 076/277] fix: cannot find Scala companion module from Java To find Scala companion mudule from Java in mixed sources, we should strip module suffix `$`. This provides workaround for #17255, but it requires some refinment to fix it because not-fully-qualified type like the following example still fails to compile due to missing symbol. ```java package example; public class Bar { private static final Foo$ MOD = Foo$.MODULE; } ``` This is because `pre` in `javaFindMember` for `Foo` in the case above is ``, not `example` and therefore `pre.findMember` looks for `.Foo` instead of `example.Foo`. I'm not sure whether the qualifier is intentionally dropped. References - https://github.com/lampepfl/dotty/pull/12884 - https://github.com/scala/scala/pull/7671 --- compiler/src/dotty/tools/dotc/core/ContextOps.scala | 12 +++++++++--- compiler/test/dotc/pos-test-pickling.blacklist | 1 + tests/pos/i17255/Bar.java | 6 ++++++ tests/pos/i17255/Foo.scala | 5 +++++ 4 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 tests/pos/i17255/Bar.java create mode 100644 tests/pos/i17255/Foo.scala diff --git a/compiler/src/dotty/tools/dotc/core/ContextOps.scala b/compiler/src/dotty/tools/dotc/core/ContextOps.scala index 55fb31fd1916..8b47fe1cd872 100644 --- a/compiler/src/dotty/tools/dotc/core/ContextOps.scala +++ b/compiler/src/dotty/tools/dotc/core/ContextOps.scala @@ -55,11 +55,17 @@ object ContextOps: final def javaFindMember(name: Name, pre: Type, lookInCompanion: Boolean, required: FlagSet = EmptyFlags, excluded: FlagSet = EmptyFlags): Denotation = assert(ctx.isJava) inContext(ctx) { - + import dotty.tools.dotc.core.NameOps.* val preSym = pre.typeSymbol - // 1. Try to search in current type and parents. - val directSearch = pre.findMember(name, pre, required, excluded) + val directSearch = + if name.isTypeName && name.endsWith(StdNames.str.MODULE_SUFFIX) then + pre.findMember(name.stripModuleClassSuffix, pre, required, excluded) match + case NoDenotation => NoDenotation + case symDenot: SymDenotation => + symDenot.companionModule.denot + else + pre.findMember(name, pre, required, excluded) // 2. Try to search in companion class if current is an object. def searchCompanionClass = if lookInCompanion && preSym.is(Flags.Module) then diff --git a/compiler/test/dotc/pos-test-pickling.blacklist b/compiler/test/dotc/pos-test-pickling.blacklist index b0da78f0a1eb..32f8cdef1386 100644 --- a/compiler/test/dotc/pos-test-pickling.blacklist +++ b/compiler/test/dotc/pos-test-pickling.blacklist @@ -29,6 +29,7 @@ i16649-irrefutable.scala strict-pattern-bindings-3.0-migration.scala i17186b.scala i11982a.scala +i17255 # Tree is huge and blows stack for printing Text i7034.scala diff --git a/tests/pos/i17255/Bar.java b/tests/pos/i17255/Bar.java new file mode 100644 index 000000000000..35269af2179f --- /dev/null +++ b/tests/pos/i17255/Bar.java @@ -0,0 +1,6 @@ +package example; + + +public class Bar { + private static final example.Foo$ MOD = example.Foo$.MODULE$; +} \ No newline at end of file diff --git a/tests/pos/i17255/Foo.scala b/tests/pos/i17255/Foo.scala new file mode 100644 index 000000000000..9608b43b430f --- /dev/null +++ b/tests/pos/i17255/Foo.scala @@ -0,0 +1,5 @@ +package example + +case class Foo(i: Int) + +object Foo \ No newline at end of file From 4cb34e5b6134c3bccc25dc61ff53da80f992aaa3 Mon Sep 17 00:00:00 2001 From: i10416 Date: Sat, 24 Feb 2024 18:42:53 +0900 Subject: [PATCH 077/277] tweak: try the original name first and then fallback to module Avoid skipping searchin a member by the original name even when name is likely companion module name. --- .../src/dotty/tools/dotc/core/ContextOps.scala | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/ContextOps.scala b/compiler/src/dotty/tools/dotc/core/ContextOps.scala index 8b47fe1cd872..3f6b49253192 100644 --- a/compiler/src/dotty/tools/dotc/core/ContextOps.scala +++ b/compiler/src/dotty/tools/dotc/core/ContextOps.scala @@ -59,13 +59,16 @@ object ContextOps: val preSym = pre.typeSymbol // 1. Try to search in current type and parents. val directSearch = - if name.isTypeName && name.endsWith(StdNames.str.MODULE_SUFFIX) then - pre.findMember(name.stripModuleClassSuffix, pre, required, excluded) match - case NoDenotation => NoDenotation - case symDenot: SymDenotation => - symDenot.companionModule.denot - else - pre.findMember(name, pre, required, excluded) + def asModule = + if name.isTypeName && name.endsWith(StdNames.str.MODULE_SUFFIX) then + pre.findMember(name.stripModuleClassSuffix, pre, required, excluded) match + case NoDenotation => NoDenotation + case symDenot: SymDenotation => + symDenot.companionModule.denot + else NoDenotation + pre.findMember(name, pre, required, excluded) match + case NoDenotation => asModule + case denot => denot // 2. Try to search in companion class if current is an object. def searchCompanionClass = if lookInCompanion && preSym.is(Flags.Module) then From eabdf44170438cbc93817d451811282b1d98ead4 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Wed, 4 Oct 2023 13:53:17 +0100 Subject: [PATCH 078/277] Fix the tparam bounds of exported inherited classes When trying to export M2.F, seeing M1#F from the prefix M2 doesn't change the bounds of F's T type parameter, which still refers to M1.this.A, rather than M2.A. So, we run asSeenFrom against that info, when eta-expanding the class into a hk type lambda. --- .../src/dotty/tools/dotc/typer/Namer.scala | 18 ++++++++++++++++-- tests/pos/i18569.scala | 11 +++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 tests/pos/i18569.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index a48026063415..fe419802c91d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -1199,8 +1199,22 @@ class Namer { typer: Typer => if mbr.isType then val forwarderName = checkNoConflict(alias.toTypeName, isPrivate = false, span) var target = pathType.select(sym) - if target.typeParams.nonEmpty then - target = target.etaExpand(target.typeParams) + val tparams = target.typeParams + if tparams.nonEmpty then + // like `target = target.etaExpand(target.typeParams)` + // except call `asSeenFrom` to fix class type parameter bounds + // e.g. in pos/i18569: + // `Test#F` should have `M2.A` or `Test.A` as bounds, not `M1#A`. + target = HKTypeLambda(tparams.map(_.paramName))( + tl => tparams.map { + case p: Symbol => + val info = p.info.asSeenFrom(pathType, sym.owner) + HKTypeLambda.toPInfo(tl.integrate(tparams, info)) + case p => + val info = p.paramInfo + HKTypeLambda.toPInfo(tl.integrate(tparams, info)) + }, + tl => tl.integrate(tparams, target.appliedTo(tparams.map(_.paramRef)))) newSymbol( cls, forwarderName, MandatoryExportTypeFlags | (sym.flags & RetainedExportTypeFlags), diff --git a/tests/pos/i18569.scala b/tests/pos/i18569.scala new file mode 100644 index 000000000000..1457f6fbe5b6 --- /dev/null +++ b/tests/pos/i18569.scala @@ -0,0 +1,11 @@ +trait M1: + trait A + trait F[T <: A] + type G[T <: A] = F[T] + +object M2 extends M1 + +trait Test: + export M2.* + def y: F[A] + def z: G[A] From 66722b9941356e4c87e3b489507ee1b8771ad9d4 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 13 Nov 2023 11:42:02 +0000 Subject: [PATCH 079/277] Move implementation into TypeApplications etaExpandWithAsf --- .../tools/dotc/core/TypeApplications.scala | 16 ++++++++++++++++ .../src/dotty/tools/dotc/typer/Namer.scala | 18 ++---------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index f1edd7cd8f8b..f5508eb2c060 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -320,6 +320,22 @@ class TypeApplications(val self: Type) extends AnyVal { } } + // Like `target.etaExpand(target.typeParams)` + // except call `asSeenFrom` to fix class type parameter bounds + // e.g. in pos/i18569: + // given prefix `M2.type` and symbol `trait F` + // the result of `prefix.select(sym)` is `M2.F` + // however F's type parameter T is `<: M1#A` rather than `<: M2.A` + // so add a call to `asSeenFrom` with prefix `M2.type` and owner `trait M1` + def etaExpandWithAsf(prefix: Type, owner: Symbol)(using Context): Type = + val tparams = self.typeParams + HKTypeLambda(tparams.map(_.paramName))( + tl => tparams.map { + case p: Symbol => HKTypeLambda.toPInfo(tl.integrate(tparams, p.info.asSeenFrom(prefix, owner))) + case p => HKTypeLambda.toPInfo(tl.integrate(tparams, p.paramInfo)) + }, + tl => tl.integrate(tparams, self.appliedTo(tparams.map(_.paramRef)))) + /** Maps [Ts] => C[Ts] to C */ def etaCollapse(using Context): Type = self match case EtaExpansion(classType) => classType diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index fe419802c91d..c531d8da01a2 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -1199,22 +1199,8 @@ class Namer { typer: Typer => if mbr.isType then val forwarderName = checkNoConflict(alias.toTypeName, isPrivate = false, span) var target = pathType.select(sym) - val tparams = target.typeParams - if tparams.nonEmpty then - // like `target = target.etaExpand(target.typeParams)` - // except call `asSeenFrom` to fix class type parameter bounds - // e.g. in pos/i18569: - // `Test#F` should have `M2.A` or `Test.A` as bounds, not `M1#A`. - target = HKTypeLambda(tparams.map(_.paramName))( - tl => tparams.map { - case p: Symbol => - val info = p.info.asSeenFrom(pathType, sym.owner) - HKTypeLambda.toPInfo(tl.integrate(tparams, info)) - case p => - val info = p.paramInfo - HKTypeLambda.toPInfo(tl.integrate(tparams, info)) - }, - tl => tl.integrate(tparams, target.appliedTo(tparams.map(_.paramRef)))) + if target.typeParams.nonEmpty then + target = target.etaExpandWithAsf(pathType, sym.owner) newSymbol( cls, forwarderName, MandatoryExportTypeFlags | (sym.flags & RetainedExportTypeFlags), From f1fc2eb0610038dc89982ac1f129af7b8e773182 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 13 Nov 2023 14:27:15 +0000 Subject: [PATCH 080/277] Make etaExpandWithAsf more self-contained --- .../tools/dotc/core/TypeApplications.scala | 30 +++++++++++-------- .../src/dotty/tools/dotc/typer/Namer.scala | 2 +- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index f5508eb2c060..c7312c75b081 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -322,19 +322,23 @@ class TypeApplications(val self: Type) extends AnyVal { // Like `target.etaExpand(target.typeParams)` // except call `asSeenFrom` to fix class type parameter bounds - // e.g. in pos/i18569: - // given prefix `M2.type` and symbol `trait F` - // the result of `prefix.select(sym)` is `M2.F` - // however F's type parameter T is `<: M1#A` rather than `<: M2.A` - // so add a call to `asSeenFrom` with prefix `M2.type` and owner `trait M1` - def etaExpandWithAsf(prefix: Type, owner: Symbol)(using Context): Type = - val tparams = self.typeParams - HKTypeLambda(tparams.map(_.paramName))( - tl => tparams.map { - case p: Symbol => HKTypeLambda.toPInfo(tl.integrate(tparams, p.info.asSeenFrom(prefix, owner))) - case p => HKTypeLambda.toPInfo(tl.integrate(tparams, p.paramInfo)) - }, - tl => tl.integrate(tparams, self.appliedTo(tparams.map(_.paramRef)))) + // e.g. from pos/i18569: + // trait M1: + // trait A + // trait F[T <: A] + // object M2 extends M1 + // Type parameter T in M2.F has an upper bound of M1#A instead of M2.A + // So we take the prefix M2.type and the F symbol's owner, M1, + // to call asSeenFrom on T's info. + def etaExpandWithAsf(using Context): Type = self match + case self: TypeRef if self.symbol.isClass => + val tparams = self.symbol.typeParams + val prefix = self.prefix + val owner = self.symbol.owner + HKTypeLambda(tparams.map(_.paramName))( + tl => tparams.map(p => HKTypeLambda.toPInfo(tl.integrate(tparams, p.info.asSeenFrom(prefix, owner)))), + tl => tl.integrate(tparams, self.appliedTo(tparams.map(_.paramRef)))) + case _ => etaExpand(typeParams) /** Maps [Ts] => C[Ts] to C */ def etaCollapse(using Context): Type = self match diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index c531d8da01a2..6621d459918b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -1200,7 +1200,7 @@ class Namer { typer: Typer => val forwarderName = checkNoConflict(alias.toTypeName, isPrivate = false, span) var target = pathType.select(sym) if target.typeParams.nonEmpty then - target = target.etaExpandWithAsf(pathType, sym.owner) + target = target.etaExpandWithAsf newSymbol( cls, forwarderName, MandatoryExportTypeFlags | (sym.flags & RetainedExportTypeFlags), From 729e5ba099688a1e92c7d5cdf9611e7d1469379c Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 28 Nov 2023 14:39:14 +0000 Subject: [PATCH 081/277] Collapse into 1 etaExpand (to rule them all) --- .../tools/dotc/core/TypeApplications.scala | 62 +++++++++---------- .../dotty/tools/dotc/core/TypeComparer.scala | 6 +- .../core/unpickleScala2/Scala2Unpickler.scala | 2 +- .../src/dotty/tools/dotc/typer/Deriving.scala | 2 +- .../src/dotty/tools/dotc/typer/Namer.scala | 2 +- .../dotty/tools/dotc/typer/RefChecks.scala | 2 +- .../src/dotty/tools/dotc/typer/Typer.scala | 2 +- 7 files changed, 39 insertions(+), 39 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index c7312c75b081..99735c6de7ad 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -33,10 +33,6 @@ object TypeApplications { */ object EtaExpansion: - def apply(tycon: Type)(using Context): Type = - assert(tycon.typeParams.nonEmpty, tycon) - tycon.etaExpand(tycon.typeParamSymbols) - /** Test that the parameter bounds in a hk type lambda `[X1,...,Xn] => C[X1, ..., Xn]` * contain the bounds of the type parameters of `C`. This is necessary to be able to * contract the hk lambda to `C`. @@ -244,7 +240,7 @@ class TypeApplications(val self: Type) extends AnyVal { def topType(using Context): Type = if self.hasSimpleKind then defn.AnyType - else etaExpand(self.typeParams) match + else self.etaExpand match case tp: HKTypeLambda => tp.derivedLambdaType(resType = tp.resultType.topType) case _ => @@ -301,45 +297,49 @@ class TypeApplications(val self: Type) extends AnyVal { /** Convert a type constructor `TC` which has type parameters `X1, ..., Xn` * to `[X1, ..., Xn] -> TC[X1, ..., Xn]`. */ - def etaExpand(tparams: List[TypeParamInfo])(using Context): Type = - HKTypeLambda.fromParams(tparams, self.appliedTo(tparams.map(_.paramRef))) - //.ensuring(res => res.EtaReduce =:= self, s"res = $res, core = ${res.EtaReduce}, self = $self, hc = ${res.hashCode}") + def etaExpand(using Context): Type = + val tparams = self.typeParams + val resType = self.appliedTo(tparams.map(_.paramRef)) + self match + case self: TypeRef if tparams.nonEmpty && self.symbol.isClass => + val prefix = self.prefix + val owner = self.symbol.owner + // Calling asSeenFrom on the type parameter infos is important + // so that class type references within another prefix have + // their type parameters' info fixed. + // e.g. from pos/i18569: + // trait M1: + // trait A + // trait F[T <: A] + // object M2 extends M1 + // Type parameter T in M1.F has an upper bound of M1#A + // But eta-expanding M2.F should have type parameters with an upper-bound of M2.A. + // So we take the prefix M2.type and the F symbol's owner, M1, + // to call asSeenFrom on T's info. + HKTypeLambda(tparams.map(_.paramName))( + tl => tparams.map(p => HKTypeLambda.toPInfo(tl.integrate(tparams, p.paramInfo.asSeenFrom(prefix, owner)))), + tl => tl.integrate(tparams, resType)) + case _ => + HKTypeLambda.fromParams(tparams, resType) /** If self is not lambda-bound, eta expand it. */ def ensureLambdaSub(using Context): Type = - if (isLambdaSub) self else EtaExpansion(self) + if isLambdaSub then self + else + assert(self.typeParams.nonEmpty, self) + self.etaExpand /** Eta expand if `self` is a (non-lambda) class reference and `bound` is a higher-kinded type */ def etaExpandIfHK(bound: Type)(using Context): Type = { val hkParams = bound.hkTypeParams if (hkParams.isEmpty) self else self match { - case self: TypeRef if self.symbol.isClass && self.typeParams.length == hkParams.length => - EtaExpansion(self) + case self: TypeRef if self.symbol.isClass && self.typeParams.hasSameLengthAs(hkParams) => + etaExpand case _ => self } } - // Like `target.etaExpand(target.typeParams)` - // except call `asSeenFrom` to fix class type parameter bounds - // e.g. from pos/i18569: - // trait M1: - // trait A - // trait F[T <: A] - // object M2 extends M1 - // Type parameter T in M2.F has an upper bound of M1#A instead of M2.A - // So we take the prefix M2.type and the F symbol's owner, M1, - // to call asSeenFrom on T's info. - def etaExpandWithAsf(using Context): Type = self match - case self: TypeRef if self.symbol.isClass => - val tparams = self.symbol.typeParams - val prefix = self.prefix - val owner = self.symbol.owner - HKTypeLambda(tparams.map(_.paramName))( - tl => tparams.map(p => HKTypeLambda.toPInfo(tl.integrate(tparams, p.info.asSeenFrom(prefix, owner)))), - tl => tl.integrate(tparams, self.appliedTo(tparams.map(_.paramRef)))) - case _ => etaExpand(typeParams) - /** Maps [Ts] => C[Ts] to C */ def etaCollapse(using Context): Type = self match case EtaExpansion(classType) => classType diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index b23bfe9fe14b..9a6ee7296239 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -594,7 +594,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling if (base.typeSymbol == cls2) return true } else if tp1.typeParams.nonEmpty && !tp1.isAnyKind then - return recur(tp1, EtaExpansion(tp2)) + return recur(tp1, tp2.etaExpand) fourthTry } @@ -734,7 +734,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling case _ => val tparams1 = tp1.typeParams if (tparams1.nonEmpty) - return recur(tp1.etaExpand(tparams1), tp2) || fourthTry + return recur(tp1.etaExpand, tp2) || fourthTry tp2 match { case EtaExpansion(tycon2: TypeRef) if tycon2.symbol.isClass && tycon2.symbol.is(JavaDefined) => recur(tp1, tycon2) || fourthTry @@ -2820,7 +2820,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling tp.symbol match case cls: ClassSymbol => if cls == defn.SingletonClass then defn.AnyType - else if cls.typeParams.nonEmpty then EtaExpansion(tp) + else if cls.typeParams.nonEmpty then tp.etaExpand else tp case sym => if !ctx.erasedTypes && sym == defn.FromJavaObjectSymbol then defn.AnyType diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 806f39ee0425..521306eb73fc 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -850,7 +850,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas } else if args.nonEmpty then tycon.safeAppliedTo(EtaExpandIfHK(sym.typeParams, args.map(translateTempPoly))) - else if (sym.typeParams.nonEmpty) tycon.etaExpand(sym.typeParams) + else if (sym.typeParams.nonEmpty) tycon.etaExpand else tycon case TYPEBOUNDStpe => val lo = readTypeRef() diff --git a/compiler/src/dotty/tools/dotc/typer/Deriving.scala b/compiler/src/dotty/tools/dotc/typer/Deriving.scala index 6def1ecc30a8..f3be1dcff766 100644 --- a/compiler/src/dotty/tools/dotc/typer/Deriving.scala +++ b/compiler/src/dotty/tools/dotc/typer/Deriving.scala @@ -165,7 +165,7 @@ trait Deriving { // case (a) ... see description above val derivedParams = clsParams.dropRight(instanceArity) val instanceType = - if (instanceArity == clsArity) clsType.etaExpand(clsParams) + if (instanceArity == clsArity) clsType.etaExpand else { val derivedParamTypes = derivedParams.map(_.typeRef) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 6621d459918b..868fcb99dc38 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -1200,7 +1200,7 @@ class Namer { typer: Typer => val forwarderName = checkNoConflict(alias.toTypeName, isPrivate = false, span) var target = pathType.select(sym) if target.typeParams.nonEmpty then - target = target.etaExpandWithAsf + target = target.etaExpand newSymbol( cls, forwarderName, MandatoryExportTypeFlags | (sym.flags & RetainedExportTypeFlags), diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index f0914a9f6664..cf30945a7751 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -377,7 +377,7 @@ object RefChecks { */ def checkOverride(checkSubType: (Type, Type) => Context ?=> Boolean, member: Symbol, other: Symbol): Unit = def memberTp(self: Type) = - if (member.isClass) TypeAlias(member.typeRef.etaExpand(member.typeParams)) + if (member.isClass) TypeAlias(member.typeRef.etaExpand) else self.memberInfo(member) def otherTp(self: Type) = self.memberInfo(other) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 165484091260..38e030ede0a9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -4283,7 +4283,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer tree1.withType(tp1) else // Eta-expand higher-kinded type - val tp1 = tree.tpe.etaExpand(tp.typeParamSymbols) + val tp1 = tree.tpe.etaExpand tree.withType(tp1) } if (ctx.mode.is(Mode.Pattern) || ctx.mode.isQuotedPattern || tree1.tpe <:< pt) tree1 From 4ff8bb1a42b85da3a940554c4fd5e2f1be6f9779 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 30 Nov 2023 16:32:18 +0000 Subject: [PATCH 082/277] Fix EtaExpansion extractor, to also honour prefix When looking at the info of the type parameters of a TypeRef, make sure to honour the reference's prefix. --- .../dotty/tools/dotc/core/TypeApplications.scala | 14 ++++++++------ tests/pos/i18569.reg1.scala | 11 +++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 tests/pos/i18569.reg1.scala diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index 99735c6de7ad..dbba562ff223 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -37,7 +37,7 @@ object TypeApplications { * contain the bounds of the type parameters of `C`. This is necessary to be able to * contract the hk lambda to `C`. */ - private def weakerBounds(tp: HKTypeLambda, tparams: List[ParamInfo])(using Context): Boolean = + private def weakerBounds(tp: HKTypeLambda, fn: Type)(using Context): Boolean = val onlyEmptyBounds = tp.typeParams.forall(_.paramInfo == TypeBounds.empty) onlyEmptyBounds // Note: this pre-test helps efficiency. It is also necessary to workaround #9965 since in some cases @@ -46,18 +46,21 @@ object TypeApplications { // In this case, we can still return true if we know that the hk lambda bounds // are empty anyway. || { + val tparams = fn.typeParams val paramRefs = tparams.map(_.paramRef) + val prefix = fn match { case fn: TypeRef => fn.prefix case _ => NoPrefix } + val owner = fn match { case fn: TypeRef => fn.symbol.owner case _ => NoSymbol } tp.typeParams.corresponds(tparams) { (param1, param2) => - param2.paramInfo frozen_<:< param1.paramInfo.substParams(tp, paramRefs) + param2.paramInfo.asSeenFrom(prefix, owner) frozen_<:< param1.paramInfo.substParams(tp, paramRefs) } } def unapply(tp: Type)(using Context): Option[Type] = tp match - case tp @ HKTypeLambda(tparams, AppliedType(fn: Type, args)) + case tp @ HKTypeLambda(tparams, AppliedType(fn, args)) if fn.typeSymbol.isClass && tparams.hasSameLengthAs(args) && args.lazyZip(tparams).forall((arg, tparam) => arg == tparam.paramRef) - && weakerBounds(tp, fn.typeParams) => Some(fn) + && weakerBounds(tp, fn) => Some(fn) case _ => None end EtaExpansion @@ -302,7 +305,6 @@ class TypeApplications(val self: Type) extends AnyVal { val resType = self.appliedTo(tparams.map(_.paramRef)) self match case self: TypeRef if tparams.nonEmpty && self.symbol.isClass => - val prefix = self.prefix val owner = self.symbol.owner // Calling asSeenFrom on the type parameter infos is important // so that class type references within another prefix have @@ -317,7 +319,7 @@ class TypeApplications(val self: Type) extends AnyVal { // So we take the prefix M2.type and the F symbol's owner, M1, // to call asSeenFrom on T's info. HKTypeLambda(tparams.map(_.paramName))( - tl => tparams.map(p => HKTypeLambda.toPInfo(tl.integrate(tparams, p.paramInfo.asSeenFrom(prefix, owner)))), + tl => tparams.map(p => HKTypeLambda.toPInfo(tl.integrate(tparams, p.paramInfo.asSeenFrom(self.prefix, owner)))), tl => tl.integrate(tparams, resType)) case _ => HKTypeLambda.fromParams(tparams, resType) diff --git a/tests/pos/i18569.reg1.scala b/tests/pos/i18569.reg1.scala new file mode 100644 index 000000000000..188ee36a02b2 --- /dev/null +++ b/tests/pos/i18569.reg1.scala @@ -0,0 +1,11 @@ +// Minimisation of the CI failure +// in scala-parallel-collections +// to do with how EtaExpansion is used +// by typeOfNew when typing a New tree + +trait Foo[+A]: + class Bar[B >: A] + +class Test: + def t1[X](foo: Foo[X]): Unit = + val bar = new foo.Bar() From 4992b4bd8893e3407050260f57e64a1c7db2035a Mon Sep 17 00:00:00 2001 From: 110416 Date: Sun, 25 Feb 2024 19:32:47 +0900 Subject: [PATCH 083/277] Update compiler/src/dotty/tools/dotc/core/ContextOps.scala Co-authored-by: Jamie Thompson --- compiler/src/dotty/tools/dotc/core/ContextOps.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/ContextOps.scala b/compiler/src/dotty/tools/dotc/core/ContextOps.scala index 3f6b49253192..a27f3cef1460 100644 --- a/compiler/src/dotty/tools/dotc/core/ContextOps.scala +++ b/compiler/src/dotty/tools/dotc/core/ContextOps.scala @@ -61,7 +61,7 @@ object ContextOps: val directSearch = def asModule = if name.isTypeName && name.endsWith(StdNames.str.MODULE_SUFFIX) then - pre.findMember(name.stripModuleClassSuffix, pre, required, excluded) match + pre.findMember(name.stripModuleClassSuffix.moduleClassName, pre, required, excluded) match case NoDenotation => NoDenotation case symDenot: SymDenotation => symDenot.companionModule.denot From 1d65c5bde5bb463d0cca0d5ecfbfea4c4d7ba15b Mon Sep 17 00:00:00 2001 From: i10416 Date: Sun, 25 Feb 2024 21:16:00 +0900 Subject: [PATCH 084/277] fix: imported symbol missing for companion module --- compiler/src/dotty/tools/dotc/core/ContextOps.scala | 5 ++++- tests/pos/i17255/Baz.java | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i17255/Baz.java diff --git a/compiler/src/dotty/tools/dotc/core/ContextOps.scala b/compiler/src/dotty/tools/dotc/core/ContextOps.scala index a27f3cef1460..427cfa47c7c1 100644 --- a/compiler/src/dotty/tools/dotc/core/ContextOps.scala +++ b/compiler/src/dotty/tools/dotc/core/ContextOps.scala @@ -41,7 +41,10 @@ object ContextOps: else pre.findMember(name, pre, required, excluded) } else // we are in the outermost context belonging to a class; self is invisible here. See inClassContext. - ctx.owner.findMember(name, ctx.owner.thisType, required, excluded) + if ctx.isJava then + javaFindMember(name, ctx.owner.thisType, lookInCompanion = true,required, excluded) + else + ctx.owner.findMember(name, ctx.owner.thisType, required, excluded) else ctx.scope.denotsNamed(name).filterWithFlags(required, excluded).toDenot(NoPrefix) } diff --git a/tests/pos/i17255/Baz.java b/tests/pos/i17255/Baz.java new file mode 100644 index 000000000000..6dbb1078949d --- /dev/null +++ b/tests/pos/i17255/Baz.java @@ -0,0 +1,7 @@ +package example; + +import example.Foo$; + +public class Baz { + private static final Foo$ MOD = Foo$.MODULE$; +} \ No newline at end of file From d84b3ca9c80bbc9e9df9f017836c5881967e013c Mon Sep 17 00:00:00 2001 From: i10416 Date: Sun, 25 Feb 2024 21:21:19 +0900 Subject: [PATCH 085/277] test: add a test to confirm scala/scala#10644 is forward-ported --- compiler/test/dotc/run-test-pickling.blacklist | 2 ++ tests/run/i17255/J.java | 13 +++++++++++++ tests/run/i17255/Module.scala | 10 ++++++++++ 3 files changed, 25 insertions(+) create mode 100644 tests/run/i17255/J.java create mode 100644 tests/run/i17255/Module.scala diff --git a/compiler/test/dotc/run-test-pickling.blacklist b/compiler/test/dotc/run-test-pickling.blacklist index 9f19b439135c..954a64db1b66 100644 --- a/compiler/test/dotc/run-test-pickling.blacklist +++ b/compiler/test/dotc/run-test-pickling.blacklist @@ -44,3 +44,5 @@ t6138 t6138-2 i12656.scala trait-static-forwarder +i17255 + diff --git a/tests/run/i17255/J.java b/tests/run/i17255/J.java new file mode 100644 index 000000000000..3dfb775423f3 --- /dev/null +++ b/tests/run/i17255/J.java @@ -0,0 +1,13 @@ +package p; + +public class J { + public static J j = new J(); + public static p.J f() { + return p.J.j; + } + public static p.Module$ module() { + return p.Module$.MODULE$; + } + + public String toString() { return "J"; } +} \ No newline at end of file diff --git a/tests/run/i17255/Module.scala b/tests/run/i17255/Module.scala new file mode 100644 index 000000000000..746da44de799 --- /dev/null +++ b/tests/run/i17255/Module.scala @@ -0,0 +1,10 @@ +package p { + object Module { + override def toString = "Module" + } +} + +object Test extends App { + assert(p.J.f().toString == "J") + assert(p.J.module().toString == "Module") +} \ No newline at end of file From cbfdf5720aac07c75aad15db63fa26a790ff5bbf Mon Sep 17 00:00:00 2001 From: i10416 Date: Sun, 25 Feb 2024 21:46:30 +0900 Subject: [PATCH 086/277] fix(test): skip a test to avoid linking error due to java source --- tests/run/i17255/Module.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/run/i17255/Module.scala b/tests/run/i17255/Module.scala index 746da44de799..f433adbf0ad6 100644 --- a/tests/run/i17255/Module.scala +++ b/tests/run/i17255/Module.scala @@ -1,3 +1,5 @@ +// scalajs: --skip + package p { object Module { override def toString = "Module" From 6db1423d8783e745b60b80b3b4ef54668b9d6318 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Wed, 21 Feb 2024 17:51:37 +0000 Subject: [PATCH 087/277] Test case for REPL bad symbolic reference --- .../test/dotty/tools/repl/ReplCompilerTests.scala | 14 ++++++++++++++ compiler/test/dotty/tools/repl/ReplTest.scala | 4 ++++ .../test/dotty/tools/repl/TabcompleteTests.scala | 4 ---- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala index 26092b73f107..8c29c8e03b33 100644 --- a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala +++ b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala @@ -409,6 +409,20 @@ class ReplCompilerTests extends ReplTest: @Test def `i13097 expect template after colon` = contextually: assert(ParseResult.isIncomplete("class C:")) + @Test def i15562: Unit = initially { + val s1 = run("List(1, 2).filter(_ % 2 == 0).foreach(println)") + assertEquals("2", storedOutput().trim) + s1 + } andThen { s1 ?=> + val comp = tabComplete("List(1, 2).filter(_ % 2 == 0).fore") + assertEquals(List("foreach"), comp.distinct) + s1 + } andThen { + val s2 = run("List(1, 2).filter(_ % 2 == 0).foreach(println)") + assertEquals("2", storedOutput().trim) + s2 + } + object ReplCompilerTests: private val pattern = Pattern.compile("\\r[\\n]?|\\n"); diff --git a/compiler/test/dotty/tools/repl/ReplTest.scala b/compiler/test/dotty/tools/repl/ReplTest.scala index ae0d0c666a9c..bc70f68e45fe 100644 --- a/compiler/test/dotty/tools/repl/ReplTest.scala +++ b/compiler/test/dotty/tools/repl/ReplTest.scala @@ -40,6 +40,10 @@ extends ReplDriver(options, new PrintStream(out, true, StandardCharsets.UTF_8.na def contextually[A](op: Context ?=> A): A = op(using initialState.context) + /** Returns the `(, )`*/ + def tabComplete(src: String)(implicit state: State): List[String] = + completions(src.length, src, state).map(_.value).sorted + extension [A](state: State) infix def andThen(op: State ?=> A): A = op(using state) diff --git a/compiler/test/dotty/tools/repl/TabcompleteTests.scala b/compiler/test/dotty/tools/repl/TabcompleteTests.scala index 0bce525e1469..e4c3a2557e7d 100644 --- a/compiler/test/dotty/tools/repl/TabcompleteTests.scala +++ b/compiler/test/dotty/tools/repl/TabcompleteTests.scala @@ -8,10 +8,6 @@ import org.junit.Test /** These tests test input that has proved problematic */ class TabcompleteTests extends ReplTest { - /** Returns the `(, )`*/ - private def tabComplete(src: String)(implicit state: State): List[String] = - completions(src.length, src, state).map(_.value).sorted - @Test def tabCompleteList = initially { val comp = tabComplete("List.r") assertEquals(List("range"), comp.distinct) From c2c78d7312ba882a1c7be3c1369e753282ed7bd9 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Wed, 21 Feb 2024 22:08:06 +0000 Subject: [PATCH 088/277] Add a test case which still fails --- .../test/dotty/tools/repl/ReplCompilerTests.scala | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala index 8c29c8e03b33..cfae36f394af 100644 --- a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala +++ b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala @@ -423,6 +423,20 @@ class ReplCompilerTests extends ReplTest: s2 } + @Test def i15562b: Unit = initially { + val s1 = run("List(1, 2).filter(_ % 2 == 0).foreach(println)") + assertEquals("2", storedOutput().trim) + s1 + } andThen { s1 ?=> + val comp = tabComplete("val x = false + true; List(1, 2).filter(_ % 2 == 0).fore") + assertEquals(List("foreach"), comp.distinct) + s1 + } andThen { + val s2 = run("List(1, 2).filter(_ % 2 == 0).foreach(println)") + assertEquals("2", storedOutput().trim) + s2 + } + object ReplCompilerTests: private val pattern = Pattern.compile("\\r[\\n]?|\\n"); From 4615a9c4ef576405ab61680a3f2ba9a11c0b33fc Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 23 Feb 2024 17:22:37 +0000 Subject: [PATCH 089/277] Avoid losing the symbols denotation on update --- compiler/src/dotty/tools/dotc/core/Symbols.scala | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 32a2da8b46b6..619ec92ae3e7 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -112,16 +112,23 @@ object Symbols extends SymUtils { private def computeDenot(lastd: SymDenotation)(using Context): SymDenotation = { util.Stats.record("Symbol.computeDenot") val now = ctx.period + val prev = checkedPeriod checkedPeriod = now - if (lastd.validFor contains now) lastd else recomputeDenot(lastd) + if lastd.validFor.contains(now) then + lastd + else + val newd = recomputeDenot(lastd) + if newd.exists then + lastDenot = newd + else + checkedPeriod = prev + newd } /** Overridden in NoSymbol */ protected def recomputeDenot(lastd: SymDenotation)(using Context): SymDenotation = { util.Stats.record("Symbol.recomputeDenot") - val newd = lastd.current.asInstanceOf[SymDenotation] - lastDenot = newd - newd + lastd.current.asSymDenotation } /** The original denotation of this symbol, without forcing anything */ From 9cfcb8c3492d4493118e7f6c3eb192c4004d4d06 Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Mon, 26 Feb 2024 13:09:24 +0100 Subject: [PATCH 090/277] Disable scala-onnx from the community build --- .../test/scala/dotty/communitybuild/CommunityBuildTest.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala b/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala index 9a4965577cf1..bf78c8e1a2cf 100644 --- a/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala +++ b/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala @@ -71,7 +71,7 @@ class CommunityBuildTestC: @Test def jacksonModuleScala = projects.jacksonModuleScala.run() @Test def libretto = projects.libretto.run() @Test def minitest = projects.minitest.run() - @Test def onnxScala = projects.onnxScala.run() + //@Test def onnxScala = projects.onnxScala.run() @Test def oslib = projects.oslib.run() // @Test def oslibWatch = projects.oslibWatch.run() @Test def parboiled2 = projects.parboiled2.run() From 2e684d8fdf489cadce57a51759cc41725038b6f6 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Sat, 24 Feb 2024 23:33:42 +0100 Subject: [PATCH 091/277] Add a new test for selection range on function parameters --- .../tools/pc/tests/SelectionRangeSuite.scala | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/SelectionRangeSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/SelectionRangeSuite.scala index 84417bb5e414..e277a67c466b 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/SelectionRangeSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/SelectionRangeSuite.scala @@ -101,3 +101,49 @@ class SelectionRangeSuite extends BaseSelectionRangeSuite: |}<>region>>a: Int<>region>>a: Int, b: Int<>region>>def func(a: Int, b: Int) = + | a + b< + | a + b + |}""".stripMargin, + List[String]( + """|object Main extends App { + | val func = (>>region>>a: Int< + | a + b + |}""".stripMargin, + """|object Main extends App { + | val func = (>>region>>a: Int, b: Int< + | a + b + |}""".stripMargin, + """|object Main extends App { + | val func = >>region>>(a: Int, b: Int) => + | a + b<>region>>val func = (a: Int, b: Int) => + | a + b< Date: Sun, 25 Feb 2024 00:25:26 +0100 Subject: [PATCH 092/277] Add selection range for a parameter list in a function/method Given a query as ```scala def func(a@@: Int, b: Int)(c: Int) = a + b + c ``` range selection will now let you choose `a: Int, b: Int`. The previous options are `a: Int` and the whole definition of `func`. --- .../tools/pc/SelectionRangeProvider.scala | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/presentation-compiler/src/main/dotty/tools/pc/SelectionRangeProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/SelectionRangeProvider.scala index a7d07b12f40c..9dce37028bea 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/SelectionRangeProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/SelectionRangeProvider.scala @@ -6,10 +6,12 @@ import java.util as ju import scala.jdk.CollectionConverters._ import scala.meta.pc.OffsetParams +import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.interactive.Interactive import dotty.tools.dotc.interactive.InteractiveDriver import dotty.tools.dotc.util.SourceFile +import dotty.tools.dotc.util.SourcePosition import dotty.tools.pc.utils.MtagsEnrichments.* import org.eclipse.lsp4j @@ -46,11 +48,7 @@ class SelectionRangeProvider( Interactive.pathTo(driver.openedTrees(uri), pos)(using ctx) val bareRanges = path - .map { tree => - val selectionRange = new SelectionRange() - selectionRange.setRange(tree.sourcePos.toLsp) - selectionRange - } + .flatMap(selectionRangesFromTree(pos)) val comments = driver.compilationUnits.get(uri).map(_.comments).toList.flatten @@ -79,6 +77,33 @@ class SelectionRangeProvider( } end selectionRange + /** Given a tree, create a seq of [[SelectionRange]]s corresponding to that tree. */ + private def selectionRangesFromTree(pos: SourcePosition)(tree: tpd.Tree)(using Context) = + def toSelectionRange(srcPos: SourcePosition) = + val selectionRange = new SelectionRange() + selectionRange.setRange(srcPos.toLsp) + selectionRange + + val treeSelectionRange = toSelectionRange(tree.sourcePos) + + tree match + case tpd.DefDef(name, paramss, tpt, rhs) => + // If source position is within a parameter list, add a selection range covering that whole list. + val selectedParams = + paramss + .iterator + .flatMap: // parameter list to a sourcePosition covering the whole list + case Seq(param) => Some(param.sourcePos) + case params @ Seq(head, tail*) => + val srcPos = head.sourcePos + val lastSpan = tail.last.span + Some(SourcePosition(srcPos.source, srcPos.span union lastSpan, srcPos.outer)) + case Seq() => None + .find(_.contains(pos)) + .map(toSelectionRange) + selectedParams ++ Seq(treeSelectionRange) + case _ => Seq(treeSelectionRange) + private def setParent( child: SelectionRange, parent: SelectionRange From e79b2e99800d2d06696e04192a63ce0e6f22bff8 Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 26 Feb 2024 13:59:52 +0100 Subject: [PATCH 093/277] Some tweaks to denotation updates - Be more specific when we go into the special case of not updating checkedPeriod - Always update lastDenotation. - Keep computeDenot small, move work to recomputeDenot --- .../src/dotty/tools/dotc/core/Symbols.scala | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 619ec92ae3e7..1cd4d5f86d05 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -110,25 +110,28 @@ object Symbols extends SymUtils { } private def computeDenot(lastd: SymDenotation)(using Context): SymDenotation = { + // Written that way do that it comes in at 32 bytes and is therefore inlineable for + // the JIT (reputedly, cutoff is at 35 bytes) util.Stats.record("Symbol.computeDenot") val now = ctx.period - val prev = checkedPeriod checkedPeriod = now - if lastd.validFor.contains(now) then - lastd - else - val newd = recomputeDenot(lastd) - if newd.exists then - lastDenot = newd - else - checkedPeriod = prev - newd + if lastd.validFor.contains(now) then lastd else recomputeDenot(lastd) } /** Overridden in NoSymbol */ protected def recomputeDenot(lastd: SymDenotation)(using Context): SymDenotation = { util.Stats.record("Symbol.recomputeDenot") - lastd.current.asSymDenotation + val newd = lastd.current.asInstanceOf[SymDenotation] + lastDenot = newd + if !newd.exists && lastd.initial.validFor.firstPhaseId > ctx.phaseId then + // We are trying to bring forward a symbol that is defined only at a later phase + // (typically, a nested Java class, invisible before erasure). + // In that case, keep the checked period to the previous validity, which + // means we will try another bring forward when the symbol is referenced + // at a later phase. Otherwise we'd get stuck on NoDenotation here. + // See #15562 and test i15562b in ReplCompilerTests + checkedPeriod = lastd.initial.validFor + newd } /** The original denotation of this symbol, without forcing anything */ @@ -798,7 +801,7 @@ object Symbols extends SymUtils { cls: ClassSymbol, name: TermName = nme.WILDCARD, selfInfo: Type = NoType)(using Context): TermSymbol = - newSymbol(cls, name, SelfSymFlags, selfInfo orElse cls.classInfo.selfType, coord = cls.coord) + newSymbol(cls, name, SelfSymFlags, selfInfo.orElse(cls.classInfo.selfType), coord = cls.coord) /** Create new type parameters with given owner, names, and flags. * @param boundsFn A function that, given type refs to the newly created @@ -965,7 +968,7 @@ object Symbols extends SymUtils { */ def getPackageClassIfDefined(path: PreName)(using Context): Symbol = staticRef(path.toTypeName, isPackage = true, generateStubs = false) - .disambiguate(_ is PackageClass).symbol + .disambiguate(_.is(PackageClass)).symbol def requiredModule(path: PreName)(using Context): TermSymbol = { val name = path.toTermName From a2212fa8c7a2f702e706dec1e04f67291824339e Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Tue, 20 Feb 2024 15:42:37 +0100 Subject: [PATCH 094/277] Bump JLine to 3.19.0 -> 3.24.1 --- project/Build.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index 64aab2371b8f..3f9f06dbb660 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -624,9 +624,9 @@ object Build { libraryDependencies ++= Seq( "org.scala-lang.modules" % "scala-asm" % "9.6.0-scala-1", // used by the backend Dependencies.compilerInterface, - "org.jline" % "jline-reader" % "3.19.0", // used by the REPL - "org.jline" % "jline-terminal" % "3.19.0", - "org.jline" % "jline-terminal-jna" % "3.19.0", // needed for Windows + "org.jline" % "jline-reader" % "3.24.1", // used by the REPL + "org.jline" % "jline-terminal" % "3.24.1", + "org.jline" % "jline-terminal-jna" % "3.24.1", // needed for Windows ("io.get-coursier" %% "coursier" % "2.0.16" % Test).cross(CrossVersion.for3Use2_13), ), From 29461f46ff5fb9acc4ea57de0ac114f1b254ea5d Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Sat, 24 Feb 2024 12:16:12 +0100 Subject: [PATCH 095/277] Bump sbt from 1.9.7 to 1.9.9 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index e8a1e246e8ad..04267b14af69 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.9.7 +sbt.version=1.9.9 From b7696fa711e113e2a6a957edeaac644557956cd6 Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Sun, 25 Feb 2024 01:09:14 +0100 Subject: [PATCH 096/277] Update Coursier test --- .../dotty/tools/coursier/CoursierScalaTests.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/test-coursier/dotty/tools/coursier/CoursierScalaTests.scala b/compiler/test-coursier/dotty/tools/coursier/CoursierScalaTests.scala index 8f9a9bd69a50..b8dfa833c437 100644 --- a/compiler/test-coursier/dotty/tools/coursier/CoursierScalaTests.scala +++ b/compiler/test-coursier/dotty/tools/coursier/CoursierScalaTests.scala @@ -76,7 +76,7 @@ class CoursierScalaTests: def emptyArgsEqualsRepl() = val output = CoursierScalaTests.csScalaCmd() - assertTrue(output.mkString("\n").contains("Unable to create a system terminal")) // Scala attempted to create REPL so we can assume it is working + assertTrue(output.mkString("\n").contains("Unable to create a terminal")) // Scala attempted to create REPL so we can assume it is working emptyArgsEqualsRepl() def run() = @@ -133,7 +133,7 @@ class CoursierScalaTests: def replWithArgs() = val output = CoursierScalaTests.csScalaCmd("-source", "3.0-migration") - assertTrue(output.mkString("\n").contains("Unable to create a system terminal")) // Scala attempted to create REPL so we can assume it is working + assertTrue(output.mkString("\n").contains("Unable to create a terminal")) // Scala attempted to create REPL so we can assume it is working replWithArgs() def argumentFile() = From adc2205606bdcff6800a118d8edfe3700b8be439 Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Mon, 26 Feb 2024 14:21:37 +0100 Subject: [PATCH 097/277] Bump JLine to 3.24.1-> 3.25.1 --- project/Build.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index 3f9f06dbb660..f54fcdc3f133 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -624,9 +624,9 @@ object Build { libraryDependencies ++= Seq( "org.scala-lang.modules" % "scala-asm" % "9.6.0-scala-1", // used by the backend Dependencies.compilerInterface, - "org.jline" % "jline-reader" % "3.24.1", // used by the REPL - "org.jline" % "jline-terminal" % "3.24.1", - "org.jline" % "jline-terminal-jna" % "3.24.1", // needed for Windows + "org.jline" % "jline-reader" % "3.25.1", // used by the REPL + "org.jline" % "jline-terminal" % "3.25.1", + "org.jline" % "jline-terminal-jna" % "3.25.1", // needed for Windows ("io.get-coursier" %% "coursier" % "2.0.16" % Test).cross(CrossVersion.for3Use2_13), ), From c7f62877e9aa4fb8d3a17bb51f7e7a6212cb64db Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Sat, 24 Feb 2024 15:02:54 -0800 Subject: [PATCH 098/277] in build, replace deprecated sbt API call --- project/PublishBinPlugin.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/PublishBinPlugin.scala b/project/PublishBinPlugin.scala index 5e5397c4b4dc..51575a0d503c 100644 --- a/project/PublishBinPlugin.scala +++ b/project/PublishBinPlugin.scala @@ -21,7 +21,7 @@ object PublishBinPlugin extends AutoPlugin { override val globalSettings = Seq(publishLocalBin := (())) override val projectSettings: Seq[Def.Setting[_]] = Def settings ( - publishLocalBin := Classpaths.publishTask(publishLocalBinConfig).value, + publishLocalBin := Classpaths.publishOrSkip(publishLocalBinConfig, publishLocal / skip).value, publishLocalBinConfig := Classpaths.publishConfig( false, // publishMavenStyle.value, Classpaths.deliverPattern(crossTarget.value), From 52bd4cfc3a178e619b0495cb9942dc48e3beccfb Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 26 Feb 2024 15:57:02 +0100 Subject: [PATCH 099/277] Rename scala2-library-tasty with experimental This is to prepare the it for release. The name of the jar will be `scala2-library-tasty-experimental` to make it clear that it is not stable yet. --- project/Build.scala | 2 ++ sbt-test/sbt-dotty/scala2-library-tasty/build.sbt | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/project/Build.scala b/project/Build.scala index 64aab2371b8f..b624466efecc 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1229,6 +1229,7 @@ object Build { lazy val `scala2-library-tasty` = project.in(file("scala2-library-tasty")). withCommonSettings(Bootstrapped). settings( + moduleName := "scala2-library-tasty-experimental", exportJars := true, Compile / packageBin / mappings := { (`scala2-library-bootstrapped` / Compile / packageBin / mappings).value @@ -1240,6 +1241,7 @@ object Build { lazy val `scala2-library-cc-tasty` = project.in(file("scala2-library-cc-tasty")). withCommonSettings(Bootstrapped). settings( + moduleName := "scala2-library-cc-tasty-experimental", exportJars := true, Compile / packageBin / mappings := { (`scala2-library-cc` / Compile / packageBin / mappings).value diff --git a/sbt-test/sbt-dotty/scala2-library-tasty/build.sbt b/sbt-test/sbt-dotty/scala2-library-tasty/build.sbt index ce95be79470f..25a0197348b7 100644 --- a/sbt-test/sbt-dotty/scala2-library-tasty/build.sbt +++ b/sbt-test/sbt-dotty/scala2-library-tasty/build.sbt @@ -1,4 +1,4 @@ scalaVersion := sys.props("plugin.scalaVersion") -libraryDependencies += "org.scala-lang" %% "scala2-library-tasty" % scalaVersion.value +libraryDependencies += "org.scala-lang" %% "scala2-library-tasty-experimental" % scalaVersion.value scalacOptions += "-Yscala2-unpickler:never" // check that we do not load symbol from the Scala 2 library classfiles (use TASTy) From 5631d76f247c3d02e21eeab135b7917f30f21394 Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 26 Feb 2024 15:58:30 +0100 Subject: [PATCH 100/277] Avoid setting lastDenot to NoDenotation in the forward reference scenario This brings back an element of the original solution. --- compiler/src/dotty/tools/dotc/core/Symbols.scala | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 1cd4d5f86d05..54b97fe1664e 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -122,15 +122,16 @@ object Symbols extends SymUtils { protected def recomputeDenot(lastd: SymDenotation)(using Context): SymDenotation = { util.Stats.record("Symbol.recomputeDenot") val newd = lastd.current.asInstanceOf[SymDenotation] - lastDenot = newd - if !newd.exists && lastd.initial.validFor.firstPhaseId > ctx.phaseId then + if newd.exists || lastd.initial.validFor.firstPhaseId <= ctx.phaseId then + lastDenot = newd + else // We are trying to bring forward a symbol that is defined only at a later phase // (typically, a nested Java class, invisible before erasure). - // In that case, keep the checked period to the previous validity, which - // means we will try another bring forward when the symbol is referenced - // at a later phase. Otherwise we'd get stuck on NoDenotation here. + // In that case, keep lastDenot as it was and set the checked period to lastDenot's + // previous validity, which means we will try another bring forward when the symbol + // is referenced at a later phase. Otherwise we'd get stuck on NoDenotation here. // See #15562 and test i15562b in ReplCompilerTests - checkedPeriod = lastd.initial.validFor + checkedPeriod = lastd.validFor newd } From 46c50e7ba25554f2ba7f9a422fb9109d5387348e Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 26 Feb 2024 18:07:42 +0100 Subject: [PATCH 101/277] Update compiler/src/dotty/tools/dotc/core/Symbols.scala --- compiler/src/dotty/tools/dotc/core/Symbols.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 54b97fe1664e..78c736649605 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -110,7 +110,7 @@ object Symbols extends SymUtils { } private def computeDenot(lastd: SymDenotation)(using Context): SymDenotation = { - // Written that way do that it comes in at 32 bytes and is therefore inlineable for + // Written that way so that it comes in at 32 bytes and is therefore inlineable for // the JIT (reputedly, cutoff is at 35 bytes) util.Stats.record("Symbol.computeDenot") val now = ctx.period From c25eddec7f4340fc8fa39b9985d4f3e7929af067 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 26 Feb 2024 17:28:56 +0000 Subject: [PATCH 102/277] Lub MatchTypeTree case body types and store as the inferred bound --- .../src/dotty/tools/dotc/core/TypeComparer.scala | 13 +------------ compiler/src/dotty/tools/dotc/typer/Typer.scala | 10 +++++++++- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 9373889b37d6..b23bfe9fe14b 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -1030,17 +1030,6 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling if tp1 ne tp1norm then recur(tp1norm, tp2) else either(recur(tp11, tp2), recur(tp12, tp2)) case tp1: MatchType => - def compareUpper = - val lub1 = tp1.cases.foldLeft(defn.NothingType: Type): (acc, case1) => - if acc.exists then - val rhs = case1.resultType match { case defn.MatchCase(_, body) => body } - val isRecursive = rhs.existsPart(_.isInstanceOf[LazyRef]) - if isRecursive then NoType else lub(acc, rhs) - else acc - if lub1.exists then - recur(lub1, tp2) - else - recur(tp1.underlying, tp2) def compareMatch = tp2 match { case tp2: MatchType => // we allow a small number of scrutinee types to be widened: @@ -1058,7 +1047,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling tp1.cases.corresponds(tp2.cases)(isSubType) case _ => false } - (!caseLambda.exists || canWidenAbstract) && compareUpper || compareMatch + (!caseLambda.exists || canWidenAbstract) && recur(tp1.underlying, tp2) || compareMatch case tp1: AnnotatedType if tp1.isRefining => isNewSubType(tp1.parent) case JavaArrayType(elem1) => diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index f1db302e958c..b96aa75b70c4 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -2373,7 +2373,15 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer report.error(MatchTypeScrutineeCannotBeHigherKinded(sel1Tpe), sel1.srcPos) val pt1 = if (bound1.isEmpty) pt else bound1.tpe val cases1 = tree.cases.mapconserve(typedTypeCase(_, sel1Tpe, pt1)) - assignType(cpy.MatchTypeTree(tree)(bound1, sel1, cases1), bound1, sel1, cases1) + val bound2 = if tree.bound.isEmpty then + val lub = cases1.foldLeft(defn.NothingType: Type): (acc, case1) => + if !acc.exists then NoType + else if case1.body.tpe.existsPart(_.isInstanceOf[LazyRef]) then NoType + else acc | TypeOps.avoid(case1.body.tpe, patVars(case1)) + if lub.exists then TypeTree(lub, inferred = true) + else bound1 + else bound1 + assignType(cpy.MatchTypeTree(tree)(bound2, sel1, cases1), bound2, sel1, cases1) } def typedByNameTypeTree(tree: untpd.ByNameTypeTree)(using Context): ByNameTypeTree = tree.result match From 000de8436787c77fa5bf220dcc025d7e6df525b6 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 22 Jan 2024 16:52:27 +0000 Subject: [PATCH 103/277] Reuse methods for prefix and owner --- .../tools/dotc/core/TypeApplications.scala | 9 +++-- tests/neg/i7820.check | 34 +++++++++++++++++++ tests/neg/i7820.scala | 4 +-- 3 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 tests/neg/i7820.check diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index dbba562ff223..223d3bb11515 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -48,9 +48,12 @@ object TypeApplications { || { val tparams = fn.typeParams val paramRefs = tparams.map(_.paramRef) - val prefix = fn match { case fn: TypeRef => fn.prefix case _ => NoPrefix } - val owner = fn match { case fn: TypeRef => fn.symbol.owner case _ => NoSymbol } + val prefix = fn.normalizedPrefix + val owner = fn.typeSymbol.maybeOwner tp.typeParams.corresponds(tparams) { (param1, param2) => + // see tests/neg/variances-constr.scala + // its B parameter should have info <: Any, using class C as the owner + // rather than info <: A, using class Inner2 as the owner param2.paramInfo.asSeenFrom(prefix, owner) frozen_<:< param1.paramInfo.substParams(tp, paramRefs) } } @@ -303,7 +306,7 @@ class TypeApplications(val self: Type) extends AnyVal { def etaExpand(using Context): Type = val tparams = self.typeParams val resType = self.appliedTo(tparams.map(_.paramRef)) - self match + self.dealias match case self: TypeRef if tparams.nonEmpty && self.symbol.isClass => val owner = self.symbol.owner // Calling asSeenFrom on the type parameter infos is important diff --git a/tests/neg/i7820.check b/tests/neg/i7820.check new file mode 100644 index 000000000000..14dfc910ae6d --- /dev/null +++ b/tests/neg/i7820.check @@ -0,0 +1,34 @@ +-- [E046] Cyclic Error: tests/neg/i7820.scala:1:23 --------------------------------------------------------------------- +1 |trait A1 { type F[X <: F[_, _], Y] } // error: cyclic reference involving type F + | ^ + | Cyclic reference involving type F + | + | Run with -explain-cyclic for more details. + | + | longer explanation available when compiling with `-explain` +-- [E046] Cyclic Error: tests/neg/i7820.scala:2:23 --------------------------------------------------------------------- +2 |trait A2 { type F[X <: F, Y] } // error: cyclic reference involving type F + | ^ + | Cyclic reference involving type F + | + | Run with -explain-cyclic for more details. + | + | longer explanation available when compiling with `-explain` +-- [E046] Cyclic Error: tests/neg/i7820.scala:3:23 --------------------------------------------------------------------- +3 |trait A3 { type F[X >: F, Y] } // error: cyclic reference involving type F + | ^ + | Cyclic reference involving type F + | + | Run with -explain-cyclic for more details. + | + | longer explanation available when compiling with `-explain` +-- Warning: tests/neg/i7820.scala:1:25 --------------------------------------------------------------------------------- +1 |trait A1 { type F[X <: F[_, _], Y] } // error: cyclic reference involving type F + | ^ + | `_` is deprecated for wildcard arguments of types: use `?` instead + | This construct can be rewritten automatically under -rewrite -source 3.4-migration. +-- Warning: tests/neg/i7820.scala:1:28 --------------------------------------------------------------------------------- +1 |trait A1 { type F[X <: F[_, _], Y] } // error: cyclic reference involving type F + | ^ + | `_` is deprecated for wildcard arguments of types: use `?` instead + | This construct can be rewritten automatically under -rewrite -source 3.4-migration. diff --git a/tests/neg/i7820.scala b/tests/neg/i7820.scala index 22ec8b7ac8b1..cc803aa1f3d6 100644 --- a/tests/neg/i7820.scala +++ b/tests/neg/i7820.scala @@ -1,3 +1,3 @@ trait A1 { type F[X <: F[_, _], Y] } // error: cyclic reference involving type F -trait A2 { type F[X <: F, Y] } // error: cyclic reference involving type F // error -trait A3 { type F[X >: F, Y] } // error: cyclic reference involving type F // error +trait A2 { type F[X <: F, Y] } // error: cyclic reference involving type F +trait A3 { type F[X >: F, Y] } // error: cyclic reference involving type F From 8412f788b35be5af356e71a08207391b0d965978 Mon Sep 17 00:00:00 2001 From: EnzeXing Date: Mon, 26 Feb 2024 22:56:52 -0500 Subject: [PATCH 104/277] Adding support for filtering Fun --- .../dotty/tools/dotc/transform/init/Objects.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala index c76f4658eecb..41d5bd963fec 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala @@ -601,10 +601,11 @@ object Objects: case _ => a def filterType(tpe: Type)(using Context): Value = - // if tpe is SAMType and a is Fun, allow it val baseClasses = tpe.baseClasses if baseClasses.isEmpty then a - else filterClass(baseClasses.head) // could have called ClassSymbol, but it does not handle OrType and AndType + else tpe match + case t @ SAMType(_, _) if a.isInstanceOf[Fun] => a // if tpe is SAMType and a is Fun, allow it + case _ => filterClass(baseClasses.head) // could have called ClassSymbol, but it does not handle OrType and AndType def filterClass(sym: Symbol)(using Context): Value = if !sym.isClass then a @@ -616,10 +617,9 @@ object Objects: case ref: Ref => Bottom case ValueSet(values) => values.map(v => v.filterClass(klass)).join case arr: OfArray => if defn.ArrayClass.isSubClass(klass) then arr else Bottom - case fun: Fun => if defn.Function1.isSubClass(klass) then fun else Bottom - // TODO: could be more precise for OfArray; possibly add class information for Fun - // If ArrayClass.isSubClass(klass) keep the array else discard (see Definitions.scala) - // For function, if any superclass is FunctionClass (or a single abstract method interface?), allow it + case fun: Fun => + val functionSuperCls = klass.baseClasses.filter(defn.isFunctionClass) + if functionSuperCls.nonEmpty then fun else Bottom extension (value: Ref | Cold.type) def widenRefOrCold(height : Int)(using Context) : Ref | Cold.type = value.widen(height).asInstanceOf[ThisValue] From 0a95653482d54704d59e9e1fa3b2c2e4b56b95c5 Mon Sep 17 00:00:00 2001 From: EnzeXing Date: Mon, 26 Feb 2024 22:59:03 -0500 Subject: [PATCH 105/277] Addressed comments --- compiler/src/dotty/tools/dotc/transform/init/Util.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Util.scala b/compiler/src/dotty/tools/dotc/transform/init/Util.scala index 1114a9efc218..756fd1a0a8e7 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Util.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Util.scala @@ -81,8 +81,8 @@ object Util: object TypeCast: def unapply(tree: Tree)(using Context): Option[(Tree, Type)] = tree match - case TypeApply(Select(qual, _), typeArg) if tree.symbol.isTypeCast => - Some(qual, typeArg.head.tpe) + case TypeApply(Select(qual, _), typeArgs) if tree.symbol.isTypeCast => + Some(qual, typeArgs.head.tpe) case _ => None def resolve(cls: ClassSymbol, sym: Symbol)(using Context): Symbol = log("resove " + cls + ", " + sym, printer, (_: Symbol).show): From c1f2022862ad590ba1359c00fea8ab051e95bf9c Mon Sep 17 00:00:00 2001 From: Kacper Korban Date: Sat, 17 Feb 2024 01:04:02 +0100 Subject: [PATCH 106/277] Port coverage filter options - Add `-coverage-exclude-packages` option that excludes packages and classes from generating coverage - Add `-coverage-exclude-files` option that excludes files from generating coverage --- .../tools/dotc/config/ScalaSettings.scala | 2 ++ .../dotc/transform/InstrumentCoverage.scala | 27 +++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index cb6d0bdab424..06fddac63df6 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -127,6 +127,8 @@ trait CommonScalaSettings: /* Coverage settings */ val coverageOutputDir = PathSetting("-coverage-out", "Destination for coverage classfiles and instrumentation data.", "", aliases = List("--coverage-out")) + val coverageExcludePackages: Setting[List[String]] = MultiStringSetting("-coverage-exclude-packages", "packages", "Semicolon separated list of regexes for packages to exclude from coverage.", aliases = List("--coverage-exclude-packages")) + val coverageExcludeFiles: Setting[List[String]] = MultiStringSetting("-coverage-exclude-files", "files", "Semicolon separated list of regexes for files to exclude from coverage.", aliases = List("--coverage-exclude-files")) /* Other settings */ val encoding: Setting[String] = StringSetting("-encoding", "encoding", "Specify character encoding used by source files.", Properties.sourceEncoding, aliases = List("--encoding")) diff --git a/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala b/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala index eac44e982603..c759f0ad3734 100644 --- a/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala +++ b/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala @@ -13,12 +13,14 @@ import core.Constants.Constant import core.NameOps.isContextFunction import core.StdNames.nme import core.Types.* +import core.Decorators.* import coverage.* import typer.LiftCoverage import util.{SourcePosition, SourceFile} import util.Spans.Span import localopt.StringInterpolatorOpt import inlines.Inlines +import scala.util.matching.Regex /** Implements code coverage by inserting calls to scala.runtime.coverage.Invoker * ("instruments" the source code). @@ -58,6 +60,18 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer: Serializer.serialize(coverage, outputPath, ctx.settings.sourceroot.value) + private def isClassIncluded(sym: Symbol)(using Context): Boolean = + val excludedClassNamePatterns = ctx.settings.coverageExcludePackages.value.map(_.r.pattern) + excludedClassNamePatterns.isEmpty || !excludedClassNamePatterns.exists( + _.matcher(sym.fullName.toText(ctx.printerFn(ctx)).show).nn.matches + ) + + private def isFileIncluded(file: SourceFile)(using Context): Boolean = + val excludedFilePatterns = ctx.settings.coverageExcludeFiles.value.map(_.r.pattern) + excludedFilePatterns.isEmpty || !excludedFilePatterns.exists( + _.matcher(file.path.replace(".scala", "")).nn.matches + ) + override protected def newTransformer(using Context) = CoverageTransformer(ctx.settings.coverageOutputDir.value) @@ -269,8 +283,17 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer: transformDefDef(tree) case tree: PackageDef => - // only transform the statements of the package - cpy.PackageDef(tree)(tree.pid, transform(tree.stats)) + if (isFileIncluded(tree.srcPos.sourcePos.source) && isClassIncluded(tree.symbol)) + // only transform the statements of the package + cpy.PackageDef(tree)(tree.pid, transform(tree.stats)) + else + tree + + case tree: TypeDef => + if (isFileIncluded(tree.srcPos.sourcePos.source) && isClassIncluded(tree.symbol)) + super.transform(tree) + else + tree case tree: Assign => // only transform the rhs From 7affcee006bf26be59ebed98482b9551c9c1afda Mon Sep 17 00:00:00 2001 From: Kacper Korban Date: Sat, 17 Feb 2024 16:00:59 +0100 Subject: [PATCH 107/277] Add tests for coverage filters --- .gitignore | 4 -- .../tools/dotc/config/ScalaSettings.scala | 4 +- tests/coverage/pos/ExcludeClass.scala | 19 +++++ .../coverage/pos/ExcludeClass.scoverage.check | 71 +++++++++++++++++++ tests/coverage/pos/ExcludeDef.scala | 9 +++ tests/coverage/pos/ExcludeDef.scoverage.check | 20 ++++++ tests/coverage/pos/ExcludeFile.scala | 11 +++ .../coverage/pos/ExcludeFile.scoverage.check | 20 ++++++ tests/coverage/pos/ExcludeOtherStuff.scala | 15 ++++ .../pos/ExcludeOtherStuff.scoverage.check | 20 ++++++ tests/coverage/pos/ExcludePackage.scala | 11 +++ .../pos/ExcludePackage.scoverage.check | 20 ++++++ 12 files changed, 218 insertions(+), 6 deletions(-) create mode 100644 tests/coverage/pos/ExcludeClass.scala create mode 100644 tests/coverage/pos/ExcludeClass.scoverage.check create mode 100644 tests/coverage/pos/ExcludeDef.scala create mode 100644 tests/coverage/pos/ExcludeDef.scoverage.check create mode 100644 tests/coverage/pos/ExcludeFile.scala create mode 100644 tests/coverage/pos/ExcludeFile.scoverage.check create mode 100644 tests/coverage/pos/ExcludeOtherStuff.scala create mode 100644 tests/coverage/pos/ExcludeOtherStuff.scoverage.check create mode 100644 tests/coverage/pos/ExcludePackage.scala create mode 100644 tests/coverage/pos/ExcludePackage.scoverage.check diff --git a/.gitignore b/.gitignore index 3d44cdefb941..0fc39ecbae5b 100644 --- a/.gitignore +++ b/.gitignore @@ -99,7 +99,3 @@ docs/_spec/.jekyll-metadata # scaladoc related scaladoc/output/ - -#coverage -coverage/ - diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 06fddac63df6..3b13ad8d74e2 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -127,8 +127,8 @@ trait CommonScalaSettings: /* Coverage settings */ val coverageOutputDir = PathSetting("-coverage-out", "Destination for coverage classfiles and instrumentation data.", "", aliases = List("--coverage-out")) - val coverageExcludePackages: Setting[List[String]] = MultiStringSetting("-coverage-exclude-packages", "packages", "Semicolon separated list of regexes for packages to exclude from coverage.", aliases = List("--coverage-exclude-packages")) - val coverageExcludeFiles: Setting[List[String]] = MultiStringSetting("-coverage-exclude-files", "files", "Semicolon separated list of regexes for files to exclude from coverage.", aliases = List("--coverage-exclude-files")) + val coverageExcludePackages: Setting[List[String]] = MultiStringSetting("-coverage-exclude-packages", "packages", "List of regexes for packages to exclude from coverage.", aliases = List("--coverage-exclude-packages")) + val coverageExcludeFiles: Setting[List[String]] = MultiStringSetting("-coverage-exclude-files", "files", "List of regexes for files to exclude from coverage.", aliases = List("--coverage-exclude-files")) /* Other settings */ val encoding: Setting[String] = StringSetting("-encoding", "encoding", "Specify character encoding used by source files.", Properties.sourceEncoding, aliases = List("--encoding")) diff --git a/tests/coverage/pos/ExcludeClass.scala b/tests/coverage/pos/ExcludeClass.scala new file mode 100644 index 000000000000..d0832380cbb0 --- /dev/null +++ b/tests/coverage/pos/ExcludeClass.scala @@ -0,0 +1,19 @@ +//> using options -coverage-exclude-packages:covtest.Klass + +package covtest + +class Klass { + def abs(i: Int) = + if i > 0 then + i + else + -i +} + +class Klass2 { + def abs(i: Int) = + if i > 0 then + i + else + -i +} diff --git a/tests/coverage/pos/ExcludeClass.scoverage.check b/tests/coverage/pos/ExcludeClass.scoverage.check new file mode 100644 index 000000000000..2e4cec37066b --- /dev/null +++ b/tests/coverage/pos/ExcludeClass.scoverage.check @@ -0,0 +1,71 @@ +# Coverage data, format version: 3.0 +# Statement data: +# - id +# - source path +# - package name +# - class name +# - class type (Class, Object or Trait) +# - full class name +# - method name +# - start offset +# - end offset +# - line number +# - symbol name +# - tree name +# - is branch +# - invocations count +# - is ignored +# - description (can be multi-line) +# ' ' sign +# ------------------------------------------ +0 +ExcludeClass.scala +covtest +Klass2 +Class +covtest.Klass2 +abs +217 +218 +16 +i +Ident +true +0 +false +i + +1 +ExcludeClass.scala +covtest +Klass2 +Class +covtest.Klass2 +abs +234 +236 +18 +unary_- +Select +true +0 +false +-i + +2 +ExcludeClass.scala +covtest +Klass2 +Class +covtest.Klass2 +abs +175 +182 +14 +abs +DefDef +false +0 +false +def abs + diff --git a/tests/coverage/pos/ExcludeDef.scala b/tests/coverage/pos/ExcludeDef.scala new file mode 100644 index 000000000000..b1e414c4e605 --- /dev/null +++ b/tests/coverage/pos/ExcludeDef.scala @@ -0,0 +1,9 @@ +//> using options -coverage-exclude-packages:covtest\..* + +package covtest + +def abs(i: Int) = + if i > 0 then + i + else + -i diff --git a/tests/coverage/pos/ExcludeDef.scoverage.check b/tests/coverage/pos/ExcludeDef.scoverage.check new file mode 100644 index 000000000000..1bdba951d6ae --- /dev/null +++ b/tests/coverage/pos/ExcludeDef.scoverage.check @@ -0,0 +1,20 @@ +# Coverage data, format version: 3.0 +# Statement data: +# - id +# - source path +# - package name +# - class name +# - class type (Class, Object or Trait) +# - full class name +# - method name +# - start offset +# - end offset +# - line number +# - symbol name +# - tree name +# - is branch +# - invocations count +# - is ignored +# - description (can be multi-line) +# ' ' sign +# ------------------------------------------ diff --git a/tests/coverage/pos/ExcludeFile.scala b/tests/coverage/pos/ExcludeFile.scala new file mode 100644 index 000000000000..b9f15244ebe3 --- /dev/null +++ b/tests/coverage/pos/ExcludeFile.scala @@ -0,0 +1,11 @@ +//> using options -coverage-exclude-files:.*ExcludeFile + +package covtest + +class Klass { + def abs(i: Int) = + if i > 0 then + i + else + -i +} diff --git a/tests/coverage/pos/ExcludeFile.scoverage.check b/tests/coverage/pos/ExcludeFile.scoverage.check new file mode 100644 index 000000000000..1bdba951d6ae --- /dev/null +++ b/tests/coverage/pos/ExcludeFile.scoverage.check @@ -0,0 +1,20 @@ +# Coverage data, format version: 3.0 +# Statement data: +# - id +# - source path +# - package name +# - class name +# - class type (Class, Object or Trait) +# - full class name +# - method name +# - start offset +# - end offset +# - line number +# - symbol name +# - tree name +# - is branch +# - invocations count +# - is ignored +# - description (can be multi-line) +# ' ' sign +# ------------------------------------------ diff --git a/tests/coverage/pos/ExcludeOtherStuff.scala b/tests/coverage/pos/ExcludeOtherStuff.scala new file mode 100644 index 000000000000..22f3c55e498c --- /dev/null +++ b/tests/coverage/pos/ExcludeOtherStuff.scala @@ -0,0 +1,15 @@ +//> using options -coverage-exclude-packages:covtest.Oject,covtest.Tait + +package covtest + +object Oject { + def abs(i: Int) = + if i > 0 then + i + else + -i +} + +trait Tait { + def abs(i: Int): Int +} diff --git a/tests/coverage/pos/ExcludeOtherStuff.scoverage.check b/tests/coverage/pos/ExcludeOtherStuff.scoverage.check new file mode 100644 index 000000000000..1bdba951d6ae --- /dev/null +++ b/tests/coverage/pos/ExcludeOtherStuff.scoverage.check @@ -0,0 +1,20 @@ +# Coverage data, format version: 3.0 +# Statement data: +# - id +# - source path +# - package name +# - class name +# - class type (Class, Object or Trait) +# - full class name +# - method name +# - start offset +# - end offset +# - line number +# - symbol name +# - tree name +# - is branch +# - invocations count +# - is ignored +# - description (can be multi-line) +# ' ' sign +# ------------------------------------------ diff --git a/tests/coverage/pos/ExcludePackage.scala b/tests/coverage/pos/ExcludePackage.scala new file mode 100644 index 000000000000..79f854447727 --- /dev/null +++ b/tests/coverage/pos/ExcludePackage.scala @@ -0,0 +1,11 @@ +//> using options -coverage-exclude-packages:covtest + +package covtest + +class Klass { + def abs(i: Int) = + if i > 0 then + i + else + -i +} diff --git a/tests/coverage/pos/ExcludePackage.scoverage.check b/tests/coverage/pos/ExcludePackage.scoverage.check new file mode 100644 index 000000000000..1bdba951d6ae --- /dev/null +++ b/tests/coverage/pos/ExcludePackage.scoverage.check @@ -0,0 +1,20 @@ +# Coverage data, format version: 3.0 +# Statement data: +# - id +# - source path +# - package name +# - class name +# - class type (Class, Object or Trait) +# - full class name +# - method name +# - start offset +# - end offset +# - line number +# - symbol name +# - tree name +# - is branch +# - invocations count +# - is ignored +# - description (can be multi-line) +# ' ' sign +# ------------------------------------------ From c01baeac783870ef5df65d75e9c2061572fafd33 Mon Sep 17 00:00:00 2001 From: Kacper Korban Date: Thu, 22 Feb 2024 17:38:42 +0100 Subject: [PATCH 108/277] Change the -coverage-exclude-classlikes option and its doc --- .../src/dotty/tools/dotc/config/ScalaSettings.scala | 2 +- .../tools/dotc/transform/InstrumentCoverage.scala | 2 +- tests/coverage/pos/ExcludeClass.scala | 2 +- tests/coverage/pos/ExcludeClass.scoverage.check | 10 +++++----- tests/coverage/pos/ExcludeDef.scala | 2 +- tests/coverage/pos/ExcludeOtherStuff.scala | 2 +- tests/coverage/pos/ExcludePackage.scala | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 3b13ad8d74e2..f684f7bbabe2 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -127,7 +127,7 @@ trait CommonScalaSettings: /* Coverage settings */ val coverageOutputDir = PathSetting("-coverage-out", "Destination for coverage classfiles and instrumentation data.", "", aliases = List("--coverage-out")) - val coverageExcludePackages: Setting[List[String]] = MultiStringSetting("-coverage-exclude-packages", "packages", "List of regexes for packages to exclude from coverage.", aliases = List("--coverage-exclude-packages")) + val coverageExcludeClasslikes: Setting[List[String]] = MultiStringSetting("-coverage-exclude-classlikes", "packages, clesses and modules", "List of regexes for packages, classes and modules to exclude from coverage.", aliases = List("--coverage-exclude-classlikes")) val coverageExcludeFiles: Setting[List[String]] = MultiStringSetting("-coverage-exclude-files", "files", "List of regexes for files to exclude from coverage.", aliases = List("--coverage-exclude-files")) /* Other settings */ diff --git a/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala b/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala index c759f0ad3734..aa3b48e53f35 100644 --- a/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala +++ b/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala @@ -61,7 +61,7 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer: Serializer.serialize(coverage, outputPath, ctx.settings.sourceroot.value) private def isClassIncluded(sym: Symbol)(using Context): Boolean = - val excludedClassNamePatterns = ctx.settings.coverageExcludePackages.value.map(_.r.pattern) + val excludedClassNamePatterns = ctx.settings.coverageExcludeClasslikes.value.map(_.r.pattern) excludedClassNamePatterns.isEmpty || !excludedClassNamePatterns.exists( _.matcher(sym.fullName.toText(ctx.printerFn(ctx)).show).nn.matches ) diff --git a/tests/coverage/pos/ExcludeClass.scala b/tests/coverage/pos/ExcludeClass.scala index d0832380cbb0..a73a8ed34e71 100644 --- a/tests/coverage/pos/ExcludeClass.scala +++ b/tests/coverage/pos/ExcludeClass.scala @@ -1,4 +1,4 @@ -//> using options -coverage-exclude-packages:covtest.Klass +//> using options -coverage-exclude-classlikes:covtest.Klass package covtest diff --git a/tests/coverage/pos/ExcludeClass.scoverage.check b/tests/coverage/pos/ExcludeClass.scoverage.check index 2e4cec37066b..5e77f0ce21a1 100644 --- a/tests/coverage/pos/ExcludeClass.scoverage.check +++ b/tests/coverage/pos/ExcludeClass.scoverage.check @@ -25,8 +25,8 @@ Klass2 Class covtest.Klass2 abs -217 -218 +219 +220 16 i Ident @@ -42,8 +42,8 @@ Klass2 Class covtest.Klass2 abs -234 236 +238 18 unary_- Select @@ -59,8 +59,8 @@ Klass2 Class covtest.Klass2 abs -175 -182 +177 +184 14 abs DefDef diff --git a/tests/coverage/pos/ExcludeDef.scala b/tests/coverage/pos/ExcludeDef.scala index b1e414c4e605..bddbe12022ef 100644 --- a/tests/coverage/pos/ExcludeDef.scala +++ b/tests/coverage/pos/ExcludeDef.scala @@ -1,4 +1,4 @@ -//> using options -coverage-exclude-packages:covtest\..* +//> using options -coverage-exclude-classlikes:covtest\..* package covtest diff --git a/tests/coverage/pos/ExcludeOtherStuff.scala b/tests/coverage/pos/ExcludeOtherStuff.scala index 22f3c55e498c..6a333560c59e 100644 --- a/tests/coverage/pos/ExcludeOtherStuff.scala +++ b/tests/coverage/pos/ExcludeOtherStuff.scala @@ -1,4 +1,4 @@ -//> using options -coverage-exclude-packages:covtest.Oject,covtest.Tait +//> using options -coverage-exclude-classlikes:covtest.Oject,covtest.Tait package covtest diff --git a/tests/coverage/pos/ExcludePackage.scala b/tests/coverage/pos/ExcludePackage.scala index 79f854447727..771ac2c1f062 100644 --- a/tests/coverage/pos/ExcludePackage.scala +++ b/tests/coverage/pos/ExcludePackage.scala @@ -1,4 +1,4 @@ -//> using options -coverage-exclude-packages:covtest +//> using options -coverage-exclude-classlikes:covtest package covtest From 8f375fc25f46179348418eceab0df6212fabfec4 Mon Sep 17 00:00:00 2001 From: Kacper Korban Date: Sun, 25 Feb 2024 21:18:03 +0100 Subject: [PATCH 109/277] Update typo in coverageExcludeClasslikes doc Co-authored-by: Guillaume Raffin --- compiler/src/dotty/tools/dotc/config/ScalaSettings.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index f684f7bbabe2..3dafedd8e2e0 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -127,7 +127,7 @@ trait CommonScalaSettings: /* Coverage settings */ val coverageOutputDir = PathSetting("-coverage-out", "Destination for coverage classfiles and instrumentation data.", "", aliases = List("--coverage-out")) - val coverageExcludeClasslikes: Setting[List[String]] = MultiStringSetting("-coverage-exclude-classlikes", "packages, clesses and modules", "List of regexes for packages, classes and modules to exclude from coverage.", aliases = List("--coverage-exclude-classlikes")) + val coverageExcludeClasslikes: Setting[List[String]] = MultiStringSetting("-coverage-exclude-classlikes", "packages, classes and modules", "List of regexes for packages, classes and modules to exclude from coverage.", aliases = List("--coverage-exclude-classlikes")) val coverageExcludeFiles: Setting[List[String]] = MultiStringSetting("-coverage-exclude-files", "files", "List of regexes for files to exclude from coverage.", aliases = List("--coverage-exclude-files")) /* Other settings */ From 5223adb474d755e1db50a79322e169388e44222c Mon Sep 17 00:00:00 2001 From: Kacper Korban Date: Sun, 25 Feb 2024 22:15:48 +0100 Subject: [PATCH 110/277] Pre compute coverage filter patterns --- .../dotc/transform/InstrumentCoverage.scala | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala b/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala index aa3b48e53f35..a39a1c6f591e 100644 --- a/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala +++ b/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala @@ -21,6 +21,7 @@ import util.Spans.Span import localopt.StringInterpolatorOpt import inlines.Inlines import scala.util.matching.Regex +import java.util.regex.Pattern /** Implements code coverage by inserting calls to scala.runtime.coverage.Invoker * ("instruments" the source code). @@ -43,6 +44,9 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer: // stores all instrumented statements private val coverage = Coverage() + private var coverageExcludeClasslikePatterns: List[Pattern] = Nil + private var coverageExcludeFilePatterns: List[Pattern] = Nil + override def run(using ctx: Context): Unit = val outputPath = ctx.settings.coverageOutputDir.value @@ -56,19 +60,21 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer: .filter(_.nn.getName.nn.startsWith("scoverage")) .foreach(_.nn.delete()) end if + + coverageExcludeClasslikePatterns = ctx.settings.coverageExcludeClasslikes.value.map(_.r.pattern) + coverageExcludeFilePatterns = ctx.settings.coverageExcludeFiles.value.map(_.r.pattern) + super.run Serializer.serialize(coverage, outputPath, ctx.settings.sourceroot.value) private def isClassIncluded(sym: Symbol)(using Context): Boolean = - val excludedClassNamePatterns = ctx.settings.coverageExcludeClasslikes.value.map(_.r.pattern) - excludedClassNamePatterns.isEmpty || !excludedClassNamePatterns.exists( + coverageExcludeClasslikePatterns.isEmpty || !coverageExcludeClasslikePatterns.exists( _.matcher(sym.fullName.toText(ctx.printerFn(ctx)).show).nn.matches ) private def isFileIncluded(file: SourceFile)(using Context): Boolean = - val excludedFilePatterns = ctx.settings.coverageExcludeFiles.value.map(_.r.pattern) - excludedFilePatterns.isEmpty || !excludedFilePatterns.exists( + coverageExcludeFilePatterns.isEmpty || !coverageExcludeFilePatterns.exists( _.matcher(file.path.replace(".scala", "")).nn.matches ) @@ -283,14 +289,14 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer: transformDefDef(tree) case tree: PackageDef => - if (isFileIncluded(tree.srcPos.sourcePos.source) && isClassIncluded(tree.symbol)) + if isFileIncluded(tree.srcPos.sourcePos.source) && isClassIncluded(tree.symbol) then // only transform the statements of the package cpy.PackageDef(tree)(tree.pid, transform(tree.stats)) else tree case tree: TypeDef => - if (isFileIncluded(tree.srcPos.sourcePos.source) && isClassIncluded(tree.symbol)) + if isFileIncluded(tree.srcPos.sourcePos.source) && isClassIncluded(tree.symbol) then super.transform(tree) else tree From 641f5db8383a8570748d916ea82f76fcc136aaf5 Mon Sep 17 00:00:00 2001 From: Kacper Korban Date: Tue, 27 Feb 2024 11:15:01 +0100 Subject: [PATCH 111/277] Apply review suggestions to coverage filter checking --- .../src/dotty/tools/dotc/transform/InstrumentCoverage.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala b/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala index a39a1c6f591e..a76919e47164 100644 --- a/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala +++ b/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala @@ -69,13 +69,15 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer: Serializer.serialize(coverage, outputPath, ctx.settings.sourceroot.value) private def isClassIncluded(sym: Symbol)(using Context): Boolean = + val fqn = sym.fullName.toText(ctx.printerFn(ctx)).show coverageExcludeClasslikePatterns.isEmpty || !coverageExcludeClasslikePatterns.exists( - _.matcher(sym.fullName.toText(ctx.printerFn(ctx)).show).nn.matches + _.matcher(fqn).nn.matches ) private def isFileIncluded(file: SourceFile)(using Context): Boolean = + val normalizedPath = file.path.replace(".scala", "") coverageExcludeFilePatterns.isEmpty || !coverageExcludeFilePatterns.exists( - _.matcher(file.path.replace(".scala", "")).nn.matches + _.matcher(normalizedPath).nn.matches ) override protected def newTransformer(using Context) = From a1c39ef64d384240deb944dec5be91e5126823f9 Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Thu, 15 Feb 2024 00:45:24 +0100 Subject: [PATCH 112/277] Add using directive to vulpix for javac options --- compiler/test/dotty/tools/utils.scala | 14 +++++++++++++- .../test/dotty/tools/vulpix/ParallelTesting.scala | 6 +++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/compiler/test/dotty/tools/utils.scala b/compiler/test/dotty/tools/utils.scala index 8161631acb44..66e2f99b84c5 100644 --- a/compiler/test/dotty/tools/utils.scala +++ b/compiler/test/dotty/tools/utils.scala @@ -81,7 +81,14 @@ def toolArgsFor(tool: ToolName, filename: Option[String])(lines: List[String]): // groups are (name, args) // note: ideally we would replace everything that requires this to use directive syntax, however scalajs: --skip has no directive equivalent yet. private val toolArg = raw"(?://|/\*| \*) ?(?i:(${ToolName.values.mkString("|")})):((?:[^*]|\*(?!/))*)".r.unanchored + +// ================================================================================================ +// =================================== VULPIX DIRECTIVES ========================================== +// ================================================================================================ + +/** Directive to specify to vulpix the options to pass to Dotty */ private val directiveOptionsArg = raw"//> using options (.*)".r.unanchored +private val directiveJavacOptions = raw"//> using javacOpt (.*)".r.unanchored // Inspect the lines for compiler options of the form // `//> using options args`, `// scalajs: args`, `/* scalajs: args`, ` * scalajs: args` etc. @@ -90,10 +97,15 @@ private val directiveOptionsArg = raw"//> using options (.*)".r.unanchored def toolArgsParse(lines: List[String], filename: Option[String]): List[(String,String)] = lines.flatMap { case toolArg("scalac", _) => sys.error(s"`// scalac: args` not supported. Please use `//> using options args`${filename.fold("")(f => s" in file $f")}") + case toolArg("javac", _) => sys.error(s"`// javac: args` not supported. Please use `//> using javacOpt args`${filename.fold("")(f => s" in file $f")}") case toolArg(name, args) => List((name, args)) case _ => Nil } ++ - lines.flatMap { case directiveOptionsArg(args) => List(("scalac", args)) case _ => Nil } + lines.flatMap { + case directiveOptionsArg(args) => List(("scalac", args)) + case directiveJavacOptions(args) => List(("javac", args)) + case _ => Nil + } import org.junit.Test import org.junit.Assert._ diff --git a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala index 59d5d3d542fd..e9975ed25b6d 100644 --- a/compiler/test/dotty/tools/vulpix/ParallelTesting.scala +++ b/compiler/test/dotty/tools/vulpix/ParallelTesting.scala @@ -498,6 +498,7 @@ trait ParallelTesting extends RunnerOrchestration { self => case None => true def scalacOptions = toolArgs.getOrElse(ToolName.Scalac, Nil) + def javacOptions = toolArgs.getOrElse(ToolName.Javac, Nil) val flags = flags0 .and(scalacOptions*) @@ -512,11 +513,10 @@ trait ParallelTesting extends RunnerOrchestration { self => def compileWithJavac(fs: Array[String]) = if (fs.nonEmpty) { val fullArgs = Array( - "javac", "-encoding", StandardCharsets.UTF_8.name, - ) ++ flags.javacFlags ++ fs + ) ++ flags.javacFlags ++ javacOptions++ fs - val process = Runtime.getRuntime.exec(fullArgs) + val process = Runtime.getRuntime.exec("javac" +: fullArgs) val output = Source.fromInputStream(process.getErrorStream).mkString if waitForJudiciously(process) != 0 then Some(output) From 3154c59f9afb0808485198edf0973ed9a37f2946 Mon Sep 17 00:00:00 2001 From: Hamza Remmal <56235032+hamzaremmal@users.noreply.github.com> Date: Sat, 25 Nov 2023 22:32:15 +0100 Subject: [PATCH 113/277] [JEP-409] Add support for sealed classes and interfaces in Java --- .../dotty/tools/dotc/parsing/JavaParsers.scala | 16 ++++++++++++++++ .../dotty/tools/dotc/parsing/JavaScanners.scala | 1 - .../dotty/tools/dotc/parsing/JavaTokens.scala | 3 ++- .../src/dotty/tools/dotc/parsing/Tokens.scala | 4 ++-- compiler/src/dotty/tools/dotc/typer/Namer.scala | 3 ++- tests/neg/i18533.check | 4 ++++ tests/neg/i18533/Cat_SCALA_ONLY.java | 5 +++++ tests/neg/i18533/Pet_SCALA_ONLY.java | 5 +++++ tests/pos/i18533/Cat.java | 5 +++++ tests/pos/i18533/Pet.java | 5 +++++ 10 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 tests/neg/i18533.check create mode 100644 tests/neg/i18533/Cat_SCALA_ONLY.java create mode 100644 tests/neg/i18533/Pet_SCALA_ONLY.java create mode 100644 tests/pos/i18533/Cat.java create mode 100644 tests/pos/i18533/Pet.java diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala index e98ff6c9d66d..83fdcebdff9f 100644 --- a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala @@ -489,6 +489,9 @@ object JavaParsers { addAnnot(scalaDot(jtpnme.VOLATILEkw)) case SYNCHRONIZED | STRICTFP => in.nextToken() + case SEALED => + flags |= Flags.Sealed + in.nextToken() case _ => val privateWithin: TypeName = if (isPackageAccess && !inInterface) thisPackageName @@ -812,6 +815,17 @@ object JavaParsers { else List() + + def permittedSubclassesOpt(isSealed: Boolean) : List[Tree] = + if in.token == PERMITS && !isSealed then + syntaxError(em"A type declaration that has a permits clause should have a sealed modifier") + if in.token == PERMITS then + in.nextToken() + repsep(() => typ(), COMMA) + else + // JEP-409: Class/Interface may omit the permits clause + Nil + def classDecl(start: Offset, mods: Modifiers): List[Tree] = { accept(CLASS) val nameOffset = in.offset @@ -825,6 +839,7 @@ object JavaParsers { else ObjectTpt() val interfaces = interfacesOpt() + val permittedSubclasses = permittedSubclassesOpt(mods.is(Flags.Sealed)) val (statics, body) = typeBody(CLASS, name) val cls = atSpan(start, nameOffset) { TypeDef(name, makeTemplate(superclass :: interfaces, body, tparams, needsDummyConstr = true)).withMods(mods) @@ -889,6 +904,7 @@ object JavaParsers { } else List(ObjectTpt()) + val permittedSubclasses = permittedSubclassesOpt(mods is Flags.Sealed) val (statics, body) = typeBody(INTERFACE, name) val iface = atSpan(start, nameOffset) { TypeDef( diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaScanners.scala b/compiler/src/dotty/tools/dotc/parsing/JavaScanners.scala index f50dcdda438c..3f993195e4f3 100644 --- a/compiler/src/dotty/tools/dotc/parsing/JavaScanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/JavaScanners.scala @@ -393,7 +393,6 @@ object JavaScanners { '5' | '6' | '7' | '8' | '9' => putChar(ch) nextChar() - case '_' => putChar(ch) nextChar() diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaTokens.scala b/compiler/src/dotty/tools/dotc/parsing/JavaTokens.scala index 2b7882173e00..5fd177f384ae 100644 --- a/compiler/src/dotty/tools/dotc/parsing/JavaTokens.scala +++ b/compiler/src/dotty/tools/dotc/parsing/JavaTokens.scala @@ -10,7 +10,7 @@ object JavaTokens extends TokensCommon { final val javaOnlyKeywords: TokenSet = tokenRange(INSTANCEOF, ASSERT) final val sharedKeywords: BitSet = BitSet( IF, FOR, ELSE, THIS, NULL, NEW, SUPER, ABSTRACT, FINAL, PRIVATE, PROTECTED, - EXTENDS, TRUE, FALSE, CLASS, IMPORT, PACKAGE, DO, THROW, TRY, CATCH, FINALLY, WHILE, RETURN ) + EXTENDS, TRUE, FALSE, CLASS, IMPORT, PACKAGE, DO, THROW, TRY, CATCH, FINALLY, WHILE, RETURN, SEALED) final val primTypes: TokenSet = tokenRange(VOID, DOUBLE) final val keywords: BitSet = sharedKeywords | javaOnlyKeywords | primTypes @@ -22,6 +22,7 @@ object JavaTokens extends TokensCommon { inline val INTERFACE = 105; enter(INTERFACE, "interface") inline val ENUM = 106; enter(ENUM, "enum") inline val IMPLEMENTS = 107; enter(IMPLEMENTS, "implements") + inline val PERMITS = 108; enter(PERMITS, "permits") /** modifiers */ inline val PUBLIC = 110; enter(PUBLIC, "public") diff --git a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala index fbf4e8d701dd..8ce46442eebd 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala @@ -78,7 +78,7 @@ abstract class TokensCommon { //inline val YIELD = 48; enter(YIELD, "yield") inline val DO = 49; enter(DO, "do") //inline val TRAIT = 50; enter(TRAIT, "trait") - //inline val SEALED = 51; enter(SEALED, "sealed") + inline val SEALED = 51; enter(SEALED, "sealed") inline val THROW = 52; enter(THROW, "throw") inline val TRY = 53; enter(TRY, "try") inline val CATCH = 54; enter(CATCH, "catch") @@ -169,7 +169,7 @@ object Tokens extends TokensCommon { inline val OBJECT = 44; enter(OBJECT, "object") inline val YIELD = 48; enter(YIELD, "yield") inline val TRAIT = 50; enter(TRAIT, "trait") - inline val SEALED = 51; enter(SEALED, "sealed") + //inline val SEALED = 51; enter(SEALED, "sealed") inline val MATCH = 58; enter(MATCH, "match") inline val LAZY = 59; enter(LAZY, "lazy") inline val THEN = 60; enter(THEN, "then") diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 868fcb99dc38..24721f1cd758 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -1546,6 +1546,7 @@ class Namer { typer: Typer => * (2) If may not derive from itself * (3) The class is not final * (4) If the class is sealed, it is defined in the same compilation unit as the current class + * (unless defined in Java. See JEP-409) * * @param isJava If true, the parent type is in Java mode, and we do not require a stable prefix */ @@ -1569,7 +1570,7 @@ class Namer { typer: Typer => if pclazz.is(Final) then report.error(ExtendFinalClass(cls, pclazz), cls.srcPos) else if pclazz.isEffectivelySealed && pclazz.associatedFile != cls.associatedFile then - if pclazz.is(Sealed) then + if pclazz.is(Sealed) && !pclazz.is(JavaDefined) then report.error(UnableToExtendSealedClass(pclazz), cls.srcPos) else if sourceVersion.isAtLeast(future) then checkFeature(nme.adhocExtensions, diff --git a/tests/neg/i18533.check b/tests/neg/i18533.check new file mode 100644 index 000000000000..76c70a6ef896 --- /dev/null +++ b/tests/neg/i18533.check @@ -0,0 +1,4 @@ +-- Error: tests/neg/i18533/Pet_SCALA_ONLY.java:3:10 -------------------------------------------------------------------- +3 |class Pet permits Cat { // error + | ^^^^^^^ + | A type declaration that has a permits clause should have a sealed modifier diff --git a/tests/neg/i18533/Cat_SCALA_ONLY.java b/tests/neg/i18533/Cat_SCALA_ONLY.java new file mode 100644 index 000000000000..4532ef2e3e6e --- /dev/null +++ b/tests/neg/i18533/Cat_SCALA_ONLY.java @@ -0,0 +1,5 @@ +package i18533; + +public class Cat extends Pet { + +} diff --git a/tests/neg/i18533/Pet_SCALA_ONLY.java b/tests/neg/i18533/Pet_SCALA_ONLY.java new file mode 100644 index 000000000000..c6784ce58999 --- /dev/null +++ b/tests/neg/i18533/Pet_SCALA_ONLY.java @@ -0,0 +1,5 @@ +package i18533; + +class Pet permits Cat { // error + +} diff --git a/tests/pos/i18533/Cat.java b/tests/pos/i18533/Cat.java new file mode 100644 index 000000000000..d7d284da90aa --- /dev/null +++ b/tests/pos/i18533/Cat.java @@ -0,0 +1,5 @@ +package i18533; + +public final class Cat extends Pet { + +} \ No newline at end of file diff --git a/tests/pos/i18533/Pet.java b/tests/pos/i18533/Pet.java new file mode 100644 index 000000000000..c6b2c10646a3 --- /dev/null +++ b/tests/pos/i18533/Pet.java @@ -0,0 +1,5 @@ +package i18533; + +public sealed class Pet permits Cat { + +} \ No newline at end of file From b734eb051baef52a8bbec33f4e7761333b99f478 Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Wed, 14 Feb 2024 18:49:49 +0100 Subject: [PATCH 114/277] [JEP-409] Add support for non-sealed classes and interfaces in Java --- compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala | 9 +++++++++ tests/neg/i18533.check | 4 ++++ tests/neg/i18533/Cat_SCALA_ONLY.java | 2 +- tests/neg/i18533/non-SCALA_ONLY.java | 6 ++++++ tests/pos/i18533/Dog.java | 5 +++++ tests/pos/i18533/Pet.java | 2 +- 6 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 tests/neg/i18533/non-SCALA_ONLY.java create mode 100644 tests/pos/i18533/Dog.java diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala index 83fdcebdff9f..79282b0e5223 100644 --- a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala @@ -492,6 +492,15 @@ object JavaParsers { case SEALED => flags |= Flags.Sealed in.nextToken() + // JEP-409: Special trick for the 'non-sealed' java keyword + case IDENTIFIER if in.name.toString == "non" => + val lookahead = in.LookaheadScanner() + ({lookahead.nextToken(); lookahead.token}, {lookahead.nextToken(); lookahead.name.toString}) match + case (MINUS, "sealed") => + in.nextToken(); in.nextToken() // skip '-' and 'sealed'. Nothing more to do + case _ => + syntaxError(em"Identifier '${in.name}' is not allowed here") + in.nextToken() case _ => val privateWithin: TypeName = if (isPackageAccess && !inInterface) thisPackageName diff --git a/tests/neg/i18533.check b/tests/neg/i18533.check index 76c70a6ef896..0e117edc3195 100644 --- a/tests/neg/i18533.check +++ b/tests/neg/i18533.check @@ -2,3 +2,7 @@ 3 |class Pet permits Cat { // error | ^^^^^^^ | A type declaration that has a permits clause should have a sealed modifier +-- Error: tests/neg/i18533/non-SCALA_ONLY.java:4:7 --------------------------------------------------------------------- +4 |public non class Test { // error + | ^^^ + | Identifier 'non' is not allowed here diff --git a/tests/neg/i18533/Cat_SCALA_ONLY.java b/tests/neg/i18533/Cat_SCALA_ONLY.java index 4532ef2e3e6e..fec994ca2a0a 100644 --- a/tests/neg/i18533/Cat_SCALA_ONLY.java +++ b/tests/neg/i18533/Cat_SCALA_ONLY.java @@ -1,5 +1,5 @@ package i18533; -public class Cat extends Pet { +public final class Cat extends Pet { } diff --git a/tests/neg/i18533/non-SCALA_ONLY.java b/tests/neg/i18533/non-SCALA_ONLY.java new file mode 100644 index 000000000000..be6aef65da13 --- /dev/null +++ b/tests/neg/i18533/non-SCALA_ONLY.java @@ -0,0 +1,6 @@ +package i18533; + +// Special test for the non-sealed trick (See JavaParsers.scala::modifiers) +public non class Test { // error + +} \ No newline at end of file diff --git a/tests/pos/i18533/Dog.java b/tests/pos/i18533/Dog.java new file mode 100644 index 000000000000..12fdfba78a88 --- /dev/null +++ b/tests/pos/i18533/Dog.java @@ -0,0 +1,5 @@ +package i18533; + +public non-sealed class Dog extends Pet { + +} \ No newline at end of file diff --git a/tests/pos/i18533/Pet.java b/tests/pos/i18533/Pet.java index c6b2c10646a3..23ab7c52d2c8 100644 --- a/tests/pos/i18533/Pet.java +++ b/tests/pos/i18533/Pet.java @@ -1,5 +1,5 @@ package i18533; -public sealed class Pet permits Cat { +public sealed class Pet permits Cat, Dog { } \ No newline at end of file From b0d00dad145e13ce9a4eeef1dcc1962f76318518 Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Thu, 15 Feb 2024 00:53:44 +0100 Subject: [PATCH 115/277] Enable preview in pos/i18533 tests --- compiler/test/dotty/tools/utils.scala | 4 ++-- tests/pos/i18533/Cat.java | 3 +++ tests/pos/i18533/Dog.java | 3 +++ tests/pos/i18533/Pet.java | 3 +++ tests/run/t9915/C_1.java | 3 --- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/compiler/test/dotty/tools/utils.scala b/compiler/test/dotty/tools/utils.scala index 66e2f99b84c5..a8c480088e08 100644 --- a/compiler/test/dotty/tools/utils.scala +++ b/compiler/test/dotty/tools/utils.scala @@ -116,6 +116,6 @@ class ToolArgsTest: @Test def `tool is present`: Unit = assertEquals("-hey" :: Nil, toolArgsFor(ToolName.Test, None)("// test: -hey" :: Nil)) @Test def `missing tool is absent`: Unit = assertEquals(Nil, toolArgsFor(ToolName.Javac, None)("// test: -hey" :: Nil)) @Test def `multitool is present`: Unit = - assertEquals("-hey" :: Nil, toolArgsFor(ToolName.Test, None)("// test: -hey" :: "// javac: -d /tmp" :: Nil)) - assertEquals("-d" :: "/tmp" :: Nil, toolArgsFor(ToolName.Javac, None)("// test: -hey" :: "// javac: -d /tmp" :: Nil)) + assertEquals("-hey" :: Nil, toolArgsFor(ToolName.Test, None)("// test: -hey" :: "// java: -d /tmp" :: Nil)) + assertEquals("-d" :: "/tmp" :: Nil, toolArgsFor(ToolName.Java, None)("// test: -hey" :: "// java: -d /tmp" :: Nil)) end ToolArgsTest diff --git a/tests/pos/i18533/Cat.java b/tests/pos/i18533/Cat.java index d7d284da90aa..33cdd99949bb 100644 --- a/tests/pos/i18533/Cat.java +++ b/tests/pos/i18533/Cat.java @@ -1,3 +1,6 @@ +//> using javacOpt --enable-preview --source 17 +//> test: -jvm 17+ + package i18533; public final class Cat extends Pet { diff --git a/tests/pos/i18533/Dog.java b/tests/pos/i18533/Dog.java index 12fdfba78a88..0b10b9f06c27 100644 --- a/tests/pos/i18533/Dog.java +++ b/tests/pos/i18533/Dog.java @@ -1,3 +1,6 @@ +//> using javacOpt --enable-preview --source 17 +//> test: -jvm 17+ + package i18533; public non-sealed class Dog extends Pet { diff --git a/tests/pos/i18533/Pet.java b/tests/pos/i18533/Pet.java index 23ab7c52d2c8..0985aa1f957f 100644 --- a/tests/pos/i18533/Pet.java +++ b/tests/pos/i18533/Pet.java @@ -1,3 +1,6 @@ +//> using javacOpt --enable-preview --source 17 +//> test: -jvm 17+ + package i18533; public sealed class Pet permits Cat, Dog { diff --git a/tests/run/t9915/C_1.java b/tests/run/t9915/C_1.java index 4269cf74e058..ec94b1412741 100644 --- a/tests/run/t9915/C_1.java +++ b/tests/run/t9915/C_1.java @@ -1,6 +1,3 @@ -/* - * javac: -encoding UTF-8 - */ public class C_1 { public static final String NULLED = "X\000ABC"; public static final String SUPPED = "𐒈𐒝𐒑𐒛𐒐𐒘𐒕𐒖"; From 55ecbfca4057908025b3551a29d3b6130647a725 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 27 Feb 2024 13:48:48 +0000 Subject: [PATCH 116/277] Use isProvisional instead of has LazyRef --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 4 ++-- tests/pos/Tuple.Drop.scala | 7 +++++++ tests/pos/Tuple.Elem.scala | 7 +++++++ 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 tests/pos/Tuple.Drop.scala create mode 100644 tests/pos/Tuple.Elem.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index b96aa75b70c4..2a8674df0155 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -2376,8 +2376,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer val bound2 = if tree.bound.isEmpty then val lub = cases1.foldLeft(defn.NothingType: Type): (acc, case1) => if !acc.exists then NoType - else if case1.body.tpe.existsPart(_.isInstanceOf[LazyRef]) then NoType - else acc | TypeOps.avoid(case1.body.tpe, patVars(case1)) + else if case1.body.tpe.isProvisional then NoType + else acc | case1.body.tpe if lub.exists then TypeTree(lub, inferred = true) else bound1 else bound1 diff --git a/tests/pos/Tuple.Drop.scala b/tests/pos/Tuple.Drop.scala new file mode 100644 index 000000000000..9b88cc227966 --- /dev/null +++ b/tests/pos/Tuple.Drop.scala @@ -0,0 +1,7 @@ +import compiletime.ops.int.* + +type Drop[T <: Tuple, N <: Int] <: Tuple = N match + case 0 => T + case S[n1] => T match + case EmptyTuple => EmptyTuple + case x *: xs => Drop[xs, n1] diff --git a/tests/pos/Tuple.Elem.scala b/tests/pos/Tuple.Elem.scala new file mode 100644 index 000000000000..81494485c321 --- /dev/null +++ b/tests/pos/Tuple.Elem.scala @@ -0,0 +1,7 @@ +import compiletime.ops.int.* + +type Elem[T <: Tuple, I <: Int] = T match + case h *: tail => + I match + case 0 => h + case S[j] => Elem[tail, j] From 7006c2b6feab165a90d24c38ca8e0d0f64b3ff84 Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Tue, 27 Feb 2024 14:55:17 +0100 Subject: [PATCH 117/277] Update Maintenance file --- MAINTENANCE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTENANCE.md b/MAINTENANCE.md index 1e80f891e987..5537d6648a2a 100644 --- a/MAINTENANCE.md +++ b/MAINTENANCE.md @@ -94,8 +94,8 @@ The following is the list of all the principal areas of the compiler and the cor - Linting (especially unused warnings) / Reporting UX: @szymon-rd ### Infrastructure -- CI: @anatoliykmetyuk -- Community Build: @anatoliykmetyuk +- CI: @hamzaremmal +- Community Build: @hamzaremmal - Open Community Build: @WojciechMazur - Vulpix: @dwijnand, @prolativ - Benchmarks: @mbovel From 47517b6c7ae80c9b293fec70d6ed6cff113ab452 Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Tue, 27 Feb 2024 15:03:55 +0100 Subject: [PATCH 118/277] Fix the pickling of `This` inside capture sets --- .../src/dotty/tools/dotc/core/tasty/TreePickler.scala | 9 ++++++++- .../src/dotty/tools/dotc/printing/PlainPrinter.scala | 5 +++-- tests/pos-custom-args/captures/i19662.scala | 9 +++++++++ 3 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 tests/pos-custom-args/captures/i19662.scala diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index d70b56fca43d..def27742c189 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -405,7 +405,14 @@ class TreePickler(pickler: TastyPickler, attributes: Attributes) { pickleType(tp) } case This(qual) => - if (qual.isEmpty) pickleType(tree.tpe) + if (qual.isEmpty) + if tree.tpe.isSingleton then pickleType(tree.tpe) + else + // This may happen when pickling a `This` inside a capture set. See #19662. + // In this case, we pickle the tree as null.asInstanceOf[tree.tpe]. + // Since the pickled tree is not the same as the input, special handling is needed + // in the tree printer when testing the pickler. See [[PlainPrinter#homogenize]]. + pickleTree(Literal(Constant(null)).cast(tree.tpe).withSpan(tree.span)) else { writeByte(QUALTHIS) val ThisType(tref) = tree.tpe: @unchecked diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 8fc0c568e125..e189e94829d0 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -15,7 +15,7 @@ import util.SourcePosition import scala.util.control.NonFatal import scala.annotation.switch import config.{Config, Feature} -import cc.{CapturingType, RetainingType, CaptureSet, ReachCapability, MaybeCapability, isBoxed, levelOwner, retainedElems} +import cc.{CapturingType, RetainingType, CaptureSet, ReachCapability, MaybeCapability, isBoxed, levelOwner, retainedElems, isRetainsLike} class PlainPrinter(_ctx: Context) extends Printer { @@ -60,7 +60,8 @@ class PlainPrinter(_ctx: Context) extends Printer { case OrType(tp1, tp2) => homogenize(tp1) | homogenize(tp2) case AnnotatedType(parent, annot) - if !ctx.mode.is(Mode.Type) && annot.symbol == defn.UncheckedVarianceAnnot => + if !ctx.mode.is(Mode.Type) && annot.symbol == defn.UncheckedVarianceAnnot + || annot.symbol.isRetainsLike => homogenize(parent) case tp: SkolemType => homogenize(tp.info) diff --git a/tests/pos-custom-args/captures/i19662.scala b/tests/pos-custom-args/captures/i19662.scala new file mode 100644 index 000000000000..24b6272a8f45 --- /dev/null +++ b/tests/pos-custom-args/captures/i19662.scala @@ -0,0 +1,9 @@ +// Modified from #19662 to make it independent of the cc stdlib. +import language.experimental.captureChecking +trait MySeq[+A] { self: MySeq[A]^ => + def map[B](f: A => B): MySeq[B]^{this, f} +} +object MySeq: + def apply(x: Int): MySeq[Int] = ??? +class C: + private def foo = MySeq(5).map { i => i } From 3287f0667bd4a6e518053fd09ad3e90ceb0609b8 Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Tue, 27 Feb 2024 15:16:29 +0100 Subject: [PATCH 119/277] Add updated to SeqViewOps --- scala2-library-cc/src/scala/collection/SeqView.scala | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scala2-library-cc/src/scala/collection/SeqView.scala b/scala2-library-cc/src/scala/collection/SeqView.scala index 7ec22cd54c83..c66d7b5f4694 100644 --- a/scala2-library-cc/src/scala/collection/SeqView.scala +++ b/scala2-library-cc/src/scala/collection/SeqView.scala @@ -30,6 +30,7 @@ trait SeqViewOps[+A, +CC[_], +C] extends Any with IterableOps[A, CC, C] { def length: Int def apply(x: Int): A def appended[B >: A](elem: B): CC[B]^{this} + def updated[B >: A](index: Int, elem: B): CC[B]^{this} def prepended[B >: A](elem: B): CC[B]^{this} def reverse: C^{this} def sorted[B >: A](implicit ord: Ordering[B]): C^{this} @@ -44,6 +45,16 @@ trait SeqView[+A] extends SeqViewOps[A, View, View[A]] with View[A] { override def map[B](f: A => B): SeqView[B]^{this, f} = new SeqView.Map(this, f) override def appended[B >: A](elem: B): SeqView[B]^{this} = new SeqView.Appended(this, elem) + + // Copied from SeqOps. This is needed due to the change of class hierarchy in stdlib. + // See #19660. + override def updated[B >: A](index: Int, elem: B): View[B]^{this} = { + if(index < 0) throw new IndexOutOfBoundsException(index.toString) + val k = knownSize + if(k >= 0 && index >= k) throw new IndexOutOfBoundsException(index.toString) + iterableFactory.from(new View.Updated(this, index, elem)) + } + override def prepended[B >: A](elem: B): SeqView[B]^{this} = new SeqView.Prepended(elem, this) override def reverse: SeqView[A]^{this} = new SeqView.Reverse(this) override def take(n: Int): SeqView[A]^{this} = new SeqView.Take(this, n) From 3419aae7d548ac9a74c4139852bf23a66302696d Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 27 Feb 2024 15:09:38 +0000 Subject: [PATCH 120/277] Fix PlusTri in pos/13633 --- tests/pos/13633.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/pos/13633.scala b/tests/pos/13633.scala index ca0f7e68e81e..8883ef98d0be 100644 --- a/tests/pos/13633.scala +++ b/tests/pos/13633.scala @@ -21,7 +21,7 @@ object Sums extends App: type Reverse[A] = ReverseLoop[A, EmptyTuple] - type PlusTri[A, B, C] = (A, B, C) match + type PlusTri[A, B, C] <: Tuple = (A, B, C) match case (false, false, false) => (false, false) case (true, false, false) | (false, true, false) | (false, false, true) => (false, true) case (true, true, false) | (true, false, true) | (false, true, true) => (true, false) From 2423198a8b68e870a42890bf325866e7acfa0942 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 27 Feb 2024 15:27:50 +0000 Subject: [PATCH 121/277] Handle NoType in disjointnessBoundary --- compiler/src/dotty/tools/dotc/core/TypeComparer.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index b23bfe9fe14b..0be68b119d40 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -2863,6 +2863,8 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling disjointnessBoundary(tp.effectiveBounds.hi) case tp: ErrorType => defn.AnyType + case NoType => // ParamRef#superTypeNormalized can return NoType + defn.AnyType end disjointnessBoundary (disjointnessBoundary(tp1), disjointnessBoundary(tp2)) match From 36392fa7f615386280670c43abe1fcb00e552a37 Mon Sep 17 00:00:00 2001 From: EnzeXing Date: Tue, 27 Feb 2024 10:49:39 -0500 Subject: [PATCH 122/277] Minor fix --- compiler/src/dotty/tools/dotc/transform/init/Objects.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala index 41d5bd963fec..5c876206b111 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala @@ -27,6 +27,7 @@ import scala.collection.immutable.ListSet import scala.collection.mutable import scala.annotation.tailrec import scala.annotation.constructorOnly +import dotty.tools.dotc.core.Flags.AbstractOrTrait /** Check initialization safety of static objects * @@ -618,8 +619,7 @@ object Objects: case ValueSet(values) => values.map(v => v.filterClass(klass)).join case arr: OfArray => if defn.ArrayClass.isSubClass(klass) then arr else Bottom case fun: Fun => - val functionSuperCls = klass.baseClasses.filter(defn.isFunctionClass) - if functionSuperCls.nonEmpty then fun else Bottom + if klass.isOneOf(AbstractOrTrait) && klass.baseClasses.exists(defn.isFunctionClass) then fun else Bottom extension (value: Ref | Cold.type) def widenRefOrCold(height : Int)(using Context) : Ref | Cold.type = value.widen(height).asInstanceOf[ThisValue] @@ -1572,7 +1572,7 @@ object Objects: report.warning("The argument should be a constant integer value", arg) res.widen(1) case _ => - res.widen(1) // TODO: changing to widen(2) causes standard library analysis to loop infinitely + if res.isInstanceOf[Fun] then res.widen(2) else res.widen(1) // TODO: changing to widen(2) causes standard library analysis to loop infinitely argInfos += ArgInfo(widened, trace.add(arg.tree), arg.tree) } From 3cabdeaa61c6aeb1cbbefa2432ea5231270c9f98 Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 14 Feb 2024 14:04:52 +0100 Subject: [PATCH 123/277] Parsing and desugaring of new into modifier on parameter types --- .../src/dotty/tools/dotc/ast/Desugar.scala | 23 ++--- compiler/src/dotty/tools/dotc/ast/Trees.scala | 1 + compiler/src/dotty/tools/dotc/ast/untpd.scala | 14 ++- .../dotty/tools/dotc/core/Definitions.scala | 5 +- .../src/dotty/tools/dotc/core/StdNames.scala | 2 +- .../src/dotty/tools/dotc/core/Types.scala | 30 +----- .../dotty/tools/dotc/parsing/Parsers.scala | 95 +++++++++++++------ .../src/dotty/tools/dotc/parsing/Tokens.scala | 3 + .../tools/dotc/printing/PlainPrinter.scala | 6 +- .../tools/dotc/printing/RefinedPrinter.scala | 5 +- .../src/dotty/tools/dotc/typer/Checking.scala | 2 +- .../src/dotty/tools/dotc/typer/Typer.scala | 3 - docs/_docs/internals/syntax.md | 6 ++ .../scala/annotation/allowConversions.scala | 10 -- 14 files changed, 107 insertions(+), 98 deletions(-) delete mode 100644 library/src/scala/annotation/allowConversions.scala diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 9591bc5a93f0..d73e9b29c492 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -178,21 +178,7 @@ object desugar { val valName = normalizeName(vdef, tpt).asTermName var mods1 = vdef.mods - def dropInto(tpt: Tree): Tree = tpt match - case Into(tpt1) => - mods1 = vdef.mods.withAddedAnnotation( - TypedSplice( - Annotation(defn.AllowConversionsAnnot, tpt.span.startPos).tree)) - tpt1 - case ByNameTypeTree(tpt1) => - cpy.ByNameTypeTree(tpt)(dropInto(tpt1)) - case PostfixOp(tpt1, op) if op.name == tpnme.raw.STAR => - cpy.PostfixOp(tpt)(dropInto(tpt1), op) - case _ => - tpt - - val vdef1 = cpy.ValDef(vdef)(name = valName, tpt = dropInto(tpt)) - .withMods(mods1) + val vdef1 = cpy.ValDef(vdef)(name = valName).withMods(mods1) if isSetterNeeded(vdef) then val setterParam = makeSyntheticParameter(tpt = SetterParamTree().watching(vdef)) @@ -1876,8 +1862,11 @@ object desugar { assert(ctx.mode.isExpr || ctx.reporter.errorsReported || ctx.mode.is(Mode.Interactive), ctx.mode) Select(t, op.name) case PrefixOp(op, t) => - val nspace = if (ctx.mode.is(Mode.Type)) tpnme else nme - Select(t, nspace.UNARY_PREFIX ++ op.name) + if op.name == tpnme.into then + Annotated(t, New(ref(defn.IntoAnnot.typeRef), Nil :: Nil)) + else + val nspace = if (ctx.mode.is(Mode.Type)) tpnme else nme + Select(t, nspace.UNARY_PREFIX ++ op.name) case ForDo(enums, body) => makeFor(nme.foreach, nme.foreach, enums, body) orElse tree case ForYield(enums, body) => diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 4ec41b95a90b..a6dad7aa6ec3 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -304,6 +304,7 @@ object Trees { def withFlags(flags: FlagSet): ThisTree[Untyped] = withMods(untpd.Modifiers(flags)) def withAddedFlags(flags: FlagSet): ThisTree[Untyped] = withMods(rawMods | flags) + def withAddedAnnotation(annot: Tree[Untyped]): ThisTree[Untyped] = withMods(rawMods.withAddedAnnotation(annot)) /** Destructively update modifiers. To be used with care. */ def setMods(mods: untpd.Modifiers): Unit = myMods = mods diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index aabfdd97d7bd..eb5ec1872ff5 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -118,7 +118,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree])(implicit @constructorOnly src: SourceFile) extends TypTree case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree)(implicit @constructorOnly src: SourceFile) extends DefTree case class ExtMethods(paramss: List[ParamClause], methods: List[Tree])(implicit @constructorOnly src: SourceFile) extends Tree - case class Into(tpt: Tree)(implicit @constructorOnly src: SourceFile) extends Tree case class MacroTree(expr: Tree)(implicit @constructorOnly src: SourceFile) extends Tree case class ImportSelector(imported: Ident, renamed: Tree = EmptyTree, bound: Tree = EmptyTree)(implicit @constructorOnly src: SourceFile) extends Tree { @@ -552,6 +551,12 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { ValDef(nme.syntheticParamName(n), if (tpt == null) TypeTree() else tpt, EmptyTree) .withFlags(flags) + def isInto(t: Tree)(using Context): Boolean = t match + case PrefixOp(Ident(tpnme.into), _) => true + case Function(_, res) => isInto(res) + case Parens(t) => isInto(t) + case _ => false + def lambdaAbstract(params: List[ValDef] | List[TypeDef], tpt: Tree)(using Context): Tree = params match case Nil => tpt @@ -666,9 +671,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { def ExtMethods(tree: Tree)(paramss: List[ParamClause], methods: List[Tree])(using Context): Tree = tree match case tree: ExtMethods if (paramss eq tree.paramss) && (methods == tree.methods) => tree case _ => finalize(tree, untpd.ExtMethods(paramss, methods)(tree.source)) - def Into(tree: Tree)(tpt: Tree)(using Context): Tree = tree match - case tree: Into if tpt eq tree.tpt => tree - case _ => finalize(tree, untpd.Into(tpt)(tree.source)) def ImportSelector(tree: Tree)(imported: Ident, renamed: Tree, bound: Tree)(using Context): Tree = tree match { case tree: ImportSelector if (imported eq tree.imported) && (renamed eq tree.renamed) && (bound eq tree.bound) => tree case _ => finalize(tree, untpd.ImportSelector(imported, renamed, bound)(tree.source)) @@ -734,8 +736,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { cpy.PatDef(tree)(mods, transform(pats), transform(tpt), transform(rhs)) case ExtMethods(paramss, methods) => cpy.ExtMethods(tree)(transformParamss(paramss), transformSub(methods)) - case Into(tpt) => - cpy.Into(tree)(transform(tpt)) case ImportSelector(imported, renamed, bound) => cpy.ImportSelector(tree)(transformSub(imported), transform(renamed), transform(bound)) case Number(_, _) | TypedSplice(_) => @@ -791,8 +791,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { this(this(this(x, pats), tpt), rhs) case ExtMethods(paramss, methods) => this(paramss.foldLeft(x)(apply), methods) - case Into(tpt) => - this(x, tpt) case ImportSelector(imported, renamed, bound) => this(this(this(x, imported), renamed), bound) case Number(_, _) => diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 3cde29ee3d79..9d610f23a067 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -642,8 +642,6 @@ class Definitions { @tu lazy val RepeatedParamClass: ClassSymbol = enterSpecialPolyClass(tpnme.REPEATED_PARAM_CLASS, Covariant, Seq(ObjectType, SeqType)) - @tu lazy val IntoType: TypeSymbol = enterAliasType(tpnme.INTO, HKTypeLambda(TypeBounds.empty :: Nil)(_.paramRefs(0))) - // fundamental classes @tu lazy val StringClass: ClassSymbol = requiredClass("java.lang.String") def StringType: Type = StringClass.typeRef @@ -1002,7 +1000,6 @@ class Definitions { @tu lazy val JavaAnnotationClass: ClassSymbol = requiredClass("java.lang.annotation.Annotation") // Annotation classes - @tu lazy val AllowConversionsAnnot: ClassSymbol = requiredClass("scala.annotation.allowConversions") @tu lazy val AnnotationDefaultAnnot: ClassSymbol = requiredClass("scala.annotation.internal.AnnotationDefault") @tu lazy val AssignedNonLocallyAnnot: ClassSymbol = requiredClass("scala.annotation.internal.AssignedNonLocally") @tu lazy val BeanPropertyAnnot: ClassSymbol = requiredClass("scala.beans.BeanProperty") @@ -1018,6 +1015,7 @@ class Definitions { @tu lazy val ImplicitAmbiguousAnnot: ClassSymbol = requiredClass("scala.annotation.implicitAmbiguous") @tu lazy val ImplicitNotFoundAnnot: ClassSymbol = requiredClass("scala.annotation.implicitNotFound") @tu lazy val InlineParamAnnot: ClassSymbol = requiredClass("scala.annotation.internal.InlineParam") + @tu lazy val IntoAnnot: ClassSymbol = requiredClass("scala.annotation.internal.into") @tu lazy val ErasedParamAnnot: ClassSymbol = requiredClass("scala.annotation.internal.ErasedParam") @tu lazy val MainAnnot: ClassSymbol = requiredClass("scala.main") @tu lazy val MappedAlternativeAnnot: ClassSymbol = requiredClass("scala.annotation.internal.MappedAlternative") @@ -2137,7 +2135,6 @@ class Definitions { orType, RepeatedParamClass, ByNameParamClass2x, - IntoType, AnyValClass, NullClass, NothingClass, diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala index a2e78add1338..9772199678d7 100644 --- a/compiler/src/dotty/tools/dotc/core/StdNames.scala +++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala @@ -131,7 +131,7 @@ object StdNames { val EXCEPTION_RESULT_PREFIX: N = "exceptionResult" val EXPAND_SEPARATOR: N = str.EXPAND_SEPARATOR val IMPORT: N = "" - val INTO: N = "" + val INTO: N = "$into" val MODULE_SUFFIX: N = str.MODULE_SUFFIX val OPS_PACKAGE: N = "" val OVERLOADED: N = "" diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 2b1f6394acdc..fd17a41ca339 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -419,8 +419,8 @@ object Types extends TypeUtils { typeSymbol eq defn.RepeatedParamClass /** Is this a parameter type that allows implicit argument converson? */ - def isConvertibleParam(using Context): Boolean = - typeSymbol eq defn.IntoType + def isInto(using Context): Boolean = + typeSymbol eq ??? /** Is this the type of a method that has a repeated parameter type as * last parameter type? @@ -4131,34 +4131,14 @@ object Types extends TypeUtils { case ExprType(resType) => ExprType(addAnnotation(resType, cls, param)) case _ => AnnotatedType(tp, Annotation(cls, param.span)) - def wrapConvertible(tp: Type) = - AppliedType(defn.IntoType.typeRef, tp :: Nil) - - /** Add `Into[..] to the type itself and if it is a function type, to all its - * curried result type(s) as well. - */ - def addInto(tp: Type): Type = tp match - case tp @ AppliedType(tycon, args) if tycon.typeSymbol == defn.RepeatedParamClass => - tp.derivedAppliedType(tycon, addInto(args.head) :: Nil) - case tp @ AppliedType(tycon, args) if defn.isFunctionNType(tp) => - wrapConvertible(tp.derivedAppliedType(tycon, args.init :+ addInto(args.last))) - case tp @ defn.RefinedFunctionOf(rinfo) => - wrapConvertible(tp.derivedRefinedType(refinedInfo = addInto(rinfo))) - case tp: MethodOrPoly => - tp.derivedLambdaType(resType = addInto(tp.resType)) - case ExprType(resType) => - ExprType(addInto(resType)) - case _ => - wrapConvertible(tp) - def paramInfo(param: Symbol) = - var paramType = param.info.annotatedToRepeated + var paramType = param.info + .annotatedToRepeated + //.mapIntoAnnot(defn.IntoType.appliedTo(_)) if param.is(Inline) then paramType = addAnnotation(paramType, defn.InlineParamAnnot, param) if param.is(Erased) then paramType = addAnnotation(paramType, defn.ErasedParamAnnot, param) - if param.hasAnnotation(defn.AllowConversionsAnnot) then - paramType = addInto(paramType) paramType apply(params.map(_.name.asTermName))( diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 50380e5b14d3..6c2e69658927 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -73,6 +73,9 @@ object Parsers { enum ParseKind: case Expr, Type, Pattern + enum IntoOK: + case Yes, No, Nested + type StageKind = Int object StageKind { val None = 0 @@ -1484,7 +1487,7 @@ object Parsers { /** Same as [[typ]], but if this results in a wildcard it emits a syntax error and * returns a tree for type `Any` instead. */ - def toplevelTyp(): Tree = rejectWildcardType(typ()) + def toplevelTyp(intoOK: IntoOK = IntoOK.No): Tree = rejectWildcardType(typ(intoOK)) private def getFunction(tree: Tree): Option[Function] = tree match { case Parens(tree1) => getFunction(tree1) @@ -1535,12 +1538,21 @@ object Parsers { * | `(' [ FunArgType {`,' FunArgType } ] `)' * | '(' [ TypedFunParam {',' TypedFunParam } ')' * MatchType ::= InfixType `match` <<< TypeCaseClauses >>> + * IntoType ::= [‘into’] IntoTargetType + * | ‘( IntoType ‘)’ + * IntoTargetType ::= Type + * | FunTypeArgs (‘=>’ | ‘?=>’) IntoType */ - def typ(): Tree = + def typ(intoOK: IntoOK = IntoOK.No): Tree = val start = in.offset var imods = Modifiers() val erasedArgs: ListBuffer[Boolean] = ListBuffer() + def nestedIntoOK(token: Int) = + if token == TLARROW then IntoOK.No + else if intoOK == IntoOK.Nested then IntoOK.Yes + else intoOK + def functionRest(params: List[Tree]): Tree = val paramSpan = Span(start, in.lastOffset) atSpan(start, in.offset) { @@ -1569,8 +1581,9 @@ object Parsers { else accept(ARROW) + def resType() = typ(nestedIntoOK(token)) val resultType = - if isPure then capturesAndResult(typ) else typ() + if isPure then capturesAndResult(resType) else resType() if token == TLARROW then for case ValDef(_, tpt, _) <- params do if isByNameType(tpt) then @@ -1605,6 +1618,12 @@ object Parsers { syntaxError(ErasedTypesCanOnlyBeFunctionTypes(), implicitKwPos(start)) t + def isIntoPrefix: Boolean = + intoOK == IntoOK.Yes + && in.isIdent(nme.into) + && in.featureEnabled(Feature.into) + && canStartTypeTokens.contains(in.lookahead.token) + var isValParamList = false if in.token == LPAREN then in.nextToken() @@ -1635,17 +1654,36 @@ object Parsers { funArgType() commaSeparatedRest(t, funArg) accept(RPAREN) + + val intoAllowed = + intoOK == IntoOK.Yes + && args.lengthCompare(1) == 0 + && (!canFollowSimpleTypeTokens.contains(in.token) || followingIsVararg()) + val byNameAllowed = in.isArrow || isPureArrow + + def sanitize(arg: Tree): Tree = arg match + case ByNameTypeTree(t) if !byNameAllowed => + syntaxError(ByNameParameterNotSupported(t), t.span) + t + case PrefixOp(id @ Ident(tpnme.into), t) if !intoAllowed => + syntaxError(em"no `into` modifier allowed here", id.span) + t + case Parens(t) => + cpy.Parens(arg)(sanitize(t)) + case arg: FunctionWithMods => + val body1 = sanitize(arg.body) + if body1 eq arg.body then arg + else FunctionWithMods(arg.args, body1, arg.mods, arg.erasedParams).withSpan(arg.span) + case Function(args, res) if !intoAllowed => + cpy.Function(arg)(args, sanitize(res)) + case arg => + arg + + val args1 = args.mapConserve(sanitize) if isValParamList || in.isArrow || isPureArrow then functionRest(args) else - val args1 = args.mapConserve: t => - if isByNameType(t) then - syntaxError(ByNameParameterNotSupported(t), t.span) - stripByNameType(t) - else - t - val tuple = atSpan(start): - makeTupleOrParens(args1) + val tuple = atSpan(start)(makeTupleOrParens(args1)) typeRest: infixTypeRest: refinedTypeRest: @@ -1660,7 +1698,7 @@ object Parsers { LambdaTypeTree(tparams, toplevelTyp()) else if in.token == ARROW || isPureArrow(nme.PUREARROW) then val arrowOffset = in.skipToken() - val body = toplevelTyp() + val body = toplevelTyp(nestedIntoOK(in.token)) atSpan(start, arrowOffset): getFunction(body) match case Some(f) => @@ -1673,6 +1711,8 @@ object Parsers { typ() else if in.token == INDENT then enclosed(INDENT, typ()) + else if isIntoPrefix then + PrefixOp(typeIdent(), typ(IntoOK.Nested)) else typeRest(infixType()) end typ @@ -2047,18 +2087,13 @@ object Parsers { else core() - private def maybeInto(tp: () => Tree) = - if in.isIdent(nme.into) - && in.featureEnabled(Feature.into) - && canStartTypeTokens.contains(in.lookahead.token) - then atSpan(in.skipToken()) { Into(tp()) } - else tp() - /** FunArgType ::= Type * | `=>' Type * | `->' [CaptureSet] Type */ - val funArgType: () => Tree = () => paramTypeOf(typ) + val funArgType: () => Tree = + () => paramTypeOf(() => typ(IntoOK.Yes)) + // We allow intoOK and filter out afterwards in typ() /** ParamType ::= ParamValueType * | `=>' ParamValueType @@ -2067,15 +2102,21 @@ object Parsers { def paramType(): Tree = paramTypeOf(paramValueType) /** ParamValueType ::= Type [`*'] + * | IntoType + * | ‘(’ IntoType ‘)’ `*' */ - def paramValueType(): Tree = { - val t = maybeInto(toplevelTyp) - if (isIdent(nme.raw.STAR)) { + def paramValueType(): Tree = + val t = toplevelTyp(IntoOK.Yes) + if isIdent(nme.raw.STAR) then + if !t.isInstanceOf[Parens] && isInto(t) then + syntaxError( + em"""`*` cannot directly follow `into` parameter + |the `into` parameter needs to be put in parentheses""", + in.offset) in.nextToken() - atSpan(startOffset(t)) { PostfixOp(t, Ident(tpnme.raw.STAR)) } - } + atSpan(startOffset(t)): + PostfixOp(t, Ident(tpnme.raw.STAR)) else t - } /** TypeArgs ::= `[' Type {`,' Type} `]' * NamedTypeArgs ::= `[' NamedTypeArg {`,' NamedTypeArg} `]' @@ -3315,7 +3356,7 @@ object Parsers { /** ContextTypes ::= FunArgType {‘,’ FunArgType} */ def contextTypes(paramOwner: ParamOwner, numLeadParams: Int, impliedMods: Modifiers): List[ValDef] = - val tps = commaSeparated(() => paramTypeOf(toplevelTyp)) + val tps = commaSeparated(() => paramTypeOf(() => toplevelTyp())) var counter = numLeadParams def nextIdx = { counter += 1; counter } val paramFlags = if paramOwner.isClass then LocalParamAccessor else Param diff --git a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala index fbf4e8d701dd..dee3e976ddb1 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala @@ -238,6 +238,9 @@ object Tokens extends TokensCommon { final val canStartPatternTokens = atomicExprTokens | openParensTokens | BitSet(USCORE, QUOTE) + val canFollowSimpleTypeTokens = + BitSet(AT, WITH, COLONop, COLONfollow, COLONeol, LBRACE, IDENTIFIER, BACKQUOTED_IDENT, ARROW, CTXARROW, MATCH, FORSOME) + final val templateIntroTokens: TokenSet = BitSet(CLASS, TRAIT, OBJECT, ENUM, CASECLASS, CASEOBJECT) final val dclIntroTokens: TokenSet = BitSet(DEF, VAL, VAR, TYPE, GIVEN) diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 8fc0c568e125..06f015e66f8d 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -285,7 +285,11 @@ class PlainPrinter(_ctx: Context) extends Printer { toTextGlobal(tp.resultType) } case AnnotatedType(tpe, annot) => - if annot.symbol == defn.InlineParamAnnot || annot.symbol == defn.ErasedParamAnnot then toText(tpe) + if annot.symbol == defn.InlineParamAnnot || annot.symbol == defn.ErasedParamAnnot + then toText(tpe) + else if annot.symbol == defn.IntoAnnot && !printDebug then + atPrec(GlobalPrec): + Str("into ") ~ toText(tpe) else toTextLocal(tpe) ~ " " ~ toText(annot) case tp: TypeVar => def toTextCaret(tp: Type) = if printDebug then toTextLocal(tp) ~ Str("^") else toText(tp) diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 5d8b448e409c..fbdbd0bf6e8b 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -244,7 +244,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { case _ => val tsym = tycon.typeSymbol if tycon.isRepeatedParam then toTextLocal(args.head) ~ "*" - else if tp.isConvertibleParam then "into " ~ toText(args.head) + else if tp.isInto then atPrec(GlobalPrec)( "into " ~ toText(args.head) ) else if defn.isFunctionSymbol(tsym) then toTextFunction(tp) else if isInfixType(tp) then val l :: r :: Nil = args: @unchecked @@ -647,6 +647,9 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { && Feature.ccEnabled && !printDebug && Phases.checkCapturesPhase.exists // might be missing on -Ytest-pickler then toTextRetainsAnnot + else if annot.symbol.enclosingClass == defn.IntoAnnot && !printDebug then + atPrec(GlobalPrec): + Str("into ") ~ toText(arg) else toTextAnnot case EmptyTree => "" diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index eadca79cd78b..24619d1048cb 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -1089,7 +1089,7 @@ trait Checking { if sym.name == nme.apply && sym.owner.derivesFrom(defn.ConversionClass) && !sym.info.isErroneous - && !expected.isConvertibleParam + && !expected.isInto then def conv = methPart(tree) match case Select(qual, _) => qual.symbol.orElse(sym.owner) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 765554059374..094c979cf688 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -2335,9 +2335,6 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer && checkedArgs(1).tpe.derivesFrom(defn.RuntimeExceptionClass) then report.error(em"throws clause cannot be defined for RuntimeException", checkedArgs(1).srcPos) - else if tycon == defn.IntoType then - // is defined in package scala but this should be hidden from user programs - report.error(em"not found: ", tpt1.srcPos) else if (ctx.isJava) if tycon eq defn.ArrayClass then checkedArgs match { diff --git a/docs/_docs/internals/syntax.md b/docs/_docs/internals/syntax.md index cfa77c6ff965..10f068e53c7f 100644 --- a/docs/_docs/internals/syntax.md +++ b/docs/_docs/internals/syntax.md @@ -211,6 +211,12 @@ FunArgType ::= Type FunArgTypes ::= FunArgType { ‘,’ FunArgType } ParamType ::= [‘=>’] ParamValueType ParamValueType ::= Type [‘*’] PostfixOp(t, "*") + | IntoType + | ‘(’ IntoType ‘)’ ‘*’ PostfixOp(t, "*") +IntoType ::= [‘into’] IntoTargetType Into(t) + | ‘(’ IntoType ‘)’ +IntoTargetType ::= Type + | FunTypeArgs (‘=>’ | ‘?=>’) IntoType TypeArgs ::= ‘[’ Types ‘]’ ts Refinement ::= :<<< [RefineDcl] {semi [RefineDcl]} >>> ds TypeBounds ::= [‘>:’ Type] [‘<:’ Type] TypeBoundsTree(lo, hi) diff --git a/library/src/scala/annotation/allowConversions.scala b/library/src/scala/annotation/allowConversions.scala deleted file mode 100644 index 9d752ee26d21..000000000000 --- a/library/src/scala/annotation/allowConversions.scala +++ /dev/null @@ -1,10 +0,0 @@ -package scala.annotation -import annotation.experimental - -/** An annotation on a parameter type that allows implicit conversions - * for its arguments. Intended for use by Scala 2, to annotate Scala 2 - * libraries. Scala 3 uses the `into` modifier on the parameter - * type instead. - */ -@experimental -class allowConversions extends scala.annotation.StaticAnnotation From 692bf77064747fab4783f5c0bcc8e936c0db6d70 Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 14 Feb 2024 17:35:10 +0100 Subject: [PATCH 124/277] Typechecking with into modifiers --- .../dotty/tools/dotc/core/Definitions.scala | 1 + .../src/dotty/tools/dotc/core/Types.scala | 44 +++++++++++-- .../tools/dotc/printing/PlainPrinter.scala | 6 +- .../tools/dotc/printing/RefinedPrinter.scala | 1 - .../src/dotty/tools/dotc/typer/Checking.scala | 2 +- .../dotty/tools/dotc/typer/RefChecks.scala | 54 +++++++++++++++- .../tools/vulpix/TestConfiguration.scala | 2 + .../src/scala/annotation/internal/Into.scala | 14 +++++ tests/neg-custom-args/convertible.check | 21 +++++++ tests/neg/into-override.check | 21 +++++++ tests/neg/into-override.scala | 23 +++++++ tests/neg/into-syntax.check | 61 +++++++++++++++++++ tests/neg/into-syntax.scala | 27 ++++++++ tests/pos/into-class.scala | 15 +++++ .../stdlibExperimentalDefinitions.scala | 3 +- tests/run/convertible.scala | 20 +++--- tests/warn/convertible.scala | 18 +++++- 17 files changed, 306 insertions(+), 27 deletions(-) create mode 100644 library/src/scala/annotation/internal/Into.scala create mode 100644 tests/neg-custom-args/convertible.check create mode 100644 tests/neg/into-override.check create mode 100644 tests/neg/into-override.scala create mode 100644 tests/neg/into-syntax.check create mode 100644 tests/neg/into-syntax.scala create mode 100644 tests/pos/into-class.scala diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 9d610f23a067..bf6f12c4f9f9 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -1016,6 +1016,7 @@ class Definitions { @tu lazy val ImplicitNotFoundAnnot: ClassSymbol = requiredClass("scala.annotation.implicitNotFound") @tu lazy val InlineParamAnnot: ClassSymbol = requiredClass("scala.annotation.internal.InlineParam") @tu lazy val IntoAnnot: ClassSymbol = requiredClass("scala.annotation.internal.into") + @tu lazy val IntoParamAnnot: ClassSymbol = requiredClass("scala.annotation.internal.$into") @tu lazy val ErasedParamAnnot: ClassSymbol = requiredClass("scala.annotation.internal.ErasedParam") @tu lazy val MainAnnot: ClassSymbol = requiredClass("scala.main") @tu lazy val MappedAlternativeAnnot: ClassSymbol = requiredClass("scala.annotation.internal.MappedAlternative") diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index fd17a41ca339..71f9ab196ed2 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -419,8 +419,9 @@ object Types extends TypeUtils { typeSymbol eq defn.RepeatedParamClass /** Is this a parameter type that allows implicit argument converson? */ - def isInto(using Context): Boolean = - typeSymbol eq ??? + def isInto(using Context): Boolean = this match + case AnnotatedType(_, annot) => annot.symbol == defn.IntoParamAnnot + case _ => false /** Is this the type of a method that has a repeated parameter type as * last parameter type? @@ -1927,7 +1928,9 @@ object Types extends TypeUtils { case res => res } defn.FunctionNOf( - mt.paramInfos.mapConserve(_.translateFromRepeated(toArray = isJava)), + mt.paramInfos.mapConserve: + _.translateFromRepeated(toArray = isJava) + .mapIntoAnnot(defn.IntoParamAnnot, null), result1, isContextual) if mt.hasErasedParams then defn.PolyFunctionOf(mt) @@ -1975,6 +1978,38 @@ object Types extends TypeUtils { case _ => this } + /** A mapping between mapping one kind of into annotation to another or + * dropping into annotations. + * @param from the into annotation to map + * @param to either the replacement annotation symbol, or `null` + * in which case the `from` annotations are dropped. + */ + def mapIntoAnnot(from: ClassSymbol, to: ClassSymbol | Null)(using Context): Type = this match + case self @ AnnotatedType(tp, annot) => + val tp1 = tp.mapIntoAnnot(from, to) + if annot.symbol == from then + if to == null then tp1 + else AnnotatedType(tp1, Annotation(to, from.span)) + else self.derivedAnnotatedType(tp1, annot) + case AppliedType(tycon, arg :: Nil) if tycon.typeSymbol == defn.RepeatedParamClass => + val arg1 = arg.mapIntoAnnot(from, to) + if arg1 eq arg then this + else AppliedType(tycon, arg1 :: Nil) + case defn.FunctionOf(argTypes, resType, isContextual) => + val resType1 = resType.mapIntoAnnot(from, to) + if resType1 eq resType then this + else defn.FunctionOf(argTypes, resType1, isContextual) + case RefinedType(parent, rname, mt: MethodOrPoly) => + val mt1 = mt.mapIntoAnnot(from, to) + if mt1 eq mt then this + else RefinedType(parent.mapIntoAnnot(from, to), rname, mt1) + case mt: MethodOrPoly => + mt.derivedLambdaType(resType = mt.resType.mapIntoAnnot(from, to)) + case tp: ExprType => + tp.derivedExprType(tp.resType.mapIntoAnnot(from, to)) + case _ => + this + /** A type capturing `ref` */ def capturing(ref: CaptureRef)(using Context): Type = if captureSet.accountsFor(ref) then this @@ -4122,6 +4157,7 @@ object Types extends TypeUtils { /** Produce method type from parameter symbols, with special mappings for repeated * and inline parameters: * - replace @repeated annotations on Seq or Array types by types + * - map into annotations to $into annotations * - add @inlineParam to inline parameters * - add @erasedParam to erased parameters * - wrap types of parameters that have an @allowConversions annotation with Into[_] @@ -4134,7 +4170,7 @@ object Types extends TypeUtils { def paramInfo(param: Symbol) = var paramType = param.info .annotatedToRepeated - //.mapIntoAnnot(defn.IntoType.appliedTo(_)) + .mapIntoAnnot(defn.IntoAnnot, defn.IntoParamAnnot) if param.is(Inline) then paramType = addAnnotation(paramType, defn.InlineParamAnnot, param) if param.is(Erased) then diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 06f015e66f8d..1a52f61d3153 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -287,9 +287,9 @@ class PlainPrinter(_ctx: Context) extends Printer { case AnnotatedType(tpe, annot) => if annot.symbol == defn.InlineParamAnnot || annot.symbol == defn.ErasedParamAnnot then toText(tpe) - else if annot.symbol == defn.IntoAnnot && !printDebug then - atPrec(GlobalPrec): - Str("into ") ~ toText(tpe) + else if (annot.symbol == defn.IntoAnnot || annot.symbol == defn.IntoParamAnnot) + && !printDebug + then atPrec(GlobalPrec)( Str("into ") ~ toText(tpe) ) else toTextLocal(tpe) ~ " " ~ toText(annot) case tp: TypeVar => def toTextCaret(tp: Type) = if printDebug then toTextLocal(tp) ~ Str("^") else toText(tp) diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index fbdbd0bf6e8b..893b34f48396 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -244,7 +244,6 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { case _ => val tsym = tycon.typeSymbol if tycon.isRepeatedParam then toTextLocal(args.head) ~ "*" - else if tp.isInto then atPrec(GlobalPrec)( "into " ~ toText(args.head) ) else if defn.isFunctionSymbol(tsym) then toTextFunction(tp) else if isInfixType(tp) then val l :: r :: Nil = args: @unchecked diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 24619d1048cb..56f67574a72d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -1082,7 +1082,7 @@ trait Checking { /** If `tree` is an application of a new-style implicit conversion (using the apply * method of a `scala.Conversion` instance), check that the expected type is - * a convertible formal parameter type or that implicit conversions are enabled. + * annotated with @$into or that implicit conversions are enabled. */ def checkImplicitConversionUseOK(tree: Tree, expected: Type)(using Context): Unit = val sym = tree.symbol diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index f0914a9f6664..6be3aa0b36d5 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -8,7 +8,7 @@ import Symbols.*, Types.*, Contexts.*, Flags.*, Names.*, NameOps.*, NameKinds.* import StdNames.*, Denotations.*, Phases.*, SymDenotations.* import NameKinds.DefaultGetterName import util.Spans.* -import scala.collection.mutable +import scala.collection.{mutable, immutable} import ast.* import MegaPhase.* import config.Printers.{checks, noPrinter, capt} @@ -368,6 +368,52 @@ object RefChecks { && atPhase(typerPhase): loop(member.info.paramInfoss, other.info.paramInfoss) + /** A map of all occurrences of `into` in a member type. + * Key: number of parameter carrying `into` annotation(s) + * Value: A list of all depths of into annotations, where each + * function arrow increases the depth. + * Example: + * def foo(x: into A, y: => [X] => into (x: X) => into B): C + * produces the map + * (0 -> List(0), 1 -> List(1, 2)) + */ + type IntoOccurrenceMap = immutable.Map[Int, List[Int]] + + def intoOccurrences(tp: Type): IntoOccurrenceMap = + + def traverseInfo(depth: Int, tp: Type): List[Int] = tp match + case AnnotatedType(tp, annot) if annot.symbol == defn.IntoParamAnnot => + depth :: traverseInfo(depth, tp) + case AppliedType(tycon, arg :: Nil) if tycon.typeSymbol == defn.RepeatedParamClass => + traverseInfo(depth, arg) + case defn.FunctionOf(_, resType, _) => + traverseInfo(depth + 1, resType) + case RefinedType(parent, rname, mt: MethodOrPoly) => + traverseInfo(depth, mt) + case tp: MethodOrPoly => + traverseInfo(depth + 1, tp.resType) + case tp: ExprType => + traverseInfo(depth, tp.resType) + case _ => + Nil + + def traverseParams(n: Int, formals: List[Type], acc: IntoOccurrenceMap): IntoOccurrenceMap = + if formals.isEmpty then acc + else + val occs = traverseInfo(0, formals.head) + traverseParams(n + 1, formals.tail, if occs.isEmpty then acc else acc + (n -> occs)) + + def traverse(n: Int, tp: Type, acc: IntoOccurrenceMap): IntoOccurrenceMap = tp match + case tp: PolyType => + traverse(n, tp.resType, acc) + case tp: MethodType => + traverse(n + tp.paramInfos.length, tp.resType, traverseParams(n, tp.paramInfos, acc)) + case _ => + acc + + traverse(0, tp, immutable.Map.empty) + end intoOccurrences + val checker = if makeOverridingPairsChecker == null then OverridingPairsChecker(clazz, self) else makeOverridingPairsChecker(clazz, self) @@ -572,6 +618,8 @@ object RefChecks { overrideError(i"needs to be declared with @targetName(${"\""}${other.targetName}${"\""}) so that external names match") else overrideError("cannot have a @targetName annotation since external names would be different") + else if intoOccurrences(memberTp(self)) != intoOccurrences(otherTp(self)) then + overrideError("has different occurrences of `into` modifiers", compareTypes = true) else if other.is(ParamAccessor) && !isInheritedAccessor(member, other) then // (1.12) report.errorOrMigrationWarning( em"cannot override val parameter ${other.showLocated}", @@ -1002,9 +1050,9 @@ object RefChecks { end checkNoPrivateOverrides def checkVolatile(sym: Symbol)(using Context): Unit = - if sym.isVolatile && !sym.is(Mutable) then + if sym.isVolatile && !sym.is(Mutable) then report.warning(VolatileOnVal(), sym.srcPos) - + /** Check that unary method definition do not receive parameters. * They can only receive inferred parameters such as type parameters and implicit parameters. */ diff --git a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala index 04be00fe921e..1defe3f4f53d 100644 --- a/compiler/test/dotty/tools/vulpix/TestConfiguration.scala +++ b/compiler/test/dotty/tools/vulpix/TestConfiguration.scala @@ -66,7 +66,9 @@ object TestConfiguration { val yCheckOptions = Array("-Ycheck:all") val commonOptions = Array("-indent") ++ checkOptions ++ noCheckOptions ++ yCheckOptions + val noYcheckCommonOptions = Array("-indent") ++ checkOptions ++ noCheckOptions val defaultOptions = TestFlags(basicClasspath, commonOptions) + val noYcheckOptions = TestFlags(basicClasspath, noYcheckCommonOptions) val unindentOptions = TestFlags(basicClasspath, Array("-no-indent") ++ checkOptions ++ noCheckOptions ++ yCheckOptions) val withCompilerOptions = defaultOptions.withClasspath(withCompilerClasspath).withRunClasspath(withCompilerClasspath) diff --git a/library/src/scala/annotation/internal/Into.scala b/library/src/scala/annotation/internal/Into.scala new file mode 100644 index 000000000000..a256636406c2 --- /dev/null +++ b/library/src/scala/annotation/internal/Into.scala @@ -0,0 +1,14 @@ +package scala.annotation.internal +import annotation.experimental + +/** An annotation on (part of) a parameter type that allows implicit conversions + * for its arguments. The `into` modifier on parameter types in Scala 3 is + * mapped to this annotation. We can also install a more generally accessible + * alias so that Scala 2 libraries can use the feature. + */ +@experimental +class into() extends annotation.StaticAnnotation + +@experimental +class $into() extends annotation.StaticAnnotation + diff --git a/tests/neg-custom-args/convertible.check b/tests/neg-custom-args/convertible.check new file mode 100644 index 000000000000..c1ba6e9e6934 --- /dev/null +++ b/tests/neg-custom-args/convertible.check @@ -0,0 +1,21 @@ +-- [E120] Naming Error: tests/neg-custom-args/convertible.scala:15:6 --------------------------------------------------- +15 |trait C[X] extends A[X]: // error + | ^ + | Name clash between defined and inherited member: + | def f(x: X): Unit in trait A at line 10 and + | override def f(x: into X): Unit in trait C at line 16 + | have the same type after erasure. + | + | Consider adding a @targetName annotation to one of the conflicting definitions + | for disambiguation. +-- [E120] Naming Error: tests/neg-custom-args/convertible.scala:18:6 --------------------------------------------------- +18 |class D[X] extends B[X], C[X] // error + | ^ + | Name clash between inherited members: + | override def f(x: X): Unit in trait B at line 13 and + | override def f(x: into X): Unit in trait C at line 16 + | have the same type after erasure. + | + | Consider adding a @targetName annotation to one of the conflicting definitions + | for disambiguation. +there was 1 feature warning; re-run with -feature for details diff --git a/tests/neg/into-override.check b/tests/neg/into-override.check new file mode 100644 index 000000000000..812470494a8b --- /dev/null +++ b/tests/neg/into-override.check @@ -0,0 +1,21 @@ +-- [E164] Declaration Error: tests/neg/into-override.scala:16:15 ------------------------------------------------------- +16 | override def f(x: into X) = super.f(x) // error + | ^ + | error overriding method f in trait A of type (x: X): Unit; + | method f of type (x: into X): Unit has different occurrences of `into` modifiers + | + | longer explanation available when compiling with `-explain` +-- [E164] Declaration Error: tests/neg/into-override.scala:18:6 -------------------------------------------------------- +18 |class D[X] extends B[X], C[X] // error + | ^ + | error overriding method f in trait B of type (x: X): Unit; + | method f in trait C of type (x: into X): Unit has different occurrences of `into` modifiers + | + | longer explanation available when compiling with `-explain` +-- [E164] Declaration Error: tests/neg/into-override.scala:21:15 ------------------------------------------------------- +21 | override def f(x: X) = super.f(x) // error + | ^ + | error overriding method f in trait C of type (x: into X): Unit; + | method f of type (x: X): Unit has different occurrences of `into` modifiers + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg/into-override.scala b/tests/neg/into-override.scala new file mode 100644 index 000000000000..645ae8756003 --- /dev/null +++ b/tests/neg/into-override.scala @@ -0,0 +1,23 @@ +//> using options -Xfatal-warnings + +import language.experimental.into + +class Text(val str: String) + +given Conversion[String, Text] = Text(_) + +trait A[X]: + def f(x: X): Unit = () + +trait B[X] extends A[X]: + override def f(x: X) = super.f(x) + +trait C[X] extends A[X]: + override def f(x: into X) = super.f(x) // error + +class D[X] extends B[X], C[X] // error + +trait E[X] extends C[X]: + override def f(x: X) = super.f(x) // error + +def f = new D[Text].f("abc") diff --git a/tests/neg/into-syntax.check b/tests/neg/into-syntax.check new file mode 100644 index 000000000000..ad1f95db93be --- /dev/null +++ b/tests/neg/into-syntax.check @@ -0,0 +1,61 @@ +-- [E040] Syntax Error: tests/neg/into-syntax.scala:7:22 --------------------------------------------------------------- +7 | def f1(x: List[into Int]) = () // error // error + | ^^^ + | ',' or ']' expected, but identifier found +-- Error: tests/neg/into-syntax.scala:11:20 ---------------------------------------------------------------------------- +11 | def f4(x: into Int*) = () // error + | ^ + | `*` cannot directly follow `into` parameter + | the `into` parameter needs to be put in parentheses +-- [E040] Syntax Error: tests/neg/into-syntax.scala:21:23 -------------------------------------------------------------- +21 | def f11(x: ((y: into Int) => into Int => Int)*) = () // error // error + | ^^^ + | ')' expected, but identifier found +-- Error: tests/neg/into-syntax.scala:24:14 ---------------------------------------------------------------------------- +24 | def f14(x: (into Int) => Int) = () // error + | ^^^^ + | no `into` modifier allowed here +-- Error: tests/neg/into-syntax.scala:25:14 ---------------------------------------------------------------------------- +25 | def f15(x: (into Int, into Int)) = () // error // error + | ^^^^ + | no `into` modifier allowed here +-- Error: tests/neg/into-syntax.scala:25:24 ---------------------------------------------------------------------------- +25 | def f15(x: (into Int, into Int)) = () // error // error + | ^^^^ + | no `into` modifier allowed here +-- Error: tests/neg/into-syntax.scala:26:14 ---------------------------------------------------------------------------- +26 | def f16(x: (into Int, into Int) => Int) = () // error // error + | ^^^^ + | no `into` modifier allowed here +-- Error: tests/neg/into-syntax.scala:26:24 ---------------------------------------------------------------------------- +26 | def f16(x: (into Int, into Int) => Int) = () // error // error + | ^^^^ + | no `into` modifier allowed here +-- [E040] Syntax Error: tests/neg/into-syntax.scala:27:27 -------------------------------------------------------------- +27 | def f17(x: into (y: into Int, z: into Int) => into Int) = () // error // error // error + | ^^^ + | ')' expected, but identifier found +-- [E019] Syntax Error: tests/neg/into-syntax.scala:27:44 -------------------------------------------------------------- +27 | def f17(x: into (y: into Int, z: into Int) => into Int) = () // error // error // error + | ^ + | Missing return type + | + | longer explanation available when compiling with `-explain` +-- [E006] Not Found Error: tests/neg/into-syntax.scala:7:17 ------------------------------------------------------------ +7 | def f1(x: List[into Int]) = () // error // error + | ^^^^ + | Not found: type into - did you mean into.type? + | + | longer explanation available when compiling with `-explain` +-- [E006] Not Found Error: tests/neg/into-syntax.scala:21:18 ----------------------------------------------------------- +21 | def f11(x: ((y: into Int) => into Int => Int)*) = () // error // error + | ^^^^ + | Not found: type into - did you mean into.type? + | + | longer explanation available when compiling with `-explain` +-- [E006] Not Found Error: tests/neg/into-syntax.scala:27:22 ----------------------------------------------------------- +27 | def f17(x: into (y: into Int, z: into Int) => into Int) = () // error // error // error + | ^^^^ + | Not found: type into - did you mean into.type? + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg/into-syntax.scala b/tests/neg/into-syntax.scala new file mode 100644 index 000000000000..8f48a603adf6 --- /dev/null +++ b/tests/neg/into-syntax.scala @@ -0,0 +1,27 @@ +//> using options -feature + +import language.experimental.into + + +object x1: + def f1(x: List[into Int]) = () // error // error +object x3: + def f3(x: ((into Int))) = () // ok +object x4: + def f4(x: into Int*) = () // error +object x5: + def f5(x: ((into Int))*) = () // ok + +object x6: + def f6(x: (into Int)*) = () // ok + def f7(x: (Int => into Int)*) = () // ok + def f8(x: (Int => (into Int))*) = () // ok + def f9(x: (y: Int) => into Int) = () // ok + def f10(x: ((y: Int) => into Int)*) = () // ok + def f11(x: ((y: into Int) => into Int => Int)*) = () // error // error + +object x7: + def f14(x: (into Int) => Int) = () // error + def f15(x: (into Int, into Int)) = () // error // error + def f16(x: (into Int, into Int) => Int) = () // error // error + def f17(x: into (y: into Int, z: into Int) => into Int) = () // error // error // error diff --git a/tests/pos/into-class.scala b/tests/pos/into-class.scala new file mode 100644 index 000000000000..2638b9a0234a --- /dev/null +++ b/tests/pos/into-class.scala @@ -0,0 +1,15 @@ +import language.experimental.into + +class Text(str: String) + +case class C(x: into Text) + +case class D(x: Text) + +given Conversion[String, Text] = Text(_) + +def Test = + val c = C("a") + val d = new C("b") + val e = c.copy() + val f = c.copy(x = "d") diff --git a/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala b/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala index 888e5c36405d..247f7ecc8e9b 100644 --- a/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala +++ b/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala @@ -57,7 +57,8 @@ val experimentalDefinitionInLibrary = Set( "scala.caps$", //// New feature: into - "scala.annotation.allowConversions", + "scala.annotation.internal.into", + "scala.annotation.internal.$into", //// New feature: @publicInBinary "scala.annotation.publicInBinary", diff --git a/tests/run/convertible.scala b/tests/run/convertible.scala index 0670d1949fd9..7a92964a1f31 100644 --- a/tests/run/convertible.scala +++ b/tests/run/convertible.scala @@ -1,4 +1,4 @@ -//> using options -Xfatal-warnings +//> using options -feature -Xfatal-warnings import language.experimental.into @@ -8,27 +8,23 @@ given Conversion[String, Text] = Text(_) @main def Test = - def f(x: into Text, y: => into Text, zs: into Text*) = - println(s"${x.str} ${y.str} ${zs.map(_.str).mkString(" ")}") + def f(xxx: into Text, yyy: => into Text, zs: (into Text)*) = + println(s"${xxx.str} ${yyy.str} ${zs.map(_.str).mkString(" ")}") f("abc", "def") // ok f("abc", "def", "xyz", "uvw") // ok f("abc", "def", "xyz", Text("uvw")) // ok - def g(x: into () => Text) = + def g(x: () => into Text) = println(x().str) g(() => "hi") -trait A[X]: - def f(x: X): Unit = () +trait C[X]: + def f(x: into X) = x -trait B[X] extends A[X]: - override def f(x: X) = super.f(x) +class D[X] extends C[X] -trait C[X] extends A[X]: - override def f(x: into X) = super.f(x) +def f = new D[Text].f("abc") -class D[X] extends B[X], C[X] -def f = new D[Text].f("abc") diff --git a/tests/warn/convertible.scala b/tests/warn/convertible.scala index c98006ecdc9b..b830093fc891 100644 --- a/tests/warn/convertible.scala +++ b/tests/warn/convertible.scala @@ -18,13 +18,27 @@ object Test: def g(x: into Text) = println(x.str) + def g2(x: into Text) = + println(x.str) + + def g3(x: Text) = + println(x.str) g("abc") // OK val gg = g - gg("abc") // straight eta expansion is also OK + gg("abc") // warn, eta expansion does not preserve into + + val c1 = if ??? then g else g2 + c1("abc") // warn, eta expansion does not preserve into + + val c2 = if ??? then g else g3 + c2("abc") // warn, eta expesnion does not preserve into + + val c3 = if ??? then g3 else g + c3("abc") // warn, eta expesnion does not preserve into def h1[X](x: X)(y: X): Unit = () def h(x: into Text) = val y = h1(x) - y("abc") // warn, inference through type variable does not propagate \ No newline at end of file + y("abc") // warn, eta expesnion does not preserve into \ No newline at end of file From b518d75306c7744a3acacfbbb9034a4965658849 Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 14 Feb 2024 18:38:35 +0100 Subject: [PATCH 125/277] Update doc page and move into annotation to annotation package --- .../dotty/tools/dotc/core/Definitions.scala | 2 +- .../reference/experimental/into-modifier.md | 67 +++++++++++++++---- .../src/scala/annotation/internal/$into.scala | 15 +++++ .../{internal/Into.scala => into.scala} | 10 +-- tests/neg-custom-args/convertible.check | 21 ------ tests/pos/into-sam.scala | 18 +++++ .../stdlibExperimentalDefinitions.scala | 2 +- 7 files changed, 91 insertions(+), 44 deletions(-) create mode 100644 library/src/scala/annotation/internal/$into.scala rename library/src/scala/annotation/{internal/Into.scala => into.scala} (52%) delete mode 100644 tests/neg-custom-args/convertible.check create mode 100644 tests/pos/into-sam.scala diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index bf6f12c4f9f9..789e744fbfc9 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -1015,7 +1015,7 @@ class Definitions { @tu lazy val ImplicitAmbiguousAnnot: ClassSymbol = requiredClass("scala.annotation.implicitAmbiguous") @tu lazy val ImplicitNotFoundAnnot: ClassSymbol = requiredClass("scala.annotation.implicitNotFound") @tu lazy val InlineParamAnnot: ClassSymbol = requiredClass("scala.annotation.internal.InlineParam") - @tu lazy val IntoAnnot: ClassSymbol = requiredClass("scala.annotation.internal.into") + @tu lazy val IntoAnnot: ClassSymbol = requiredClass("scala.annotation.into") @tu lazy val IntoParamAnnot: ClassSymbol = requiredClass("scala.annotation.internal.$into") @tu lazy val ErasedParamAnnot: ClassSymbol = requiredClass("scala.annotation.internal.ErasedParam") @tu lazy val MainAnnot: ClassSymbol = requiredClass("scala.main") diff --git a/docs/_docs/reference/experimental/into-modifier.md b/docs/_docs/reference/experimental/into-modifier.md index 2ee4c74539b3..0c1d24b1d970 100644 --- a/docs/_docs/reference/experimental/into-modifier.md +++ b/docs/_docs/reference/experimental/into-modifier.md @@ -32,10 +32,10 @@ The `into` modifier on the type of `elems` means that implicit conversions can b `into` also allows conversions on the results of function arguments. For instance, consider the new proposed signature of the `flatMap` method on `List[A]`: ```scala - def flatMap[B](f: into A => IterableOnce[B]): List[B] + def flatMap[B](f: A => into IterableOnce[B]): List[B] ``` -This allows a conversion of the actual argument to the function type `A => IterableOnce[B]`. Crucially, it also allows that conversion to be applied to -the function result. So the following would work: +This accepts all actual arguments `f` that, when applied to an `A`, give a result +that is convertible to `IterableOnce[B]`. So the following would work: ```scala scala> val xs = List(1, 2, 3) scala> xs.flatMap(x => x.toString * x) @@ -49,7 +49,7 @@ When applied to a vararg parameter, `into` allows a conversion on each argument number of `IterableOnce[Char]` arguments, and also allows implicit conversions into `IterableOnce[Char]`: ```scala -def concatAll(xss: into IterableOnce[Char]*): List[Char] = +def concatAll(xss: (into IterableOnce[Char])*): List[Char] = xss.foldLeft(List[Char]())(_ ++ _) ``` Here, the call @@ -58,24 +58,63 @@ concatAll(List('a'), "bc", Array('d', 'e')) ``` would apply two _different_ implicit conversions: the conversion from `String` to `Iterable[Char]` gets applied to the second argument and the conversion from `Array[Char]` to `Iterable[Char]` gets applied to the third argument. +Note that a vararg parameter type with into modifiers needs to be put in parentheses, as is shown in the example above. This is to make the precedence clear: each element of the argument sequence is converted by itself. + ## Retrofitting Scala 2 libraries -A new annotation `allowConversions` has the same effect as an `into` modifier. It is defined as an `@experimental` class in package `scala.annotation`. It is intended to be used for retrofitting Scala 2 library code so that Scala 3 conversions can be applied to arguments without language imports. For instance, the definitions of +There is also an annotation `@into` in the `scala.annotation` package that has +has the same effect as an `into` modifier. It is intended to be used for retrofitting Scala 2 library code so that Scala 3 conversions can be applied to arguments without language imports. For instance, the definitions of `++` and `flatMap` in the Scala 2.13 `List` class could be retrofitted as follows. ```scala - def ++ (@allowConversions elems: IterableOnce[A]): List[A] - def flatMap[B](@allowConversions f: A => IterableOnce[B]): List[B] + def ++ (elems: IterableOnce[A] @into): List[A] + def flatMap[B](f: A => IterableOnce[B] @into): List[B] +``` +For Scala 3 code, the `into` modifier is preferred, because it adheres to the principle that annotations should not influence typing and type inference in Scala. + +## Restrictions + +The `into` modifier is only allowed in the types method parameters. It can be given either for the whole type, or some result type of a top-level function type, but not anywhere else. The `into` modifier does not propagate outside the method. In particular, a partially applied method does not propagate `into` modifiers to its result. + +**Example:** + +Say we have +```scala +def f(x: Int)(y: into Text): Unit +``` +then +```scala +f(3) : Text => Unit +``` +Note the `into` modifier is not longer present on the type of `f(3)`. Therefore, follow-on arguments to `f(3)` do not allow implicit conversions. Generally it is not possible to +define function types that allow implicit conversions on their arguments, but it is possible to define SAM types that allow conversions. E.g. +```scala +trait ConvArg: + def apply(x: into Text): Unit + +val x: ConvArg = f(3)(_) +``` + +Note this is similar to the way vararg parameters are handled in Scala. If we have +```scala +def g(x: Int)(y: Int*): Unit +``` +then +```scala +g(4) : Seq[Int] => Unit ``` -For Scala 3 code, the `into` modifier is preferred. First, because it is shorter, -and second, because it adheres to the principle that annotations should not influence -typing and type inference in Scala. +Observe that the vararg annotation also got dropped in the result type of `g(4)`. ## Syntax changes The addition to the grammar is: ``` -ParamType ::= [‘=>’] ParamValueType -ParamValueType ::= [‘into‘] ExactParamType -ExactParamType ::= Type [‘*’] +ParamType ::= [‘=>’] ParamValueType +ParamValueType ::= Type [‘*’] + | IntoType + | ‘(’ IntoType ‘)’ ‘*’ +IntoType ::= [‘into’] IntoTargetType + | ‘(’ IntoType ‘)’ +IntoTargetType ::= Type + | FunTypeArgs (‘=>’ | ‘?=>’) IntoType ``` -As the grammar shows, `into` can only applied to the type of a parameter; it is illegal in other positions. +As the grammar shows, `into` can only applied to the type of a parameter; it is illegal in other positions. Also, `into` modifiers in vararg types have to be enclosed in parentheses. diff --git a/library/src/scala/annotation/internal/$into.scala b/library/src/scala/annotation/internal/$into.scala new file mode 100644 index 000000000000..7009d829483f --- /dev/null +++ b/library/src/scala/annotation/internal/$into.scala @@ -0,0 +1,15 @@ +package scala.annotation.internal +import annotation.experimental + +/** An internal annotation on (part of) a parameter type that allows implicit conversions + * for its arguments. The publicly visible `into` annotation in the parent package + * `annotation` gets mapped to `$into` by the compiler in all places where + * conversions should be allowed. The reason for the split into two annotations + * is that `annotation.into` is given in source code and may propagate in unspecified + * ways through type inference. By contrast `$into` is constrained to be occur only + * on parameters of method types. This makes implicit conversion insertion + * predictable and independent of the un-specified aspects of type inference. + */ +@experimental +class $into() extends annotation.StaticAnnotation + diff --git a/library/src/scala/annotation/internal/Into.scala b/library/src/scala/annotation/into.scala similarity index 52% rename from library/src/scala/annotation/internal/Into.scala rename to library/src/scala/annotation/into.scala index a256636406c2..70a53ff9478d 100644 --- a/library/src/scala/annotation/internal/Into.scala +++ b/library/src/scala/annotation/into.scala @@ -1,14 +1,10 @@ -package scala.annotation.internal +package scala.annotation import annotation.experimental /** An annotation on (part of) a parameter type that allows implicit conversions * for its arguments. The `into` modifier on parameter types in Scala 3 is - * mapped to this annotation. We can also install a more generally accessible - * alias so that Scala 2 libraries can use the feature. + * mapped to this annotation. The annotation is intended to be used directly in + * Scala 2 sources only. For Scala 3, the `into` modifier should be preferred. */ @experimental class into() extends annotation.StaticAnnotation - -@experimental -class $into() extends annotation.StaticAnnotation - diff --git a/tests/neg-custom-args/convertible.check b/tests/neg-custom-args/convertible.check deleted file mode 100644 index c1ba6e9e6934..000000000000 --- a/tests/neg-custom-args/convertible.check +++ /dev/null @@ -1,21 +0,0 @@ --- [E120] Naming Error: tests/neg-custom-args/convertible.scala:15:6 --------------------------------------------------- -15 |trait C[X] extends A[X]: // error - | ^ - | Name clash between defined and inherited member: - | def f(x: X): Unit in trait A at line 10 and - | override def f(x: into X): Unit in trait C at line 16 - | have the same type after erasure. - | - | Consider adding a @targetName annotation to one of the conflicting definitions - | for disambiguation. --- [E120] Naming Error: tests/neg-custom-args/convertible.scala:18:6 --------------------------------------------------- -18 |class D[X] extends B[X], C[X] // error - | ^ - | Name clash between inherited members: - | override def f(x: X): Unit in trait B at line 13 and - | override def f(x: into X): Unit in trait C at line 16 - | have the same type after erasure. - | - | Consider adding a @targetName annotation to one of the conflicting definitions - | for disambiguation. -there was 1 feature warning; re-run with -feature for details diff --git a/tests/pos/into-sam.scala b/tests/pos/into-sam.scala new file mode 100644 index 000000000000..7513b5c5b0de --- /dev/null +++ b/tests/pos/into-sam.scala @@ -0,0 +1,18 @@ + +//> using options -feature -Xfatal-warnings + +import language.experimental.into + +class Text(val str: String) + +given Conversion[String, Text] = Text(_) +object Test: + def f(x: Int)(y: into Text): Unit = () + val _: Text => Unit = f(3) + + trait ConvArg: + def apply(x: into Text): Unit + + val x: ConvArg = f(3)(_) + + x("abc") diff --git a/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala b/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala index 247f7ecc8e9b..ca48dd2d8a5f 100644 --- a/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala +++ b/tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala @@ -57,7 +57,7 @@ val experimentalDefinitionInLibrary = Set( "scala.caps$", //// New feature: into - "scala.annotation.internal.into", + "scala.annotation.into", "scala.annotation.internal.$into", //// New feature: @publicInBinary From bd5e331dbe45ebc2805e44cff006ac3ddf947ee4 Mon Sep 17 00:00:00 2001 From: odersky Date: Thu, 15 Feb 2024 10:40:26 +0100 Subject: [PATCH 126/277] Fix typos --- docs/_docs/reference/experimental/into-modifier.md | 4 ++-- library/src/scala/annotation/internal/$into.scala | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/_docs/reference/experimental/into-modifier.md b/docs/_docs/reference/experimental/into-modifier.md index 0c1d24b1d970..358bd0305699 100644 --- a/docs/_docs/reference/experimental/into-modifier.md +++ b/docs/_docs/reference/experimental/into-modifier.md @@ -73,7 +73,7 @@ For Scala 3 code, the `into` modifier is preferred, because it adheres to the pr ## Restrictions -The `into` modifier is only allowed in the types method parameters. It can be given either for the whole type, or some result type of a top-level function type, but not anywhere else. The `into` modifier does not propagate outside the method. In particular, a partially applied method does not propagate `into` modifiers to its result. +The `into` modifier is only allowed in the types of method parameters. It can be given either for the whole type, or some result type of a top-level function type, but not anywhere else. The `into` modifier does not propagate outside the method. In particular, a partially applied method does not propagate `into` modifiers to its result. **Example:** @@ -117,4 +117,4 @@ IntoType ::= [‘into’] IntoTargetType IntoTargetType ::= Type | FunTypeArgs (‘=>’ | ‘?=>’) IntoType ``` -As the grammar shows, `into` can only applied to the type of a parameter; it is illegal in other positions. Also, `into` modifiers in vararg types have to be enclosed in parentheses. +As the grammar shows, `into` can only applied in the type of a parameter; it is illegal in other positions. Also, `into` modifiers in vararg types have to be enclosed in parentheses. diff --git a/library/src/scala/annotation/internal/$into.scala b/library/src/scala/annotation/internal/$into.scala index 7009d829483f..4d8788724e25 100644 --- a/library/src/scala/annotation/internal/$into.scala +++ b/library/src/scala/annotation/internal/$into.scala @@ -6,7 +6,7 @@ import annotation.experimental * `annotation` gets mapped to `$into` by the compiler in all places where * conversions should be allowed. The reason for the split into two annotations * is that `annotation.into` is given in source code and may propagate in unspecified - * ways through type inference. By contrast `$into` is constrained to be occur only + * ways through type inference. By contrast `$into` is constrained to occur only * on parameters of method types. This makes implicit conversion insertion * predictable and independent of the un-specified aspects of type inference. */ From cea5af1bdd0d4eb63d297cc756571ec17c46157e Mon Sep 17 00:00:00 2001 From: odersky Date: Tue, 27 Feb 2024 19:57:16 +0100 Subject: [PATCH 127/277] Implement review suggestions --- compiler/src/dotty/tools/dotc/core/Types.scala | 4 ++-- docs/_docs/reference/experimental/into-modifier.md | 2 +- tests/warn/convertible.scala | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 71f9ab196ed2..e38fbbb4b355 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1928,7 +1928,7 @@ object Types extends TypeUtils { case res => res } defn.FunctionNOf( - mt.paramInfos.mapConserve: + mt.paramInfos.mapConserve: _.translateFromRepeated(toArray = isJava) .mapIntoAnnot(defn.IntoParamAnnot, null), result1, isContextual) @@ -1989,7 +1989,7 @@ object Types extends TypeUtils { val tp1 = tp.mapIntoAnnot(from, to) if annot.symbol == from then if to == null then tp1 - else AnnotatedType(tp1, Annotation(to, from.span)) + else AnnotatedType(tp1, Annotation(to, annot.tree.span)) else self.derivedAnnotatedType(tp1, annot) case AppliedType(tycon, arg :: Nil) if tycon.typeSymbol == defn.RepeatedParamClass => val arg1 = arg.mapIntoAnnot(from, to) diff --git a/docs/_docs/reference/experimental/into-modifier.md b/docs/_docs/reference/experimental/into-modifier.md index 358bd0305699..54da5f976320 100644 --- a/docs/_docs/reference/experimental/into-modifier.md +++ b/docs/_docs/reference/experimental/into-modifier.md @@ -63,7 +63,7 @@ Note that a vararg parameter type with into modifiers needs to be put in parenth ## Retrofitting Scala 2 libraries There is also an annotation `@into` in the `scala.annotation` package that has -has the same effect as an `into` modifier. It is intended to be used for retrofitting Scala 2 library code so that Scala 3 conversions can be applied to arguments without language imports. For instance, the definitions of +the same effect as an `into` modifier. It is intended to be used for retrofitting Scala 2 library code so that Scala 3 conversions can be applied to arguments without language imports. For instance, the definitions of `++` and `flatMap` in the Scala 2.13 `List` class could be retrofitted as follows. ```scala def ++ (elems: IterableOnce[A] @into): List[A] diff --git a/tests/warn/convertible.scala b/tests/warn/convertible.scala index b830093fc891..b701cac32cec 100644 --- a/tests/warn/convertible.scala +++ b/tests/warn/convertible.scala @@ -32,13 +32,13 @@ object Test: c1("abc") // warn, eta expansion does not preserve into val c2 = if ??? then g else g3 - c2("abc") // warn, eta expesnion does not preserve into + c2("abc") // warn, eta expansion does not preserve into val c3 = if ??? then g3 else g - c3("abc") // warn, eta expesnion does not preserve into + c3("abc") // warn, eta expansion does not preserve into def h1[X](x: X)(y: X): Unit = () def h(x: into Text) = val y = h1(x) - y("abc") // warn, eta expesnion does not preserve into \ No newline at end of file + y("abc") // warn, eta expansion does not preserve into \ No newline at end of file From 84024e98ef2952e76434e5b955c69385d319584d Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Tue, 27 Feb 2024 19:16:07 +0100 Subject: [PATCH 128/277] Fix test directive --- tests/neg/i18533.check | 8 ++++---- .../i18533/{non-SCALA_ONLY.java => Non_SCALA_ONLY.java} | 2 +- tests/pos/i18533/Cat.java | 2 +- tests/pos/i18533/Dog.java | 1 - tests/pos/i18533/Pet.java | 1 - 5 files changed, 6 insertions(+), 8 deletions(-) rename tests/neg/i18533/{non-SCALA_ONLY.java => Non_SCALA_ONLY.java} (98%) diff --git a/tests/neg/i18533.check b/tests/neg/i18533.check index 0e117edc3195..ed5027f01ac7 100644 --- a/tests/neg/i18533.check +++ b/tests/neg/i18533.check @@ -1,8 +1,8 @@ +-- Error: tests/neg/i18533/Non_SCALA_ONLY.java:4:7 --------------------------------------------------------------------- +4 |public non class Test { // error + | ^^^ + | Identifier 'non' is not allowed here -- Error: tests/neg/i18533/Pet_SCALA_ONLY.java:3:10 -------------------------------------------------------------------- 3 |class Pet permits Cat { // error | ^^^^^^^ | A type declaration that has a permits clause should have a sealed modifier --- Error: tests/neg/i18533/non-SCALA_ONLY.java:4:7 --------------------------------------------------------------------- -4 |public non class Test { // error - | ^^^ - | Identifier 'non' is not allowed here diff --git a/tests/neg/i18533/non-SCALA_ONLY.java b/tests/neg/i18533/Non_SCALA_ONLY.java similarity index 98% rename from tests/neg/i18533/non-SCALA_ONLY.java rename to tests/neg/i18533/Non_SCALA_ONLY.java index be6aef65da13..cde3b72e12d5 100644 --- a/tests/neg/i18533/non-SCALA_ONLY.java +++ b/tests/neg/i18533/Non_SCALA_ONLY.java @@ -3,4 +3,4 @@ // Special test for the non-sealed trick (See JavaParsers.scala::modifiers) public non class Test { // error -} \ No newline at end of file +} diff --git a/tests/pos/i18533/Cat.java b/tests/pos/i18533/Cat.java index 33cdd99949bb..394f8de37c13 100644 --- a/tests/pos/i18533/Cat.java +++ b/tests/pos/i18533/Cat.java @@ -1,5 +1,5 @@ //> using javacOpt --enable-preview --source 17 -//> test: -jvm 17+ +// test: -jvm 17+ package i18533; diff --git a/tests/pos/i18533/Dog.java b/tests/pos/i18533/Dog.java index 0b10b9f06c27..73d137313dc7 100644 --- a/tests/pos/i18533/Dog.java +++ b/tests/pos/i18533/Dog.java @@ -1,5 +1,4 @@ //> using javacOpt --enable-preview --source 17 -//> test: -jvm 17+ package i18533; diff --git a/tests/pos/i18533/Pet.java b/tests/pos/i18533/Pet.java index 0985aa1f957f..990c4fbabd70 100644 --- a/tests/pos/i18533/Pet.java +++ b/tests/pos/i18533/Pet.java @@ -1,5 +1,4 @@ //> using javacOpt --enable-preview --source 17 -//> test: -jvm 17+ package i18533; From 96c91da83a32fd44b38df10b26789dd278eefc55 Mon Sep 17 00:00:00 2001 From: 110416 Date: Wed, 28 Feb 2024 11:39:35 +0900 Subject: [PATCH 129/277] Apply suggestions from code review Test imported type as well as fully-qualified type to check `findRef` codepath. Co-authored-by: Jamie Thompson --- tests/run/i17255/J.java | 3 +++ tests/run/i17255/Module.scala | 1 + 2 files changed, 4 insertions(+) diff --git a/tests/run/i17255/J.java b/tests/run/i17255/J.java index 3dfb775423f3..3c6d64d75ab9 100644 --- a/tests/run/i17255/J.java +++ b/tests/run/i17255/J.java @@ -5,6 +5,9 @@ public class J { public static p.J f() { return p.J.j; } + public static Module$ module2() { + return p.Module$.MODULE$; + } public static p.Module$ module() { return p.Module$.MODULE$; } diff --git a/tests/run/i17255/Module.scala b/tests/run/i17255/Module.scala index f433adbf0ad6..e681264093da 100644 --- a/tests/run/i17255/Module.scala +++ b/tests/run/i17255/Module.scala @@ -9,4 +9,5 @@ package p { object Test extends App { assert(p.J.f().toString == "J") assert(p.J.module().toString == "Module") + assert(p.J.module2().toString == "Module") } \ No newline at end of file From 22020f37f96b64042c3b85371792220f4f957fcb Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 27 Feb 2024 18:28:27 +0100 Subject: [PATCH 130/277] Specialized retained inline FunctionN apply methods Fixes #19724 --- .../dotc/transform/SpecializeFunctions.scala | 25 ++++++++++++++++--- tests/pos/i19724.scala | 5 ++++ tests/run/i19724.scala | 18 +++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 tests/pos/i19724.scala create mode 100644 tests/run/i19724.scala diff --git a/compiler/src/dotty/tools/dotc/transform/SpecializeFunctions.scala b/compiler/src/dotty/tools/dotc/transform/SpecializeFunctions.scala index 094d6024eb4e..43aef6279cec 100644 --- a/compiler/src/dotty/tools/dotc/transform/SpecializeFunctions.scala +++ b/compiler/src/dotty/tools/dotc/transform/SpecializeFunctions.scala @@ -3,7 +3,7 @@ package transform import ast.Trees.*, ast.tpd, core.* import Contexts.*, Types.*, Decorators.*, Symbols.*, DenotTransformers.* -import SymDenotations.*, Scopes.*, StdNames.*, NameOps.*, Names.* +import SymDenotations.*, Scopes.*, StdNames.*, NameOps.*, Names.*, NameKinds.* import MegaPhase.MiniPhase @@ -25,7 +25,24 @@ class SpecializeFunctions extends MiniPhase { /** Create forwarders from the generic applys to the specialized ones. */ override def transformDefDef(ddef: DefDef)(using Context) = { - if ddef.name != nme.apply + // Note on special case for inline `apply`s: + // `apply` and `apply$retainedBody` are specialized in this transformation. + // `apply$retainedBody` have the name kind `BodyRetainerName`, these contain + // the runtime implementation of an inline `apply` that implements (or overrides) + // the `FunctionN.apply` method. The inline method is not specialized, it will + // be replaced with the implementation of `apply$retainedBody`. The following code + // inline def apply(x: Int): Double = x.toDouble:Double + // private def apply$retainedBody(x: Int): Double = x.toDouble:Double + // in is transformed into + // inline def apply(x: Int): Double = x.toDouble:Double + // private def apply$retainedBody(x: Int): Double = this.apply$mcDI$sp(x) + // def apply$mcDI$sp(v: Int): Double = x.toDouble:Double + // after erasure it will become + // def apply(v: Int): Double = this.apply$mcDI$sp(v) // from apply$retainedBody + // def apply$mcDI$sp(v: Int): Double = v.toDouble():Double + // def apply(v1: Object): Object = Double.box(this.apply(Int.unbox(v1))) // erasure bridge + + if ddef.name.asTermName.exclude(BodyRetainerName) != nme.apply || ddef.termParamss.length != 1 || ddef.termParamss.head.length > 2 || !ctx.owner.isClass @@ -44,12 +61,12 @@ class SpecializeFunctions extends MiniPhase { defn.isSpecializableFunction(cls, paramTypes, retType) } - if (sym.is(Flags.Deferred) || !isSpecializable) return ddef + if (sym.is(Flags.Deferred) || sym.is(Flags.Inline) || !isSpecializable) return ddef val specializedApply = newSymbol( cls, specName.nn, - sym.flags | Flags.Synthetic, + (sym.flags | Flags.Synthetic) &~ Flags.Private, // Private flag can be set if the name is a BodyRetainerName sym.info ).entered diff --git a/tests/pos/i19724.scala b/tests/pos/i19724.scala new file mode 100644 index 000000000000..776cf9167890 --- /dev/null +++ b/tests/pos/i19724.scala @@ -0,0 +1,5 @@ +object repro: + abstract class Mapper[A, B] extends (A => B) + + given Mapper[Int, Double] with + inline def apply(v: Int): Double = v.toDouble diff --git a/tests/run/i19724.scala b/tests/run/i19724.scala new file mode 100644 index 000000000000..0ed6fcb94c57 --- /dev/null +++ b/tests/run/i19724.scala @@ -0,0 +1,18 @@ +class F0 extends (() => Double): + inline def apply(): Double = 1.toDouble + +class F1 extends (Int => Double): + inline def apply(v: Int): Double = v.toDouble + +class F2 extends ((Int, Int) => Double): + inline def apply(v1: Int, v2: Int): Double = (v1 + v2).toDouble + +@main def Test = + val f0: (() => Double) = new F0 + assert(f0() == 1.0) + + val f1: (Int => Double) = new F1 + assert(f1(3) == 3.0) + + val f2: ((Int, Int) => Double) = new F2 + assert(f2(3, 2) == 5.0) From 71b983b13ddfc6b14a24f7a30c3d9813e78d2fd3 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 20 Feb 2024 09:31:34 +0100 Subject: [PATCH 131/277] Lift all non trivial prefixes for default parameters Checking if the prefix is pure is not enough to know if we need to list the prefix. In the case of default parameters, the prefix tree might be used several times to compute the default values. This expression should only be computed once and therefore it should be lifted if there is some computation/allocation involved. Furthermore, if the prefix contains a local definition, it must be lifted to avoid duplicating the definition. A similar situation could happen with dependent default parameters. This currently works as expected. Fixes #15315 --- .../dotty/tools/dotc/typer/EtaExpansion.scala | 25 ++++++++- .../backend/jvm/DottyBytecodeTests.scala | 52 +++++++++++++++++++ tests/run/i15315.scala | 5 ++ 3 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 tests/run/i15315.scala diff --git a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala index 2c441c2f915e..b09580d51943 100644 --- a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala +++ b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala @@ -122,7 +122,10 @@ abstract class Lifter { case TypeApply(fn, targs) => cpy.TypeApply(tree)(liftApp(defs, fn), targs) case Select(pre, name) if isPureRef(tree) => - cpy.Select(tree)(liftPrefix(defs, pre), name) + val liftedPrefix = + if tree.symbol.is(HasDefaultParams) then liftPrefix(defs, pre) + else liftNonIdempotentPrefix(defs, pre) + cpy.Select(tree)(liftedPrefix, name) case Block(stats, expr) => liftApp(defs ++= stats, expr) case New(tpt) => @@ -138,8 +141,26 @@ abstract class Lifter { * * unless `pre` is idempotent. */ - def liftPrefix(defs: mutable.ListBuffer[Tree], tree: Tree)(using Context): Tree = + def liftNonIdempotentPrefix(defs: mutable.ListBuffer[Tree], tree: Tree)(using Context): Tree = if (isIdempotentExpr(tree)) tree else lift(defs, tree) + + /** Lift prefix `pre` of an application `pre.f(...)` to + * + * val x0 = pre + * x0.f(...) + * + * unless `pre` is idempotent reference, a `this` reference, a literal value, or a or the prefix of an `init` (`New` tree). + * + * Note that default arguments will refer to the prefix, we do not want + * to re-evaluate a complex expression each time we access a getter. + */ + def liftPrefix(defs: mutable.ListBuffer[Tree], tree: Tree)(using Context): Tree = + tree match + case tree: Literal => tree + case tree: This => tree + case tree: New => tree // prefix of call + case tree: RefTree if isIdempotentExpr(tree) => tree + case _ => lift(defs, tree) } /** No lifting at all */ diff --git a/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala b/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala index 94d42952a6eb..51390e35b527 100644 --- a/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala +++ b/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala @@ -1733,6 +1733,58 @@ class DottyBytecodeTests extends DottyBytecodeTest { assertSameCode(instructions, expected) } } + + @Test def newInPrefixesOfDefaultParam = { + val source = + s"""class A: + | def f(x: Int = 1): Int = x + | + |class Test: + | def meth1() = (new A).f() + | def meth2() = { val a = new A; a.f() } + """.stripMargin + + checkBCode(source) { dir => + val clsIn = dir.lookupName("Test.class", directory = false).input + val clsNode = loadClassNode(clsIn) + val meth1 = getMethod(clsNode, "meth1") + val meth2 = getMethod(clsNode, "meth2") + + val instructions1 = instructionsFromMethod(meth1) + val instructions2 = instructionsFromMethod(meth2) + + assert(instructions1 == instructions2, + "`assert` was not properly inlined in `meth1`\n" + + diffInstructions(instructions1, instructions2)) + } + } + + @Test def newInDependentOfDefaultParam = { + val source = + s"""class A: + | def i: Int = 1 + | + |class Test: + | def f(a: A)(x: Int = a.i): Int = x + | def meth1() = f(new A)() + | def meth2() = { val a = new A; f(a)() } + """.stripMargin + + checkBCode(source) { dir => + val clsIn = dir.lookupName("Test.class", directory = false).input + val clsNode = loadClassNode(clsIn) + val meth1 = getMethod(clsNode, "meth1") + val meth2 = getMethod(clsNode, "meth2") + + val instructions1 = instructionsFromMethod(meth1) + val instructions2 = instructionsFromMethod(meth2) + + assert(instructions1 == instructions2, + "`assert` was not properly inlined in `meth1`\n" + + diffInstructions(instructions1, instructions2)) + } + } + } object invocationReceiversTestCode { diff --git a/tests/run/i15315.scala b/tests/run/i15315.scala new file mode 100644 index 000000000000..d9cab7b87b81 --- /dev/null +++ b/tests/run/i15315.scala @@ -0,0 +1,5 @@ +class A: + def f(x: Int = 1): Int = x + +@main def Test() = + (new A{}).f() From db1dcdc0e11516a61c4edc25776a6ea0d5dacf78 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Wed, 28 Feb 2024 10:26:46 +0000 Subject: [PATCH 132/277] Fix run-macros/type-show --- tests/run-macros/type-show/Test_2.scala | 30 +++++++++++++++++++------ 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/tests/run-macros/type-show/Test_2.scala b/tests/run-macros/type-show/Test_2.scala index ace303a6596e..de845f3e84dd 100644 --- a/tests/run-macros/type-show/Test_2.scala +++ b/tests/run-macros/type-show/Test_2.scala @@ -1,18 +1,34 @@ object Test { import TypeToolbox.* + + def assertEql[A](obt: A, exp: A): Unit = + assert(obt == exp, s"\nexpected: $exp\nobtained: $obt") + def main(args: Array[String]): Unit = { val x = 5 - assert(show[x.type] == "x.type") - assert(show[Nil.type] == "scala.Nil.type") - assert(show[Int] == "scala.Int") - assert(show[Int => Int] == "scala.Function1[scala.Int, scala.Int]") - assert(show[(Int, String)] == "scala.Tuple2[scala.Int, scala.Predef.String]") - assert(show[[X] =>> X match { case Int => Int }] == + assertEql(show[x.type], "x.type") + assertEql(show[Nil.type], "scala.Nil.type") + assertEql(show[Int], "scala.Int") + assertEql(show[Int => Int], "scala.Function1[scala.Int, scala.Int]") + assertEql(show[(Int, String)], "scala.Tuple2[scala.Int, scala.Predef.String]") + assertEql(show[[X] =>> X match { case Int => Int }], """[X >: scala.Nothing <: scala.Any] =>> X match { | case scala.Int => scala.Int |}""".stripMargin) - assert(showStructure[[X] =>> X match { case Int => Int }] == """TypeLambda(List(X), List(TypeBounds(TypeRef(ThisType(TypeRef(NoPrefix(), "scala")), "Nothing"), TypeRef(ThisType(TypeRef(NoPrefix(), "scala")), "Any"))), MatchType(TypeRef(ThisType(TypeRef(NoPrefix(), "scala")), "Any"), ParamRef(binder, 0), List(MatchCase(TypeRef(TermRef(ThisType(TypeRef(NoPrefix(), "")), "scala"), "Int"), TypeRef(TermRef(ThisType(TypeRef(NoPrefix(), "")), "scala"), "Int")))))""") + assertEql(showStructure[[X] =>> X match { case Int => Int }], + """TypeLambda("""+ + """List(X), """+ + """List(TypeBounds("""+ + """TypeRef(ThisType(TypeRef(NoPrefix(), "scala")), "Nothing"), """+ + """TypeRef(ThisType(TypeRef(NoPrefix(), "scala")), "Any"))), """+ + """MatchType("""+ + """TypeRef(TermRef(ThisType(TypeRef(NoPrefix(), "")), "scala"), "Int"), """+ // match type bound + """ParamRef(binder, 0), """+ + """List("""+ + """MatchCase("""+ + """TypeRef(TermRef(ThisType(TypeRef(NoPrefix(), "")), "scala"), "Int"), """+ + """TypeRef(TermRef(ThisType(TypeRef(NoPrefix(), "")), "scala"), "Int")))))""") // TODO: more complex types: // - implicit function types From 432cdbda63b932a14162f4509280a1668c56f9cb Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Wed, 28 Feb 2024 13:28:02 +0100 Subject: [PATCH 133/277] Add scala3-bootstrapped/testCompilation to 'test_windows_fast' --- .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 3d94d869a42f..05f2a06a1468 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -227,7 +227,7 @@ jobs: uses: actions/checkout@v4 - name: Test - run: sbt ";scala3-bootstrapped/compile" + run: sbt ";scala3-bootstrapped/compile; scala3-bootstrapped/testCompilation" shell: cmd - name: build binary From 4742d7d012f2acdc35aed7e83bc8fd95966fd39d Mon Sep 17 00:00:00 2001 From: Katarzyna Marek Date: Wed, 28 Feb 2024 13:28:03 +0100 Subject: [PATCH 134/277] Weekly backport from metals (#19787) https://github.com/scalameta/metals/pull/6074 https://github.com/scalameta/metals/pull/6129 --- .../tools/pc/completions/Completions.scala | 28 +- .../pc/completions/MatchCaseCompletions.scala | 355 +++++++++--------- .../completion/CompletionCaseSuite.scala | 51 ++- .../completion/CompletionExtensionSuite.scala | 41 ++ .../completion/CompletionMatchSuite.scala | 47 ++- .../completion/CompletionWorkspaceSuite.scala | 49 +++ 6 files changed, 368 insertions(+), 203 deletions(-) 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 d6ca15b35129..955982afcf51 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala @@ -497,14 +497,18 @@ class Completions( val query = completionPos.query if completionMode.is(Mode.Scope) && query.nonEmpty then val visitor = new CompilerSearchVisitor(sym => - indexedContext.lookupSym(sym) match - case IndexedContext.Result.InScope => false - case _ => - completionsWithSuffix( - sym, - sym.decodedName, - CompletionValue.Workspace(_, _, _, sym) - ).map(visit).forall(_ == true), + if !(sym.is(Flags.ExtensionMethod) || + (sym.maybeOwner.is(Flags.Implicit) && sym.maybeOwner.isClass)) + then + indexedContext.lookupSym(sym) match + case IndexedContext.Result.InScope => false + case _ => + completionsWithSuffix( + sym, + sym.decodedName, + CompletionValue.Workspace(_, _, _, sym) + ).map(visit).forall(_ == true) + else false, ) Some(search.search(query, buildTargetIdentifier, visitor).nn) else if completionMode.is(Mode.Member) then @@ -526,8 +530,10 @@ class Completions( ) end isImplicitClass - def isImplicitClassMethod = sym.is(Flags.Method) && !sym.isConstructor && - isImplicitClass(sym.maybeOwner) + def isDefaultVariableSetter = sym.is(Flags.Accessor) && sym.is(Flags.Method) + def isImplicitClassMember = + isImplicitClass(sym.maybeOwner) && !sym.is(Flags.Synthetic) && sym.isPublic + && !sym.isConstructor && !isDefaultVariableSetter if isExtensionMethod then completionsWithSuffix( @@ -535,7 +541,7 @@ class Completions( sym.decodedName, CompletionValue.Extension(_, _, _) ).map(visit).forall(_ == true) - else if isImplicitClassMethod then + else if isImplicitClassMember then completionsWithSuffix( sym, sym.decodedName, diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/MatchCaseCompletions.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/MatchCaseCompletions.scala index edb489228d92..bd94f2f3983a 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/MatchCaseCompletions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/MatchCaseCompletions.scala @@ -6,10 +6,12 @@ import java.net.URI import scala.collection.mutable import scala.collection.mutable.ListBuffer import scala.jdk.CollectionConverters._ +import scala.meta.internal.metals.ReportContext import scala.meta.internal.pc.CompletionFuzzy import scala.meta.pc.PresentationCompilerConfig import scala.meta.pc.SymbolSearch +import dotty.tools.toOption import dotty.tools.dotc.ast.tpd.* import dotty.tools.dotc.core.Constants.Constant import dotty.tools.dotc.core.Contexts.Context @@ -30,6 +32,8 @@ import dotty.tools.dotc.util.SourcePosition import dotty.tools.pc.AutoImports.AutoImportsGenerator import dotty.tools.pc.AutoImports.SymbolImport import dotty.tools.pc.MetalsInteractive.* +import dotty.tools.pc.printer.ShortenedTypePrinter +import dotty.tools.pc.printer.ShortenedTypePrinter.IncludeDefaultParam import dotty.tools.pc.utils.MtagsEnrichments.* import org.eclipse.lsp4j as l @@ -62,7 +66,7 @@ object CaseKeywordCompletion: patternOnly: Option[String] = None, hasBind: Boolean = false, includeExhaustive: Option[NewLineOptions] = None - ): List[CompletionValue] = + )(using ReportContext): List[CompletionValue] = import indexedContext.ctx val definitions = indexedContext.ctx.definitions val clientSupportsSnippets = config.isCompletionSnippetsEnabled() @@ -72,153 +76,162 @@ object CaseKeywordCompletion: patternOnly, hasBind ) - val parents: Parents = selector match + val printer = ShortenedTypePrinter(search, IncludeDefaultParam.Never)(using indexedContext) + val selTpe = selector match case EmptyTree => - val seenFromType = parent match - case TreeApply(fun, _) if !fun.typeOpt.isErroneous => fun.typeOpt - case _ => parent.typeOpt - seenFromType.paramInfoss match - case (head :: Nil) :: _ - if definitions.isFunctionType(head) || head.isRef( - definitions.PartialFunctionClass - ) => - val argTypes = head.argTypes.init - new Parents(argTypes, definitions) - case _ => new Parents(NoType, definitions) - case sel => new Parents(sel.typeOpt, definitions) - - val selectorSym = parents.selector.widen.metalsDealias.typeSymbol - - // Special handle case when selector is a tuple or `FunctionN`. - if definitions.isTupleClass(selectorSym) || definitions.isFunctionClass( - selectorSym - ) - then - if patternOnly.isEmpty then - val selectorTpe = parents.selector.show - val tpeLabel = - if !selectorTpe.contains("x$1") then selectorTpe - else selector.symbol.info.show - val label = s"case ${tpeLabel} =>" - List( - CompletionValue.CaseKeyword( - selectorSym, - label, - Some( - if config.isCompletionSnippetsEnabled() then "case ($0) =>" - else "case () =>" - ), - Nil, - range = Some(completionPos.toEditRange), - command = config.parameterHintsCommand().nn.asScala, + parent match + case TreeApply(fun, _) if !fun.tpe.isErroneous => + fun.tpe.paramInfoss match + case (head :: Nil) :: _ + if definitions.isFunctionType(head) || head.isRef( + definitions.PartialFunctionClass + ) => + val args = head.argTypes.init + if args.length > 1 then + Some(definitions.tupleType(args).widen.metalsDealias) + else args.headOption.map(_.widen.metalsDealias) + case _ => None + case _ => None + case sel => + Some(sel.tpe.widen.metalsDealias) + + selTpe + .map { selTpe => + val selectorSym = selTpe.typeSymbol + // Special handle case when selector is a tuple or `FunctionN`. + if definitions.isTupleClass(selectorSym) || definitions.isFunctionClass( + selectorSym ) - ) - else Nil - else - val result = ListBuffer.empty[SymbolImport] - val isVisited = mutable.Set.empty[Symbol] - def visit(symImport: SymbolImport): Unit = - - def recordVisit(s: Symbol): Unit = - if s != NoSymbol && !isVisited(s) then - isVisited += s - recordVisit(s.moduleClass) - recordVisit(s.sourceModule) - - val sym = symImport.sym - if !isVisited(sym) then - recordVisit(sym) - if completionGenerator.fuzzyMatches(symImport.name) then - result += symImport - end visit - - // Step 0: case for selector type - selectorSym.info match - case NoType => () - case _ => - if !(selectorSym.is(Sealed) && - (selectorSym.is(Abstract) || selectorSym.is(Trait))) - then visit((autoImportsGen.inferSymbolImport(selectorSym))) - - // Step 1: walk through scope members. - def isValid(sym: Symbol) = !parents.isParent(sym) - && (sym.is(Case) || sym.is(Flags.Module) || sym.isClass) - && parents.isSubClass(sym, false) - && (sym.isPublic || sym.isAccessibleFrom(selectorSym.info)) - indexedContext.scopeSymbols - .foreach(s => - val ts = s.info.metalsDealias.typeSymbol - if isValid(ts) then visit(autoImportsGen.inferSymbolImport(ts)) - ) - // Step 2: walk through known subclasses of sealed types. - val sealedDescs = subclassesForType( - parents.selector.widen.metalsDealias.bounds.hi - ) - sealedDescs.foreach { sym => - val symbolImport = autoImportsGen.inferSymbolImport(sym) - visit(symbolImport) - } - val res = result.result().flatMap { - case si @ SymbolImport(sym, name, importSel) => - completionGenerator.labelForCaseMember(sym, name.value).map { label => - (si, label) - } - } - val caseItems = - if res.isEmpty then completionGenerator.caseKeywordOnly + then + if patternOnly.isEmpty then + val selectorTpe = selTpe.show + val tpeLabel = + if !selectorTpe.contains("x$1") then selectorTpe + else selector.symbol.info.show + val label = s"case ${tpeLabel} =>" + List( + CompletionValue.CaseKeyword( + selectorSym, + label, + Some( + if config.isCompletionSnippetsEnabled() then "case ($0) =>" + else "case () =>" + ), + Nil, + range = Some(completionPos.toEditRange), + command = config.parameterHintsCommand().toOption.flatMap(_.asScala), + ) + ) + else Nil else - res.map((si, label) => - completionGenerator.toCompletionValue( - si.sym, - label, - autoImportsGen.renderImports(si.importSel.toList), + val result = ListBuffer.empty[SymbolImport] + val isVisited = mutable.Set.empty[Symbol] + + val isBottom = Set[Symbol]( + definitions.NullClass, + definitions.NothingClass, + ) + val tpes = Set(selectorSym, selectorSym.companion) + def isSubclass(sym: Symbol) = tpes.exists(par => sym.isSubClass(par)) + + def visit(symImport: SymbolImport): Unit = + + def recordVisit(s: Symbol): Unit = + if s != NoSymbol && !isVisited(s) then + isVisited += s + recordVisit(s.moduleClass) + recordVisit(s.sourceModule) + + val sym = symImport.sym + if !isVisited(sym) then + recordVisit(sym) + if completionGenerator.fuzzyMatches(symImport.name) then + result += symImport + end visit + + // Step 1: walk through scope members. + def isValid(sym: Symbol) = !tpes(sym) && + !isBottom(sym) && + isSubclass(sym) && + (sym.is(Case) || sym.is(Flags.Module) || sym.isClass) && + (sym.isPublic || sym.isAccessibleFrom(selectorSym.info)) + + indexedContext.scopeSymbols + .foreach(s => + val ts = s.info.metalsDealias.typeSymbol + if isValid(ts) then visit(autoImportsGen.inferSymbolImport(ts)) ) + // Step 2: walk through known subclasses of sealed types. + val sealedDescs = subclassesForType( + selTpe.bounds.hi ) + sealedDescs.foreach { sym => + val symbolImport = autoImportsGen.inferSymbolImport(sym) + visit(symbolImport) + } + val res = result.result().flatMap { + case si @ SymbolImport(sym, name, importSel) => + completionGenerator.labelForCaseMember(sym, name.value).map { + label => + (si, label) + } + } + val caseItems = + if res.isEmpty then completionGenerator.caseKeywordOnly + else + res.map((si, label) => + completionGenerator.toCompletionValue( + si.sym, + label, + autoImportsGen.renderImports(si.importSel.toList), + ) + ) - includeExhaustive match - // In `List(foo).map { cas@@} we want to provide also `case (exhaustive)` completion - // which works like exhaustive match. - case Some(NewLineOptions(moveToNewLine, addNewLineAfter)) => - val sealedMembers = - val sealedMembers0 = - res.filter((si, _) => sealedDescs.contains(si.sym)) - sortSubclasses( - selectorSym.info, - sealedMembers0, - completionPos.sourceUri, - search - ) - sealedMembers match - case Nil => caseItems - case (_, label) :: tail => - val (newLine, addIndent) = - if moveToNewLine then ("\n\t", "\t") else ("", "") - val insertText = Some( - tail - .map(_._2) - .mkString( - if clientSupportsSnippets then - s"$newLine${label} $$0\n$addIndent" - else s"$newLine${label}\n$addIndent", - s"\n$addIndent", - if addNewLineAfter then "\n" else "" + includeExhaustive match + // In `List(foo).map { cas@@} we want to provide also `case (exhaustive)` completion + // which works like exhaustive match. + case Some(NewLineOptions(moveToNewLine, addNewLineAfter)) => + val sealedMembers = + val sealedMembers0 = + res.filter((si, _) => sealedDescs.contains(si.sym)) + sortSubclasses( + selectorSym.info, + sealedMembers0, + completionPos.sourceUri, + search, + ) + sealedMembers match + case (_, label) :: tail if tail.length > 0 => + val (newLine, addIndent) = + if moveToNewLine then ("\n\t", "\t") else ("", "") + val insertText = Some( + tail + .map(_._2) + .mkString( + if clientSupportsSnippets then + s"$newLine${label} $$0\n$addIndent" + else s"$newLine${label}\n$addIndent", + s"\n$addIndent", + if addNewLineAfter then "\n" else "", + ) ) - ) - val allImports = - sealedMembers.flatMap(_._1.importSel).distinct - val importEdit = autoImportsGen.renderImports(allImports) - val exhaustive = CompletionValue.MatchCompletion( - s"case (exhaustive)", - insertText, - importEdit.toList, - s" ${selectorSym.decodedName} (${res.length} cases)" - ) - exhaustive :: caseItems + val allImports = + sealedMembers.flatMap(_._1.importSel).distinct + val importEdit = autoImportsGen.renderImports(allImports) + val exhaustive = CompletionValue.MatchCompletion( + s"case (exhaustive)", + insertText, + importEdit.toList, + s" ${printer.tpe(selTpe)} (${res.length} cases)", + ) + exhaustive :: caseItems + case _ => caseItems + end match + case None => caseItems end match - case None => caseItems - end match - end if - + end if + } + .getOrElse(Nil) end contribute /** @@ -237,14 +250,18 @@ object CaseKeywordCompletion: search: SymbolSearch, autoImportsGen: AutoImportsGenerator, noIndent: Boolean - ): List[CompletionValue] = + )(using ReportContext): List[CompletionValue] = import indexedContext.ctx val clientSupportsSnippets = config.isCompletionSnippetsEnabled() + val printer = ShortenedTypePrinter(search, IncludeDefaultParam.Never)(using indexedContext) + val completionGenerator = CompletionValueGenerator( completionPos, clientSupportsSnippets ) + + val tpeStr = printer.tpe(selector.tpe.widen.metalsDealias.bounds.hi) val tpe = selector.typeOpt.widen.metalsDealias.bounds.hi match case tr @ TypeRef(_, _) => tr.underlying case t => t @@ -290,7 +307,7 @@ object CaseKeywordCompletion: "match (exhaustive)", insertText, importEdit.toList, - s" ${tpe.typeSymbol.decodedName} (${labels.length} cases)" + s" $tpeStr (${labels.length} cases)" ) List(basicMatch, exhaustive) completions @@ -315,14 +332,13 @@ object CaseKeywordCompletion: defnSymbols.getOrElse(semancticName, -1) } - def sealedStrictDescendants(sym: Symbol)(using Context): List[Symbol] = - sym.sealedStrictDescendants - .filter(child => - !(child.is(Sealed) && (child.is(Abstract) || child.is(Trait))) - && (child.isPublic || child.isAccessibleFrom(sym.info)) && - child.name != StdNames.tpnme.LOCAL_CHILD - ) - .map(_.sourceSymbol) + def sealedDescendants(sym: Symbol)(using Context): List[Symbol] = + sym.sealedDescendants.filter(child => + !(child.is(Sealed) && (child.is(Abstract) || child.is(Trait))) + && child.maybeOwner.exists + && (child.isPublic || child.isAccessibleFrom(sym.info)) + && child.name != StdNames.tpnme.LOCAL_CHILD + ) def subclassesForType(tpe: Type)(using Context): List[Symbol] = /** @@ -345,16 +361,17 @@ object CaseKeywordCompletion: * because `A <:< (B & C) == false`. */ def isExhaustiveMember(sym: Symbol): Boolean = - val symTpe = sym.info match + sym.info match case cl: ClassInfo => - cl.parents + val parentsMerged = cl.parents .reduceLeftOption((tp1, tp2) => tp1.&(tp2)) .getOrElse(sym.info) - case simple => simple - symTpe <:< tpe + + cl.selfType <:< tpe || parentsMerged <:< tpe + case simple => simple <:< tpe val parents = getParentTypes(tpe, List.empty) - parents.toList.map(sealedStrictDescendants) match + parents.toList.map(sealedDescendants) match case Nil => Nil case subcls :: Nil => subcls case subcls => @@ -365,34 +382,6 @@ object CaseKeywordCompletion: end CaseKeywordCompletion -class Parents(val selector: Type, definitions: Definitions)(using Context): - def this(tpes: List[Type], definitions: Definitions)(using Context) = - this( - tpes match - case Nil => NoType - case head :: Nil => head - case _ => definitions.tupleType(tpes) - , - definitions - ) - - val isParent: Set[Symbol] = - Set(selector.typeSymbol, selector.typeSymbol.companion) - .filterNot(_ == NoSymbol) - val isBottom: Set[Symbol] = Set[Symbol]( - definitions.NullClass, - definitions.NothingClass - ) - def isSubClass(typeSymbol: Symbol, includeReverse: Boolean)(using - Context - ): Boolean = - !isBottom(typeSymbol) && - isParent.exists { parent => - typeSymbol.isSubClass(parent) || - (includeReverse && parent.isSubClass(typeSymbol)) - } -end Parents - class CompletionValueGenerator( completionPos: CompletionPos, clientSupportsSnippets: Boolean, diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionCaseSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionCaseSuite.scala index 7a00c0397644..521880b3a84b 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionCaseSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionCaseSuite.scala @@ -261,7 +261,7 @@ class CompletionCaseSuite extends BaseCompletionSuite: |}""".stripMargin, """|case None => scala |case Some(value) => scala - |case (exhaustive) Option (2 cases) + |case (exhaustive) Option[Int] (2 cases) |""".stripMargin ) @@ -303,7 +303,7 @@ class CompletionCaseSuite extends BaseCompletionSuite: |}""".stripMargin, """|case None => scala |case Some(value) => scala - |case (exhaustive) Option (2 cases) + |case (exhaustive) Option[Int] (2 cases) |""".stripMargin ) @@ -317,7 +317,7 @@ class CompletionCaseSuite extends BaseCompletionSuite: |}""".stripMargin, """|case None => scala |case Some(value) => scala - |case (exhaustive) Option (2 cases) + |case (exhaustive) Option[Int] (2 cases) |""".stripMargin ) @@ -531,7 +531,7 @@ class CompletionCaseSuite extends BaseCompletionSuite: |""".stripMargin ) - @Test def `private-member` = + @Test def `private-member1` = check( """ |package example @@ -724,7 +724,7 @@ class CompletionCaseSuite extends BaseCompletionSuite: |""".stripMargin, "case (Int, Int) => scala", ) - + @Test def `keyword-only` = check( """ @@ -738,3 +738,44 @@ class CompletionCaseSuite extends BaseCompletionSuite: "case", ) + @Test def `union-type` = + check( + """ + |case class Foo(a: Int) + |case class Bar(b: Int) + | + |object O { + | val x: Foo | Bar = ??? + | val y = List(x).map{ ca@@ } + |}""".stripMargin, + """|case Bar(b) => test + |case Foo(a) => test + |case (exhaustive) Foo | Bar (2 cases) + |""".stripMargin + ) + + + @Test def `union-type-edit` = + checkEdit( + """ + |case class Foo(a: Int) + |case class Bar(b: Int) + | + |object O { + | val x: Foo | Bar = ??? + | val y = List(x).map{ ca@@ } + |}""".stripMargin, + s"""|case class Foo(a: Int) + |case class Bar(b: Int) + | + |object O { + | val x: Foo | Bar = ??? + | val y = List(x).map{ + |\tcase Foo(a) => $$0 + |\tcase Bar(b) => + | } + |} + |""".stripMargin, + filter = _.contains("exhaustive") + ) + 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 c01b38e7cf61..f48ba06f699c 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionExtensionSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionExtensionSuite.scala @@ -374,3 +374,44 @@ class CompletionExtensionSuite extends BaseCompletionSuite: |} |""".stripMargin ) + + @Test def `implicit-val-var` = + check( + """|package example + | + |object Test: + | implicit class TestOps(val testArg: Int): + | var testVar: Int = 42 + | val testVal: Int = 42 + | def testOps(b: Int): String = ??? + | + |def main = 100.test@@ + |""".stripMargin, + """|testArg: Int (implicit) + |testVal: Int (implicit) + |testVar: Int (implicit) + |testOps(b: Int): String (implicit) + |""".stripMargin + ) + + @Test def `implicit-val-edit` = + checkEdit( + """|package example + | + |object Test: + | implicit class TestOps(a: Int): + | val testVal: Int = 42 + | + |def main = 100.test@@ + |""".stripMargin, + """|package example + | + |import example.Test.TestOps + | + |object Test: + | implicit class TestOps(a: Int): + | val testVal: Int = 42 + | + |def main = 100.testVal + |""".stripMargin + ) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionMatchSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionMatchSuite.scala index 142667171c75..c818307aa7df 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionMatchSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionMatchSuite.scala @@ -19,7 +19,7 @@ class CompletionMatchSuite extends BaseCompletionSuite: | Option(1) match@@ |}""".stripMargin, """|match - |match (exhaustive) Option (2 cases) + |match (exhaustive) Option[Int] (2 cases) |""".stripMargin ) @@ -31,7 +31,7 @@ class CompletionMatchSuite extends BaseCompletionSuite: | println(1) |}""".stripMargin, """|match - |match (exhaustive) Option (2 cases) + |match (exhaustive) Option[Int] (2 cases) |""".stripMargin ) @@ -42,7 +42,7 @@ class CompletionMatchSuite extends BaseCompletionSuite: | Option(1).match@@ |}""".stripMargin, """|match - |match (exhaustive) Option (2 cases) + |match (exhaustive) Option[Int] (2 cases) |""".stripMargin ) @@ -341,7 +341,7 @@ class CompletionMatchSuite extends BaseCompletionSuite: |object A { | List(Option(1)).map{ ca@@ } |}""".stripMargin, - """|case (exhaustive) Option (2 cases) + """|case (exhaustive) Option[Int] (2 cases) |""".stripMargin, filter = _.contains("exhaustive") ) @@ -670,3 +670,42 @@ class CompletionMatchSuite extends BaseCompletionSuite: |""".stripMargin, filter = _.contains("exhaustive"), ) + + @Test def `union-type` = + check( + """ + |case class Foo(a: Int) + |case class Bar(b: Int) + | + |object O { + | val x: Foo | Bar = ??? + | val y = x match@@ + |}""".stripMargin, + """|match + |match (exhaustive) Foo | Bar (2 cases) + |""".stripMargin + ) + + @Test def `union-type-edit` = + checkEdit( + """ + |case class Foo(a: Int) + |case class Bar(b: Int) + | + |object O { + | val x: Foo | Bar = ??? + | val y = x match@@ + |}""".stripMargin, + s"""|case class Foo(a: Int) + |case class Bar(b: Int) + | + |object O { + | val x: Foo | Bar = ??? + | val y = x match + |\tcase Foo(a) => $$0 + |\tcase Bar(b) => + | + |} + |""".stripMargin, + filter = _.contains("exhaustive") + ) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionWorkspaceSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionWorkspaceSuite.scala index 82085932247d..52e565a5a78b 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionWorkspaceSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionWorkspaceSuite.scala @@ -887,3 +887,52 @@ class CompletionWorkspaceSuite extends BaseCompletionSuite: """|method - demo.O(i: Int): Int |""".stripMargin ) + + @Test def `implicit-class-val` = + check( + """|package demo + | + |object O { + | implicit class CursorOps(val bar: Int) + |} + | + |object Main { + | val x = bar@@ + |} + |""".stripMargin, + "" + ) + + @Test def `implicit-class-def` = + check( + """|package demo + | + |object O { + | implicit class CursorOps(val bar: Int) { + | def fooBar = 42 + | } + |} + | + |object Main { + | val x = fooB@@ + |} + |""".stripMargin, + "" + ) + + @Test def `extension-method` = + check( + """|package demo + | + |object O { + | extension (bar: Int) { + | def fooBar = 42 + | } + |} + | + |object Main { + | val x = fooB@@ + |} + |""".stripMargin, + "" + ) From 784abfb829ae0a03462fabebf4b11a8845959efd Mon Sep 17 00:00:00 2001 From: noti0na1 <8036790+noti0na1@users.noreply.github.com> Date: Wed, 28 Feb 2024 15:42:48 +0000 Subject: [PATCH 135/277] Don't force to compute the owner of a symbol --- compiler/src/dotty/tools/dotc/typer/Nullables.scala | 2 +- tests/explicit-nulls/pos/i19808.scala | 6 ++++++ tests/pos/i19808.scala | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 tests/explicit-nulls/pos/i19808.scala create mode 100644 tests/pos/i19808.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Nullables.scala b/compiler/src/dotty/tools/dotc/typer/Nullables.scala index cc3fac3a6ffd..914fc0acb89d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Nullables.scala +++ b/compiler/src/dotty/tools/dotc/typer/Nullables.scala @@ -283,7 +283,7 @@ object Nullables: */ def usedOutOfOrder(using Context): Boolean = val refSym = ref.symbol - val refOwner = refSym.owner + val refOwner = refSym.maybeOwner @tailrec def recur(s: Symbol): Boolean = s != NoSymbol diff --git a/tests/explicit-nulls/pos/i19808.scala b/tests/explicit-nulls/pos/i19808.scala new file mode 100644 index 000000000000..57937ecabb03 --- /dev/null +++ b/tests/explicit-nulls/pos/i19808.scala @@ -0,0 +1,6 @@ +import scala.reflect.Selectable.reflectiveSelectable + +def saveRedir(what: {def validate: List[String]}) = + what.validate match + case Nil => ??? + case xs => ??? diff --git a/tests/pos/i19808.scala b/tests/pos/i19808.scala new file mode 100644 index 000000000000..57937ecabb03 --- /dev/null +++ b/tests/pos/i19808.scala @@ -0,0 +1,6 @@ +import scala.reflect.Selectable.reflectiveSelectable + +def saveRedir(what: {def validate: List[String]}) = + what.validate match + case Nil => ??? + case xs => ??? From 89d61044a166b842febee7e7584cc6b09a0761ed Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 26 Feb 2024 12:55:14 +0100 Subject: [PATCH 136/277] Improve error message when using experimental definitions When an experimental definition is used, the error message shows how to enable the experimental mode. Previously we only did this for experimental language features, but not for experimental definitions. --- .../src/dotty/tools/dotc/config/Feature.scala | 27 +++++++++---------- tests/neg/use-experimental-def.check | 10 +++++++ tests/neg/use-experimental-def.scala | 7 +++++ 3 files changed, 30 insertions(+), 14 deletions(-) create mode 100644 tests/neg/use-experimental-def.check create mode 100644 tests/neg/use-experimental-def.scala diff --git a/compiler/src/dotty/tools/dotc/config/Feature.scala b/compiler/src/dotty/tools/dotc/config/Feature.scala index f2ed58a5c8ca..448473a57885 100644 --- a/compiler/src/dotty/tools/dotc/config/Feature.scala +++ b/compiler/src/dotty/tools/dotc/config/Feature.scala @@ -135,26 +135,25 @@ object Feature: if !isExperimentalEnabled then report.error( em"""Experimental $which may only be used under experimental mode: - | 1. In a definition marked as @experimental - | 2. Compiling with the -experimental compiler flag - | 3. With a nightly or snapshot version of the compiler$note + | 1. in a definition marked as @experimental, or + | 2. compiling with the -experimental compiler flag, or + | 3. with a nightly or snapshot version of the compiler.$note """, srcPos) private def ccException(sym: Symbol)(using Context): Boolean = ccEnabled && defn.ccExperimental.contains(sym) def checkExperimentalDef(sym: Symbol, srcPos: SrcPos)(using Context) = - if !isExperimentalEnabled then - val experimentalSym = - if sym.hasAnnotation(defn.ExperimentalAnnot) then sym - else if sym.owner.hasAnnotation(defn.ExperimentalAnnot) then sym.owner - else NoSymbol - if !ccException(experimentalSym) then - val symMsg = - if experimentalSym.exists - then i"$experimentalSym is marked @experimental" - else i"$sym inherits @experimental" - report.error(em"$symMsg and therefore may only be used in an experimental scope.", srcPos) + val experimentalSym = + if sym.hasAnnotation(defn.ExperimentalAnnot) then sym + else if sym.owner.hasAnnotation(defn.ExperimentalAnnot) then sym.owner + else NoSymbol + if !ccException(experimentalSym) then + val note = + if experimentalSym.exists + then i"$experimentalSym is marked @experimental" + else i"$sym inherits @experimental" + checkExperimentalFeature("definition", srcPos, s"\n\n$note") /** Check that experimental compiler options are only set for snapshot or nightly compiler versions. */ def checkExperimentalSettings(using Context): Unit = diff --git a/tests/neg/use-experimental-def.check b/tests/neg/use-experimental-def.check new file mode 100644 index 000000000000..66c4a7a305b5 --- /dev/null +++ b/tests/neg/use-experimental-def.check @@ -0,0 +1,10 @@ +-- Error: tests/neg/use-experimental-def.scala:7:15 -------------------------------------------------------------------- +7 |def bar: Int = foo // error + | ^^^ + | Experimental definition may only be used under experimental mode: + | 1. in a definition marked as @experimental, or + | 2. compiling with the -experimental compiler flag, or + | 3. with a nightly or snapshot version of the compiler. + | + | method foo is marked @experimental + | diff --git a/tests/neg/use-experimental-def.scala b/tests/neg/use-experimental-def.scala new file mode 100644 index 000000000000..68ce0d6987ab --- /dev/null +++ b/tests/neg/use-experimental-def.scala @@ -0,0 +1,7 @@ +//> using options -Yno-experimental + +import scala.annotation.experimental + +@experimental def foo: Int = 1 + +def bar: Int = foo // error From 670c3653d095e1fcbce897925e5e0002481d5d40 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 28 Feb 2024 17:24:01 +0100 Subject: [PATCH 137/277] Fix _Test with Scala 2 library with CC TASTy (fast)_ CI workflow --- .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 05f2a06a1468..16923df581e8 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -153,7 +153,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 "scala2-library-cc/compile; scala2-library-cc-tasty/compile; scala3-bootstrapped/testCompilation i3" + run: ./project/scripts/sbt ";set ThisBuild/Build.scala2Library := Build.Scala2LibraryCCTasty; scala2-library-cc/compile; scala2-library-cc-tasty/compile; scala3-bootstrapped/testCompilation i3" test_scala2_library_tasty: runs-on: [self-hosted, Linux] From 5773540ca6efe70bb7f8a35575a8bcfdda5a21a9 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 28 Feb 2024 17:38:03 +0100 Subject: [PATCH 138/277] Add nightly tests for `scala2-library-cc-tasty` Only test a subset of tests that are known to currently work. --- .github/workflows/ci.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 05f2a06a1468..4fc6bd7d63b7 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -198,9 +198,9 @@ jobs: - name: Test with Scala 2 library TASTy 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" + # TODO increase coverage to `scala3-bootstrapped/test` + - name: Test with Scala 2 library with CC TASTy + run: ./project/scripts/sbt ";set ThisBuild/Build.scala2Library := Build.Scala2LibraryCCTasty ;scala3-bootstrapped/testCompilation pos" test_windows_fast: From 1f7789f71aea94c38aa53b4f9505c825d3c9a2d6 Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Tue, 27 Feb 2024 18:25:51 +0100 Subject: [PATCH 139/277] Improve error reporting for missing members Co-Authored-By: valentin2.schneeberger@gmail.com Co-Authored-By: sana.carlo@gmail.com Co-Authored-By: mehdi.ala03@gmail.com --- .../dotty/tools/dotc/typer/RefChecks.scala | 12 ++++----- tests/neg/i19731.check | 27 +++++++++++++++++++ tests/neg/i19731.scala | 17 ++++++++++++ 3 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 tests/neg/i19731.check create mode 100644 tests/neg/i19731.scala diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index cf30945a7751..ff44ba6d010d 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -654,8 +654,8 @@ object RefChecks { val missingMethods = grouped.toList flatMap { case (name, syms) => - val withoutSetters = syms filterNot (_.isSetter) - if (withoutSetters.nonEmpty) withoutSetters else syms + syms.filterConserve(!_.isSetter) + .distinctBy(_.signature) // Avoid duplication for similar definitions (#19731) } def stubImplementations: List[String] = { @@ -666,7 +666,7 @@ object RefChecks { if (regrouped.tail.isEmpty) membersStrings(regrouped.head._2) - else (regrouped.sortBy("" + _._1.name) flatMap { + else (regrouped.sortBy(_._1.name.toString()) flatMap { case (owner, members) => ("// Members declared in " + owner.fullName) +: membersStrings(members) :+ "" }).init @@ -685,7 +685,7 @@ object RefChecks { return } - for (member <- missing) { + for (member <- missingMethods) { def showDclAndLocation(sym: Symbol) = s"${sym.showDcl} in ${sym.owner.showLocated}" def undefined(msg: String) = @@ -1002,9 +1002,9 @@ object RefChecks { end checkNoPrivateOverrides def checkVolatile(sym: Symbol)(using Context): Unit = - if sym.isVolatile && !sym.is(Mutable) then + if sym.isVolatile && !sym.is(Mutable) then report.warning(VolatileOnVal(), sym.srcPos) - + /** Check that unary method definition do not receive parameters. * They can only receive inferred parameters such as type parameters and implicit parameters. */ diff --git a/tests/neg/i19731.check b/tests/neg/i19731.check new file mode 100644 index 000000000000..eebfb924d199 --- /dev/null +++ b/tests/neg/i19731.check @@ -0,0 +1,27 @@ +-- Error: tests/neg/i19731.scala:4:6 ----------------------------------------------------------------------------------- +4 |class F1 extends Foo: // error + | ^ + | class F1 needs to be abstract, since def foo(): Unit in class F1 is not defined +-- Error: tests/neg/i19731.scala:7:6 ----------------------------------------------------------------------------------- +7 |class F2 extends Foo: // error + | ^ + | class F2 needs to be abstract, since: + | it has 2 unimplemented members. + | /** As seen from class F2, the missing signatures are as follows. + | * For convenience, these are usable as stub implementations. + | */ + | def foo(): Unit = ??? + | def foo(x: Int): Unit = ??? +-- Error: tests/neg/i19731.scala:16:6 ---------------------------------------------------------------------------------- +16 |class B1 extends Bar: // error + | ^ + | class B1 needs to be abstract, since: + | it has 2 unimplemented members. + | /** As seen from class B1, the missing signatures are as follows. + | * For convenience, these are usable as stub implementations. + | */ + | // Members declared in B1 + | def foo(x: Int): Unit = ??? + | + | // Members declared in Bar + | def foo(): Unit = ??? diff --git a/tests/neg/i19731.scala b/tests/neg/i19731.scala new file mode 100644 index 000000000000..75fff0e53872 --- /dev/null +++ b/tests/neg/i19731.scala @@ -0,0 +1,17 @@ +trait Foo: + def foo(): Unit + +class F1 extends Foo: // error + def foo(): Unit + +class F2 extends Foo: // error + def foo(): Unit + def foo(x: Int): Unit + + +trait Bar: + def foo(): Unit + def foo(x: Int): Unit + +class B1 extends Bar: // error + def foo(x: Int): Unit From 63146b4a60f89a4b3bdadcb241127a1671b0f949 Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 28 Feb 2024 22:20:47 +0100 Subject: [PATCH 140/277] Fix Function tree copier It did not copy correctly instances of the FunctionWithMods subclass. Fixes #19751 --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 9 ++++---- compiler/src/dotty/tools/dotc/ast/untpd.scala | 6 ++++- tests/pos-custom-args/captures/i19751.scala | 22 +++++++++++++++++++ 3 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 tests/pos-custom-args/captures/i19751.scala diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 4ec41b95a90b..05adedabf43b 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -1254,11 +1254,12 @@ object Trees { case _ => finalize(tree, untpd.Ident(name)(sourceFile(tree))) } def Select(tree: Tree)(qualifier: Tree, name: Name)(using Context): Select = tree match { - case tree: SelectWithSig => - if ((qualifier eq tree.qualifier) && (name == tree.name)) tree - else finalize(tree, SelectWithSig(qualifier, name, tree.sig)(sourceFile(tree))) case tree: Select if (qualifier eq tree.qualifier) && (name == tree.name) => tree - case _ => finalize(tree, untpd.Select(qualifier, name)(sourceFile(tree))) + case _ => + val tree1 = tree match + case tree: SelectWithSig => untpd.SelectWithSig(qualifier, name, tree.sig)(using sourceFile(tree)) + case _ => untpd.Select(qualifier, name)(using sourceFile(tree)) + finalize(tree, tree1) } /** Copy Ident or Select trees */ def Ref(tree: RefTree)(name: Name)(using Context): RefTree = tree match { diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index aabfdd97d7bd..8afcfd9c6ac3 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -609,7 +609,11 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { } def Function(tree: Tree)(args: List[Tree], body: Tree)(using Context): Tree = tree match { case tree: Function if (args eq tree.args) && (body eq tree.body) => tree - case _ => finalize(tree, untpd.Function(args, body)(tree.source)) + case _ => + val tree1 = tree match + case tree: FunctionWithMods => untpd.FunctionWithMods(args, body, tree.mods, tree.erasedParams)(using tree.source) + case _ => untpd.Function(args, body)(using tree.source) + finalize(tree, tree1) } def PolyFunction(tree: Tree)(targs: List[Tree], body: Tree)(using Context): Tree = tree match { case tree: PolyFunction if (targs eq tree.targs) && (body eq tree.body) => tree diff --git a/tests/pos-custom-args/captures/i19751.scala b/tests/pos-custom-args/captures/i19751.scala new file mode 100644 index 000000000000..b6023cc0ff87 --- /dev/null +++ b/tests/pos-custom-args/captures/i19751.scala @@ -0,0 +1,22 @@ +import language.experimental.captureChecking +import annotation.capability +import caps.cap + +trait Ptr[A] +@capability trait Scope: + def allocate(size: Int): Ptr[Unit]^{this} + + +object Scope: + def confined[A](fn: Scope ?->{cap} A): A = + val scope = new Scope: + def allocate(size: Int) = new Ptr[Unit] {} + fn(using scope) + +def Test: Unit = + val s = Scope.confined: + val s2 = summon[Scope] + Scope.confined: + s2.allocate(5) + 5 + From 6b52789b7c63c70da27933f50ccfb58084b5cd96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Rochala?= <48657087+rochala@users.noreply.github.com> Date: Thu, 29 Feb 2024 10:33:35 +0100 Subject: [PATCH 141/277] Unify completion pos usage, fix presentation compiler crash in interpolation (#19614) Fixes crash for added tests in `CompletionInterpolatorSuite` along with unification and better naming for completion pos, source pos, and span usage. --- .../tools/dotc/interactive/Completion.scala | 57 +++--- .../dotc/interactive/CustomCompletion.scala | 130 ------------- .../interactive/CustomCompletionTests.scala | 171 ------------------ .../tools/languageserver/CompletionTest.scala | 108 +++++++---- .../dotty/tools/pc/AutoImportsProvider.scala | 2 +- .../completions/AmmoniteIvyCompletions.scala | 2 +- .../tools/pc/completions/CompletionPos.scala | 58 +++--- .../pc/completions/CompletionProvider.scala | 13 +- .../tools/pc/completions/Completions.scala | 33 ++-- .../completions/InterpolatorCompletions.scala | 13 +- .../pc/completions/KeywordsCompletions.scala | 11 +- .../pc/completions/MatchCaseCompletions.scala | 4 +- .../CompletionInterpolatorSuite.scala | 55 ++++-- .../completion/CompletionKeywordSuite.scala | 19 +- .../completion/CompletionPatternSuite.scala | 4 +- .../pc/tests/completion/CompletionSuite.scala | 133 +++++++++++++- 16 files changed, 320 insertions(+), 493 deletions(-) delete mode 100644 compiler/test/dotty/tools/dotc/interactive/CustomCompletion.scala delete mode 100644 compiler/test/dotty/tools/dotc/interactive/CustomCompletionTests.scala diff --git a/compiler/src/dotty/tools/dotc/interactive/Completion.scala b/compiler/src/dotty/tools/dotc/interactive/Completion.scala index 5237f19d19ae..025a2022500d 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Completion.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Completion.scala @@ -90,29 +90,22 @@ object Completion: val completionSymbolKind: Mode = path match - case untpd.Ident(_) :: untpd.Import(_, _) :: _ => Mode.ImportOrExport - case untpd.Ident(_) :: (_: untpd.ImportSelector) :: _ => Mode.ImportOrExport - case untpd.Literal(Constants.Constant(_: String)) :: _ => Mode.Term // literal completions + case GenericImportSelector(sel) => + if sel.imported.span.contains(pos.span) then Mode.ImportOrExport // import scala.@@ + else if sel.isGiven && sel.bound.span.contains(pos.span) then Mode.ImportOrExport + else Mode.None // import scala.{util => u@@} + case GenericImportOrExport(_) => Mode.ImportOrExport | Mode.Scope // import TrieMa@@ + case untpd.Literal(Constants.Constant(_: String)) :: _ => Mode.Term | Mode.Scope // literal completions case (ref: untpd.RefTree) :: _ => - if (ref.name.isTermName) Mode.Term - else if (ref.name.isTypeName) Mode.Type - else Mode.None + val maybeSelectMembers = if ref.isInstanceOf[untpd.Select] then Mode.Member else Mode.Scope - case (sel: untpd.ImportSelector) :: _ => - if sel.imported.span.contains(pos.span) then Mode.ImportOrExport - else Mode.None // Can't help completing the renaming + if (ref.name.isTermName) Mode.Term | maybeSelectMembers + else if (ref.name.isTypeName) Mode.Type | maybeSelectMembers + else Mode.None - case (_: untpd.ImportOrExport) :: _ => Mode.ImportOrExport case _ => Mode.None - val completionKind: Mode = - path match - case Nil | (_: untpd.PackageDef) :: _ => Mode.None - case untpd.Ident(_) :: (_: untpd.ImportSelector) :: _ => Mode.Member - case (_: untpd.Select) :: _ => Mode.Member - case _ => Mode.Scope - - completionSymbolKind | completionKind + completionSymbolKind /** When dealing with in varios palces we check to see if they are * due to incomplete backticks. If so, we ensure we get the full prefix @@ -141,18 +134,11 @@ object Completion: i + 1 path match - case (sel: untpd.ImportSelector) :: _ => - completionPrefix(sel.imported :: Nil, pos) - - case untpd.Ident(_) :: (sel: untpd.ImportSelector) :: _ if !sel.isGiven => - if sel.isWildcard then pos.source.content()(pos.point - 1).toString + case GenericImportSelector(sel) => + if sel.isGiven then completionPrefix(sel.bound :: Nil, pos) + else if sel.isWildcard then pos.source.content()(pos.point - 1).toString else completionPrefix(sel.imported :: Nil, pos) - case (tree: untpd.ImportOrExport) :: _ => - tree.selectors.find(_.span.contains(pos.span)).map: selector => - completionPrefix(selector :: Nil, pos) - .getOrElse("") - // Foo.`se will result in Select(Ident(Foo), ) case (select: untpd.Select) :: _ if select.name == nme.ERROR => checkBacktickPrefix(select.source.content(), select.nameSpan.start, select.span.end) @@ -169,6 +155,20 @@ object Completion: end completionPrefix + private object GenericImportSelector: + def unapply(path: List[untpd.Tree]): Option[untpd.ImportSelector] = + path match + case untpd.Ident(_) :: (sel: untpd.ImportSelector) :: _ => Some(sel) + case (sel: untpd.ImportSelector) :: _ => Some(sel) + case _ => None + + private object GenericImportOrExport: + def unapply(path: List[untpd.Tree]): Option[untpd.ImportOrExport] = + path match + case untpd.Ident(_) :: (importOrExport: untpd.ImportOrExport) :: _ => Some(importOrExport) + case (importOrExport: untpd.ImportOrExport) :: _ => Some(importOrExport) + case _ => None + /** Inspect `path` to determine the offset where the completion result should be inserted. */ def completionOffset(untpdPath: List[untpd.Tree]): Int = untpdPath match @@ -211,7 +211,6 @@ object Completion: case tpd.Select(qual, _) :: _ if qual.typeOpt.hasSimpleKind => completer.selectionCompletions(qual) case tpd.Select(qual, _) :: _ => Map.empty case (tree: tpd.ImportOrExport) :: _ => completer.directMemberCompletions(tree.expr) - case (_: untpd.ImportSelector) :: tpd.Import(expr, _) :: _ => completer.directMemberCompletions(expr) case _ => completer.scopeCompletions interactiv.println(i"""completion info with pos = $pos, diff --git a/compiler/test/dotty/tools/dotc/interactive/CustomCompletion.scala b/compiler/test/dotty/tools/dotc/interactive/CustomCompletion.scala deleted file mode 100644 index 7b422a1164ae..000000000000 --- a/compiler/test/dotty/tools/dotc/interactive/CustomCompletion.scala +++ /dev/null @@ -1,130 +0,0 @@ -package dotty.tools.dotc.interactive - -import dotty.tools.dotc.ast.tpd._ -import dotty.tools.dotc.ast.untpd -import dotty.tools.dotc.core.Contexts._ -import dotty.tools.dotc.core.Denotations.SingleDenotation -import dotty.tools.dotc.core.Flags._ -import dotty.tools.dotc.core.NameOps._ -import dotty.tools.dotc.core.Names.{Name, termName} -import dotty.tools.dotc.core.StdNames.nme -import dotty.tools.dotc.core.Symbols.{Symbol, defn} -import dotty.tools.dotc.core.TypeError -import dotty.tools.dotc.util.Chars.{isOperatorPart, isScalaLetter} -import dotty.tools.dotc.util.SourcePosition - -object CustomCompletion { - - def completions( - pos: SourcePosition, - dependencyCompleteOpt: Option[String => (Int, Seq[String])], - enableDeep: Boolean - )(using Context): (Int, List[Completion]) = { - val path = Interactive.pathTo(ctx.compilationUnit.tpdTree, pos.span) - computeCompletions(pos, path, dependencyCompleteOpt, enableDeep)(using Interactive.contextOfPath(path)) - } - - def computeCompletions( - pos: SourcePosition, - path: List[Tree], - dependencyCompleteOpt: Option[String => (Int, Seq[String])], - enableDeep: Boolean - )(using Context): (Int, List[Completion]) = { - val mode = Completion.completionMode(path, pos) - val prefix = Completion.completionPrefix(path, pos) - val completer = new DeepCompleter(mode, prefix, pos) - - var extra = List.empty[Completion] - - val completions = path match { - case Select(qual, _) :: _ => completer.selectionCompletions(qual) - case Import(Ident(name), _) :: _ if name.decode.toString == "$ivy" && dependencyCompleteOpt.nonEmpty => - val complete = dependencyCompleteOpt.get - val (pos, completions) = complete(prefix) - val input0 = prefix.take(pos) - extra ++= completions.distinct.toList - .map(s => Completion(label(termName(input0 + s)), "", Nil)) - Map.empty - case Import(expr, _) :: _ => completer.directMemberCompletions(expr) - case (_: untpd.ImportSelector) :: Import(expr, _) :: _ => completer.directMemberCompletions(expr) - case _ => - completer.scopeCompletions ++ { - if (enableDeep) completer.deepCompletions - else Nil - } - } - - val describedCompletions = extra ++ describeCompletions(completions) - val offset = Completion.completionOffset(path) - - (pos.span.start - prefix.length, describedCompletions) - } - - private type CompletionMap = Map[Name, Seq[SingleDenotation]] - - private def describeCompletions(completions: CompletionMap)(using Context): List[Completion] = { - for - (name, denots) <- completions.toList - denot <- denots - yield - Completion(label(name), Completion.description(denot), List(denot.symbol)) - } - - class DeepCompleter(mode: Completion.Mode, prefix: String, pos: SourcePosition) extends Completion.Completer(mode, prefix, pos): - def deepCompletions(using Context): Map[Name, Seq[SingleDenotation]] = { - - def allMembers(s: Symbol) = - try s.info.allMembers - catch { - case _: dotty.tools.dotc.core.TypeError => Nil - } - def rec(t: Symbol): Seq[Symbol] = { - val children = - if (t.is(Package) || t.is(PackageVal) || t.is(PackageClass)) { - allMembers(t).map(_.symbol).filter(_ != t).flatMap(rec) - } else Nil - - t +: children.toSeq - } - - val syms = for { - member <- allMembers(defn.RootClass).map(_.symbol).toList - sym <- rec(member) - if sym.name.toString.startsWith(prefix) - } yield sym - - syms.map(sym => (sym.fullName, List(sym: SingleDenotation))).toMap - } - - private val bslash = '\\' - private val specialChars = Set('[', ']', '(', ')', '{', '}', '.', ',', ';') - - def label(name: Name): String = { - - def maybeQuote(name: Name, recurse: Boolean): String = - if (recurse && name.isTermName) - name.asTermName.qualToString(maybeQuote(_, true), maybeQuote(_, false)) - else { - // initially adapted from - // https://github.com/scala/scala/blob/decbd53f1bde4600c8ff860f30a79f028a8e431d/src/reflect/scala/reflect/internal/Printers.scala#L573-L584 - val decName = name.decode.toString - val hasSpecialChar = decName.exists { ch => - specialChars(ch) || ch.isWhitespace - } - def isOperatorLike = (name.isOperatorName || decName.exists(isOperatorPart)) && - decName.exists(isScalaLetter) && - !decName.contains(bslash) - lazy val term = name.toTermName - - val needsBackTicks = hasSpecialChar || - isOperatorLike || - nme.keywords(term) && term != nme.USCOREkw - - if (needsBackTicks) s"`$decName`" - else decName - } - - maybeQuote(name, true) - } -} - diff --git a/compiler/test/dotty/tools/dotc/interactive/CustomCompletionTests.scala b/compiler/test/dotty/tools/dotc/interactive/CustomCompletionTests.scala deleted file mode 100644 index a43a5cafce21..000000000000 --- a/compiler/test/dotty/tools/dotc/interactive/CustomCompletionTests.scala +++ /dev/null @@ -1,171 +0,0 @@ -package dotty.tools -package dotc.interactive - -import dotc.ast.tpd -import dotc.{CompilationUnit, Compiler, Run} -import dotc.core.Contexts.Context -import dotc.core.Mode -import dotc.reporting.StoreReporter -import dotc.util.{SourceFile, SourcePosition} -import dotc.util.Spans.Span - -import org.junit.Test - -class CustomCompletionTests extends DottyTest: - - private def completions( - input: String, - dependencyCompleter: Option[String => (Int, Seq[String])] = None, - deep: Boolean = false, - extraDefinitions: String = "" - ): (Int, Seq[Completion]) = - val prefix = extraDefinitions + """ - object Wrapper { - val expr = { - """ - val suffix = """ - } - } - """ - - val allCode = prefix + input + suffix - val index = prefix.length + input.length - - val run = new Run( - new Compiler, - initialCtx.fresh - .addMode(Mode.ReadPositions | Mode.Interactive) - // discard errors - comment out this line to print them in the console - .setReporter(new StoreReporter(null)) - .setSetting(initialCtx.settings.YstopAfter, List("typer")) - ) - val file = SourceFile.virtual("", allCode, maybeIncomplete = true) - given ctx: Context = run.runContext.withSource(file) - val unit = CompilationUnit(file) - ctx - .run.nn - .compileUnits(unit :: Nil, ctx) - - // ignoring compilation errors here - the input code - // to complete likely doesn't compile - - unit.tpdTree = { - import tpd._ - unit.tpdTree match { - case PackageDef(_, p) => - p.reverseIterator.collectFirst { - case TypeDef(_, tmpl: Template) => - tmpl.body - .collectFirst { case dd: ValDef if dd.name.show == "expr" => dd } - .getOrElse(sys.error("Unexpected tree shape")) - } - .getOrElse(sys.error("Unexpected tree shape")) - case _ => sys.error("Unexpected tree shape") - } - } - val ctx1 = ctx.fresh.setCompilationUnit(unit) - val srcPos = SourcePosition(file, Span(index)) - val (offset0, completions) = - if (deep || dependencyCompleter.nonEmpty) - CustomCompletion.completions(srcPos, dependencyCompleteOpt = dependencyCompleter, enableDeep = deep)(using ctx1) - else - Completion.completions(srcPos)(using ctx1) - val offset = offset0 - prefix.length - (offset, completions) - - - @Test def simple(): Unit = - val prefix = "scala.collection.immutable." - val input = prefix + "Ma" - - val (offset, completions0) = completions(input) - val labels = completions0.map(_.label) - - assert(offset == prefix.length) - assert(labels.contains("Map")) - - @Test def custom(): Unit = - val prefix = "import $ivy." - val input = prefix + "scala" - - val dependencies = Seq( - "scalaCompiler", - "scalaLibrary", - "other" - ) - val (offset, completions0) = completions( - input, - dependencyCompleter = Some { dep => - val matches = dependencies.filter(_.startsWith(dep)) - (0, matches) - } - ) - val labels = completions0.map(_.label) - - assert(offset == prefix.length) - assert(labels.contains("scalaCompiler")) - assert(labels.contains("scalaLibrary")) - assert(labels.length == 2) - - @Test def backTicks(): Unit = - val prefix = "Foo." - val input = prefix + "a" - - val extraDefinitions = - """object Foo { def a1 = 2; def `a-b` = 3 } - |""".stripMargin - val (offset, completions0) = completions( - input, - extraDefinitions = extraDefinitions, - deep = true // Enables CustomCompleter - ) - val labels = completions0.map(_.label) - - assert(offset == prefix.length) - assert(labels.contains("a1")) - assert(labels.contains("`a-b`")) - - @Test def backTicksDependencies(): Unit = - val prefix = "import $ivy." - val input = prefix + "`org.scala-lang:scala-`" - - val dependencies = Seq( - "org.scala-lang:scala-compiler", - "org.scala-lang:scala-library", - "other" - ) - val (offset, completions0) = completions( - input, - dependencyCompleter = Some { dep => - val matches = dependencies.filter(_.startsWith(dep)) - (0, matches) - } - ) - val labels = completions0.map(_.label) - - // Seems backticks mess with that for now... - // assert(offset == prefix.length) - assert(labels.contains("`org.scala-lang:scala-compiler`")) - assert(labels.contains("`org.scala-lang:scala-library`")) - assert(labels.length == 2) - - @Test def deep(): Unit = - val prefix = "" - val input = prefix + "ListBuf" - - val (offset, completions0) = completions(input, deep = true) - val labels = completions0.map(_.label) - - assert(offset == prefix.length) - assert(labels.contains("scala.collection.mutable.ListBuffer")) - - @Test def deepType(): Unit = - val prefix = "" - val input = prefix + "Function2" - - val (offset, completions0) = completions(input, deep = true) - val labels = completions0.map(_.label) - - assert(offset == prefix.length) - assert(labels.contains("scala.Function2")) - diff --git a/language-server/test/dotty/tools/languageserver/CompletionTest.scala b/language-server/test/dotty/tools/languageserver/CompletionTest.scala index 4c54637b367f..95123096983d 100644 --- a/language-server/test/dotty/tools/languageserver/CompletionTest.scala +++ b/language-server/test/dotty/tools/languageserver/CompletionTest.scala @@ -96,10 +96,10 @@ class CompletionTest { @Test def importCompleteFromPackage: Unit = { withSources( - code"""package a - abstract class MyClass""", - code"""package b - import a.My${m1}""" + code"""|package a + |abstract class MyClass""", + code"""|package b + |import a.My${m1}""" ).completion(("MyClass", Class, "a.MyClass")) } @@ -111,11 +111,11 @@ class CompletionTest { } @Test def importCompleteIncludesSynthetic: Unit = { - code"""case class MyCaseClass(foobar: Int) - object O { - val x = MyCaseClass(0) - import x.c${m1} - }""" + code"""|case class MyCaseClass(foobar: Int) + |object O { + | val x = MyCaseClass(0) + | import x.c${m1} + |}""" .completion( ("copy", Method, "(foobar: Int): MyCaseClass"), ("canEqual", Method, "(that: Any): Boolean"), @@ -131,11 +131,11 @@ class CompletionTest { @Test def importCompleteWithClassAndCompanion: Unit = { withSources( - code"""package pkg0 - class Foo - object Foo""", - code"""package pgk1 - import pkg0.F${m1}""" + code"""|package pkg0 + |class Foo + |object Foo""", + code"""|package pgk1 + |import pkg0.F${m1}""" ).completion( ("Foo", Class, "pkg0.Foo"), ("Foo", Module, "pkg0.Foo"), @@ -144,22 +144,22 @@ class CompletionTest { @Test def importCompleteIncludePackage: Unit = { withSources( - code"""package foo.bar - abstract classFizz""", + code"""|package foo.bar + |abstract classFizz""", code"""import foo.b${m1}""" ).completion(("bar", Module, "foo.bar")) } @Test def importCompleteIncludeMembers: Unit = { withSources( - code"""object MyObject { - val myVal = 0 - def myDef = 0 - var myVar = 0 - object myObject - abstract class myClass - trait myTrait - }""", + code"""|object MyObject { + | val myVal = 0 + | def myDef = 0 + | var myVar = 0 + | object myObject + | abstract class myClass + | trait myTrait + |}""", code"""import MyObject.my${m1}""" ).completion( ("myVal", Field, "Int"), @@ -201,9 +201,9 @@ class CompletionTest { } @Test def completeJavaModuleClass: Unit = { - code"""object O { - val out = java.io.FileDesc${m1} - }""" + code"""|object O { + | val out = java.io.FileDesc${m1} + |}""" .completion(("FileDescriptor", Module, "java.io.FileDescriptor")) } @@ -213,22 +213,26 @@ class CompletionTest { ("FileDescriptor", Class, "java.io.FileDescriptor"), ("FileDescriptor", Module, "java.io.FileDescriptor"), ) + } + @Test def noImportRename: Unit = { + code"""import java.io.{FileDescriptor => Fo$m1}""" + .noCompletions() } @Test def importGivenByType: Unit = { - code"""trait Foo - object Bar - import Bar.{given Fo$m1}""" + code"""|trait Foo + |object Bar + |import Bar.{given Fo$m1}""" .completion(("Foo", Class, "Foo")) } @Test def markDeprecatedSymbols: Unit = { - code"""object Foo { - @deprecated - val bar = 0 - } - import Foo.ba${m1}""" + code"""|object Foo { + | @deprecated + | val bar = 0 + |} + |import Foo.ba${m1}""" .completion(results => { assertEquals(1, results.size) val result = results.head @@ -290,11 +294,11 @@ class CompletionTest { } @Test def completionOnRenamedImport2: Unit = { - code"""import java.util.{HashMap => MyImportedSymbol} - trait Foo { - import java.io.{FileDescriptor => MyImportedSymbol} - val x: MyImp${m1} - }""" + code"""|import java.util.{HashMap => MyImportedSymbol} + |trait Foo { + | import java.io.{FileDescriptor => MyImportedSymbol} + | val x: MyImp${m1} + |}""" .completion( ("MyImportedSymbol", Class, "java.io.FileDescriptor"), ("MyImportedSymbol", Module, "java.io.FileDescriptor"), @@ -1679,4 +1683,28 @@ class CompletionTest { ("Numeric", Field, "Numeric"), ("Numeric", Field, "scala.math.Numeric") )) + + @Test def `empty-import-selector`: Unit = + code"""|import java.$m1 + |""" + .completion(results => { + val interestingResults = results.filter(_.getLabel().startsWith("util")) + assertEquals(1, interestingResults.size) + }) + + @Test def `empty-export-selector`: Unit = + code"""|export java.$m1 + |""" + .completion(results => { + val interestingResults = results.filter(_.getLabel().startsWith("util")) + assertEquals(1, interestingResults.size) + }) + + @Test def methodsWithInstantiatedTypeVars: Unit = + code"""|object M: + | Map.empty[Int, String].getOrEls$m1 + |""" + .completion(m1, Set( + ("getOrElse", Method, "[V1 >: String](key: Int, default: => V1): V1"), + )) } diff --git a/presentation-compiler/src/main/dotty/tools/pc/AutoImportsProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/AutoImportsProvider.scala index b95c5fb949e0..8546bbf62384 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/AutoImportsProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/AutoImportsProvider.scala @@ -67,7 +67,7 @@ final class AutoImportsProvider( val results = symbols.result.filter(isExactMatch(_, name)) if results.nonEmpty then - val correctedPos = CompletionPos.infer(pos, params, path).sourcePos + val correctedPos = CompletionPos.infer(pos, params, path).toSourcePosition val mkEdit = path match // if we are in import section just specify full name diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/AmmoniteIvyCompletions.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/AmmoniteIvyCompletions.scala index 39f7144835c9..ec4a1813a437 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/AmmoniteIvyCompletions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/AmmoniteIvyCompletions.scala @@ -13,7 +13,7 @@ object AmmoniteIvyCompletions: completionPos: CompletionPos, text: String )(using Context): List[CompletionValue] = - val pos = completionPos.sourcePos + val pos = completionPos.originalCursorPosition val query = selector.collectFirst { case sel: ImportSelector if sel.sourcePos.encloses(pos) && sel.sourcePos.`end` > pos.`end` => 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 53d867c924a6..6e828f8f2058 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionPos.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionPos.scala @@ -6,53 +6,45 @@ import java.net.URI import scala.meta.pc.OffsetParams import dotty.tools.dotc.ast.untpd.* -import dotty.tools.dotc.ast.untpd.ImportSelector import dotty.tools.dotc.core.Contexts.* -import dotty.tools.dotc.core.StdNames.* -import dotty.tools.dotc.util.Chars import dotty.tools.dotc.util.SourcePosition -import dotty.tools.dotc.util.Spans +import dotty.tools.dotc.util.Spans.* import dotty.tools.dotc.interactive.Completion import dotty.tools.pc.utils.MtagsEnrichments.* import org.eclipse.lsp4j as l -import scala.annotation.tailrec + +case object Cursor: + val value = "CURSOR" case class CompletionPos( - start: Int, - end: Int, - query: String, - cursorPos: SourcePosition, - sourceUri: URI + queryStart: Int, + identEnd: Int, + query: String, + originalCursorPosition: SourcePosition, + sourceUri: URI ): - - def sourcePos: SourcePosition = cursorPos.withSpan(Spans.Span(start, end)) - def stripSuffixEditRange: l.Range = new l.Range(cursorPos.offsetToPos(start), cursorPos.offsetToPos(end)) - def toEditRange: l.Range = cursorPos.withStart(start).withEnd(cursorPos.point).toLsp - -end CompletionPos + def queryEnd: Int = originalCursorPosition.point + def stripSuffixEditRange: l.Range = new l.Range(originalCursorPosition.offsetToPos(queryStart), originalCursorPosition.offsetToPos(identEnd)) + def toEditRange: l.Range = originalCursorPosition.withStart(queryStart).withEnd(originalCursorPosition.point).toLsp + def toSourcePosition: SourcePosition = originalCursorPosition.withSpan(Span(queryStart, queryEnd, queryEnd)) object CompletionPos: def infer( - cursorPos: SourcePosition, + sourcePos: SourcePosition, offsetParams: OffsetParams, adjustedPath: List[Tree] )(using Context): CompletionPos = - infer(cursorPos, offsetParams.uri().nn, offsetParams.text().nn, adjustedPath) + val identEnd = adjustedPath match + case (refTree: RefTree) :: _ if refTree.name.toString.contains(Cursor.value) => + refTree.span.end - Cursor.value.length + case _ => sourcePos.end - def infer( - cursorPos: SourcePosition, - uri: URI, - text: String, - adjustedPath: List[Tree] - )(using Context): CompletionPos = - val identEnd = inferIdentEnd(cursorPos, text) - val query = Completion.completionPrefix(adjustedPath, cursorPos) - val start = cursorPos.point - query.length() + val query = Completion.completionPrefix(adjustedPath, sourcePos) + val start = sourcePos.end - query.length() - CompletionPos(start, identEnd, query.nn, cursorPos, uri) - end infer + CompletionPos(start, identEnd, query.nn, sourcePos, offsetParams.uri.nn) /** * Infer the indentation by counting the number of spaces in the given line. @@ -76,12 +68,4 @@ object CompletionPos: (i, tabIndented) end inferIndent - /** - * Returns the end offset of the identifier starting as the given offset position. - */ - private def inferIdentEnd(pos: SourcePosition, text: String): Int = - var i = pos.point - while i < text.length() && Chars.isIdentifierPart(text.charAt(i)) do i += 1 - i - end CompletionPos 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..a583e31a9e0c 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala @@ -61,11 +61,10 @@ class CompletionProvider( val locatedCtx = Interactive.contextOfPath(tpdPath)(using newctx) val indexedCtx = IndexedContext(locatedCtx) - val completionPos = - CompletionPos.infer(pos, params, adjustedPath)(using locatedCtx) + val completionPos = CompletionPos.infer(pos, params, adjustedPath)(using locatedCtx) val autoImportsGen = AutoImports.generator( - completionPos.sourcePos, + completionPos.toSourcePosition, text, unit.tpdTree, unit.comments, @@ -75,7 +74,6 @@ class CompletionProvider( val (completions, searchResult) = new Completions( - pos, text, locatedCtx, search, @@ -120,7 +118,7 @@ class CompletionProvider( * val a = 1 * @@ * }}} - * it's required to modify actual code by addition Ident. + * it's required to modify actual code by additional Ident. * * Otherwise, completion poisition doesn't point at any tree * because scala parser trim end position to the last statement pos. @@ -168,7 +166,7 @@ class CompletionProvider( additionalEdits: List[TextEdit] = Nil, range: Option[LspRange] = None ): CompletionItem = - val oldText = params.text().nn.substring(completionPos.start, completionPos.end) + val oldText = params.text().nn.substring(completionPos.queryStart, completionPos.identEnd) val editRange = if newText.startsWith(oldText) then completionPos.stripSuffixEditRange else completionPos.toEditRange @@ -287,6 +285,3 @@ class CompletionProvider( end match end completionItems end CompletionProvider - -case object Cursor: - val value = "CURSOR" 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 955982afcf51..abb15d45f88a 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala @@ -37,7 +37,6 @@ import dotty.tools.dotc.core.Denotations.SingleDenotation import dotty.tools.dotc.interactive.Interactive class Completions( - pos: SourcePosition, text: String, ctx: Context, search: SymbolSearch, @@ -56,7 +55,7 @@ class Completions( given context: Context = ctx private lazy val coursierComplete = new CoursierComplete(BuildInfo.scalaVersion) - private lazy val completionMode = Completion.completionMode(adjustedPath, pos) + private lazy val completionMode = Completion.completionMode(adjustedPath, completionPos.originalCursorPosition) private lazy val shouldAddSnippet = path match @@ -83,8 +82,8 @@ class Completions( if !sym.name.endsWith(Cursor.value) then false else val realNameLength = sym.decodedName.length() - Cursor.value.length() - sym.source == pos.source && - sym.span.start + realNameLength == pos.span.end + sym.source == completionPos.originalCursorPosition.source && + sym.span.start + realNameLength == completionPos.queryEnd val generalExclude = isUninterestingSymbol(sym) || @@ -107,7 +106,7 @@ class Completions( end includeSymbol def completions(): (List[CompletionValue], SymbolSearch.Result) = - val (advanced, exclusive) = advancedCompletions(path, pos, completionPos) + val (advanced, exclusive) = advancedCompletions(path, completionPos) val (all, result) = if exclusive then (advanced, SymbolSearch.Result.COMPLETE) else @@ -116,19 +115,19 @@ class Completions( val allAdvanced = advanced ++ keywords path match // should not show completions for toplevel - case Nil | (_: PackageDef) :: _ if pos.source.file.extension != "sc" => + case Nil | (_: PackageDef) :: _ if completionPos.originalCursorPosition.source.file.extension != "sc" => (allAdvanced, SymbolSearch.Result.COMPLETE) case Select(qual, _) :: _ if qual.typeOpt.isErroneous => (allAdvanced, SymbolSearch.Result.COMPLETE) case Select(qual, _) :: _ => - val compilerCompletions = Completion.rawCompletions(pos, completionMode, completionPos.query, path, adjustedPath) + val compilerCompletions = Completion.rawCompletions(completionPos.originalCursorPosition, completionMode, completionPos.query, path, adjustedPath) val (compiler, result) = compilerCompletions .toList .flatMap(toCompletionValues) .filterInteresting(qual.typeOpt.widenDealias) (allAdvanced ++ compiler, result) case _ => - val compilerCompletions = Completion.rawCompletions(pos, completionMode, completionPos.query, path, adjustedPath) + val compilerCompletions = Completion.rawCompletions(completionPos.originalCursorPosition, completionMode, completionPos.query, path, adjustedPath) val (compiler, result) = compilerCompletions .toList .flatMap(toCompletionValues) @@ -265,9 +264,9 @@ class Completions( */ private def advancedCompletions( path: List[Tree], - pos: SourcePosition, completionPos: CompletionPos ): (List[CompletionValue], Boolean) = + val pos = completionPos.originalCursorPosition lazy val rawPath = Paths .get(pos.source.path).nn lazy val rawFileName = rawPath @@ -396,7 +395,6 @@ class Completions( val completions = InterpolatorCompletions .contribute( text, - pos, completionPos, indexedContext, lit, @@ -445,7 +443,7 @@ class Completions( // 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 => - advancedCompletions(tl, pos, completionPos) + advancedCompletions(tl, completionPos) case _ => val args = NamedArgCompletions.contribute( @@ -550,14 +548,7 @@ class Completions( else false, ) Some(search.searchMethods(query, buildTargetIdentifier, visitor).nn) - else - val filtered = indexedContext.scopeSymbols - .filter(sym => !sym.isConstructor && (!sym.is(Synthetic) || sym.is(Module))) - - filtered.map { sym => - visit(CompletionValue.Scope(sym.decodedName, sym, findSuffix(sym))) - } - Some(SymbolSearch.Result.INCOMPLETE) + else Some(SymbolSearch.Result.INCOMPLETE) end enrichWithSymbolSearch @@ -657,7 +648,7 @@ class Completions( private def isNotLocalForwardReference(sym: Symbol)(using Context): Boolean = !sym.isLocalToBlock || - !sym.srcPos.isAfter(pos) || + !sym.srcPos.isAfter(completionPos.originalCursorPosition) || sym.is(Param) private def computeRelevancePenalty( @@ -676,7 +667,7 @@ class Completions( def symbolRelevance(sym: Symbol): Int = var relevance = 0 // symbols defined in this file are more relevant - if pos.source != sym.source || sym.is(Package) then + if completionPos.originalCursorPosition.source != sym.source || sym.is(Package) then relevance |= IsNotDefinedInFile // fields are more relevant than non fields (such as method) 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 95fbeec0cac0..2a8ead70ea33 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/InterpolatorCompletions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/InterpolatorCompletions.scala @@ -12,6 +12,7 @@ import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Flags import dotty.tools.dotc.core.Flags.* import dotty.tools.dotc.core.Symbols.Symbol +import dotty.tools.dotc.util.Spans import dotty.tools.dotc.core.Types.Type import dotty.tools.dotc.util.SourcePosition import dotty.tools.pc.CompilerSearchVisitor @@ -24,7 +25,6 @@ object InterpolatorCompletions: def contribute( text: String, - pos: SourcePosition, completionPos: CompletionPos, indexedContext: IndexedContext, lit: Literal, @@ -35,12 +35,12 @@ object InterpolatorCompletions: config: PresentationCompilerConfig, buildTargetIdentifier: String )(using Context, ReportContext) = - InterpolationSplice(pos.span.point, text.toCharArray().nn, text) match + InterpolationSplice(completionPos.queryEnd, text.toCharArray().nn, text) match case Some(interpolator) => InterpolatorCompletions.contributeScope( text, lit, - pos, + completionPos, interpolator, indexedContext, completions, @@ -55,7 +55,6 @@ object InterpolatorCompletions: lit, path, text, - pos, completionPos, completions, snippetsEnabled, @@ -106,7 +105,6 @@ object InterpolatorCompletions: lit: Literal, path: List[Tree], text: String, - cursor: SourcePosition, completionPos: CompletionPos, completions: Completions, areSnippetsSupported: Boolean, @@ -166,7 +164,7 @@ object InterpolatorCompletions: label, Some(newText(name, suffix.toEditOpt, identOrSelect)), Nil, - Some(cursor.withStart(identOrSelect.span.start).toLsp), + Some(completionPos.originalCursorPosition.withStart(identOrSelect.span.start).toLsp), // Needed for VS Code which will not show the completion otherwise Some(identOrSelect.name.toString() + "." + label), denot.symbol, @@ -219,7 +217,7 @@ object InterpolatorCompletions: private def contributeScope( text: String, lit: Literal, - position: SourcePosition, + completionPos: CompletionPos, interpolator: InterpolationSplice, indexedContext: IndexedContext, completions: Completions, @@ -230,6 +228,7 @@ object InterpolatorCompletions: )(using ctx: Context, reportsContext: ReportContext): List[CompletionValue] = val litStartPos = lit.span.start val litEndPos = lit.span.end - Cursor.value.length() + val position = completionPos.originalCursorPosition val span = position.span val nameStart = span.withStart(span.start - interpolator.name.size) diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/KeywordsCompletions.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/KeywordsCompletions.scala index e912bc49032f..abbf43174bc7 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/KeywordsCompletions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/KeywordsCompletions.scala @@ -21,7 +21,7 @@ object KeywordsCompletions: comments: List[Comment] )(using ctx: Context): List[CompletionValue] = lazy val notInComment = - checkIfNotInComment(completionPos.cursorPos, comments) + checkIfNotInComment(completionPos.originalCursorPosition, comments) path match case Nil | (_: PackageDef) :: _ if completionPos.query.isEmpty() => @@ -33,8 +33,7 @@ object KeywordsCompletions: case _ => val isExpression = this.isExpression(path) val isBlock = this.isBlock(path) - val isDefinition = - this.isDefinition(path, completionPos.query, completionPos.cursorPos) + val isDefinition = this.isDefinition(path, completionPos.query, completionPos.originalCursorPosition) val isMethodBody = this.isMethodBody(path) val isTemplate = this.isTemplate(path) val isPackage = this.isPackage(path) @@ -191,10 +190,10 @@ object KeywordsCompletions: case untpdTree: untpd.Tree => collectTypeAndModuleDefs(untpdTree, { case typeDef: (untpd.TypeDef | untpd.ModuleDef) => - typeDef.span.exists && typeDef.span.end < pos.sourcePos.span.start + typeDef.span.exists && typeDef.span.end < pos.queryStart case _ => false }) - .filter(tree => tree.span.exists && tree.span.end < pos.start) + .filter(tree => tree.span.exists && tree.span.end < pos.queryStart) .maxByOption(_.span.end) case _ => None } @@ -208,7 +207,7 @@ object KeywordsCompletions: template.derived.isEmpty ) - val untpdPath = NavigateAST.untypedPath(pos.cursorPos.span) + val untpdPath = NavigateAST.untypedPath(pos.originalCursorPosition.span) findLastSatisfyingTree(untpdPath).orElse { enclosing match case (typeDef: TypeDef) :: _ if typeDef.symbol.isEnumClass => untpdPath.headOption diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/MatchCaseCompletions.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/MatchCaseCompletions.scala index bd94f2f3983a..7f1d92305309 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/MatchCaseCompletions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/MatchCaseCompletions.scala @@ -526,8 +526,8 @@ class MatchCaseExtractor( name.toString().replace(Cursor.value, "") ) && (text .charAt( - completionPos.start - 1 - ) == ' ' || text.charAt(completionPos.start - 1) == '.') => + completionPos.queryStart - 1 + ) == ' ' || text.charAt(completionPos.queryStart - 1) == '.') => Some(qualifier) case _ => None end MatchExtractor diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionInterpolatorSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionInterpolatorSuite.scala index d70f28d08486..d9dc635ce21a 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionInterpolatorSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionInterpolatorSuite.scala @@ -40,11 +40,11 @@ class CompletionInterpolatorSuite extends BaseCompletionSuite: @Test def `string2` = checkEdit( - s"""|object Main { - | val myName = "" - | def message = "$$myNa@@me" - |} - |""".stripMargin, + """|object Main { + | val myName = "" + | def message = "$myNa@@me" + |} + |""".stripMargin, """|object Main { | val myName = "" | def message = s"${myName$0}me" @@ -558,18 +558,6 @@ class CompletionInterpolatorSuite extends BaseCompletionSuite: filter = _.contains("hello") ) - @Test def `brace-token-error-pos` = - checkEditLine( - """|object Main { - | val hello = "" - | ___ - |} - |""".stripMargin, - """s"Hello ${@@"""".stripMargin, - """s"Hello ${hello"""".stripMargin, - filter = _.contains("hello") - ) - @Test def `brace-token-error` = checkEditLine( """|object Main { @@ -759,3 +747,36 @@ class CompletionInterpolatorSuite extends BaseCompletionSuite: |}""".stripMargin, filter = _.contains("[A]") ) + + @Test def `dont-show-when-writing-before-dollar` = + check( + """|object M: + | val host = "" + | val path = "" + | + | println(s"host@@$path")} + |""".stripMargin, + "" + ) + + @Test def `show-when-writing-between-dollars` = + check( + """|object M: + | val host = "" + | val path = "" + | + | println(s"$host@@$path")} + |""".stripMargin, + "host: String" + ) + + @Test def `show-when-writing-between-dollars-2` = + check( + """|object M: + | val host = "" + | val path = "" + | + | println(s"$ho@@$path")} + |""".stripMargin, + "host: String" + ) 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 dc972ec22533..c828cd4e6e67 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionKeywordSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionKeywordSuite.scala @@ -38,7 +38,7 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | // tr@@ |} |""".stripMargin, - "transparentTrait - scala.annotation (commit: '')", + "", includeCommitCharacter = true ) @@ -57,7 +57,7 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | **/ |} |""".stripMargin, - "transparentTrait - scala.annotation (commit: '')", + "", includeCommitCharacter = true ) @@ -412,8 +412,6 @@ class CompletionKeywordSuite extends BaseCompletionSuite: |} """.stripMargin, """|def - |derived - scala.CanEqual - |deprecated - scala.runtime.stdLibPatches.language |""".stripMargin, ) @@ -428,7 +426,6 @@ class CompletionKeywordSuite extends BaseCompletionSuite: """.stripMargin, """|val |var - |varargs - scala.annotation |""".stripMargin ) @@ -467,13 +464,8 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | def hello(u@@) |}""".stripMargin, """|using (commit: '') - |unsafe - scala.caps (commit: '') - |unsafeNulls - scala.runtime.stdLibPatches.language (commit: '') - |unused - scala.annotation (commit: '') - |unshared - scala.annotation.internal (commit: '') |""".stripMargin, includeCommitCharacter = true, - topLines = Some(5) ) @Test def `not-using` = @@ -481,12 +473,7 @@ class CompletionKeywordSuite extends BaseCompletionSuite: """|object A{ | def hello(a: String, u@@) |}""".stripMargin, - """|unsafe - scala.caps - |unsafeNulls - scala.runtime.stdLibPatches.language - |unused - scala.annotation - |unshared - scala.annotation.internal - |unspecialized - scala.annotation""".stripMargin, - topLines = Some(5) + "", ) @Test def `extends-class` = diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionPatternSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionPatternSuite.scala index df6a3f705be9..6d2261bbfe66 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionPatternSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionPatternSuite.scala @@ -54,9 +54,7 @@ class CompletionPatternSuite extends BaseCompletionSuite: | case ma@@ | } |}""".stripMargin, - """|macros - scala.languageFeature.experimental - |macroImpl - scala.reflect.macros.internal - |""".stripMargin + "" ) @Test def `bind2` = diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala index 8f47582e4806..addd86fc32ab 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala @@ -1608,7 +1608,7 @@ class CompletionSuite extends BaseCompletionSuite: assertSingleItem = false ) - @Test def `prepend-instead-of-replace-duplicate-word` = + @Test def `prepend-duplicate-word` = checkEdit( """|object O: | println@@println() @@ -1622,10 +1622,10 @@ class CompletionSuite extends BaseCompletionSuite: @Test def `replace-when-inside` = checkEdit( """|object O: - | print@@ln() + | pri@@nt() |""".stripMargin, """|object O: - | println() + | print() |""".stripMargin, assertSingleItem = false ) @@ -1734,3 +1734,130 @@ class CompletionSuite extends BaseCompletionSuite: filter = _.contains("[") ) + @Test def `empty-import` = + check( + """|import @@ + |""".stripMargin, + """|java + |javax + |""".stripMargin, + filter = _.startsWith("java") + ) + + @Test def `empty-import-selector` = + check( + """|import java.@@ + |""".stripMargin, + """|util java + |""".stripMargin, + filter = _.startsWith("util") + ) + + @Test def `empty-export` = + check( + """|export @@ + |""".stripMargin, + """|java + |javax + |""".stripMargin, + filter = _.startsWith("java") + ) + + @Test def `empty-export-selector` = + check( + """|export java.@@ + |""".stripMargin, + """|util java + |""".stripMargin, + filter = _.startsWith("util") + ) + + @Test def `annotation` = + check( + """|@Over@@ + |object M {} + |""".stripMargin, + """|Override java.lang + |""".stripMargin, + filter = _ == "Override java.lang" + ) + + @Test def `no-annotation` = + check( + """| + |object M { + | Overr@@ + |} + |""".stripMargin, + """|Override java.lang + |""".stripMargin, + filter = _ == "Override java.lang" + ) + + @Test def `no-annotation-param-first-pos` = + check( + """| + |object M { + | def hello(Overr@@) + |} + |""".stripMargin, + "" + ) + + @Test def `no-annotation-param-second-pos` = + check( + """| + |object M { + | def hello(x: Int, Overr@@) + |} + |""".stripMargin, + "" + ) + + @Test def `no-annotation-param-second-list` = + check( + """| + |object M { + | def hello(x: Int)(Overr@@) + |} + |""".stripMargin, + "" + ) + + + @Test def `annotation-param-first-pos` = + check( + """| + |object M { + | def hello(@Overr@@) + |} + |""".stripMargin, + """|Override java.lang + |""".stripMargin, + filter = _ == "Override java.lang" + ) + + @Test def `annotation-param-second-pos` = + check( + """| + |object M { + | def hello(x: Int, @Overr@@) + |} + |""".stripMargin, + """|Override java.lang + |""".stripMargin, + filter = _ == "Override java.lang" + ) + + @Test def `annotation-param-second-list` = + check( + """| + |object M { + | def hello(x: Int)( @Overr@@) + |} + |""".stripMargin, + """|Override java.lang + |""".stripMargin, + filter = _ == "Override java.lang" + ) + From cd68604247c56524631e841a93cfac89c2377cc6 Mon Sep 17 00:00:00 2001 From: odersky Date: Thu, 29 Feb 2024 11:13:19 +0100 Subject: [PATCH 142/277] Use fixed copying instead of writing code out --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 9591bc5a93f0..53287465614a 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -1978,10 +1978,7 @@ object desugar { val applyVParams = args.zipWithIndex.map { case (p, n) => makeSyntheticParameter(n + 1, p) } - tree match - case tree: FunctionWithMods => - untpd.FunctionWithMods(applyVParams, result, tree.mods, tree.erasedParams) - case _ => untpd.Function(applyVParams, result) + cpy.Function(tree)(applyVParams, result).asInstanceOf[untpd.Function] } } From e746116dd0d52462d309d96f81898e039ce74162 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 28 Feb 2024 15:20:18 +0100 Subject: [PATCH 143/277] Tag experimental API tests Add explicitly `-experimental -Yno-experimental` to tests that use definitions that are `@experimental` in the standard library. `-Yno-experimental` disables the experimental mode from nightly builds and `-experimental` adds `@experimental` to all top-level definitions. --- tests/neg-macros/i18677-a.check | 4 ++-- tests/neg-macros/i18677-a/Macro_1.scala | 2 +- tests/neg-macros/i18677-a/Test_2.scala | 2 +- tests/neg-macros/i18677-b.check | 4 ++-- tests/neg-macros/i18677-b/Macro_1.scala | 2 +- tests/neg-macros/i18677-b/Test_2.scala | 2 +- tests/neg-macros/newClassExtendsNoParents/Macro_1.scala | 2 ++ tests/neg-macros/newClassExtendsNoParents/Test_2.scala | 2 ++ tests/neg-macros/newClassExtendsOnlyTrait/Macro_1.scala | 2 ++ tests/neg-macros/newClassExtendsOnlyTrait/Test_2.scala | 2 ++ tests/pos-macros/annot-in-object/Macro_1.scala | 2 ++ tests/pos-macros/annot-in-object/Test_2.scala | 2 ++ tests/pos-macros/annot-suspend/Macro_1.scala | 2 ++ tests/pos-macros/annot-suspend/Test_2.scala | 2 ++ tests/pos-macros/annot-then-inline/Macro_1.scala | 2 ++ tests/pos-macros/annot-then-inline/Test_2.scala | 2 ++ tests/pos-macros/i15413/Macro_1.scala | 2 +- tests/pos-macros/i15413/Test_2.scala | 2 ++ tests/pos-macros/i15413b/Macro_1.scala | 2 +- tests/pos-macros/i15413b/Test_2.scala | 2 ++ tests/pos-macros/i19526b/Test.scala | 2 ++ .../run-macros/Xmacro-settings-compileTimeEnv/Test.scala | 2 +- tests/run-macros/Xmacro-settings-simple/M1.scala | 2 ++ tests/run-macros/annot-add-global-class/Macro_1.scala | 2 ++ tests/run-macros/annot-add-global-class/Test_2.scala | 2 ++ tests/run-macros/annot-add-global-object/Macro_1.scala | 2 ++ tests/run-macros/annot-add-global-object/Test_2.scala | 2 ++ tests/run-macros/annot-add-local-class/Macro_1.scala | 2 ++ tests/run-macros/annot-add-local-class/Test_2.scala | 2 ++ tests/run-macros/annot-add-local-object/Macro_1.scala | 2 ++ tests/run-macros/annot-add-local-object/Test_2.scala | 2 ++ tests/run-macros/annot-add-nested-class/Macro_1.scala | 2 ++ tests/run-macros/annot-add-nested-class/Test_2.scala | 2 ++ tests/run-macros/annot-add-nested-object/Macro_1.scala | 2 ++ tests/run-macros/annot-add-nested-object/Test_2.scala | 2 ++ tests/run-macros/annot-annot-order/Macro_1.scala | 2 ++ tests/run-macros/annot-annot-order/Test_2.scala | 2 ++ tests/run-macros/annot-bind/Macro_1.scala | 2 ++ tests/run-macros/annot-bind/Test_2.scala | 2 ++ tests/run-macros/annot-changeVal/Macro_1.scala | 2 ++ tests/run-macros/annot-changeVal/Test_2.scala | 2 ++ tests/run-macros/annot-concrete-class/Macro_1.scala | 8 +++++--- tests/run-macros/annot-concrete-class/Test_2.scala | 4 ++-- tests/run-macros/annot-export/Macro_1.scala | 2 ++ tests/run-macros/annot-export/Test_2.scala | 2 ++ tests/run-macros/annot-gen2/Macro_1.scala | 2 ++ tests/run-macros/annot-gen2/Macro_2.scala | 2 ++ tests/run-macros/annot-gen2/Test_3.scala | 2 ++ tests/run-macros/annot-generate/Macro_1.scala | 2 ++ tests/run-macros/annot-generate/Macro_2.scala | 2 ++ tests/run-macros/annot-generate/Test_3.scala | 2 ++ tests/run-macros/annot-macro-main/Macro_1.scala | 2 ++ tests/run-macros/annot-macro-main/Test_2.scala | 2 ++ tests/run-macros/annot-memo/Macro_1.scala | 2 ++ tests/run-macros/annot-memo/Test_2.scala | 2 ++ tests/run-macros/annot-mod-class-add-def/Macro_1.scala | 2 ++ tests/run-macros/annot-mod-class-add-def/Test_2.scala | 2 ++ .../annot-mod-class-add-inner-class/Macro_1.scala | 2 ++ .../annot-mod-class-add-inner-class/Test_2.scala | 2 ++ .../run-macros/annot-mod-class-add-lazy-val/Macro_1.scala | 2 ++ .../run-macros/annot-mod-class-add-lazy-val/Test_2.scala | 2 ++ .../annot-mod-class-add-local-class/Macro_1.scala | 2 ++ .../annot-mod-class-add-local-class/Test_2.scala | 2 ++ tests/run-macros/annot-mod-class-add-val/Macro_1.scala | 2 ++ tests/run-macros/annot-mod-class-add-val/Test_2.scala | 2 ++ tests/run-macros/annot-mod-class-add-var/Macro_1.scala | 2 ++ tests/run-macros/annot-mod-class-add-var/Test_2.scala | 2 ++ tests/run-macros/annot-mod-class-data/Macro_1.scala | 2 ++ tests/run-macros/annot-mod-class-data/Test_2.scala | 2 ++ tests/run-macros/annot-mod-class-equals/Macro_1.scala | 2 ++ tests/run-macros/annot-mod-class-equals/Test_2.scala | 2 ++ tests/run-macros/annot-mod-class-mod-def/Macro_1.scala | 2 ++ tests/run-macros/annot-mod-class-mod-def/Test_2.scala | 2 ++ tests/run-macros/annot-mod-class-mod-val/Macro_1.scala | 2 ++ tests/run-macros/annot-mod-class-mod-val/Test_2.scala | 2 ++ .../run-macros/annot-mod-class-override-def/Macro_1.scala | 2 ++ .../run-macros/annot-mod-class-override-def/Test_2.scala | 2 ++ .../run-macros/annot-mod-class-override-val/Macro_1.scala | 2 ++ .../run-macros/annot-mod-class-override-val/Test_2.scala | 2 ++ .../annot-mod-class-unused-new-sym/Macro_1.scala | 2 ++ .../annot-mod-class-unused-new-sym/Test_2.scala | 2 ++ tests/run-macros/annot-result-order/Macro_1.scala | 2 ++ tests/run-macros/annot-result-order/Test_2.scala | 2 ++ tests/run-macros/annot-simple-fib/Macro_1.scala | 2 ++ tests/run-macros/annot-simple-fib/Test_2.scala | 2 ++ tests/run-macros/i11685/Macro_1.scala | 2 ++ tests/run-macros/i11685/Test_2.scala | 2 ++ tests/run-macros/i16734b/Macro_1.scala | 2 ++ tests/run-macros/i16734b/Test_2.scala | 2 ++ tests/run-macros/newClass/Macro_1.scala | 2 ++ tests/run-macros/newClass/Test_2.scala | 2 ++ tests/run-macros/newClassExtends/Macro_1.scala | 2 ++ tests/run-macros/newClassExtends/Test_2.scala | 2 ++ tests/run-macros/newClassExtendsClassParams/Macro_1.scala | 2 ++ tests/run-macros/newClassExtendsClassParams/Test_2.scala | 2 ++ tests/run-macros/newClassSelf/Macro_1.scala | 2 ++ tests/run-macros/newClassSelf/Test_2.scala | 2 ++ tests/run/main-annotation-birthday.scala | 1 + tests/run/main-annotation-dash-dash.scala | 1 + tests/run/main-annotation-default-value-1.scala | 1 + tests/run/main-annotation-default-value-2.scala | 1 + tests/run/main-annotation-example.scala | 1 + tests/run/main-annotation-flags.scala | 1 + tests/run/main-annotation-help-override.scala | 1 + tests/run/main-annotation-help.scala | 1 + tests/run/main-annotation-homemade-annot-1.scala | 1 + tests/run/main-annotation-homemade-annot-2.scala | 1 + tests/run/main-annotation-homemade-annot-3.scala | 1 + tests/run/main-annotation-homemade-annot-4.scala | 1 + tests/run/main-annotation-homemade-annot-5.scala | 1 + tests/run/main-annotation-homemade-annot-6.scala | 1 + tests/run/main-annotation-homemade-parser-1.scala | 1 + tests/run/main-annotation-homemade-parser-2.scala | 1 + tests/run/main-annotation-homemade-parser-3.scala | 1 + tests/run/main-annotation-homemade-parser-4.scala | 1 + tests/run/main-annotation-homemade-parser-5.scala | 1 + tests/run/main-annotation-multiple.scala | 1 + tests/run/main-annotation-named-params.scala | 1 + tests/run/main-annotation-newMain.scala | 1 + tests/run/main-annotation-no-parameters-no-parens.scala | 1 + tests/run/main-annotation-no-parameters.scala | 1 + tests/run/main-annotation-overload.scala | 1 + tests/run/main-annotation-param-annot-1.scala | 1 + tests/run/main-annotation-param-annot-2.scala | 1 + .../run/main-annotation-param-annot-invalid-params.scala | 1 + tests/run/main-annotation-return-type-1.scala | 1 + tests/run/main-annotation-return-type-2.scala | 1 + tests/run/main-annotation-short-name.scala | 1 + tests/run/main-annotation-simple.scala | 1 + tests/run/main-annotation-top-level.scala | 1 + tests/run/main-annotation-types.scala | 1 + tests/run/main-annotation-vararg-1.scala | 1 + tests/run/main-annotation-vararg-2.scala | 1 + tests/run/main-annotation-wrong-param-1.scala | 1 + tests/run/main-annotation-wrong-param-names.scala | 1 + tests/run/main-annotation-wrong-param-number.scala | 1 + tests/run/main-annotation-wrong-param-type.scala | 1 + tests/run/main-calculator-example.scala | 3 ++- tests/run/tupled-function-andThen.scala | 2 ++ tests/run/tupled-function-apply.scala | 2 ++ tests/run/tupled-function-compose.scala | 2 ++ tests/run/tupled-function-extension-method.scala | 2 ++ tests/run/tupled-function-tupled.scala | 2 ++ tests/run/tupled-function-untupled.scala | 2 ++ 144 files changed, 244 insertions(+), 17 deletions(-) diff --git a/tests/neg-macros/i18677-a.check b/tests/neg-macros/i18677-a.check index 976ff7bddda2..963affc47181 100644 --- a/tests/neg-macros/i18677-a.check +++ b/tests/neg-macros/i18677-a.check @@ -7,10 +7,10 @@ |The tree does not conform to the compiler's tree invariants. | |Macro was: - |@scala.annotation.internal.SourceFile("tests/neg-macros/i18677-a/Test_2.scala") @extendFoo class AFoo() + |@scala.annotation.internal.SourceFile("tests/neg-macros/i18677-a/Test_2.scala") @scala.annotation.experimental @extendFoo class AFoo() | |The macro returned: - |@scala.annotation.internal.SourceFile("tests/neg-macros/i18677-a/Test_2.scala") @extendFoo class AFoo() extends Foo + |@scala.annotation.internal.SourceFile("tests/neg-macros/i18677-a/Test_2.scala") @scala.annotation.experimental @extendFoo class AFoo() extends Foo | |Error: |assertion failed: Parents of class symbol differs from the parents in the tree for class AFoo diff --git a/tests/neg-macros/i18677-a/Macro_1.scala b/tests/neg-macros/i18677-a/Macro_1.scala index f624d2d15782..c3df616ed4e6 100644 --- a/tests/neg-macros/i18677-a/Macro_1.scala +++ b/tests/neg-macros/i18677-a/Macro_1.scala @@ -1,4 +1,4 @@ -//> using -expermiental +//> using options -experimental -Yno-experimental import annotation.MacroAnnotation import quoted.* diff --git a/tests/neg-macros/i18677-a/Test_2.scala b/tests/neg-macros/i18677-a/Test_2.scala index 486d7e09a4bc..5fb6680df0ca 100644 --- a/tests/neg-macros/i18677-a/Test_2.scala +++ b/tests/neg-macros/i18677-a/Test_2.scala @@ -1,4 +1,4 @@ -//> using -expermiental +//> using options -experimental -Yno-experimental @extendFoo class AFoo // error \ No newline at end of file diff --git a/tests/neg-macros/i18677-b.check b/tests/neg-macros/i18677-b.check index b6d817a53706..b8fecde2e36d 100644 --- a/tests/neg-macros/i18677-b.check +++ b/tests/neg-macros/i18677-b.check @@ -7,10 +7,10 @@ |The tree does not conform to the compiler's tree invariants. | |Macro was: - |@scala.annotation.internal.SourceFile("tests/neg-macros/i18677-b/Test_2.scala") @extendFoo class AFoo() + |@scala.annotation.internal.SourceFile("tests/neg-macros/i18677-b/Test_2.scala") @scala.annotation.experimental @extendFoo class AFoo() | |The macro returned: - |@scala.annotation.internal.SourceFile("tests/neg-macros/i18677-b/Test_2.scala") @extendFoo class AFoo() extends Foo + |@scala.annotation.internal.SourceFile("tests/neg-macros/i18677-b/Test_2.scala") @scala.annotation.experimental @extendFoo class AFoo() extends Foo | |Error: |assertion failed: Parents of class symbol differs from the parents in the tree for class AFoo diff --git a/tests/neg-macros/i18677-b/Macro_1.scala b/tests/neg-macros/i18677-b/Macro_1.scala index b2ff946ad302..9e1b9be5e696 100644 --- a/tests/neg-macros/i18677-b/Macro_1.scala +++ b/tests/neg-macros/i18677-b/Macro_1.scala @@ -1,4 +1,4 @@ -//> using -expermiental +//> using options -experimental -Yno-experimental import annotation.MacroAnnotation import quoted.* diff --git a/tests/neg-macros/i18677-b/Test_2.scala b/tests/neg-macros/i18677-b/Test_2.scala index 486d7e09a4bc..5fb6680df0ca 100644 --- a/tests/neg-macros/i18677-b/Test_2.scala +++ b/tests/neg-macros/i18677-b/Test_2.scala @@ -1,4 +1,4 @@ -//> using -expermiental +//> using options -experimental -Yno-experimental @extendFoo class AFoo // error \ No newline at end of file diff --git a/tests/neg-macros/newClassExtendsNoParents/Macro_1.scala b/tests/neg-macros/newClassExtendsNoParents/Macro_1.scala index 5280ffba0f53..663e5e959e87 100644 --- a/tests/neg-macros/newClassExtendsNoParents/Macro_1.scala +++ b/tests/neg-macros/newClassExtendsNoParents/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.quoted.* inline def makeClass(inline name: String): Any = ${ makeClassExpr('name) } diff --git a/tests/neg-macros/newClassExtendsNoParents/Test_2.scala b/tests/neg-macros/newClassExtendsNoParents/Test_2.scala index eada3ba7e67a..733879441e91 100644 --- a/tests/neg-macros/newClassExtendsNoParents/Test_2.scala +++ b/tests/neg-macros/newClassExtendsNoParents/Test_2.scala @@ -1 +1,3 @@ +//> using options -experimental -Yno-experimental + def test: Any = makeClass("foo") // error diff --git a/tests/neg-macros/newClassExtendsOnlyTrait/Macro_1.scala b/tests/neg-macros/newClassExtendsOnlyTrait/Macro_1.scala index d1fd45399157..a6a4753185ba 100644 --- a/tests/neg-macros/newClassExtendsOnlyTrait/Macro_1.scala +++ b/tests/neg-macros/newClassExtendsOnlyTrait/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.quoted.* inline def makeClass(inline name: String): Foo = ${ makeClassExpr('name) } diff --git a/tests/neg-macros/newClassExtendsOnlyTrait/Test_2.scala b/tests/neg-macros/newClassExtendsOnlyTrait/Test_2.scala index d8636c811214..b9aaa2a87c60 100644 --- a/tests/neg-macros/newClassExtendsOnlyTrait/Test_2.scala +++ b/tests/neg-macros/newClassExtendsOnlyTrait/Test_2.scala @@ -1 +1,3 @@ +//> using options -experimental -Yno-experimental + def test: Foo = makeClass("foo") // error diff --git a/tests/pos-macros/annot-in-object/Macro_1.scala b/tests/pos-macros/annot-in-object/Macro_1.scala index 52c5daec1f29..143bd46b8ecc 100644 --- a/tests/pos-macros/annot-in-object/Macro_1.scala +++ b/tests/pos-macros/annot-in-object/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ diff --git a/tests/pos-macros/annot-in-object/Test_2.scala b/tests/pos-macros/annot-in-object/Test_2.scala index 4fc43d4f2e41..146b426b0bf8 100644 --- a/tests/pos-macros/annot-in-object/Test_2.scala +++ b/tests/pos-macros/annot-in-object/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @Foo.void @Foo.Bar.void def test = 0 diff --git a/tests/pos-macros/annot-suspend/Macro_1.scala b/tests/pos-macros/annot-suspend/Macro_1.scala index afbf05e568c7..3c391a1a041f 100644 --- a/tests/pos-macros/annot-suspend/Macro_1.scala +++ b/tests/pos-macros/annot-suspend/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ diff --git a/tests/pos-macros/annot-suspend/Test_2.scala b/tests/pos-macros/annot-suspend/Test_2.scala index ee8529fa4414..8014af03235c 100644 --- a/tests/pos-macros/annot-suspend/Test_2.scala +++ b/tests/pos-macros/annot-suspend/Test_2.scala @@ -1,2 +1,4 @@ +//> using options -experimental -Yno-experimental + @void def test = 0 diff --git a/tests/pos-macros/annot-then-inline/Macro_1.scala b/tests/pos-macros/annot-then-inline/Macro_1.scala index 8e966be862cd..99fece18299a 100644 --- a/tests/pos-macros/annot-then-inline/Macro_1.scala +++ b/tests/pos-macros/annot-then-inline/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ diff --git a/tests/pos-macros/annot-then-inline/Test_2.scala b/tests/pos-macros/annot-then-inline/Test_2.scala index 3e72fcaaae1d..99cb2e4e4d5b 100644 --- a/tests/pos-macros/annot-then-inline/Test_2.scala +++ b/tests/pos-macros/annot-then-inline/Test_2.scala @@ -1,2 +1,4 @@ +//> using options -experimental -Yno-experimental + @useInlinedIdentity def test = 0 diff --git a/tests/pos-macros/i15413/Macro_1.scala b/tests/pos-macros/i15413/Macro_1.scala index 56fd4f0f0887..6166a5d6f55d 100644 --- a/tests/pos-macros/i15413/Macro_1.scala +++ b/tests/pos-macros/i15413/Macro_1.scala @@ -1,4 +1,4 @@ -//> using options -Werror -WunstableInlineAccessors +//> using options -experimental -Yno-experimental -Werror -WunstableInlineAccessors import scala.quoted.* import scala.annotation.publicInBinary diff --git a/tests/pos-macros/i15413/Test_2.scala b/tests/pos-macros/i15413/Test_2.scala index a8310a8970fd..7f8c90161c66 100644 --- a/tests/pos-macros/i15413/Test_2.scala +++ b/tests/pos-macros/i15413/Test_2.scala @@ -1,2 +1,4 @@ +//> using options -experimental -Yno-experimental + def test = new Macro().foo diff --git a/tests/pos-macros/i15413b/Macro_1.scala b/tests/pos-macros/i15413b/Macro_1.scala index c1e9bab422f8..b8a91eaba0fe 100644 --- a/tests/pos-macros/i15413b/Macro_1.scala +++ b/tests/pos-macros/i15413b/Macro_1.scala @@ -1,4 +1,4 @@ -//> using options -Werror -WunstableInlineAccessors +//> using options -experimental -Yno-experimental -Werror -WunstableInlineAccessors package bar diff --git a/tests/pos-macros/i15413b/Test_2.scala b/tests/pos-macros/i15413b/Test_2.scala index 5fc688c79b68..f03559b9adb9 100644 --- a/tests/pos-macros/i15413b/Test_2.scala +++ b/tests/pos-macros/i15413b/Test_2.scala @@ -1 +1,3 @@ +//> using options -experimental -Yno-experimental + def test = bar.foo diff --git a/tests/pos-macros/i19526b/Test.scala b/tests/pos-macros/i19526b/Test.scala index 1cc037298e01..ede2db53c5b0 100644 --- a/tests/pos-macros/i19526b/Test.scala +++ b/tests/pos-macros/i19526b/Test.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + package crash.test case class Stack private[crash] ( diff --git a/tests/run-macros/Xmacro-settings-compileTimeEnv/Test.scala b/tests/run-macros/Xmacro-settings-compileTimeEnv/Test.scala index 620d2b85d185..aee87a46ce81 100644 --- a/tests/run-macros/Xmacro-settings-compileTimeEnv/Test.scala +++ b/tests/run-macros/Xmacro-settings-compileTimeEnv/Test.scala @@ -1,4 +1,4 @@ -//> using options -Xmacro-settings:a,b=1,c.b.a=x.y.z=1,myLogger.level=INFO +//> using options -experimental -Yno-experimental -Xmacro-settings:a,b=1,c.b.a=x.y.z=1,myLogger.level=INFO import scala.compiletime.* diff --git a/tests/run-macros/Xmacro-settings-simple/M1.scala b/tests/run-macros/Xmacro-settings-simple/M1.scala index 1210d1abe05e..57a8be886ba1 100644 --- a/tests/run-macros/Xmacro-settings-simple/M1.scala +++ b/tests/run-macros/Xmacro-settings-simple/M1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + package x import scala.quoted.* diff --git a/tests/run-macros/annot-add-global-class/Macro_1.scala b/tests/run-macros/annot-add-global-class/Macro_1.scala index 128b66bd6eb1..6ac77913e3ab 100644 --- a/tests/run-macros/annot-add-global-class/Macro_1.scala +++ b/tests/run-macros/annot-add-global-class/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + package mymacro import scala.annotation.{experimental, MacroAnnotation} diff --git a/tests/run-macros/annot-add-global-class/Test_2.scala b/tests/run-macros/annot-add-global-class/Test_2.scala index 11386bcc0bc5..824dd2381760 100644 --- a/tests/run-macros/annot-add-global-class/Test_2.scala +++ b/tests/run-macros/annot-add-global-class/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import mymacro.addClass @addClass def foo(): Unit = diff --git a/tests/run-macros/annot-add-global-object/Macro_1.scala b/tests/run-macros/annot-add-global-object/Macro_1.scala index b8d1dfd7dc42..f7c901a49aa5 100644 --- a/tests/run-macros/annot-add-global-object/Macro_1.scala +++ b/tests/run-macros/annot-add-global-object/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable diff --git a/tests/run-macros/annot-add-global-object/Test_2.scala b/tests/run-macros/annot-add-global-object/Test_2.scala index 2007c751bbec..181bc4e935ea 100644 --- a/tests/run-macros/annot-add-global-object/Test_2.scala +++ b/tests/run-macros/annot-add-global-object/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @addClass def foo(): Unit = println("macro generated main") println("executed in: " + (new Throwable().getStackTrace().head.getClassName)) diff --git a/tests/run-macros/annot-add-local-class/Macro_1.scala b/tests/run-macros/annot-add-local-class/Macro_1.scala index 8cbf30dfc923..57a2d543ffbc 100644 --- a/tests/run-macros/annot-add-local-class/Macro_1.scala +++ b/tests/run-macros/annot-add-local-class/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable diff --git a/tests/run-macros/annot-add-local-class/Test_2.scala b/tests/run-macros/annot-add-local-class/Test_2.scala index e52ca30f8d9f..8fe4f9db5656 100644 --- a/tests/run-macros/annot-add-local-class/Test_2.scala +++ b/tests/run-macros/annot-add-local-class/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @main def Test(): Unit = @addClass def foo(): Unit = println("macro generated main") diff --git a/tests/run-macros/annot-add-local-object/Macro_1.scala b/tests/run-macros/annot-add-local-object/Macro_1.scala index d02ee7600194..6f6e11e7361c 100644 --- a/tests/run-macros/annot-add-local-object/Macro_1.scala +++ b/tests/run-macros/annot-add-local-object/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable diff --git a/tests/run-macros/annot-add-local-object/Test_2.scala b/tests/run-macros/annot-add-local-object/Test_2.scala index a7f6d74a02e2..0ff7862fb338 100644 --- a/tests/run-macros/annot-add-local-object/Test_2.scala +++ b/tests/run-macros/annot-add-local-object/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @main def Test(): Unit = @addClass def foo(): Unit = println("macro generated main") diff --git a/tests/run-macros/annot-add-nested-class/Macro_1.scala b/tests/run-macros/annot-add-nested-class/Macro_1.scala index 2edbe5e48cd3..e13e3841501a 100644 --- a/tests/run-macros/annot-add-nested-class/Macro_1.scala +++ b/tests/run-macros/annot-add-nested-class/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable diff --git a/tests/run-macros/annot-add-nested-class/Test_2.scala b/tests/run-macros/annot-add-nested-class/Test_2.scala index f363cf58c3a4..b92225b7f107 100644 --- a/tests/run-macros/annot-add-nested-class/Test_2.scala +++ b/tests/run-macros/annot-add-nested-class/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + class Foo(): @addClass def foo(): Unit = println("macro generated main") diff --git a/tests/run-macros/annot-add-nested-object/Macro_1.scala b/tests/run-macros/annot-add-nested-object/Macro_1.scala index e10455e88678..f8cde8de5bf0 100644 --- a/tests/run-macros/annot-add-nested-object/Macro_1.scala +++ b/tests/run-macros/annot-add-nested-object/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable diff --git a/tests/run-macros/annot-add-nested-object/Test_2.scala b/tests/run-macros/annot-add-nested-object/Test_2.scala index 2bf54d73d0e6..cf6b3a8400fe 100644 --- a/tests/run-macros/annot-add-nested-object/Test_2.scala +++ b/tests/run-macros/annot-add-nested-object/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + class Foo(): @addClass def foo(): Unit = println("macro generated main") diff --git a/tests/run-macros/annot-annot-order/Macro_1.scala b/tests/run-macros/annot-annot-order/Macro_1.scala index 0e1e71488aae..9d3e8e40c01a 100644 --- a/tests/run-macros/annot-annot-order/Macro_1.scala +++ b/tests/run-macros/annot-annot-order/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ diff --git a/tests/run-macros/annot-annot-order/Test_2.scala b/tests/run-macros/annot-annot-order/Test_2.scala index a112c0a2e096..2c073bdcbb7b 100644 --- a/tests/run-macros/annot-annot-order/Test_2.scala +++ b/tests/run-macros/annot-annot-order/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @print("foo") def foo(): Unit = () diff --git a/tests/run-macros/annot-bind/Macro_1.scala b/tests/run-macros/annot-bind/Macro_1.scala index a0aa69ca356f..0997f35ccf4a 100644 --- a/tests/run-macros/annot-bind/Macro_1.scala +++ b/tests/run-macros/annot-bind/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ diff --git a/tests/run-macros/annot-bind/Test_2.scala b/tests/run-macros/annot-bind/Test_2.scala index e30ead520721..60895adabc24 100644 --- a/tests/run-macros/annot-bind/Test_2.scala +++ b/tests/run-macros/annot-bind/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @bind("a") val foo: String = "foo" diff --git a/tests/run-macros/annot-changeVal/Macro_1.scala b/tests/run-macros/annot-changeVal/Macro_1.scala index 8f865afade5b..d55282f8c390 100644 --- a/tests/run-macros/annot-changeVal/Macro_1.scala +++ b/tests/run-macros/annot-changeVal/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.experimental import scala.quoted.* import scala.annotation.MacroAnnotation diff --git a/tests/run-macros/annot-changeVal/Test_2.scala b/tests/run-macros/annot-changeVal/Test_2.scala index 6e0e44ad8885..8e048e885651 100644 --- a/tests/run-macros/annot-changeVal/Test_2.scala +++ b/tests/run-macros/annot-changeVal/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import ChangeVal._ class Bar: diff --git a/tests/run-macros/annot-concrete-class/Macro_1.scala b/tests/run-macros/annot-concrete-class/Macro_1.scala index 54d1bc7c20ce..e91f9c1ccafe 100644 --- a/tests/run-macros/annot-concrete-class/Macro_1.scala +++ b/tests/run-macros/annot-concrete-class/Macro_1.scala @@ -1,16 +1,18 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.MacroAnnotation import scala.quoted.* class implementAFoo extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = import quotes.reflect.* tree match - case ClassDef(name, cstr, parents, self, body) => + case ClassDef(name, cstr, parents, self, body) => val owner = tree.symbol val sym = Symbol.newMethod(tree.symbol, "foo", ByNameType.apply(TypeRepr.of[String])) val mtd = DefDef.apply(sym, _ => Some(Literal(StringConstant("Hello, I was added by a MacroAnnotation and without being defined in the class.")))) List(ClassDef.copy(tree)(name, cstr, parents, self, mtd :: body)) case _ => report.errorAndAbort(s"@implementAFoo can only be applied to classes that extend AFoo") - + end implementAFoo diff --git a/tests/run-macros/annot-concrete-class/Test_2.scala b/tests/run-macros/annot-concrete-class/Test_2.scala index 713b0d814813..7b8fc5cd0f94 100644 --- a/tests/run-macros/annot-concrete-class/Test_2.scala +++ b/tests/run-macros/annot-concrete-class/Test_2.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental trait AFoo: def foo: String @@ -5,7 +6,6 @@ trait AFoo: @implementAFoo class Foo extends AFoo -@main def Test = +@main def Test = val foo = new Foo println(foo.foo) - \ No newline at end of file diff --git a/tests/run-macros/annot-export/Macro_1.scala b/tests/run-macros/annot-export/Macro_1.scala index 9a8267bfae4b..fbe97684079b 100644 --- a/tests/run-macros/annot-export/Macro_1.scala +++ b/tests/run-macros/annot-export/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable.Map diff --git a/tests/run-macros/annot-export/Test_2.scala b/tests/run-macros/annot-export/Test_2.scala index abae5716bc5d..86bbee9c93fd 100644 --- a/tests/run-macros/annot-export/Test_2.scala +++ b/tests/run-macros/annot-export/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + object Bar: @returnClassName def f(): String = ??? // def f(): String = "Bar" diff --git a/tests/run-macros/annot-gen2/Macro_1.scala b/tests/run-macros/annot-gen2/Macro_1.scala index 169dda5eec0f..05428aac7375 100644 --- a/tests/run-macros/annot-gen2/Macro_1.scala +++ b/tests/run-macros/annot-gen2/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ diff --git a/tests/run-macros/annot-gen2/Macro_2.scala b/tests/run-macros/annot-gen2/Macro_2.scala index 4182caf8113e..3e2e228abb3e 100644 --- a/tests/run-macros/annot-gen2/Macro_2.scala +++ b/tests/run-macros/annot-gen2/Macro_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ diff --git a/tests/run-macros/annot-gen2/Test_3.scala b/tests/run-macros/annot-gen2/Test_3.scala index 1a7ca80f6479..08abafdb2741 100644 --- a/tests/run-macros/annot-gen2/Test_3.scala +++ b/tests/run-macros/annot-gen2/Test_3.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + class Bar: @foo def bar(s: String) = s diff --git a/tests/run-macros/annot-generate/Macro_1.scala b/tests/run-macros/annot-generate/Macro_1.scala index 8679edcfc0c3..b88cc62afb06 100644 --- a/tests/run-macros/annot-generate/Macro_1.scala +++ b/tests/run-macros/annot-generate/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ diff --git a/tests/run-macros/annot-generate/Macro_2.scala b/tests/run-macros/annot-generate/Macro_2.scala index b37f62f70da5..911625eac645 100644 --- a/tests/run-macros/annot-generate/Macro_2.scala +++ b/tests/run-macros/annot-generate/Macro_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ diff --git a/tests/run-macros/annot-generate/Test_3.scala b/tests/run-macros/annot-generate/Test_3.scala index 7077fd544111..591b3e864f31 100644 --- a/tests/run-macros/annot-generate/Test_3.scala +++ b/tests/run-macros/annot-generate/Test_3.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + class Bar: @foo def bar(x: Int) = x + 1 diff --git a/tests/run-macros/annot-macro-main/Macro_1.scala b/tests/run-macros/annot-macro-main/Macro_1.scala index 0de1a69f81a5..2a585bee2bc1 100644 --- a/tests/run-macros/annot-macro-main/Macro_1.scala +++ b/tests/run-macros/annot-macro-main/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable diff --git a/tests/run-macros/annot-macro-main/Test_2.scala b/tests/run-macros/annot-macro-main/Test_2.scala index cdf7f6fd78da..a6733ec1c220 100644 --- a/tests/run-macros/annot-macro-main/Test_2.scala +++ b/tests/run-macros/annot-macro-main/Test_2.scala @@ -1 +1,3 @@ +//> using options -experimental -Yno-experimental + @mainMacro def Test(): Unit = println("macro generated main") diff --git a/tests/run-macros/annot-memo/Macro_1.scala b/tests/run-macros/annot-memo/Macro_1.scala index 5672bd6358c1..c18260cc0f95 100644 --- a/tests/run-macros/annot-memo/Macro_1.scala +++ b/tests/run-macros/annot-memo/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable diff --git a/tests/run-macros/annot-memo/Test_2.scala b/tests/run-macros/annot-memo/Test_2.scala index 10afee3fa8bc..da58e550adda 100644 --- a/tests/run-macros/annot-memo/Test_2.scala +++ b/tests/run-macros/annot-memo/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + class Bar: @memoize def fib(n: Int): Int = diff --git a/tests/run-macros/annot-mod-class-add-def/Macro_1.scala b/tests/run-macros/annot-mod-class-add-def/Macro_1.scala index cec3a60350bc..855dce06f279 100644 --- a/tests/run-macros/annot-mod-class-add-def/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-add-def/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable diff --git a/tests/run-macros/annot-mod-class-add-def/Test_2.scala b/tests/run-macros/annot-mod-class-add-def/Test_2.scala index 05596baee900..d6aae4e90cf3 100644 --- a/tests/run-macros/annot-mod-class-add-def/Test_2.scala +++ b/tests/run-macros/annot-mod-class-add-def/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @addIndirectToString("This is Foo") class Foo //> private def string$macro$1: String = "This is Foo" diff --git a/tests/run-macros/annot-mod-class-add-inner-class/Macro_1.scala b/tests/run-macros/annot-mod-class-add-inner-class/Macro_1.scala index cb98fc75ea74..395bfd7a28db 100644 --- a/tests/run-macros/annot-mod-class-add-inner-class/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-add-inner-class/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable diff --git a/tests/run-macros/annot-mod-class-add-inner-class/Test_2.scala b/tests/run-macros/annot-mod-class-add-inner-class/Test_2.scala index d06d13c439e6..b90d237b60d4 100644 --- a/tests/run-macros/annot-mod-class-add-inner-class/Test_2.scala +++ b/tests/run-macros/annot-mod-class-add-inner-class/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @addInnerClass class Foo //> class Show: diff --git a/tests/run-macros/annot-mod-class-add-lazy-val/Macro_1.scala b/tests/run-macros/annot-mod-class-add-lazy-val/Macro_1.scala index ff2f67a41bab..f72f28b610d6 100644 --- a/tests/run-macros/annot-mod-class-add-lazy-val/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-add-lazy-val/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable diff --git a/tests/run-macros/annot-mod-class-add-lazy-val/Test_2.scala b/tests/run-macros/annot-mod-class-add-lazy-val/Test_2.scala index 657b40b42fc8..5aa0601e037e 100644 --- a/tests/run-macros/annot-mod-class-add-lazy-val/Test_2.scala +++ b/tests/run-macros/annot-mod-class-add-lazy-val/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @addMemoToString("This is Foo") class Foo //> private lazy val string$macro$1: String = "This is Foo" diff --git a/tests/run-macros/annot-mod-class-add-local-class/Macro_1.scala b/tests/run-macros/annot-mod-class-add-local-class/Macro_1.scala index e9a1baec44bd..0156812adeb1 100644 --- a/tests/run-macros/annot-mod-class-add-local-class/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-add-local-class/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable diff --git a/tests/run-macros/annot-mod-class-add-local-class/Test_2.scala b/tests/run-macros/annot-mod-class-add-local-class/Test_2.scala index 60aa28ffaf2a..db4c975992d0 100644 --- a/tests/run-macros/annot-mod-class-add-local-class/Test_2.scala +++ b/tests/run-macros/annot-mod-class-add-local-class/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @addInnerClass class Foo //> def toString(): String = diff --git a/tests/run-macros/annot-mod-class-add-val/Macro_1.scala b/tests/run-macros/annot-mod-class-add-val/Macro_1.scala index 34b7cd879abe..fc0294dcb051 100644 --- a/tests/run-macros/annot-mod-class-add-val/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-add-val/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable diff --git a/tests/run-macros/annot-mod-class-add-val/Test_2.scala b/tests/run-macros/annot-mod-class-add-val/Test_2.scala index 40816f5c8c84..f6ea732f3084 100644 --- a/tests/run-macros/annot-mod-class-add-val/Test_2.scala +++ b/tests/run-macros/annot-mod-class-add-val/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @addMemoToString("This is Foo") class Foo //> private val string$macro$1: String = "This is Foo" diff --git a/tests/run-macros/annot-mod-class-add-var/Macro_1.scala b/tests/run-macros/annot-mod-class-add-var/Macro_1.scala index d1cc26102ff3..be38689613e7 100644 --- a/tests/run-macros/annot-mod-class-add-var/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-add-var/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable diff --git a/tests/run-macros/annot-mod-class-add-var/Test_2.scala b/tests/run-macros/annot-mod-class-add-var/Test_2.scala index 5058e826b863..c2ee86fbced5 100644 --- a/tests/run-macros/annot-mod-class-add-var/Test_2.scala +++ b/tests/run-macros/annot-mod-class-add-var/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @addCountToString("This is Foo: ") class Foo: //> private var count$macro$1: Int = 0 diff --git a/tests/run-macros/annot-mod-class-data/Macro_1.scala b/tests/run-macros/annot-mod-class-data/Macro_1.scala index 05f63165e1b6..a175eb274268 100644 --- a/tests/run-macros/annot-mod-class-data/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-data/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted.* diff --git a/tests/run-macros/annot-mod-class-data/Test_2.scala b/tests/run-macros/annot-mod-class-data/Test_2.scala index 23e5191a3aeb..5def49c2daf8 100644 --- a/tests/run-macros/annot-mod-class-data/Test_2.scala +++ b/tests/run-macros/annot-mod-class-data/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @data class Foo(val a: String, val b: Int) //> override def toString(): String = Seq(this.a, this.b).mkString("Foo(", ", ", ")") //> override def equals(that: Any): Boolean = diff --git a/tests/run-macros/annot-mod-class-equals/Macro_1.scala b/tests/run-macros/annot-mod-class-equals/Macro_1.scala index 3527ec3289c6..10184eada1e2 100644 --- a/tests/run-macros/annot-mod-class-equals/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-equals/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted.* diff --git a/tests/run-macros/annot-mod-class-equals/Test_2.scala b/tests/run-macros/annot-mod-class-equals/Test_2.scala index a4b3b406c4ce..1e5287743c8b 100644 --- a/tests/run-macros/annot-mod-class-equals/Test_2.scala +++ b/tests/run-macros/annot-mod-class-equals/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @equals class Foo(val a: String, val b: Int) //> override def equals(that: Any): Boolean = //> that match diff --git a/tests/run-macros/annot-mod-class-mod-def/Macro_1.scala b/tests/run-macros/annot-mod-class-mod-def/Macro_1.scala index 98fc91f31322..7a73b0a773e9 100644 --- a/tests/run-macros/annot-mod-class-mod-def/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-mod-def/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable diff --git a/tests/run-macros/annot-mod-class-mod-def/Test_2.scala b/tests/run-macros/annot-mod-class-mod-def/Test_2.scala index 7e5da4d7b31d..b0f2b4531986 100644 --- a/tests/run-macros/annot-mod-class-mod-def/Test_2.scala +++ b/tests/run-macros/annot-mod-class-mod-def/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @modToString("This is Foo") class Foo: override def toString(): String = "?" //> override def toString(): String = "This is Foo" diff --git a/tests/run-macros/annot-mod-class-mod-val/Macro_1.scala b/tests/run-macros/annot-mod-class-mod-val/Macro_1.scala index 036703a8a374..fda7b5f037d8 100644 --- a/tests/run-macros/annot-mod-class-mod-val/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-mod-val/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable diff --git a/tests/run-macros/annot-mod-class-mod-val/Test_2.scala b/tests/run-macros/annot-mod-class-mod-val/Test_2.scala index d75138f0dc41..862977e2aa31 100644 --- a/tests/run-macros/annot-mod-class-mod-val/Test_2.scala +++ b/tests/run-macros/annot-mod-class-mod-val/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @setValue("valDef", "a") @setValue("varDef", "b") @setValue("lazyVarDef", "c") diff --git a/tests/run-macros/annot-mod-class-override-def/Macro_1.scala b/tests/run-macros/annot-mod-class-override-def/Macro_1.scala index 7d591a39b091..e6d7bba79d54 100644 --- a/tests/run-macros/annot-mod-class-override-def/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-override-def/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable diff --git a/tests/run-macros/annot-mod-class-override-def/Test_2.scala b/tests/run-macros/annot-mod-class-override-def/Test_2.scala index 0fca75ba9d6a..8c6121664208 100644 --- a/tests/run-macros/annot-mod-class-override-def/Test_2.scala +++ b/tests/run-macros/annot-mod-class-override-def/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @genToString("This is Foo") class Foo //> override def toString(): String = "This is Foo" diff --git a/tests/run-macros/annot-mod-class-override-val/Macro_1.scala b/tests/run-macros/annot-mod-class-override-val/Macro_1.scala index c64e06686fa0..d7409a649427 100644 --- a/tests/run-macros/annot-mod-class-override-val/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-override-val/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable diff --git a/tests/run-macros/annot-mod-class-override-val/Test_2.scala b/tests/run-macros/annot-mod-class-override-val/Test_2.scala index 52d56723980d..f067ba678af8 100644 --- a/tests/run-macros/annot-mod-class-override-val/Test_2.scala +++ b/tests/run-macros/annot-mod-class-override-val/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + class Foo: val val1: String = "?" def def1: String = "?" diff --git a/tests/run-macros/annot-mod-class-unused-new-sym/Macro_1.scala b/tests/run-macros/annot-mod-class-unused-new-sym/Macro_1.scala index 0da1e4106e8e..fbcb9049d947 100644 --- a/tests/run-macros/annot-mod-class-unused-new-sym/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-unused-new-sym/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable diff --git a/tests/run-macros/annot-mod-class-unused-new-sym/Test_2.scala b/tests/run-macros/annot-mod-class-unused-new-sym/Test_2.scala index dd93d0df2917..340b7503ff71 100644 --- a/tests/run-macros/annot-mod-class-unused-new-sym/Test_2.scala +++ b/tests/run-macros/annot-mod-class-unused-new-sym/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @newUnusedSymbol class Foo diff --git a/tests/run-macros/annot-result-order/Macro_1.scala b/tests/run-macros/annot-result-order/Macro_1.scala index 5976e27965ef..c81641037b67 100644 --- a/tests/run-macros/annot-result-order/Macro_1.scala +++ b/tests/run-macros/annot-result-order/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ diff --git a/tests/run-macros/annot-result-order/Test_2.scala b/tests/run-macros/annot-result-order/Test_2.scala index fce105f3cc6c..06b050d11c29 100644 --- a/tests/run-macros/annot-result-order/Test_2.scala +++ b/tests/run-macros/annot-result-order/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @print("foo") def foo(): Unit = () diff --git a/tests/run-macros/annot-simple-fib/Macro_1.scala b/tests/run-macros/annot-simple-fib/Macro_1.scala index 1740f922b63e..e5852d5ce73c 100644 --- a/tests/run-macros/annot-simple-fib/Macro_1.scala +++ b/tests/run-macros/annot-simple-fib/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ import scala.collection.mutable.Map diff --git a/tests/run-macros/annot-simple-fib/Test_2.scala b/tests/run-macros/annot-simple-fib/Test_2.scala index 7e22982553ac..534f4569b619 100644 --- a/tests/run-macros/annot-simple-fib/Test_2.scala +++ b/tests/run-macros/annot-simple-fib/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + class Bar: @memoize def fib(n: Int): Int = diff --git a/tests/run-macros/i11685/Macro_1.scala b/tests/run-macros/i11685/Macro_1.scala index 08920854a813..72965266dddd 100644 --- a/tests/run-macros/i11685/Macro_1.scala +++ b/tests/run-macros/i11685/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + package test import scala.quoted.* diff --git a/tests/run-macros/i11685/Test_2.scala b/tests/run-macros/i11685/Test_2.scala index f8531376dcd8..eaab3af7acb5 100644 --- a/tests/run-macros/i11685/Test_2.scala +++ b/tests/run-macros/i11685/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import test.MyMacro trait Command { diff --git a/tests/run-macros/i16734b/Macro_1.scala b/tests/run-macros/i16734b/Macro_1.scala index f1e8e12d308d..e080193c398a 100644 --- a/tests/run-macros/i16734b/Macro_1.scala +++ b/tests/run-macros/i16734b/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.quoted.* inline def typeVariances[A <: AnyKind]: String = diff --git a/tests/run-macros/i16734b/Test_2.scala b/tests/run-macros/i16734b/Test_2.scala index f5481aaf96cf..81316875d561 100644 --- a/tests/run-macros/i16734b/Test_2.scala +++ b/tests/run-macros/i16734b/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + type F1Inv[A] type F1Cov[+A] type F1Con[-A] diff --git a/tests/run-macros/newClass/Macro_1.scala b/tests/run-macros/newClass/Macro_1.scala index e7ae59c5331b..75f757c038dc 100644 --- a/tests/run-macros/newClass/Macro_1.scala +++ b/tests/run-macros/newClass/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.quoted.* inline def makeClass(inline name: String): Any = ${ makeClassExpr('name) } diff --git a/tests/run-macros/newClass/Test_2.scala b/tests/run-macros/newClass/Test_2.scala index 6868674547fe..b126e90a5e41 100644 --- a/tests/run-macros/newClass/Test_2.scala +++ b/tests/run-macros/newClass/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @main def Test: Unit = { val foo = makeClass("foo") println(foo.getClass) diff --git a/tests/run-macros/newClassExtends/Macro_1.scala b/tests/run-macros/newClassExtends/Macro_1.scala index 99f639158761..d23b8fba88b6 100644 --- a/tests/run-macros/newClassExtends/Macro_1.scala +++ b/tests/run-macros/newClassExtends/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.quoted.* inline def makeClass(inline name: String): Foo = ${ makeClassExpr('name) } diff --git a/tests/run-macros/newClassExtends/Test_2.scala b/tests/run-macros/newClassExtends/Test_2.scala index 1db791749bab..8d782e346a68 100644 --- a/tests/run-macros/newClassExtends/Test_2.scala +++ b/tests/run-macros/newClassExtends/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @main def Test: Unit = { val foo: Foo = makeClass("foo") foo.foo() diff --git a/tests/run-macros/newClassExtendsClassParams/Macro_1.scala b/tests/run-macros/newClassExtendsClassParams/Macro_1.scala index f6eebc9487e5..e5d28c0ceb9b 100644 --- a/tests/run-macros/newClassExtendsClassParams/Macro_1.scala +++ b/tests/run-macros/newClassExtendsClassParams/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.quoted.* inline def makeClass(inline name: String): Foo = ${ makeClassExpr('name) } diff --git a/tests/run-macros/newClassExtendsClassParams/Test_2.scala b/tests/run-macros/newClassExtendsClassParams/Test_2.scala index 1db791749bab..8d782e346a68 100644 --- a/tests/run-macros/newClassExtendsClassParams/Test_2.scala +++ b/tests/run-macros/newClassExtendsClassParams/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @main def Test: Unit = { val foo: Foo = makeClass("foo") foo.foo() diff --git a/tests/run-macros/newClassSelf/Macro_1.scala b/tests/run-macros/newClassSelf/Macro_1.scala index 864015c896f0..46871d4d6b4c 100644 --- a/tests/run-macros/newClassSelf/Macro_1.scala +++ b/tests/run-macros/newClassSelf/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.quoted.* inline def makeClass(inline name: String): Bar = ${ makeClassExpr('name) } diff --git a/tests/run-macros/newClassSelf/Test_2.scala b/tests/run-macros/newClassSelf/Test_2.scala index 0c6d522de58f..437be3ca519d 100644 --- a/tests/run-macros/newClassSelf/Test_2.scala +++ b/tests/run-macros/newClassSelf/Test_2.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + @main def Test: Unit = { val a: Bar = makeClass("A") a.bar() diff --git a/tests/run/main-annotation-birthday.scala b/tests/run/main-annotation-birthday.scala index 563bb2628e62..32cf28784ced 100644 --- a/tests/run/main-annotation-birthday.scala +++ b/tests/run/main-annotation-birthday.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-dash-dash.scala b/tests/run/main-annotation-dash-dash.scala index bf4a1a4e238c..3fe0f47983d5 100644 --- a/tests/run/main-annotation-dash-dash.scala +++ b/tests/run/main-annotation-dash-dash.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-default-value-1.scala b/tests/run/main-annotation-default-value-1.scala index 40888c947bb6..cf4ba79e1aff 100644 --- a/tests/run/main-annotation-default-value-1.scala +++ b/tests/run/main-annotation-default-value-1.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-default-value-2.scala b/tests/run/main-annotation-default-value-2.scala index 76ee1bb5cc9f..8b60e6197405 100644 --- a/tests/run/main-annotation-default-value-2.scala +++ b/tests/run/main-annotation-default-value-2.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-example.scala b/tests/run/main-annotation-example.scala index 478ab6baeb4b..926496e595e7 100644 --- a/tests/run/main-annotation-example.scala +++ b/tests/run/main-annotation-example.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.* diff --git a/tests/run/main-annotation-flags.scala b/tests/run/main-annotation-flags.scala index 7e502585489d..8a579e6e2d00 100644 --- a/tests/run/main-annotation-flags.scala +++ b/tests/run/main-annotation-flags.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-help-override.scala b/tests/run/main-annotation-help-override.scala index d174e13ac891..bfff85c5a353 100644 --- a/tests/run/main-annotation-help-override.scala +++ b/tests/run/main-annotation-help-override.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-help.scala b/tests/run/main-annotation-help.scala index e7fdf7c362de..d68bb0d7e874 100644 --- a/tests/run/main-annotation-help.scala +++ b/tests/run/main-annotation-help.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-homemade-annot-1.scala b/tests/run/main-annotation-homemade-annot-1.scala index 3caa2c7e6b00..3106dae4006f 100644 --- a/tests/run/main-annotation-homemade-annot-1.scala +++ b/tests/run/main-annotation-homemade-annot-1.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.concurrent._ diff --git a/tests/run/main-annotation-homemade-annot-2.scala b/tests/run/main-annotation-homemade-annot-2.scala index a131aa336d47..980241ff93d3 100644 --- a/tests/run/main-annotation-homemade-annot-2.scala +++ b/tests/run/main-annotation-homemade-annot-2.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.collection.mutable diff --git a/tests/run/main-annotation-homemade-annot-3.scala b/tests/run/main-annotation-homemade-annot-3.scala index d024ba300665..4a894777c562 100644 --- a/tests/run/main-annotation-homemade-annot-3.scala +++ b/tests/run/main-annotation-homemade-annot-3.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.* diff --git a/tests/run/main-annotation-homemade-annot-4.scala b/tests/run/main-annotation-homemade-annot-4.scala index b4ea510aa677..b50e89523475 100644 --- a/tests/run/main-annotation-homemade-annot-4.scala +++ b/tests/run/main-annotation-homemade-annot-4.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.* diff --git a/tests/run/main-annotation-homemade-annot-5.scala b/tests/run/main-annotation-homemade-annot-5.scala index fc5e34e41d6c..a129a51da7eb 100644 --- a/tests/run/main-annotation-homemade-annot-5.scala +++ b/tests/run/main-annotation-homemade-annot-5.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.* diff --git a/tests/run/main-annotation-homemade-annot-6.scala b/tests/run/main-annotation-homemade-annot-6.scala index 39d258803901..5a92e6382d3d 100644 --- a/tests/run/main-annotation-homemade-annot-6.scala +++ b/tests/run/main-annotation-homemade-annot-6.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.* diff --git a/tests/run/main-annotation-homemade-parser-1.scala b/tests/run/main-annotation-homemade-parser-1.scala index be2adc4a5f72..94d43bf19cc5 100644 --- a/tests/run/main-annotation-homemade-parser-1.scala +++ b/tests/run/main-annotation-homemade-parser-1.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-homemade-parser-2.scala b/tests/run/main-annotation-homemade-parser-2.scala index 1a51400d9f37..4f40f9b42b27 100644 --- a/tests/run/main-annotation-homemade-parser-2.scala +++ b/tests/run/main-annotation-homemade-parser-2.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-homemade-parser-3.scala b/tests/run/main-annotation-homemade-parser-3.scala index 1e5a4c0dae00..066e40f1b3a0 100644 --- a/tests/run/main-annotation-homemade-parser-3.scala +++ b/tests/run/main-annotation-homemade-parser-3.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-homemade-parser-4.scala b/tests/run/main-annotation-homemade-parser-4.scala index fc087354c16e..668aa040380c 100644 --- a/tests/run/main-annotation-homemade-parser-4.scala +++ b/tests/run/main-annotation-homemade-parser-4.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-homemade-parser-5.scala b/tests/run/main-annotation-homemade-parser-5.scala index f7443f34cab3..123631312ef7 100644 --- a/tests/run/main-annotation-homemade-parser-5.scala +++ b/tests/run/main-annotation-homemade-parser-5.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-multiple.scala b/tests/run/main-annotation-multiple.scala index 62a5fa04cc18..dbc66d0df9ca 100644 --- a/tests/run/main-annotation-multiple.scala +++ b/tests/run/main-annotation-multiple.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-named-params.scala b/tests/run/main-annotation-named-params.scala index 8d677d65978d..4cfa2c8049b4 100644 --- a/tests/run/main-annotation-named-params.scala +++ b/tests/run/main-annotation-named-params.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-newMain.scala b/tests/run/main-annotation-newMain.scala index a28e9d2ab96a..5b00a46ce7e9 100644 --- a/tests/run/main-annotation-newMain.scala +++ b/tests/run/main-annotation-newMain.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.* diff --git a/tests/run/main-annotation-no-parameters-no-parens.scala b/tests/run/main-annotation-no-parameters-no-parens.scala index 7ba87c82c745..b62fd55538de 100644 --- a/tests/run/main-annotation-no-parameters-no-parens.scala +++ b/tests/run/main-annotation-no-parameters-no-parens.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-no-parameters.scala b/tests/run/main-annotation-no-parameters.scala index 951254f07bf7..fc92a5680e07 100644 --- a/tests/run/main-annotation-no-parameters.scala +++ b/tests/run/main-annotation-no-parameters.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-overload.scala b/tests/run/main-annotation-overload.scala index 939f2044f227..60f9b68a58a2 100644 --- a/tests/run/main-annotation-overload.scala +++ b/tests/run/main-annotation-overload.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-param-annot-1.scala b/tests/run/main-annotation-param-annot-1.scala index d16e4fac8848..5cf29b9f4efb 100644 --- a/tests/run/main-annotation-param-annot-1.scala +++ b/tests/run/main-annotation-param-annot-1.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-param-annot-2.scala b/tests/run/main-annotation-param-annot-2.scala index 0ee99038910a..76033f24e614 100644 --- a/tests/run/main-annotation-param-annot-2.scala +++ b/tests/run/main-annotation-param-annot-2.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-param-annot-invalid-params.scala b/tests/run/main-annotation-param-annot-invalid-params.scala index 076c7ff80750..46bc812863b1 100644 --- a/tests/run/main-annotation-param-annot-invalid-params.scala +++ b/tests/run/main-annotation-param-annot-invalid-params.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-return-type-1.scala b/tests/run/main-annotation-return-type-1.scala index 641786661613..1366cceeba8a 100644 --- a/tests/run/main-annotation-return-type-1.scala +++ b/tests/run/main-annotation-return-type-1.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-return-type-2.scala b/tests/run/main-annotation-return-type-2.scala index 986c1f0eae94..e2dc6b8ae4e6 100644 --- a/tests/run/main-annotation-return-type-2.scala +++ b/tests/run/main-annotation-return-type-2.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-short-name.scala b/tests/run/main-annotation-short-name.scala index 72e37acdce5c..4a179fb793e1 100644 --- a/tests/run/main-annotation-short-name.scala +++ b/tests/run/main-annotation-short-name.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-simple.scala b/tests/run/main-annotation-simple.scala index 47407c85e36c..7d2fd501849b 100644 --- a/tests/run/main-annotation-simple.scala +++ b/tests/run/main-annotation-simple.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-top-level.scala b/tests/run/main-annotation-top-level.scala index 52ca42205d9e..3e2bb7bb2fb4 100644 --- a/tests/run/main-annotation-top-level.scala +++ b/tests/run/main-annotation-top-level.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-types.scala b/tests/run/main-annotation-types.scala index 249c9d010268..0ee6220a1196 100644 --- a/tests/run/main-annotation-types.scala +++ b/tests/run/main-annotation-types.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-vararg-1.scala b/tests/run/main-annotation-vararg-1.scala index a1b99cd5b150..0227054e0189 100644 --- a/tests/run/main-annotation-vararg-1.scala +++ b/tests/run/main-annotation-vararg-1.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-vararg-2.scala b/tests/run/main-annotation-vararg-2.scala index becb5958ad8e..8521795388b2 100644 --- a/tests/run/main-annotation-vararg-2.scala +++ b/tests/run/main-annotation-vararg-2.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-wrong-param-1.scala b/tests/run/main-annotation-wrong-param-1.scala index ef6ada37b9e3..6c9e9e991136 100644 --- a/tests/run/main-annotation-wrong-param-1.scala +++ b/tests/run/main-annotation-wrong-param-1.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-wrong-param-names.scala b/tests/run/main-annotation-wrong-param-names.scala index c428c955b5cd..90622d543bf1 100644 --- a/tests/run/main-annotation-wrong-param-names.scala +++ b/tests/run/main-annotation-wrong-param-names.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-wrong-param-number.scala b/tests/run/main-annotation-wrong-param-number.scala index e607a85e4dc2..b8ef8c0ea9e7 100644 --- a/tests/run/main-annotation-wrong-param-number.scala +++ b/tests/run/main-annotation-wrong-param-number.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-annotation-wrong-param-type.scala b/tests/run/main-annotation-wrong-param-type.scala index 2228a8faf7df..0fbae70a48a5 100644 --- a/tests/run/main-annotation-wrong-param-type.scala +++ b/tests/run/main-annotation-wrong-param-type.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip import scala.annotation.newMain diff --git a/tests/run/main-calculator-example.scala b/tests/run/main-calculator-example.scala index 857792f11967..fc2e1397009b 100644 --- a/tests/run/main-calculator-example.scala +++ b/tests/run/main-calculator-example.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental // scalajs: --skip sealed trait Expression: @@ -23,7 +24,7 @@ import scala.annotation.{ MainAnnotation, experimental } import scala.annotation.MainAnnotation.{ Info, Parameter } import scala.util.CommandLineParser.FromString -@experimental class showAndEval extends MainAnnotation[FromString, Expression]: +class showAndEval extends MainAnnotation[FromString, Expression]: def command(info: Info, args: Seq[String]): Option[Seq[String]] = assert(info.parameters.forall(param => param.typeName == "Number"), "Only Number parameters allowed") println(s"executing ${info.name} with inputs: ${args.mkString(" ")}") diff --git a/tests/run/tupled-function-andThen.scala b/tests/run/tupled-function-andThen.scala index 94236e9267e1..0068143f9d3f 100644 --- a/tests/run/tupled-function-andThen.scala +++ b/tests/run/tupled-function-andThen.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.util.TupledFunction object Test { diff --git a/tests/run/tupled-function-apply.scala b/tests/run/tupled-function-apply.scala index 7d2162a565ac..69cfeef91dd1 100644 --- a/tests/run/tupled-function-apply.scala +++ b/tests/run/tupled-function-apply.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.util.TupledFunction object Test { diff --git a/tests/run/tupled-function-compose.scala b/tests/run/tupled-function-compose.scala index 4cf83563274d..d984b8a9184a 100644 --- a/tests/run/tupled-function-compose.scala +++ b/tests/run/tupled-function-compose.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.util.TupledFunction object Test { def main(args: Array[String]): Unit = { diff --git a/tests/run/tupled-function-extension-method.scala b/tests/run/tupled-function-extension-method.scala index be5ccbd5ca17..fc3319aa4c15 100644 --- a/tests/run/tupled-function-extension-method.scala +++ b/tests/run/tupled-function-extension-method.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.util.TupledFunction object Test { def main(args: Array[String]): Unit = { diff --git a/tests/run/tupled-function-tupled.scala b/tests/run/tupled-function-tupled.scala index 6e7d94b3ac3d..5a799be167c3 100644 --- a/tests/run/tupled-function-tupled.scala +++ b/tests/run/tupled-function-tupled.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.util.TupledFunction object Test { diff --git a/tests/run/tupled-function-untupled.scala b/tests/run/tupled-function-untupled.scala index e5e3d8c29c3a..34b81c74c4f6 100644 --- a/tests/run/tupled-function-untupled.scala +++ b/tests/run/tupled-function-untupled.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.util.TupledFunction object Test { def main(args: Array[String]): Unit = { From 55df3f3bf1a9ae18de681f4180a8fecda5ed06da Mon Sep 17 00:00:00 2001 From: Katarzyna Marek Date: Tue, 27 Feb 2024 12:50:21 +0100 Subject: [PATCH 144/277] bugfix: Auto imports in worksheets in Scala 3 --- .../src/main/dotty/tools/pc/AutoImports.scala | 40 +++++++---- .../tools/pc/base/BaseAutoImportsSuite.scala | 12 ++++ .../pc/tests/edit/AutoImportsSuite.scala | 68 +++++++++++++++++++ 3 files changed, 108 insertions(+), 12 deletions(-) diff --git a/presentation-compiler/src/main/dotty/tools/pc/AutoImports.scala b/presentation-compiler/src/main/dotty/tools/pc/AutoImports.scala index 0ccaec14927c..e86732c3453d 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/AutoImports.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/AutoImports.scala @@ -302,11 +302,24 @@ object AutoImports: }.headOption case _ => None - def skipUsingDirectivesOffset = + def firstMemberDefinitionStart(tree: Tree)(using Context): Option[Int] = + tree match + case PackageDef(_, stats) => + stats.flatMap { + case s: PackageDef => firstMemberDefinitionStart(s) + case stat if stat.span.exists => Some(stat.span.start) + case _ => None + }.headOption + case _ => None + + + def skipUsingDirectivesOffset( + firstObjectPos: Int = firstMemberDefinitionStart(tree).getOrElse(0) + ): Int = + val firstObjectLine = pos.source.offsetToLine(firstObjectPos) comments .takeWhile(comment => - !comment.isDocComment && comment.span.end < firstObjectBody(tree) - .fold(0)(_.span.start) + !comment.isDocComment && pos.source.offsetToLine(comment.span.end) + 1 < firstObjectLine ) .lastOption .fold(0)(_.span.end + 1) @@ -318,7 +331,7 @@ object AutoImports: val (lineNumber, padTop) = lastImportStatement match case Some(stm) => (stm.endPos.line + 1, false) case None if pkg.pid.symbol.isEmptyPackage => - (pos.source.offsetToLine(skipUsingDirectivesOffset), false) + (pos.source.offsetToLine(skipUsingDirectivesOffset()), false) case None => val pos = pkg.pid.endPos val line = @@ -330,7 +343,7 @@ object AutoImports: new AutoImportPosition(offset, text, padTop) } - def forScript(isAmmonite: Boolean): Option[AutoImportPosition] = + def forScript(path: String): Option[AutoImportPosition] = firstObjectBody(tree).map { tmpl => val lastImportStatement = tmpl.body.takeWhile(_.isInstanceOf[Import]).lastOption @@ -340,10 +353,11 @@ object AutoImports: offset case None => val scriptOffset = - if isAmmonite then - ScriptFirstImportPosition.ammoniteScStartOffset(text, comments) - else - ScriptFirstImportPosition.scalaCliScStartOffset(text, comments) + if path.isAmmoniteGeneratedFile + then ScriptFirstImportPosition.ammoniteScStartOffset(text, comments) + else if path.isScalaCLIGeneratedFile + then ScriptFirstImportPosition.scalaCliScStartOffset(text, comments) + else Some(skipUsingDirectivesOffset(tmpl.span.start)) scriptOffset.getOrElse { val tmplPoint = tmpl.self.srcPos.span.point @@ -359,14 +373,16 @@ object AutoImports: def fileStart = AutoImportPosition( - skipUsingDirectivesOffset, + skipUsingDirectivesOffset(), 0, padTop = false ) val scriptPos = - if path.isAmmoniteGeneratedFile then forScript(isAmmonite = true) - else if path.isScalaCLIGeneratedFile then forScript(isAmmonite = false) + if path.isAmmoniteGeneratedFile || + path.isScalaCLIGeneratedFile || + path.isWorksheet + then forScript(path) else None scriptPos diff --git a/presentation-compiler/test/dotty/tools/pc/base/BaseAutoImportsSuite.scala b/presentation-compiler/test/dotty/tools/pc/base/BaseAutoImportsSuite.scala index f2732c28e93a..ece4456a313a 100644 --- a/presentation-compiler/test/dotty/tools/pc/base/BaseAutoImportsSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/base/BaseAutoImportsSuite.scala @@ -41,6 +41,18 @@ trait BaseAutoImportsSuite extends BaseCodeActionSuite: selection ) + def checkWorksheetEdit( + original: String, + expected: String, + selection: Int = 0 + ): Unit = + checkEditSelection( + "example.worksheet.sc", + original, + expected, + selection + ) + def checkEditSelection( filename: String, original: String, diff --git a/presentation-compiler/test/dotty/tools/pc/tests/edit/AutoImportsSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/edit/AutoImportsSuite.scala index b355a2cf7735..a862df975d0b 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/edit/AutoImportsSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/edit/AutoImportsSuite.scala @@ -342,6 +342,69 @@ class AutoImportsSuite extends BaseAutoImportsSuite: ) ) + @Test def `worksheet-import` = + checkWorksheetEdit( + worksheetPcWrapper( + """|//> using scala 3.3.0 + | + |// Some comment + | + |// Object comment + |object A { + | val p: <> = ??? + |} + |""".stripMargin + ), + worksheetPcWrapper( + """|//> using scala 3.3.0 + | + |// Some comment + |import java.nio.file.Path + | + |// Object comment + |object A { + | val p: Path = ??? + |} + |""".stripMargin + ) + ) + + @Test def `object-import` = + checkEdit( + """|object A { + | //some comment + | val p: <> = ??? + |} + |""".stripMargin, + """|import java.nio.file.Path + |object A { + | //some comment + | val p: Path = ??? + |} + |""".stripMargin, + ) + + @Test def `toplevels-import` = + checkEdit( + """|//some comment + | + |val p: <> = ??? + | + |//some other comment + | + |val v = 1 + |""".stripMargin, + """|//some comment + |import java.nio.file.Path + | + |val p: Path = ??? + | + |//some other comment + | + |val v = 1 + |""".stripMargin, + ) + private def ammoniteWrapper(code: String): String = // Vaguely looks like a scala file that Ammonite generates // from a sc file. @@ -359,6 +422,11 @@ class AutoImportsSuite extends BaseAutoImportsSuite: |} |""".stripMargin + private def worksheetPcWrapper(code: String): String = + s"""|object worksheet{ + |$code + |}""".stripMargin + // https://dotty.epfl.ch/docs/internals/syntax.html#soft-keywords @Test def `soft-keyword-check-test` = From 2708c8c367a37fce87a655850908b10d766abb1c Mon Sep 17 00:00:00 2001 From: i10416 Date: Fri, 1 Mar 2024 01:41:24 +0900 Subject: [PATCH 145/277] fix(#19806): wrong tasty of scala module class reference This commit makes the following diff to TASTy for i17255 files. The TASTy before this commit relied on the compiler (aka all TASTy clients) intrinsically knowing how to resolve Module$ when the definition is actually Module[ModuleClass]. ```sh scalac tests/run/i17255/J.java tests/run/i17255/Module.scala -Yprint-tasty -Yjava-tasty ``` ```diff 90: EMPTYCLAUSE 91: TERMREF 17 [Module] 93: SHAREDtype 12 95: ELIDED 96: SHAREDtype 91 98: STATIC 99: DEFDEF(12) 18 [module] 102: EMPTYCLAUSE - 103: SELECTtpt 19 [Module$] + 103: SELECTtpt 19 [Module[ModuleClass]] 105: SHAREDtype 3 107: ELIDED 108: TYPEREF 17 [Module] 110: SHAREDtype 3 112: STATIC ``` --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 1f0adc9f1421..6d537ea62c7c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -688,7 +688,11 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer report.error(StableIdentPattern(tree, pt), tree.srcPos) def typedSelect(tree0: untpd.Select, pt: Type, qual: Tree)(using Context): Tree = - val selName = tree0.name + val selName = + if ctx.isJava && tree0.name.isTypeName && tree0.name.endsWith(StdNames.str.MODULE_SUFFIX) then + tree0.name.stripModuleClassSuffix.moduleClassName + else + tree0.name val tree = cpy.Select(tree0)(qual, selName) val superAccess = qual.isInstanceOf[Super] val rawType = selectionType(tree, qual) From ab1ab3cafbefc5401a149833b98bd97f223dd40f Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Thu, 29 Feb 2024 17:32:44 +0100 Subject: [PATCH 146/277] add test and better debug info in error message --- .../dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 11 ++++++++++- tests/pos/i19629.scala | 10 ++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i19629.scala diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index b95e4df663a1..57c0b2217e9d 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -65,6 +65,15 @@ class TreeUnpickler(reader: TastyReader, /** A map from addresses of definition entries to the symbols they define */ private val symAtAddr = new mutable.HashMap[Addr, Symbol] + private def addrOfSymbol(sym: Symbol): Option[Addr] = symAtAddr.iterator.collectFirst { + case (addr, s) if s == sym => addr + } + + private def locatedSymbol(sym: Symbol)(using Context): String = + addrOfSymbol(sym) match + case Some(addr) => i"local $sym @ ${addr.index}" + case None => i"external $sym" + /** A temporary map from addresses of definition entries to the trees they define. * Used to remember trees of symbols that are created by a completion. Emptied * once the tree is inlined into a larger tree. @@ -297,7 +306,7 @@ class TreeUnpickler(reader: TastyReader, /** The symbol defined by current definition */ def symbolAtCurrent()(using Context): Symbol = symAtAddr.get(currentAddr) match { case Some(sym) => - assert(ctx.owner == sym.owner, i"owner discrepancy for $sym, expected: ${ctx.owner}, found: ${sym.owner}") + assert(ctx.owner == sym.owner, i"owner discrepancy for ${locatedSymbol(sym)}, expected: ${locatedSymbol(ctx.owner)}, found: ${locatedSymbol(sym.owner)}") sym case None => createSymbol() diff --git a/tests/pos/i19629.scala b/tests/pos/i19629.scala new file mode 100644 index 000000000000..ec96e94e70dd --- /dev/null +++ b/tests/pos/i19629.scala @@ -0,0 +1,10 @@ +trait CP[A,B] +trait TypeEqK[F[_], G[_]] + +trait Knit[CP[_, _], F[_]] { + type Res + + def visit[R]( + caseInFst: [F1[_], Y] => (k: Knit[CP, F1]) => (ev: TypeEqK[F, [x] =>> CP[F1[x], Y]]) => R + ): R +} From 0d79122293f875ea2511654350c59e86f16039fe Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Fri, 1 Mar 2024 11:36:14 +0100 Subject: [PATCH 147/277] used derived types to type arguments of dependent function type --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 6 +++--- tests/run/i19629/Test_2.scala | 12 ++++++++++++ tests/run/i19629/lib_1.scala | 10 ++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 tests/run/i19629/Test_2.scala create mode 100644 tests/run/i19629/lib_1.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 1f0adc9f1421..9ef075f95e3a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1463,14 +1463,14 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer if isErasedClass then arg.withAddedFlags(Erased) else arg } return typedDependent(newParams) - val resTpt = TypeTree(mt.nonDependentResultApprox).withSpan(body.span) - val typeArgs = appDef.termParamss.head.map(_.tpt) :+ resTpt val core = if mt.hasErasedParams then TypeTree(defn.PolyFunctionClass.typeRef) else + val resTpt = TypeTree(mt.nonDependentResultApprox).withSpan(body.span) + val paramTpts = appDef.termParamss.head.map(p => TypeTree(p.tpt.tpe).withSpan(p.tpt.span)) val funSym = defn.FunctionSymbol(numArgs, isContextual, isImpure) val tycon = TypeTree(funSym.typeRef) - AppliedTypeTree(tycon, typeArgs) + AppliedTypeTree(tycon, paramTpts :+ resTpt) RefinedTypeTree(core, List(appDef), ctx.owner.asClass) end typedDependent diff --git a/tests/run/i19629/Test_2.scala b/tests/run/i19629/Test_2.scala new file mode 100644 index 000000000000..c9d1ee7f79e5 --- /dev/null +++ b/tests/run/i19629/Test_2.scala @@ -0,0 +1,12 @@ + +class Container[Y1, G[_]]: + lazy val outer: Knit[CP, G] = new: + type Res = Y1 + def visit[R](caseInFst: [F1[_], Y] => (k: Knit[CP, F1]) => (ev: TypeEqK[G, [x] =>> CP[F1[x], Y]]) => R): R = + caseInFst[G, Res](outer)(new TypeEqK[G, [x] =>> CP[G[x], Res]] {}) + +@main def Test = + val knit = new Container[Unit, Option].outer + val res = knit.visit: + [F1[_], Y] => (k: Knit[CP, F1]) => (ev: TypeEqK[Option, [x] =>> CP[F1[x], Y]]) => 42 + assert(res == 42) diff --git a/tests/run/i19629/lib_1.scala b/tests/run/i19629/lib_1.scala new file mode 100644 index 000000000000..ec96e94e70dd --- /dev/null +++ b/tests/run/i19629/lib_1.scala @@ -0,0 +1,10 @@ +trait CP[A,B] +trait TypeEqK[F[_], G[_]] + +trait Knit[CP[_, _], F[_]] { + type Res + + def visit[R]( + caseInFst: [F1[_], Y] => (k: Knit[CP, F1]) => (ev: TypeEqK[F, [x] =>> CP[F1[x], Y]]) => R + ): R +} From b95cd75286145a8f72409bcf395c9c95a28709cd Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 24 Apr 2023 08:50:23 -0700 Subject: [PATCH 148/277] Repl truncation copes with null --- compiler/src/dotty/tools/repl/Rendering.scala | 22 +++++++++++-------- .../dotty/tools/repl/ReplCompilerTests.scala | 9 ++++++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/compiler/src/dotty/tools/repl/Rendering.scala b/compiler/src/dotty/tools/repl/Rendering.scala index 517815615f2a..fe3bd3bc4668 100644 --- a/compiler/src/dotty/tools/repl/Rendering.scala +++ b/compiler/src/dotty/tools/repl/Rendering.scala @@ -71,13 +71,16 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None): // In order to figure out if it did get truncated, we invoke it twice - once with the `maxElements` that we // want to print, and once without a limit. If the first is shorter, truncation did occur. val notTruncated = stringOfMaybeTruncated(value, Int.MaxValue) - val maybeTruncatedByElementCount = stringOfMaybeTruncated(value, maxElements) - val maybeTruncated = truncate(maybeTruncatedByElementCount, maxCharacters) - - // our string representation may have been truncated by element and/or character count - // if so, append an info string - but only once - if (notTruncated.length == maybeTruncated.length) maybeTruncated - else s"$maybeTruncated ... large output truncated, print value to show all" + if notTruncated == null then null else + val maybeTruncated = + val maybeTruncatedByElementCount = stringOfMaybeTruncated(value, maxElements) + truncate(maybeTruncatedByElementCount, maxCharacters) + + // our string representation may have been truncated by element and/or character count + // if so, append an info string - but only once + if notTruncated.length == maybeTruncated.length then maybeTruncated + else s"$maybeTruncated ... large output truncated, print value to show all" + end if } } @@ -95,8 +98,9 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None): "replStringOf should only be called on values creating using `classLoader()`, but `classLoader()` has not been called so far") val maxPrintElements = ctx.settings.VreplMaxPrintElements.valueIn(ctx.settingsState) val maxPrintCharacters = ctx.settings.VreplMaxPrintCharacters.valueIn(ctx.settingsState) - val res = myReplStringOf(value, maxPrintElements, maxPrintCharacters) - if res == null then "null // non-null reference has null-valued toString" else res + Option(value) + .flatMap(v => Option(myReplStringOf(v, maxPrintElements, maxPrintCharacters))) + .getOrElse("null // non-null reference has null-valued toString") /** Load the value of the symbol using reflection. * diff --git a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala index cfae36f394af..0afedd4d7626 100644 --- a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala +++ b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala @@ -437,6 +437,15 @@ class ReplCompilerTests extends ReplTest: s2 } + @Test def `i17333 print null result of toString`: Unit = + initially: + run("val tpolecat = new Object { override def toString(): String = null }") + .andThen: + assertEquals("val tpolecat: Object = null // non-null reference has null-valued toString", lines().head) + +end ReplCompilerTests + + object ReplCompilerTests: private val pattern = Pattern.compile("\\r[\\n]?|\\n"); From 302aacaecba4b7bb5c92b26f86c0071f56e791ed Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Thu, 27 Apr 2023 10:18:10 -0700 Subject: [PATCH 149/277] Improve message for "null toString" per review Also refactor the stringOf reflection to lookup method once. Add worst-case fallback to use String.valueOf. Re-enable some tests which appear not to crash. --- compiler/src/dotty/tools/repl/Rendering.scala | 93 ++++++++++--------- .../dotty/tools/repl/ReplCompilerTests.scala | 50 +++++----- 2 files changed, 75 insertions(+), 68 deletions(-) diff --git a/compiler/src/dotty/tools/repl/Rendering.scala b/compiler/src/dotty/tools/repl/Rendering.scala index fe3bd3bc4668..adefe62d2b5f 100644 --- a/compiler/src/dotty/tools/repl/Rendering.scala +++ b/compiler/src/dotty/tools/repl/Rendering.scala @@ -50,39 +50,40 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None): // We need to use the ScalaRunTime class coming from the scala-library // on the user classpath, and not the one available in the current // classloader, so we use reflection instead of simply calling - // `ScalaRunTime.replStringOf`. Probe for new API without extraneous newlines. - // For old API, try to clean up extraneous newlines by stripping suffix and maybe prefix newline. + // `ScalaRunTime.stringOf`. Also probe for new stringOf that does string quoting, etc. val scalaRuntime = Class.forName("scala.runtime.ScalaRunTime", true, myClassLoader) val renderer = "stringOf" - def stringOfMaybeTruncated(value: Object, maxElements: Int): String = { - try { - val meth = scalaRuntime.getMethod(renderer, classOf[Object], classOf[Int], classOf[Boolean]) - val truly = java.lang.Boolean.TRUE - meth.invoke(null, value, maxElements, truly).asInstanceOf[String] - } catch { - case _: NoSuchMethodException => - val meth = scalaRuntime.getMethod(renderer, classOf[Object], classOf[Int]) - meth.invoke(null, value, maxElements).asInstanceOf[String] - } - } - - (value: Object, maxElements: Int, maxCharacters: Int) => { - // `ScalaRuntime.stringOf` may truncate the output, in which case we want to indicate that fact to the user - // In order to figure out if it did get truncated, we invoke it twice - once with the `maxElements` that we - // want to print, and once without a limit. If the first is shorter, truncation did occur. - val notTruncated = stringOfMaybeTruncated(value, Int.MaxValue) - if notTruncated == null then null else - val maybeTruncated = - val maybeTruncatedByElementCount = stringOfMaybeTruncated(value, maxElements) - truncate(maybeTruncatedByElementCount, maxCharacters) - - // our string representation may have been truncated by element and/or character count - // if so, append an info string - but only once - if notTruncated.length == maybeTruncated.length then maybeTruncated - else s"$maybeTruncated ... large output truncated, print value to show all" - end if - } - + val stringOfInvoker: (Object, Int) => String = + def richStringOf: (Object, Int) => String = + val method = scalaRuntime.getMethod(renderer, classOf[Object], classOf[Int], classOf[Boolean]) + val richly = java.lang.Boolean.TRUE // add a repl option for enriched output + (value, maxElements) => method.invoke(null, value, maxElements, richly).asInstanceOf[String] + def poorStringOf: (Object, Int) => String = + try + val method = scalaRuntime.getMethod(renderer, classOf[Object], classOf[Int]) + (value, maxElements) => method.invoke(null, value, maxElements).asInstanceOf[String] + catch case _: NoSuchMethodException => (value, maxElements) => String.valueOf(value).take(maxElements) + try richStringOf + catch case _: NoSuchMethodException => poorStringOf + def stringOfMaybeTruncated(value: Object, maxElements: Int): String = stringOfInvoker(value, maxElements) + + // require value != null + // `ScalaRuntime.stringOf` returns null iff value.toString == null, let caller handle that. + // `ScalaRuntime.stringOf` may truncate the output, in which case we want to indicate that fact to the user + // In order to figure out if it did get truncated, we invoke it twice - once with the `maxElements` that we + // want to print, and once without a limit. If the first is shorter, truncation did occur. + // Note that `stringOf` has new API in flight to handle truncation, see stringOfMaybeTruncated. + (value: Object, maxElements: Int, maxCharacters: Int) => + stringOfMaybeTruncated(value, Int.MaxValue) match + case null => null + case notTruncated => + val maybeTruncated = + val maybeTruncatedByElementCount = stringOfMaybeTruncated(value, maxElements) + truncate(maybeTruncatedByElementCount, maxCharacters) + // our string representation may have been truncated by element and/or character count + // if so, append an info string - but only once + if notTruncated.length == maybeTruncated.length then maybeTruncated + else s"$maybeTruncated ... large output truncated, print value to show all" } myClassLoader } @@ -93,14 +94,20 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None): else str.substring(0, str.offsetByCodePoints(0, maxPrintCharacters - 1)) /** Return a String representation of a value we got from `classLoader()`. */ - private[repl] def replStringOf(value: Object)(using Context): String = + private[repl] def replStringOf(sym: Symbol, value: Object)(using Context): String = assert(myReplStringOf != null, "replStringOf should only be called on values creating using `classLoader()`, but `classLoader()` has not been called so far") val maxPrintElements = ctx.settings.VreplMaxPrintElements.valueIn(ctx.settingsState) val maxPrintCharacters = ctx.settings.VreplMaxPrintCharacters.valueIn(ctx.settingsState) - Option(value) - .flatMap(v => Option(myReplStringOf(v, maxPrintElements, maxPrintCharacters))) - .getOrElse("null // non-null reference has null-valued toString") + // stringOf returns null if value.toString returns null. Show some text as a fallback. + def toIdentityString(value: Object): String = + s"${value.getClass.getName}@${System.identityHashCode(value).toHexString}" + def fallback = s"""${toIdentityString(value)} // return value of "${sym.name}.toString" is null""" + if value == null then "null" else + myReplStringOf(value, maxPrintElements, maxPrintCharacters) match + case null => fallback + case res => res + end if /** Load the value of the symbol using reflection. * @@ -112,17 +119,15 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None): val symValue = resObj .getDeclaredMethods.find(_.getName == sym.name.encode.toString) .flatMap(result => rewrapValueClass(sym.info.classSymbol, result.invoke(null))) - val valueString = symValue.map(replStringOf) + symValue + .filter(_ => sym.is(Flags.Method) || sym.info != defn.UnitType) + .map(value => stripReplPrefix(replStringOf(sym, value))) - if (!sym.is(Flags.Method) && sym.info == defn.UnitType) - None + private def stripReplPrefix(s: String): String = + if (s.startsWith(REPL_WRAPPER_NAME_PREFIX)) + s.drop(REPL_WRAPPER_NAME_PREFIX.length).dropWhile(c => c.isDigit || c == '$') else - valueString.map { s => - if (s.startsWith(REPL_WRAPPER_NAME_PREFIX)) - s.drop(REPL_WRAPPER_NAME_PREFIX.length).dropWhile(c => c.isDigit || c == '$') - else - s - } + s /** Rewrap value class to their Wrapper class * diff --git a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala index 0afedd4d7626..a179b5e47f47 100644 --- a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala +++ b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala @@ -4,8 +4,9 @@ import scala.language.unsafeNulls import java.util.regex.Pattern -import org.junit.Assert.{assertTrue => assert, _} -import org.junit.{Ignore, Test} +import org.junit.Assert.{assertEquals, assertFalse, assertTrue} +import org.junit.Assert.{assertTrue => assert} +import org.junit.Test import dotty.tools.dotc.core.Contexts.Context class ReplCompilerTests extends ReplTest: @@ -107,28 +108,21 @@ class ReplCompilerTests extends ReplTest: assertEquals(expected, lines()) } - // FIXME: Tests are not run in isolation, the classloader is corrupted after the first exception - @Ignore @Test def i3305: Unit = { - initially { - run("null.toString") - assert(storedOutput().startsWith("java.lang.NullPointerException")) - } + @Test def `i3305 SOE meh`: Unit = initially: + run("def foo: Int = 1 + foo; foo") + assert(storedOutput().startsWith("java.lang.StackOverflowError")) - initially { - run("def foo: Int = 1 + foo; foo") - assert(storedOutput().startsWith("def foo: Int\njava.lang.StackOverflowError")) - } + @Test def `i3305 NPE`: Unit = initially: + run("null.toString") + assert(storedOutput().startsWith("java.lang.NullPointerException")) - initially { - run("""throw new IllegalArgumentException("Hello")""") - assert(storedOutput().startsWith("java.lang.IllegalArgumentException: Hello")) - } + @Test def `i3305 IAE`: Unit = initially: + run("""throw new IllegalArgumentException("Hello")""") + assertTrue(storedOutput().startsWith("java.lang.IllegalArgumentException: Hello")) - initially { - run("val (x, y) = null") - assert(storedOutput().startsWith("scala.MatchError: null")) - } - } + @Test def `i3305 ME`: Unit = initially: + run("val (x, y) = null") + assert(storedOutput().startsWith("scala.MatchError: null")) @Test def i2789: Unit = initially { run("(x: Int) => println(x)") @@ -441,10 +435,18 @@ class ReplCompilerTests extends ReplTest: initially: run("val tpolecat = new Object { override def toString(): String = null }") .andThen: - assertEquals("val tpolecat: Object = null // non-null reference has null-valued toString", lines().head) - -end ReplCompilerTests + val last = lines().last + assertTrue(last, last.startsWith("val tpolecat: Object = anon")) + assertTrue(last, last.endsWith("""// return value of "tpolecat.toString" is null""")) + @Test def `i17333 print toplevel object with null toString`: Unit = + initially: + run("object tpolecat { override def toString(): String = null }") + .andThen: + run("tpolecat") + val last = lines().last + assertTrue(last, last.startsWith("val res0: tpolecat.type = tpolecat")) + assertTrue(last, last.endsWith("""// return value of "res0.toString" is null""")) object ReplCompilerTests: From 6c9cd41d788a5ff99674ef5bbd4822f2604c71d9 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 1 Mar 2024 14:10:16 +0100 Subject: [PATCH 150/277] Test `publicInBinary` as if on a stable release Follow-up to #19811 --- .../test/dotty/tools/backend/jvm/PublicInBinaryTests.scala | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/test/dotty/tools/backend/jvm/PublicInBinaryTests.scala b/compiler/test/dotty/tools/backend/jvm/PublicInBinaryTests.scala index 25b46532e58b..eebb2b23247a 100644 --- a/compiler/test/dotty/tools/backend/jvm/PublicInBinaryTests.scala +++ b/compiler/test/dotty/tools/backend/jvm/PublicInBinaryTests.scala @@ -39,6 +39,11 @@ class PublicInBinaryTests extends DottyBytecodeTest { private def checkPublicClass(classNode: ClassNode): Unit = assert((classNode.access & privateOrProtectedOpcode) == 0) + override def initCtx = + val ctx0 = super.initCtx + ctx0.setSetting(ctx0.settings.experimental, true) + ctx0.setSetting(ctx0.settings.YnoExperimental, true) + @Test def publicInBinaryDef(): Unit = { val code = From 8584bb8c772f7244e89c4c0328408abdc73526e2 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 1 Mar 2024 14:18:52 +0100 Subject: [PATCH 151/277] Split research plugin from experimental compiler version --- compiler/src/dotty/tools/dotc/config/Feature.scala | 2 +- compiler/src/dotty/tools/dotc/config/Properties.scala | 9 +++++---- compiler/src/dotty/tools/dotc/plugins/Plugins.scala | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/Feature.scala b/compiler/src/dotty/tools/dotc/config/Feature.scala index f2ed58a5c8ca..f4b77990caf0 100644 --- a/compiler/src/dotty/tools/dotc/config/Feature.scala +++ b/compiler/src/dotty/tools/dotc/config/Feature.scala @@ -163,7 +163,7 @@ object Feature: do checkExperimentalFeature(s"feature $setting", NoSourcePosition) def isExperimentalEnabled(using Context): Boolean = - (Properties.experimental && !ctx.settings.YnoExperimental.value) || ctx.settings.experimental.value + (Properties.unstableExperimentalEnabled && !ctx.settings.YnoExperimental.value) || ctx.settings.experimental.value /** Handle language import `import language..` if it is one * of the global imports `pureFunctions` or `captureChecking`. In this case diff --git a/compiler/src/dotty/tools/dotc/config/Properties.scala b/compiler/src/dotty/tools/dotc/config/Properties.scala index 1e9cc82112af..3392882057e7 100644 --- a/compiler/src/dotty/tools/dotc/config/Properties.scala +++ b/compiler/src/dotty/tools/dotc/config/Properties.scala @@ -86,11 +86,12 @@ trait PropertiesTrait { /** Whether the current version of compiler is experimental * - * 1. Snapshot, nightly releases and non-bootstrapped compiler are experimental. - * 2. Features supported by experimental versions of the compiler: - * - research plugins + * Snapshot, nightly releases and non-bootstrapped compiler are experimental. */ - val experimental: Boolean = versionString.contains("SNAPSHOT") || versionString.contains("NIGHTLY") || versionString.contains("nonbootstrapped") + val unstableExperimentalEnabled: Boolean = versionString.contains("SNAPSHOT") || versionString.contains("NIGHTLY") || versionString.contains("nonbootstrapped") + + /** Whether the current version of compiler supports research plugins. */ + val researchPluginEnabled: Boolean = versionString.contains("SNAPSHOT") || versionString.contains("NIGHTLY") || versionString.contains("nonbootstrapped") val copyrightString: String = scalaPropOrElse("copyright.string", "(c) 2002-2017 LAMP/EPFL") diff --git a/compiler/src/dotty/tools/dotc/plugins/Plugins.scala b/compiler/src/dotty/tools/dotc/plugins/Plugins.scala index 05b9f0cf75d7..31176bb2fb2c 100644 --- a/compiler/src/dotty/tools/dotc/plugins/Plugins.scala +++ b/compiler/src/dotty/tools/dotc/plugins/Plugins.scala @@ -129,7 +129,7 @@ trait Plugins { val updatedPlan = Plugins.schedule(plan, pluginPhases) // add research plugins - if Properties.experimental && !ctx.settings.YnoExperimental.value then + if Properties.researchPluginEnabled then plugins.collect { case p: ResearchPlugin => p }.foldRight(updatedPlan) { (plug, plan) => plug.init(options(plug), plan) } From 390d9567eed83d3bf5814a963e34e02461e238fc Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Fri, 1 Mar 2024 14:33:28 +0100 Subject: [PATCH 152/277] print null result of replStringOf as null --- compiler/src/dotty/tools/repl/Rendering.scala | 4 +--- compiler/test/dotty/tools/repl/ReplCompilerTests.scala | 8 ++++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/repl/Rendering.scala b/compiler/src/dotty/tools/repl/Rendering.scala index adefe62d2b5f..d5688d1038b4 100644 --- a/compiler/src/dotty/tools/repl/Rendering.scala +++ b/compiler/src/dotty/tools/repl/Rendering.scala @@ -100,9 +100,7 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None): val maxPrintElements = ctx.settings.VreplMaxPrintElements.valueIn(ctx.settingsState) val maxPrintCharacters = ctx.settings.VreplMaxPrintCharacters.valueIn(ctx.settingsState) // stringOf returns null if value.toString returns null. Show some text as a fallback. - def toIdentityString(value: Object): String = - s"${value.getClass.getName}@${System.identityHashCode(value).toHexString}" - def fallback = s"""${toIdentityString(value)} // return value of "${sym.name}.toString" is null""" + def fallback = s"""null // result of "${sym.name}.toString" is null""" if value == null then "null" else myReplStringOf(value, maxPrintElements, maxPrintCharacters) match case null => fallback diff --git a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala index a179b5e47f47..a5bdddc51118 100644 --- a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala +++ b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala @@ -436,8 +436,8 @@ class ReplCompilerTests extends ReplTest: run("val tpolecat = new Object { override def toString(): String = null }") .andThen: val last = lines().last - assertTrue(last, last.startsWith("val tpolecat: Object = anon")) - assertTrue(last, last.endsWith("""// return value of "tpolecat.toString" is null""")) + assertTrue(last, last.startsWith("val tpolecat: Object = null")) + assertTrue(last, last.endsWith("""// result of "tpolecat.toString" is null""")) @Test def `i17333 print toplevel object with null toString`: Unit = initially: @@ -445,8 +445,8 @@ class ReplCompilerTests extends ReplTest: .andThen: run("tpolecat") val last = lines().last - assertTrue(last, last.startsWith("val res0: tpolecat.type = tpolecat")) - assertTrue(last, last.endsWith("""// return value of "res0.toString" is null""")) + assertTrue(last, last.startsWith("val res0: tpolecat.type = null")) + assertTrue(last, last.endsWith("""// result of "res0.toString" is null""")) object ReplCompilerTests: From 1ef2574fa7c61ac6bd2f1c38c663a4e2dec5d887 Mon Sep 17 00:00:00 2001 From: odersky Date: Fri, 1 Mar 2024 20:15:23 +0100 Subject: [PATCH 153/277] Drop FreeSeqFactory from stdlib-cc FreeSeqFactory was a construction to demonstrate type safety for certain iterableFactory.from calls where we rely in the fact that for all Seqs iterableFactory has an eager implementation of from. While that shows that we _can_ make it typesafe, it does not work at runtime as a drop-in replacement for stdlib since of course stdlib does not have a FreeSeqFactory. This commit drop FreeSeqFactory and adds three unsafeAssumePure calls instead, with explanations. Fixes #19745 --- scala2-library-cc/src/scala/collection/Factory.scala | 12 ++++++++---- scala2-library-cc/src/scala/collection/Seq.scala | 8 ++++---- .../src/scala/collection/generic/IsSeq.scala | 4 ++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/scala2-library-cc/src/scala/collection/Factory.scala b/scala2-library-cc/src/scala/collection/Factory.scala index 5392d7e2c642..d66ab08e4abb 100644 --- a/scala2-library-cc/src/scala/collection/Factory.scala +++ b/scala2-library-cc/src/scala/collection/Factory.scala @@ -297,16 +297,20 @@ object IterableFactory { } // !!! Needed to add this separate trait -trait FreeSeqFactory[+CC[A]] extends IterableFactory[CC]: - def from[A](source: IterableOnce[A]^): CC[A] - override def apply[A](elems: A*): CC[A] = from(elems) +//trait FreeSeqFactory[+CC[A]] extends IterableFactory[CC]: +// def from[A](source: IterableOnce[A]^): CC[A] +// override def apply[A](elems: A*): CC[A] + +// type FreeSeqFactory[+CC[A] <: SeqOps[A, Seq, Seq[A]]] = SeqFactory[CC] /** * @tparam CC Collection type constructor (e.g. `List`) */ -trait SeqFactory[+CC[A] <: SeqOps[A, Seq, Seq[A]]] extends FreeSeqFactory[CC] { +trait SeqFactory[+CC[A] <: SeqOps[A, Seq, Seq[A]]] extends IterableFactory[CC] { import SeqFactory.UnapplySeqWrapper final def unapplySeq[A](x: CC[A] @uncheckedVariance): UnapplySeqWrapper[A] = new UnapplySeqWrapper(x) // TODO is uncheckedVariance sound here? + def from[A](source: IterableOnce[A]^): CC[A] + override def apply[A](elems: A*): CC[A] = from(elems) } object SeqFactory { diff --git a/scala2-library-cc/src/scala/collection/Seq.scala b/scala2-library-cc/src/scala/collection/Seq.scala index 334546d67dad..65927154c4b6 100644 --- a/scala2-library-cc/src/scala/collection/Seq.scala +++ b/scala2-library-cc/src/scala/collection/Seq.scala @@ -81,8 +81,6 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self => override def view: SeqView[A] = new SeqView.Id[A](this) - def iterableFactory: FreeSeqFactory[CC] - /** Get the element at the specified index. This operation is provided for convenience in `Seq`. It should * not be assumed to be efficient unless you have an `IndexedSeq`. */ @throws[IndexOutOfBoundsException] @@ -167,7 +165,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self => def prependedAll[B >: A](prefix: IterableOnce[B]^): CC[B] = iterableFactory.from(prefix match { case prefix: Iterable[B] => new View.Concat(prefix, this) case _ => prefix.iterator ++ iterator - }) + }).unsafeAssumePure // assume pure OK since iterableFactory.from is eager for Seq /** Alias for `prependedAll` */ @`inline` override final def ++: [B >: A](prefix: IterableOnce[B]^): CC[B] = prependedAll(prefix) @@ -532,6 +530,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self => @deprecated("Use .reverseIterator.map(f).to(...) instead of .reverseMap(f)", "2.13.0") def reverseMap[B](f: A => B): CC[B] = iterableFactory.from(new View.Map(View.fromIteratorProvider(() => reverseIterator), f)) + .unsafeAssumePure // assume pure OK since iterableFactory.from is eager for Seq /** Iterates over distinct permutations of elements. * @@ -947,7 +946,8 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self => */ def patch[B >: A](from: Int, other: IterableOnce[B]^, replaced: Int): CC[B] = iterableFactory.from(new View.Patched(this, from, other, replaced)) - + .unsafeAssumePure // assume pure OK since iterableFactory.from is eager for Seq + /** A copy of this $coll with one single replaced element. * @param index the position of the replacement * @param elem the replacing element diff --git a/scala2-library-cc/src/scala/collection/generic/IsSeq.scala b/scala2-library-cc/src/scala/collection/generic/IsSeq.scala index 041d74f84d9c..7b5e50499c0c 100644 --- a/scala2-library-cc/src/scala/collection/generic/IsSeq.scala +++ b/scala2-library-cc/src/scala/collection/generic/IsSeq.scala @@ -84,7 +84,7 @@ object IsSeq { def toIterable: Iterable[Char] = new immutable.WrappedString(s) protected[this] def coll: String = s protected[this] def fromSpecific(coll: IterableOnce[Char]^): String = coll.iterator.mkString - def iterableFactory: FreeSeqFactory[immutable.ArraySeq] = immutable.ArraySeq.untagged + def iterableFactory: IterableFactory[immutable.ArraySeq] = immutable.ArraySeq.untagged override def empty: String = "" protected[this] def newSpecificBuilder: mutable.Builder[Char, String] = new StringBuilder def iterator: Iterator[Char] = s.iterator @@ -102,7 +102,7 @@ object IsSeq { def toIterable: Iterable[A] = mutable.ArraySeq.make[A](a) protected def coll: Array[A] = a protected def fromSpecific(coll: IterableOnce[A]^): Array[A] = Array.from(coll) - def iterableFactory: FreeSeqFactory[mutable.ArraySeq] = mutable.ArraySeq.untagged + def iterableFactory: IterableFactory[mutable.ArraySeq] = mutable.ArraySeq.untagged override def empty: Array[A] = Array.empty[A] protected def newSpecificBuilder: mutable.Builder[A, Array[A]] = Array.newBuilder def iterator: Iterator[A] = a.iterator From 4464a73f7b016366be5ac06283223a1fddeb043f Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 2 Mar 2024 11:12:07 +0100 Subject: [PATCH 154/277] Drop override in SeqFactory Another method that was added for the typesafety demonstration, which should be removed now. --- scala2-library-cc/src/scala/collection/Factory.scala | 9 --------- 1 file changed, 9 deletions(-) diff --git a/scala2-library-cc/src/scala/collection/Factory.scala b/scala2-library-cc/src/scala/collection/Factory.scala index d66ab08e4abb..99f584b972fc 100644 --- a/scala2-library-cc/src/scala/collection/Factory.scala +++ b/scala2-library-cc/src/scala/collection/Factory.scala @@ -296,21 +296,12 @@ object IterableFactory { } } -// !!! Needed to add this separate trait -//trait FreeSeqFactory[+CC[A]] extends IterableFactory[CC]: -// def from[A](source: IterableOnce[A]^): CC[A] -// override def apply[A](elems: A*): CC[A] - -// type FreeSeqFactory[+CC[A] <: SeqOps[A, Seq, Seq[A]]] = SeqFactory[CC] - /** * @tparam CC Collection type constructor (e.g. `List`) */ trait SeqFactory[+CC[A] <: SeqOps[A, Seq, Seq[A]]] extends IterableFactory[CC] { import SeqFactory.UnapplySeqWrapper final def unapplySeq[A](x: CC[A] @uncheckedVariance): UnapplySeqWrapper[A] = new UnapplySeqWrapper(x) // TODO is uncheckedVariance sound here? - def from[A](source: IterableOnce[A]^): CC[A] - override def apply[A](elems: A*): CC[A] = from(elems) } object SeqFactory { From 7aca3c4feb514190ae31000e7138215e86caeca9 Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Sun, 3 Mar 2024 23:16:37 +0100 Subject: [PATCH 155/277] Fix the pickling of `This` in a capture set --- .../tools/dotc/core/tasty/TreePickler.scala | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index def27742c189..7d2d95aa9601 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -405,19 +405,21 @@ class TreePickler(pickler: TastyPickler, attributes: Attributes) { pickleType(tp) } case This(qual) => + // This may be needed when pickling a `This` inside a capture set. See #19662 and #19859. + // In this case, we pickle the tree as null.asInstanceOf[tree.tpe]. + // Since the pickled tree is not the same as the input, special handling is needed + // in the tree printer when testing the pickler. See [[PlainPrinter#homogenize]]. + inline def pickleCapturedThis = + pickleTree(Literal(Constant(null)).cast(tree.tpe).withSpan(tree.span)) if (qual.isEmpty) if tree.tpe.isSingleton then pickleType(tree.tpe) - else - // This may happen when pickling a `This` inside a capture set. See #19662. - // In this case, we pickle the tree as null.asInstanceOf[tree.tpe]. - // Since the pickled tree is not the same as the input, special handling is needed - // in the tree printer when testing the pickler. See [[PlainPrinter#homogenize]]. - pickleTree(Literal(Constant(null)).cast(tree.tpe).withSpan(tree.span)) - else { - writeByte(QUALTHIS) - val ThisType(tref) = tree.tpe: @unchecked - pickleTree(qual.withType(tref)) - } + else pickleCapturedThis + else + tree.tpe match + case ThisType(tref) => + writeByte(QUALTHIS) + pickleTree(qual.withType(tref)) + case _ => pickleCapturedThis case Select(qual, name) => name match { case OuterSelectName(_, levels) => From 96e1d4eec8b879e26c120a4a59d28ddaf35ac035 Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Mon, 4 Mar 2024 12:33:52 +0100 Subject: [PATCH 156/277] Add test for #19842 --- tests/neg-macros/i19842.check | 32 +++++++++++++++++++++++++++++ tests/neg-macros/i19842/Macro.scala | 29 ++++++++++++++++++++++++++ tests/neg-macros/i19842/Test.scala | 9 ++++++++ 3 files changed, 70 insertions(+) create mode 100644 tests/neg-macros/i19842.check create mode 100644 tests/neg-macros/i19842/Macro.scala create mode 100644 tests/neg-macros/i19842/Test.scala diff --git a/tests/neg-macros/i19842.check b/tests/neg-macros/i19842.check new file mode 100644 index 000000000000..b22efc51a94a --- /dev/null +++ b/tests/neg-macros/i19842.check @@ -0,0 +1,32 @@ +-- Error: tests/neg-macros/i19842/Test.scala:9:50 ---------------------------------------------------------------------- +9 |@main def Test = summon[Serializer[ValidationCls]] // error + | ^ + |Malformed tree was found while expanding macro with -Xcheck-macros. + |The tree does not conform to the compiler's tree invariants. + | + |Macro was: + |scala.quoted.runtime.Expr.splice[Serializer[ValidationCls]](((contextual$2: scala.quoted.Quotes) ?=> Macros.makeSerializer[ValidationCls](scala.quoted.Type.of[ValidationCls](contextual$2), contextual$2))) + | + |The macro returned: + |{ + | object objectSerializer$macro$1 extends Serializer[ValidationCls] { this: objectSerializer$macro$1.type => + | + | } + | objectSerializer$macro$1 + |} + | + |Error: + |assertion failed: Parents of class symbol differs from the parents in the tree for object objectSerializer$macro$1 + | + |Parents in symbol: [class Object, trait Serializer] + |Parents in tree: [trait Serializer] + | + | + |stacktrace available when compiling with `-Ydebug` + |--------------------------------------------------------------------------------------------------------------------- + |Inline stack trace + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + |This location contains code that was inlined from Test.scala:5 +5 | implicit inline def implicitMakeSerializer[T]: Serializer[T] = ${ Macros.makeSerializer[T] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --------------------------------------------------------------------------------------------------------------------- diff --git a/tests/neg-macros/i19842/Macro.scala b/tests/neg-macros/i19842/Macro.scala new file mode 100644 index 000000000000..481c0b2468b0 --- /dev/null +++ b/tests/neg-macros/i19842/Macro.scala @@ -0,0 +1,29 @@ + +import scala.annotation.{experimental, targetName} +import scala.quoted.* +import scala.util.Try + +object Macros { + def makeSerializer[T: Type](using Quotes): Expr[Serializer[T]] = { + import quotes.reflect.* + + val tpe: TypeRepr = TypeRepr.of[T] + val name: String = Symbol.freshName("objectSerializer") + + val modSym: Symbol = Symbol.newModule( + Symbol.spliceOwner, + name, + Flags.Implicit, + Flags.EmptyFlags, + // Without TypeRep.of[Object] it would fail with java.lang.AssertionError: assertion failed: First parent must be a class + List(TypeRepr.of[Object], TypeRepr.of[Serializer[T]]), + _ => Nil, + Symbol.noSymbol + ) + + val (modValDef: ValDef, modClassDef: ClassDef) = + ClassDef.module(modSym, List(TypeTree.of[Serializer[T]]), Nil) + + Block(List(modValDef, modClassDef), Ref(modSym)).asExprOf[Serializer[T]] + } +} \ No newline at end of file diff --git a/tests/neg-macros/i19842/Test.scala b/tests/neg-macros/i19842/Test.scala new file mode 100644 index 000000000000..ba1611d97696 --- /dev/null +++ b/tests/neg-macros/i19842/Test.scala @@ -0,0 +1,9 @@ + +trait Serializer[@specialized T] + +object Serializer: + implicit inline def implicitMakeSerializer[T]: Serializer[T] = ${ Macros.makeSerializer[T] } + +case class ValidationCls(string: String) + +@main def Test = summon[Serializer[ValidationCls]] // error \ No newline at end of file From f0cd5650853109d45475d558ef7adffe4fbd268b Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 4 Mar 2024 09:20:06 +0000 Subject: [PATCH 157/277] Rework MatchType recursion in collectParts This patch fixes a recursion situation in collectParts, by reimplementing a previous fix. Recursion is already attempted to be cutoff with `partSeen`, and `handleRecursion` is also used to prevent any unhandled recursion situations (like the one fixed here) from crashing the compiler. For context, AppliedType aren't hash-consed (i.e. the flyweight pattern) which means that every time you apply the same type arguments to the same type constructor you get a fresh AppliedType. Using i18171 as an example, the sequence of events where this matters is: 0. When typing BAZ, so much earlier than the collectParts call, because the MatchType on the rhs of BAZ reduces at definition site, the RHS is reduced to the `DFVal[BAZREC[T]]`, which means that BAZ's info is a TypeAlias rather than a MatchAlias, meaning it can dealias. 1. `BAZREC[Any]` is extracted by MatchType.InDisguise, which applies the Any to return a fresh MatchType 2. `Tuple.Map[Any, BAZ]` is also extracted by MatchType.InDisguise, which returns its own fresh MatchType 3. `BAZ[h]` dealiases to a fresh `DFVal[BAZREC[h]]` instance (see step 0) 4. `BAZREC[h]` is extracted by MatchType.InDisguise, repeating the cycle The reason that the cases with MatchType.InDisguise and MatchType were introduced is i17395. Looking back, it seems the only need is to capture any parts that are in the reduction of an applied MatchType. With this patch applied in the case of i18171, this now cuts off quickly, as `BAZREC[Any]` doesn't reduce to anything. In the case of i17395, `ExtractPart[ValuePartHolder]` reduces to `Value`, so `Value` is successfully recorded as a part. --- .../dotty/tools/dotc/typer/Implicits.scala | 8 +------ tests/pos/i17395-spec.ordered.scala | 17 ++++++++++++++ tests/pos/i19857.scala | 23 +++++++++++++++++++ 3 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 tests/pos/i17395-spec.ordered.scala create mode 100644 tests/pos/i19857.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 0a26ea697a6a..5162b3fed1b9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -661,15 +661,9 @@ trait ImplicitRunInfo: case t: TypeLambda => for p <- t.paramRefs do partSeen += p traverseChildren(t) - case t: MatchType => - traverseChildren(t) - traverse(t.normalized) - case MatchType.InDisguise(mt) - if !t.isInstanceOf[LazyRef] // skip recursive applications (eg. Tuple.Map) - => - traverse(mt) case t => traverseChildren(t) + traverse(t.normalized) catch case ex: Throwable => handleRecursive("collectParts of", t.show, ex) def apply(tp: Type): collection.Set[Type] = diff --git a/tests/pos/i17395-spec.ordered.scala b/tests/pos/i17395-spec.ordered.scala new file mode 100644 index 000000000000..6e6ae8dd1e59 --- /dev/null +++ b/tests/pos/i17395-spec.ordered.scala @@ -0,0 +1,17 @@ +trait ThingWithPart { type Part } +type PartField[A] = ThingWithPart { type Part = A } +type ExtractPart[B] = B match { case PartField[a] => a } + +trait TC[C] +object TC: + def tcForOptionPart[D](implicit tc: TC[ExtractPart[D]]): TC[Option[ExtractPart[D]]] = new {} + +class Value +object Value: + implicit val tcValue: TC[Value] = new {} + +class ValuePartHolder extends ThingWithPart { type Part = Value } + +class Test: + def t1: Unit = + val tc = TC.tcForOptionPart[ValuePartHolder] diff --git a/tests/pos/i19857.scala b/tests/pos/i19857.scala new file mode 100644 index 000000000000..aeb6e49111c6 --- /dev/null +++ b/tests/pos/i19857.scala @@ -0,0 +1,23 @@ +sealed trait DFTypeAny + +sealed trait DFTuple[T <: NonEmptyTuple] extends DFTypeAny + +sealed trait DFBit extends DFTypeAny + +sealed trait DFValOf[T] + +type Of[T] <: DFTypeAny = T match + case DFTypeAny => T & DFTypeAny + case Product => FromProduct[T] + +type JUSTVAL[T] = DFValOf[Of[T]] + +type FromProduct[T <: Product] <: DFTypeAny = T match + case NonEmptyTuple => DFTuple[Tuple.Map[T, JUSTVAL]] + +trait Width2[T] + +object Width2: + inline given [T]: Width2[T] = new Width2[T] {} + +val x = summon[Width2[Of[(DFBit, DFBit)]]] From fcc6fcac0cc267b61b705f574a3f1784ffb257c5 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 4 Mar 2024 14:02:25 +0100 Subject: [PATCH 158/277] Increase BootstrappedOnlyCompilationTests timeout Some of the tests in this file are a bit heavy and tend to timeout when the CI is overloaded. Tests that take may take longer include tests with the tasty inspector and the staging tests. --- .../dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala b/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala index ab2adddbb16e..5e9a01a77ca7 100644 --- a/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala @@ -206,7 +206,7 @@ class BootstrappedOnlyCompilationTests { object BootstrappedOnlyCompilationTests extends ParallelTesting { // Test suite configuration -------------------------------------------------- - def maxDuration = 60.seconds + def maxDuration = 100.seconds def numberOfSlaves = Runtime.getRuntime().availableProcessors() def safeMode = Properties.testsSafeMode def isInteractive = SummaryReport.isInteractive From d687dee2edac1078526af7e14837c742d458bb4d Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 4 Mar 2024 13:14:28 +0000 Subject: [PATCH 159/277] Rework ParamRef#underlying handling in disjointnessBoundary --- compiler/src/dotty/tools/dotc/core/TypeComparer.scala | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 0be68b119d40..9128b1f11e45 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -2857,14 +2857,19 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling tp case tp: HKTypeLambda => tp + case tp: ParamRef => + val st = tp.superTypeNormalized + if st.exists then + disjointnessBoundary(st) + else + // workaround for when ParamRef#underlying returns NoType + defn.AnyType case tp: TypeProxy => disjointnessBoundary(tp.superTypeNormalized) case tp: WildcardType => disjointnessBoundary(tp.effectiveBounds.hi) case tp: ErrorType => defn.AnyType - case NoType => // ParamRef#superTypeNormalized can return NoType - defn.AnyType end disjointnessBoundary (disjointnessBoundary(tp1), disjointnessBoundary(tp2)) match From a6dd92fa342ef2288e0c92e6885afc0e27eee9f2 Mon Sep 17 00:00:00 2001 From: Matt Bovel Date: Tue, 27 Feb 2024 19:15:07 +0100 Subject: [PATCH 160/277] Use isStatic intsead of isStaticOwner in hasLocalInstantiation Co-Authored-By: Dale Wijnand Co-Authored-By: noti0na1 Co-Authored-By: odersky <795990+odersky@users.noreply.github.com> --- .../tools/dotc/transform/ExplicitOuter.scala | 2 +- .../outer-ref-elimination.check | 9 ++++ .../outer-ref-elimination.scala | 41 +++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 tests/generic-java-signatures/outer-ref-elimination.check create mode 100644 tests/generic-java-signatures/outer-ref-elimination.scala diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala index f57595293ae1..e34dbfe3e1d8 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -227,7 +227,7 @@ object ExplicitOuter { private def hasLocalInstantiation(cls: ClassSymbol)(using Context): Boolean = // Modules are normally locally instantiated, except if they are declared in a trait, // in which case they will be instantiated in the classes that mix in the trait. - cls.owner.ownersIterator.takeWhile(!_.isStatic).exists(_.isTerm) + cls.owner.ownersIterator.takeWhile(!_.isStaticOwner).exists(_.isTerm) || cls.is(Private, butNot = Module) || cls.is(Module) && !cls.owner.is(Trait) diff --git a/tests/generic-java-signatures/outer-ref-elimination.check b/tests/generic-java-signatures/outer-ref-elimination.check new file mode 100644 index 000000000000..f8437b1a40b7 --- /dev/null +++ b/tests/generic-java-signatures/outer-ref-elimination.check @@ -0,0 +1,9 @@ +List(public T1$C1()) +List(public T2$$anon$1$C2()) +List(public T3$C3$1()) +List(public T4$$anon$2$C4()) +List(public T5$C5(T5)) +List(public T6$$anon$3$C6()) +List(public T7$C7$1()) +List(public T8$$anon$4$C8()) +List(public T9$C9$1(T9)) diff --git a/tests/generic-java-signatures/outer-ref-elimination.scala b/tests/generic-java-signatures/outer-ref-elimination.scala new file mode 100644 index 000000000000..09dec07ff59c --- /dev/null +++ b/tests/generic-java-signatures/outer-ref-elimination.scala @@ -0,0 +1,41 @@ +// This test checks that references to outer classes in inner classes are +// eliminated in some cases when they are not used. This is done in the +// ExplicitOuter phase. See issue #19569 for discussions. + +object helper { + def test(cls: Class[?]) = println(cls.getDeclaredConstructors.toList) +} + +import helper.test + +object T1 { class C1; test(classOf[C1]) } +object T2 { new AnyRef { class C2; test(classOf[C2]) } } +object T3 { def t3(): Unit = { class C3; test(classOf[C3]) } } +object T4 { def t4(): Unit = new AnyRef { class C4; test(classOf[C4]) } } + +// The outer reference in C5 is not eliminated because C5 is publicly +// accessible as a member of T5. Therefore, its constructor needs to conform +// to the expected signature, with the outer reference parameter. +class T5 { class C5; test(classOf[C5]) } + +class T6 { new AnyRef { class C6; test(classOf[C6]) } } +class T7 { def t7(): Unit = { class C7; test(classOf[C7]) } } +class T8 { def t8(): Unit = new AnyRef { class C8; test(classOf[C8]) } } + +// Here, the outer reference in C9 is not eliminated because C9 needs to access +// the field x. +class T9 { var x = 451; def t9(): Unit = { class C9 {def getX = x}; test(classOf[C9])} } + +object Test { + def main(args: Array[String]): Unit = { + T1 + T2 + T3.t3() + T4.t4() + new T5() + new T6() + new T7().t7() + new T8().t8() + new T9().t9() + } +} From c00a4869e46488a1d8566d9544064cc39b2e6aa9 Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Sun, 3 Mar 2024 20:37:44 +0100 Subject: [PATCH 161/277] Hide capture sets when the current unit is not capture checked --- .../src/dotty/tools/dotc/printing/PlainPrinter.scala | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 0c308a4ba6d0..f1b03f251117 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -242,10 +242,12 @@ class PlainPrinter(_ctx: Context) extends Printer { val refsText = if showAsCap then rootSetText else toTextCaptureSet(refs) toTextCapturing(parent, refsText, boxText) case tp @ RetainingType(parent, refs) => - val refsText = refs match - case ref :: Nil if ref.symbol == defn.captureRoot => rootSetText - case _ => toTextRetainedElems(refs) - toTextCapturing(parent, refsText, "") ~ Str("R").provided(printDebug) + if ctx.compilationUnit.needsCaptureChecking then + val refsText = refs match + case ref :: Nil if ref.symbol == defn.captureRoot => rootSetText + case _ => toTextRetainedElems(refs) + toTextCapturing(parent, refsText, "") ~ Str("R").provided(printDebug) + else toText(parent) case tp: PreviousErrorType if ctx.settings.XprintTypes.value => "" // do not print previously reported error message because they may try to print this error type again recuresevely case tp: ErrorType => From 99abbddf873b9bf0e1f430a97d9e89ba0f47f7d8 Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Mon, 4 Mar 2024 02:58:26 +0100 Subject: [PATCH 162/277] Use `Feature.ccEnabledSomewhere` instead of `needsCaptureChecking` --- compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index f1b03f251117..ac7b4ef39604 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -242,7 +242,7 @@ class PlainPrinter(_ctx: Context) extends Printer { val refsText = if showAsCap then rootSetText else toTextCaptureSet(refs) toTextCapturing(parent, refsText, boxText) case tp @ RetainingType(parent, refs) => - if ctx.compilationUnit.needsCaptureChecking then + if Feature.ccEnabledSomewhere then val refsText = refs match case ref :: Nil if ref.symbol == defn.captureRoot => rootSetText case _ => toTextRetainedElems(refs) From 9ef26769ea8c40486e0214461c6bdf3ec5f5354b Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Thu, 29 Feb 2024 16:49:18 +0100 Subject: [PATCH 163/277] Update `SeqView.updated` --- .../src/scala/collection/Seq.scala | 2 +- .../src/scala/collection/SeqView.scala | 17 +++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/scala2-library-cc/src/scala/collection/Seq.scala b/scala2-library-cc/src/scala/collection/Seq.scala index 65927154c4b6..db044d5fa9f5 100644 --- a/scala2-library-cc/src/scala/collection/Seq.scala +++ b/scala2-library-cc/src/scala/collection/Seq.scala @@ -957,7 +957,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self => * lazy collection this exception may be thrown at a later time or not at * all (if the end of the collection is never evaluated). */ - def updated[B >: A](index: Int, elem: B): CC[B] = { + override def updated[B >: A](index: Int, elem: B): CC[B] = { if(index < 0) throw new IndexOutOfBoundsException(index.toString) val k = knownSize if(k >= 0 && index >= k) throw new IndexOutOfBoundsException(index.toString) diff --git a/scala2-library-cc/src/scala/collection/SeqView.scala b/scala2-library-cc/src/scala/collection/SeqView.scala index c66d7b5f4694..49338b446127 100644 --- a/scala2-library-cc/src/scala/collection/SeqView.scala +++ b/scala2-library-cc/src/scala/collection/SeqView.scala @@ -30,11 +30,17 @@ trait SeqViewOps[+A, +CC[_], +C] extends Any with IterableOps[A, CC, C] { def length: Int def apply(x: Int): A def appended[B >: A](elem: B): CC[B]^{this} - def updated[B >: A](index: Int, elem: B): CC[B]^{this} def prepended[B >: A](elem: B): CC[B]^{this} def reverse: C^{this} def sorted[B >: A](implicit ord: Ordering[B]): C^{this} + // Placeholder implementation for that method in SeqOps. + // This is needed due to the change in the class hierarchy in cc stdlib. + // See #19660 and #19819. + def updated[B >: A](index: Int, elem: B): CC[B]^{this} = + assert(false, "This is a placeholder implementation in the capture checked Scala 2 library.") + ??? + def reverseIterator: Iterator[A]^{this} = reversed.iterator } @@ -46,15 +52,6 @@ trait SeqView[+A] extends SeqViewOps[A, View, View[A]] with View[A] { override def map[B](f: A => B): SeqView[B]^{this, f} = new SeqView.Map(this, f) override def appended[B >: A](elem: B): SeqView[B]^{this} = new SeqView.Appended(this, elem) - // Copied from SeqOps. This is needed due to the change of class hierarchy in stdlib. - // See #19660. - override def updated[B >: A](index: Int, elem: B): View[B]^{this} = { - if(index < 0) throw new IndexOutOfBoundsException(index.toString) - val k = knownSize - if(k >= 0 && index >= k) throw new IndexOutOfBoundsException(index.toString) - iterableFactory.from(new View.Updated(this, index, elem)) - } - override def prepended[B >: A](elem: B): SeqView[B]^{this} = new SeqView.Prepended(elem, this) override def reverse: SeqView[A]^{this} = new SeqView.Reverse(this) override def take(n: Int): SeqView[A]^{this} = new SeqView.Take(this, n) From e304d8a3c1b3ec1d508379d9b587f0c7f7a78319 Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Mon, 4 Mar 2024 17:37:00 +0100 Subject: [PATCH 164/277] Move more methods from SeqOps to SeqViewOps --- .../src/scala/collection/Seq.scala | 16 +++++------ .../src/scala/collection/SeqView.scala | 28 ++++++++++++++++++- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/scala2-library-cc/src/scala/collection/Seq.scala b/scala2-library-cc/src/scala/collection/Seq.scala index db044d5fa9f5..aac1439668c4 100644 --- a/scala2-library-cc/src/scala/collection/Seq.scala +++ b/scala2-library-cc/src/scala/collection/Seq.scala @@ -206,7 +206,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self => * * @return a new $coll consisting of all the elements of this $coll without duplicates. */ - def distinct: C = distinctBy(identity) + override def distinct: C = distinctBy(identity) /** Selects all the elements of this $coll ignoring the duplicates as determined by `==` after applying * the transforming function `f`. @@ -215,7 +215,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self => * @tparam B the type of the elements after being transformed by `f` * @return a new $coll consisting of all the elements of this $coll without duplicates. */ - def distinctBy[B](f: A -> B): C = fromSpecific(new View.DistinctBy(this, f)) + override def distinctBy[B](f: A -> B): C = fromSpecific(new View.DistinctBy(this, f)) /** Returns new $coll with elements in reversed order. * @@ -293,7 +293,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self => * all elements of this $coll followed by the minimal number of occurrences of `elem` so * that the resulting collection has a length of at least `len`. */ - def padTo[B >: A](len: Int, elem: B): CC[B] = iterableFactory.from(new View.PadTo(this, len, elem)) + override def padTo[B >: A](len: Int, elem: B): CC[B] = iterableFactory.from(new View.PadTo(this, len, elem)) /** Computes the length of the longest segment that starts from the first element * and whose elements all satisfy some predicate. @@ -544,7 +544,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self => * // List(b, b, a) * }}} */ - def permutations: Iterator[C] = + override def permutations: Iterator[C] = if (isEmpty) Iterator.single(coll) else new PermutationsItr @@ -585,7 +585,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self => * // List(b, a) * }}} */ - def combinations(n: Int): Iterator[C] = + override def combinations(n: Int): Iterator[C] = if (n < 0 || n > size) Iterator.empty else new CombinationsItr(n) @@ -759,7 +759,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self => * List("Bobby", "Bob", "John", "Steve", "Tom") * }}} */ - def sortWith(lt: (A, A) => Boolean): C = sorted(Ordering.fromLessThan(lt)) + override def sortWith(lt: (A, A) => Boolean): C = sorted(Ordering.fromLessThan(lt)) /** Sorts this $coll according to the Ordering which results from transforming * an implicitly given Ordering with a transformation function. @@ -786,7 +786,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self => * res0: Array[String] = Array(The, dog, fox, the, lazy, over, brown, quick, jumped) * }}} */ - def sortBy[B](f: A => B)(implicit ord: Ordering[B]): C = sorted(ord on f) + override def sortBy[B](f: A => B)(implicit ord: Ordering[B]): C = sorted(ord on f) /** Produces the range of all indices of this sequence. * $willForceEvaluation @@ -944,7 +944,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any with SeqViewOps[A, CC, C] { self => * except that `replaced` elements starting from `from` are replaced * by all the elements of `other`. */ - def patch[B >: A](from: Int, other: IterableOnce[B]^, replaced: Int): CC[B] = + override def patch[B >: A](from: Int, other: IterableOnce[B]^, replaced: Int): CC[B] = iterableFactory.from(new View.Patched(this, from, other, replaced)) .unsafeAssumePure // assume pure OK since iterableFactory.from is eager for Seq diff --git a/scala2-library-cc/src/scala/collection/SeqView.scala b/scala2-library-cc/src/scala/collection/SeqView.scala index 49338b446127..c2c4a6e5da21 100644 --- a/scala2-library-cc/src/scala/collection/SeqView.scala +++ b/scala2-library-cc/src/scala/collection/SeqView.scala @@ -34,12 +34,38 @@ trait SeqViewOps[+A, +CC[_], +C] extends Any with IterableOps[A, CC, C] { def reverse: C^{this} def sorted[B >: A](implicit ord: Ordering[B]): C^{this} - // Placeholder implementation for that method in SeqOps. + // Placeholder implementations for the corresponding methods in SeqOps. // This is needed due to the change in the class hierarchy in cc stdlib. // See #19660 and #19819. + // ------------------- def updated[B >: A](index: Int, elem: B): CC[B]^{this} = assert(false, "This is a placeholder implementation in the capture checked Scala 2 library.") ??? + def padTo[B >: A](len: Int, elem: B): CC[B]^{this} = + assert(false, "This is a placeholder implementation in the capture checked Scala 2 library.") + ??? + def patch[B >: A](from: Int, other: IterableOnce[B]^, replaced: Int): CC[B]^{this, other} = + assert(false, "This is a placeholder implementation in the capture checked Scala 2 library.") + ??? + def combinations(n: Int): Iterator[C^{this}]^{this} = + assert(false, "This is a placeholder implementation in the capture checked Scala 2 library.") + ??? + def sortBy[B](f: A => B)(implicit ord: Ordering[B]): C^{this, f} = + assert(false, "This is a placeholder implementation in the capture checked Scala 2 library.") + ??? + def sortWith(lt: (A, A) => Boolean): C^{this, lt} = + assert(false, "This is a placeholder implementation in the capture checked Scala 2 library.") + ??? + def permutations: Iterator[C^{this}]^{this} = + assert(false, "This is a placeholder implementation in the capture checked Scala 2 library.") + ??? + def distinct: C^{this} = + assert(false, "This is a placeholder implementation in the capture checked Scala 2 library.") + ??? + def distinctBy[B](f: A -> B): C^{this} = + assert(false, "This is a placeholder implementation in the capture checked Scala 2 library.") + ??? + // ------------------- def reverseIterator: Iterator[A]^{this} = reversed.iterator } From af69895358d57c7273218424e57efa7e211d566d Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Tue, 5 Mar 2024 00:49:37 +0100 Subject: [PATCH 165/277] Restore pre-3.3.2 behavior of `inline implicit def` `inline implicit def` is not really a supported feature since it combines Scala 3's `inline` with Scala 2's `implicit` where the latter should eventually be deprecated. This however didn't prevent at least one project from using this combination in a way that was broken by #18249, see #19862 for the details. The issue is that when definining: implicit def foo(x: A): B = ... Then `foo` is a valid implicit search candidate when looking up an implicit `Function1[A, B]`. However, before #18249 if instead we wrote: inline implicit def foo(x: A): B = ... Then `foo` would be considered as an implicit search candidate but discarded because eta-expansion was disabled. There is no particular reason for `inline implicit def` to behave differently from `implicit def` here, but since `implicit def` is a legacy feature and since Scala 3.3 is an LTS release, we choose to restore the pre-#18249 behavior for compatibility reasons. Fixes #19862. --- compiler/src/dotty/tools/dotc/core/Flags.scala | 1 + compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 ++ tests/pos/i19862.scala | 8 ++++++++ 3 files changed, 11 insertions(+) create mode 100644 tests/pos/i19862.scala diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index be43cbc8dfcf..249940d8ff99 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -581,6 +581,7 @@ object Flags { val LazyGiven: FlagSet = Given | Lazy val InlineOrProxy: FlagSet = Inline | InlineProxy // An inline method or inline argument proxy */ val InlineMethod: FlagSet = Inline | Method + val InlineImplicitMethod: FlagSet = Implicit | InlineMethod val InlineParam: FlagSet = Inline | Param val InlineByNameProxy: FlagSet = InlineProxy | Method val JavaEnum: FlagSet = JavaDefined | Enum // A Java enum trait diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index b1bb5805bdc4..47bd25e5d45e 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -3993,10 +3993,12 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer // Reasons NOT to eta expand: // - we reference a constructor + // - we reference an inline implicit def (see #19862) // - we are in a pattern // - the current tree is a synthetic apply which is not expandable (eta-expasion would simply undo that) if arity >= 0 && !tree.symbol.isConstructor + && !tree.symbol.isAllOf(InlineImplicitMethod) && !ctx.mode.is(Mode.Pattern) && !(isSyntheticApply(tree) && !functionExpected) then diff --git a/tests/pos/i19862.scala b/tests/pos/i19862.scala new file mode 100644 index 000000000000..8467f9a65280 --- /dev/null +++ b/tests/pos/i19862.scala @@ -0,0 +1,8 @@ +import scala.language.implicitConversions + +object Test: + implicit inline def uhOh[A](value: A): A = + compiletime.error("Should not have been called") + def test = + // Compiles because `uhOh` fails to eta-expand and we fallback to `Predef.$conforms[A, A]` + summon[Function1[Int, Int]] From 44aa3c62bba824968c307abf4737f2f22ec841e5 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 5 Mar 2024 11:22:32 +0000 Subject: [PATCH 166/277] Avoid crash after StopMacroExpansion When a splice throws a StopMacroExpansion, it's replaced by an EmptyTree, which has NoType. Which means you can't cast it, as you can't call .asInstanceOf on it. So handle this before calling ensureConforms. --- compiler/src/dotty/tools/dotc/inlines/Inlines.scala | 8 ++++---- tests/neg-macros/i19851/Macro_1.scala | 9 +++++++++ tests/neg-macros/i19851/Test_2.scala | 3 +++ 3 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 tests/neg-macros/i19851/Macro_1.scala create mode 100644 tests/neg-macros/i19851/Test_2.scala diff --git a/compiler/src/dotty/tools/dotc/inlines/Inlines.scala b/compiler/src/dotty/tools/dotc/inlines/Inlines.scala index a97917e28771..1d2c291786db 100644 --- a/compiler/src/dotty/tools/dotc/inlines/Inlines.scala +++ b/compiler/src/dotty/tools/dotc/inlines/Inlines.scala @@ -494,14 +494,14 @@ object Inlines: // Take care that only argument bindings go into `bindings`, since positions are // different for bindings from arguments and bindings from body. - val res = tpd.Inlined(call, bindings, expansion) + val inlined = tpd.Inlined(call, bindings, expansion) - if !hasOpaqueProxies then res + if !hasOpaqueProxies || !inlined.tpe.exists then inlined else val target = - if inlinedMethod.is(Transparent) then call.tpe & res.tpe + if inlinedMethod.is(Transparent) then call.tpe & inlined.tpe else call.tpe - res.ensureConforms(target) + inlined.ensureConforms(target) // Make sure that the sealing with the declared type // is type correct. Without it we might get problems since the // expression's type is the opaque alias but the call's type is diff --git a/tests/neg-macros/i19851/Macro_1.scala b/tests/neg-macros/i19851/Macro_1.scala new file mode 100644 index 000000000000..33b2aa2e2849 --- /dev/null +++ b/tests/neg-macros/i19851/Macro_1.scala @@ -0,0 +1,9 @@ +import scala.quoted.* + +opaque type Box[A] = Any +object Box: + transparent inline def pack[A]: Nothing => Box[A] = ${ packImpl[A] } + + private def packImpl[A](using Quotes, Type[A]): Expr[Nothing => Box[A]] = + import quotes.reflect.* + report.errorAndAbort("Not implemented") diff --git a/tests/neg-macros/i19851/Test_2.scala b/tests/neg-macros/i19851/Test_2.scala new file mode 100644 index 000000000000..ab2f01a7019a --- /dev/null +++ b/tests/neg-macros/i19851/Test_2.scala @@ -0,0 +1,3 @@ +class Test: + def t1: Unit = + Box.pack[Int] // error From dc6b3cd20a40da2da8e1e8dc0eaa64e3008f5516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Tue, 5 Mar 2024 13:30:02 +0100 Subject: [PATCH 167/277] Fix #19524: Protect use of `HeaderIdGenerator` with `synchronized`. Hopefully this is the only source of the race condition that we have been observing. --- .../comments/markdown/SectionRenderingExtension.scala | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/comments/markdown/SectionRenderingExtension.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/comments/markdown/SectionRenderingExtension.scala index 0acb1c02a69e..134ab17715fe 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/comments/markdown/SectionRenderingExtension.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/comments/markdown/SectionRenderingExtension.scala @@ -35,7 +35,14 @@ object SectionRenderingExtension extends HtmlRenderer.HtmlRendererExtension: val idSuffix = repeatedIds.getOrElseUpdate((c, headerText), 0) val ifSuffixStr = if(idSuffix == 0) then "" else idSuffix.toString repeatedIds.update((c, headerText), idSuffix + 1) - val id = idGenerator.getId(headerText + ifSuffixStr) + + /* #19524 flexmark's `HeaderIdGenerator` does not appear to be thread-safe, + * so we protect its usage with a full `synchronize`. + */ + val id = idGenerator.synchronized { + idGenerator.getId(headerText + ifSuffixStr) + } + val anchor = AnchorLink(s"#$id") val headerClass: String = header.getLevel match case 1 => "h500" From 0fe04905dec86b6d58b44cee824ed4a4a8c8b59e Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 5 Mar 2024 12:33:12 +0000 Subject: [PATCH 168/277] Use ??? instead of EmptyTree for StopMacroExpansion. --- compiler/src/dotty/tools/dotc/inlines/Inlines.scala | 2 +- compiler/src/dotty/tools/dotc/transform/Splicer.scala | 2 +- tests/neg-macros/i9014b.check | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/inlines/Inlines.scala b/compiler/src/dotty/tools/dotc/inlines/Inlines.scala index 1d2c291786db..789c680339ea 100644 --- a/compiler/src/dotty/tools/dotc/inlines/Inlines.scala +++ b/compiler/src/dotty/tools/dotc/inlines/Inlines.scala @@ -496,7 +496,7 @@ object Inlines: // different for bindings from arguments and bindings from body. val inlined = tpd.Inlined(call, bindings, expansion) - if !hasOpaqueProxies || !inlined.tpe.exists then inlined + if !hasOpaqueProxies then inlined else val target = if inlinedMethod.is(Transparent) then call.tpe & inlined.tpe diff --git a/compiler/src/dotty/tools/dotc/transform/Splicer.scala b/compiler/src/dotty/tools/dotc/transform/Splicer.scala index 93ba1845e484..e42f997e7265 100644 --- a/compiler/src/dotty/tools/dotc/transform/Splicer.scala +++ b/compiler/src/dotty/tools/dotc/transform/Splicer.scala @@ -72,7 +72,7 @@ object Splicer { if !ctx.reporter.hasErrors then report.error("Macro expansion was aborted by the macro without any errors reported. Macros should issue errors to end-users when aborting a macro expansion with StopMacroExpansion.", splicePos) // errors have been emitted - EmptyTree + ref(defn.Predef_undefined).withType(ErrorType(em"macro expansion was stopped")) case ex: StopInterpretation => report.error(ex.msg, ex.pos) ref(defn.Predef_undefined).withType(ErrorType(ex.msg)) diff --git a/tests/neg-macros/i9014b.check b/tests/neg-macros/i9014b.check index de0be2d5c1fa..4098bccf462b 100644 --- a/tests/neg-macros/i9014b.check +++ b/tests/neg-macros/i9014b.check @@ -7,4 +7,4 @@ | | given_Bar | - | But given instance given_Bar does not match type Bar. + | But macro expansion was stopped. From 9cc9107ab26ba50a52b18fac4cdda47aaf286b84 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 169/277] 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 95123096983d..d0ceb37c07ba 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 dd9edbce288afde3b7c967e3b818d2cd1a07a49d Mon Sep 17 00:00:00 2001 From: Matt Bovel Date: Tue, 5 Mar 2024 15:11:30 +0100 Subject: [PATCH 170/277] Refactor hasOnlyLocalInstantiation to use isLocalToCompilationUnit --- compiler/src/dotty/tools/dotc/core/SymDenotations.scala | 2 +- .../src/dotty/tools/dotc/transform/ExplicitOuter.scala | 9 ++++----- .../generic-java-signatures/outer-ref-elimination.check | 1 + .../generic-java-signatures/outer-ref-elimination.scala | 3 +++ 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index b3fe5757720e..77849e1f0624 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1208,7 +1208,7 @@ object SymDenotations { final def isLocalToCompilationUnit(using Context): Boolean = is(Private) - || owner.ownersIterator.exists(_.isTerm) + || owner.ownersIterator.takeWhile(!_.isStaticOwner).exists(_.isTerm) || accessBoundary(defn.RootClass).isContainedIn(symbol.topLevelClass) final def isTransparentClass(using Context): Boolean = diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala index e34dbfe3e1d8..b976dfaa2f9f 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -218,18 +218,17 @@ object ExplicitOuter { */ private def needsOuterAlways(cls: ClassSymbol)(using Context): Boolean = needsOuterIfReferenced(cls) && - (!hasLocalInstantiation(cls) || // needs outer because we might not know whether outer is referenced or not + (!hasOnlyLocalInstantiation(cls) || // needs outer because we might not know whether outer is referenced or not cls.mixins.exists(needsOuterIfReferenced) || // needs outer for parent traits cls.info.parents.exists(parent => // needs outer to potentially pass along to parent needsOuterIfReferenced(parent.classSymbol.asClass))) /** Class is only instantiated in the compilation unit where it is defined */ - private def hasLocalInstantiation(cls: ClassSymbol)(using Context): Boolean = + private def hasOnlyLocalInstantiation(cls: ClassSymbol)(using Context): Boolean = // Modules are normally locally instantiated, except if they are declared in a trait, // in which case they will be instantiated in the classes that mix in the trait. - cls.owner.ownersIterator.takeWhile(!_.isStaticOwner).exists(_.isTerm) - || cls.is(Private, butNot = Module) - || cls.is(Module) && !cls.owner.is(Trait) + if cls.is(Module) then !cls.owner.is(Trait) + else cls.isLocalToCompilationUnit /** The outer parameter accessor of cass `cls` */ private def outerParamAccessor(cls: ClassSymbol)(using Context): TermSymbol = diff --git a/tests/generic-java-signatures/outer-ref-elimination.check b/tests/generic-java-signatures/outer-ref-elimination.check index f8437b1a40b7..7dd664e5d766 100644 --- a/tests/generic-java-signatures/outer-ref-elimination.check +++ b/tests/generic-java-signatures/outer-ref-elimination.check @@ -7,3 +7,4 @@ List(public T6$$anon$3$C6()) List(public T7$C7$1()) List(public T8$$anon$4$C8()) List(public T9$C9$1(T9)) +List(public T10$C10()) diff --git a/tests/generic-java-signatures/outer-ref-elimination.scala b/tests/generic-java-signatures/outer-ref-elimination.scala index 09dec07ff59c..6e4e8218c535 100644 --- a/tests/generic-java-signatures/outer-ref-elimination.scala +++ b/tests/generic-java-signatures/outer-ref-elimination.scala @@ -26,6 +26,8 @@ class T8 { def t8(): Unit = new AnyRef { class C8; test(classOf[C8]) } } // the field x. class T9 { var x = 451; def t9(): Unit = { class C9 {def getX = x}; test(classOf[C9])} } +class T10 { private[T10] class C10; test(classOf[C10]) } + object Test { def main(args: Array[String]): Unit = { T1 @@ -37,5 +39,6 @@ object Test { new T7().t7() new T8().t8() new T9().t9() + new T10() } } From 25035d78e84ec32133be51f41b41c08a3fc879e2 Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Tue, 5 Mar 2024 19:27:39 +0100 Subject: [PATCH 171/277] Tweak generics.IsSeq --- .../src/scala/collection/generic/IsSeq.scala | 28 ++++++++----------- tests/run/enrich-gentraversable.scala | 1 + 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/scala2-library-cc/src/scala/collection/generic/IsSeq.scala b/scala2-library-cc/src/scala/collection/generic/IsSeq.scala index 7b5e50499c0c..a165b53e0bd9 100644 --- a/scala2-library-cc/src/scala/collection/generic/IsSeq.scala +++ b/scala2-library-cc/src/scala/collection/generic/IsSeq.scala @@ -54,24 +54,20 @@ object IsSeq { seqOpsIsSeqVal.asInstanceOf[IsSeq[CC0[A0]] { type A = A0; type C = CC0[A0] }] /** !!! Under cc, views are not Seqs and can't use SeqOps. - * So this should be renamed to seqViewIsIterable - */ - implicit def seqViewIsSeq[CC0[X] <: SeqView[X], A0]: IsIterable[CC0[A0]] { type A = A0; type C = View[A0] } = - new IsIterable[CC0[A0]] { - type A = A0 - type C = View[A] - def apply(coll: CC0[A0]): IterableOps[A0, View, View[A0]] = coll - } + * Therefore, [[seqViewIsSeq]] now returns an [[IsIterable]]. + * The helper method [[seqViewIsSeq_]] is added to make the binary compatible. + */ + @annotation.targetName("seqViewIsSeq") + def seqViewIsSeq_[CC0[X] <: SeqView[X], A0]: IsSeq[CC0[A0]] { type A = A0; type C = View[A0] } = ??? + implicit inline def seqViewIsSeq[CC0[X] <: SeqView[X], A0]: IsIterable[CC0[A0]] { type A = A0; type C = View[A0] } = seqViewIsSeq_[CC0, A0].asInstanceOf /** !!! Under cc, views are not Seqs and can't use SeqOps. - * So this should be renamed to stringViewIsIterable - */ - implicit val stringViewIsSeq: IsIterable[StringView] { type A = Char; type C = View[Char] } = - new IsIterable[StringView] { - type A = Char - type C = View[Char] - def apply(coll: StringView): IterableOps[Char, View, View[Char]] = coll - } + * Therefore, [[stringViewIsSeq]] now returns an [[IsIterable]]. + * The helper method [[stringViewIsSeq__]] is added to make the binary compatible. + */ + @annotation.targetName("stringViewIsSeq") + val stringViewIsSeq_ : IsSeq[StringView] { type A = Char; type C = View[Char] } = ??? + inline implicit def stringViewIsSeq: IsIterable[StringView] { type A = Char; type C = View[Char] } = stringViewIsSeq_.asInstanceOf implicit val stringIsSeq: IsSeq[String] { type A = Char; type C = String } = new IsSeq[String] { diff --git a/tests/run/enrich-gentraversable.scala b/tests/run/enrich-gentraversable.scala index 43514e5a5136..887a6aea7983 100644 --- a/tests/run/enrich-gentraversable.scala +++ b/tests/run/enrich-gentraversable.scala @@ -3,6 +3,7 @@ import scala.language.postfixOps object Test extends App { import scala.collection.generic.IsIterable + import scala.collection.generic.IsSeq.seqViewIsSeq import scala.collection.{BuildFrom, Iterable, IterableOps, View} import scala.collection.immutable.TreeMap From 76ed7ebc70ea317852db9efa60496f4845cb2b26 Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Tue, 5 Mar 2024 20:46:17 +0100 Subject: [PATCH 172/277] Apply suggestion from Nico --- scala2-library-cc/src/scala/collection/generic/IsSeq.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scala2-library-cc/src/scala/collection/generic/IsSeq.scala b/scala2-library-cc/src/scala/collection/generic/IsSeq.scala index a165b53e0bd9..420a81d94ab4 100644 --- a/scala2-library-cc/src/scala/collection/generic/IsSeq.scala +++ b/scala2-library-cc/src/scala/collection/generic/IsSeq.scala @@ -58,7 +58,8 @@ object IsSeq { * The helper method [[seqViewIsSeq_]] is added to make the binary compatible. */ @annotation.targetName("seqViewIsSeq") - def seqViewIsSeq_[CC0[X] <: SeqView[X], A0]: IsSeq[CC0[A0]] { type A = A0; type C = View[A0] } = ??? + @annotation.publicInBinary + private[IsSeq] def seqViewIsSeq_[CC0[X] <: SeqView[X], A0]: IsSeq[CC0[A0]] { type A = A0; type C = View[A0] } = ??? implicit inline def seqViewIsSeq[CC0[X] <: SeqView[X], A0]: IsIterable[CC0[A0]] { type A = A0; type C = View[A0] } = seqViewIsSeq_[CC0, A0].asInstanceOf /** !!! Under cc, views are not Seqs and can't use SeqOps. @@ -66,7 +67,8 @@ object IsSeq { * The helper method [[stringViewIsSeq__]] is added to make the binary compatible. */ @annotation.targetName("stringViewIsSeq") - val stringViewIsSeq_ : IsSeq[StringView] { type A = Char; type C = View[Char] } = ??? + @annotation.publicInBinary + private[IsSeq] val stringViewIsSeq_ : IsSeq[StringView] { type A = Char; type C = View[Char] } = ??? inline implicit def stringViewIsSeq: IsIterable[StringView] { type A = Char; type C = View[Char] } = stringViewIsSeq_.asInstanceOf implicit val stringIsSeq: IsSeq[String] { type A = Char; type C = String } = From bb90d857a95964312b2652ab5f5f71afcf3023ff Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Fri, 1 Mar 2024 13:38:27 +0100 Subject: [PATCH 173/277] Adapt for scala/scala3 --- .github/workflows/ci.yaml | 108 +++++++++++++++---------------- project/Build.scala | 16 ++--- project/scripts/cmdScaladocTests | 6 +- 3 files changed, 65 insertions(+), 65 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a51f7337017e..80960212f8c1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -53,7 +53,7 @@ jobs: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || github.event_name == 'push' || ( github.event_name == 'pull_request' @@ -62,17 +62,17 @@ jobs: ) || ( github.event_name == 'workflow_dispatch' - && github.repository == 'lampepfl/dotty' + && github.repository == 'scala/scala3' )" steps: - name: Set JDK 17 as default run: echo "/usr/lib/jvm/java-17-openjdk-amd64/bin" >> $GITHUB_PATH - ## Workaround for https://github.com/actions/runner/issues/2033 (See https://github.com/lampepfl/dotty/pull/19720) + ## Workaround for https://github.com/actions/runner/issues/2033 (See https://github.com/scala/scala3/pull/19720) - name: Reset existing repo run: | - git config --global --add safe.directory /__w/dotty/dotty - git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -105,7 +105,7 @@ jobs: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || github.event_name == 'push' || github.event_name == 'merge_group' || ( @@ -115,7 +115,7 @@ jobs: ) || ( github.event_name == 'workflow_dispatch' - && github.repository == 'lampepfl/dotty' + && github.repository == 'scala/scala3' )" steps: @@ -124,8 +124,8 @@ jobs: - name: Reset existing repo run: | - git config --global --add safe.directory /__w/dotty/dotty - git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -164,14 +164,14 @@ jobs: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || ( github.event_name == 'pull_request' && contains(github.event.pull_request.body, '[test_scala2_library_tasty]') ) || ( github.event_name == 'workflow_dispatch' - && github.repository == 'lampepfl/dotty' + && github.repository == 'scala/scala3' )" steps: @@ -180,8 +180,8 @@ jobs: - name: Reset existing repo run: | - git config --global --add safe.directory /__w/dotty/dotty - git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -220,8 +220,8 @@ jobs: - name: Reset existing repo shell: cmd run: | - git config --global --add safe.directory /__w/dotty/dotty - git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Git Checkout uses: actions/checkout@v4 @@ -252,7 +252,7 @@ jobs: test_windows_full: runs-on: [self-hosted, Windows] - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || github.event_name == 'push' || ( github.event_name == 'pull_request' @@ -264,8 +264,8 @@ jobs: - name: Reset existing repo shell: cmd run: | - git config --global --add safe.directory /__w/dotty/dotty - git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Git Checkout uses: actions/checkout@v4 @@ -288,7 +288,7 @@ jobs: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || github.event_name == 'push' || github.event_name == 'merge_group' || ( @@ -298,7 +298,7 @@ jobs: ) || ( github.event_name == 'workflow_dispatch' - && github.repository == 'lampepfl/dotty' + && github.repository == 'scala/scala3' )" steps: - name: Set JDK 17 as default @@ -306,8 +306,8 @@ jobs: - name: Reset existing repo run: | - git config --global --add safe.directory /__w/dotty/dotty - git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -339,7 +339,7 @@ jobs: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || github.event_name == 'push' || github.event_name == 'merge_group' || ( @@ -350,7 +350,7 @@ jobs: ) || ( github.event_name == 'workflow_dispatch' - && github.repository == 'lampepfl/dotty' + && github.repository == 'scala/scala3' )" steps: @@ -358,8 +358,8 @@ jobs: run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo run: | - git config --global --add safe.directory /__w/dotty/dotty - git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -375,7 +375,7 @@ jobs: - name: Test run: | - git config --global --add safe.directory /__w/dotty/dotty + git config --global --add safe.directory /__w/scala3/scala3 git submodule sync git submodule update --init --recursive --jobs 7 ./project/scripts/sbt "community-build/testOnly dotty.communitybuild.CommunityBuildTestA" @@ -393,7 +393,7 @@ jobs: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || github.event_name == 'push' || github.event_name == 'merge_group' || ( @@ -404,7 +404,7 @@ jobs: ) || ( github.event_name == 'workflow_dispatch' - && github.repository == 'lampepfl/dotty' + && github.repository == 'scala/scala3' )" steps: @@ -412,8 +412,8 @@ jobs: run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo run: | - git config --global --add safe.directory /__w/dotty/dotty - git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -429,7 +429,7 @@ jobs: - name: Test run: | - git config --global --add safe.directory /__w/dotty/dotty + git config --global --add safe.directory /__w/scala3/scala3 git submodule sync git submodule update --init --recursive --jobs 7 ./project/scripts/sbt "community-build/testOnly dotty.communitybuild.CommunityBuildTestB" @@ -447,7 +447,7 @@ jobs: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || github.event_name == 'push' || github.event_name == 'merge_group' || ( @@ -458,7 +458,7 @@ jobs: ) || ( github.event_name == 'workflow_dispatch' - && github.repository == 'lampepfl/dotty' + && github.repository == 'scala/scala3' )" steps: @@ -466,8 +466,8 @@ jobs: run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo run: | - git config --global --add safe.directory /__w/dotty/dotty - git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -483,7 +483,7 @@ jobs: - name: Test run: | - git config --global --add safe.directory /__w/dotty/dotty + git config --global --add safe.directory /__w/scala3/scala3 git submodule sync git submodule update --init --recursive --jobs 7 ./project/scripts/sbt "community-build/testOnly dotty.communitybuild.CommunityBuildTestC" @@ -501,7 +501,7 @@ jobs: - ${{ github.workspace }}/../../cache/sbt:/root/.sbt - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || github.event_name == 'push' || ( github.event_name == 'pull_request' @@ -510,7 +510,7 @@ jobs: ) || ( github.event_name == 'workflow_dispatch' - && github.repository == 'lampepfl/dotty' + && github.repository == 'scala/scala3' )" steps: @@ -519,8 +519,8 @@ jobs: - name: Reset existing repo run: | - git config --global --add safe.directory /__w/dotty/dotty - git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -547,7 +547,7 @@ jobs: - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache - if: "github.event_name == 'schedule' && github.repository == 'lampepfl/dotty' + if: "github.event_name == 'schedule' && github.repository == 'scala/scala3' || ( github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/') @@ -559,7 +559,7 @@ jobs: ) || ( github.event_name == 'workflow_dispatch' - && github.repository == 'lampepfl/dotty' + && github.repository == 'scala/scala3' )" steps: @@ -568,8 +568,8 @@ jobs: - name: Reset existing repo run: | - git config --global --add safe.directory /__w/dotty/dotty - git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -603,7 +603,7 @@ jobs: - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache needs: [test_non_bootstrapped, test, mima, community_build_a, community_build_b, community_build_c, test_sbt, test_java8] - if: "(github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && github.repository == 'lampepfl/dotty'" + if: "(github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && github.repository == 'scala/scala3'" env: NIGHTLYBUILD: yes PGP_PW: ${{ secrets.PGP_PW }} # PGP passphrase @@ -616,8 +616,8 @@ jobs: run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo run: | - git config --global --add safe.directory /__w/dotty/dotty - git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -658,7 +658,7 @@ jobs: - ${{ github.workspace }}/../../cache/ivy:/root/.ivy2/cache - ${{ github.workspace }}/../../cache/general:/root/.cache needs: [publish_nightly] - if: "(github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && github.repository == 'lampepfl/dotty'" + if: "(github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && github.repository == 'scala/scala3'" env: NIGHTLYBUILD: yes DOTTY_WEBSITE_BOT_TOKEN: ${{ secrets.BOT_TOKEN }} # If you need to change this: @@ -672,8 +672,8 @@ jobs: steps: - name: Reset existing repo run: | - git config --global --add safe.directory /__w/dotty/dotty - git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 @@ -689,7 +689,7 @@ jobs: - name: Generate Website run: | - git config --global --add safe.directory /__w/dotty/dotty + git config --global --add safe.directory /__w/scala3/scala3 ./project/scripts/genDocs -doc-snapshot - name: Deploy Website to dotty-website @@ -727,8 +727,8 @@ jobs: run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo run: | - git config --global --add safe.directory /__w/dotty/dotty - git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/lampepfl/dotty" && git reset --hard FETCH_HEAD || true + git config --global --add safe.directory /__w/scala3/scala3 + git -c "http.https://github.com/.extraheader=" fetch --recurse-submodules=no "https://github.com/scala/scala3" && git reset --hard FETCH_HEAD || true - name: Checkout cleanup script uses: actions/checkout@v4 diff --git a/project/Build.scala b/project/Build.scala index 172290630599..ba6fe5a555fd 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -140,8 +140,8 @@ object Build { val stdlibBootstrappedVersion = "2.13.12" val dottyOrganization = "org.scala-lang" - val dottyGithubUrl = "https://github.com/lampepfl/dotty" - val dottyGithubRawUserContentUrl = "https://raw.githubusercontent.com/lampepfl/dotty" + val dottyGithubUrl = "https://github.com/scala/scala3" + val dottyGithubRawUserContentUrl = "https://raw.githubusercontent.com/scala/scala3" val isRelease = sys.env.get("RELEASEBUILD") == Some("yes") @@ -379,7 +379,7 @@ object Build { "-skip-by-regex:.+\\.impl($|\\..+)", "-project-logo", "docs/_assets/images/logo.svg", "-social-links:" + - "github::https://github.com/lampepfl/dotty," + + "github::https://github.com/scala/scala3," + "discord::https://discord.com/invite/scala," + "twitter::https://twitter.com/scala_lang", // contains special definitions which are "transplanted" elsewhere @@ -1859,7 +1859,7 @@ object Build { .add(ProjectVersion(baseVersion)) .remove[VersionsDictionaryUrl] .add(SourceLinks(List( - s"${temp.getAbsolutePath}=github://lampepfl/dotty/language-reference-stable" + s"${temp.getAbsolutePath}=github://scala/scala3/language-reference-stable" ))) .withTargets(List("___fake___.scala")) } @@ -2027,7 +2027,7 @@ object Build { scmInfo := Some( ScmInfo( url(dottyGithubUrl), - "scm:git:git@github.com:lampepfl/dotty.git" + "scm:git:git@github.com:scala/scala3.git" ) ), developers := List( @@ -2262,7 +2262,7 @@ object ScaladocConfigs { sys.env.get("GITHUB_SHA") match { case Some(sha) => s"${sourcesPrefix}github://${sys.env("GITHUB_REPOSITORY")}/$sha$outputPrefix" - case None => s"${sourcesPrefix}github://lampepfl/dotty/$v$outputPrefix" + case None => s"${sourcesPrefix}github://scala/scala3/$v$outputPrefix" } def defaultSourceLinks(version: String = dottyNonBootstrappedVersion, refVersion: String = dottyVersion) = Def.task { @@ -2273,7 +2273,7 @@ object ScaladocConfigs { scalaSrcLink(stdLibVersion, srcManaged(version, "scala") + "="), dottySrcLink(refVersion, "library/src=", "#library/src"), dottySrcLink(refVersion), - "docs=github://lampepfl/dotty/main#docs" + "docs=github://scala/scala3/main#docs" ) ) } @@ -2281,7 +2281,7 @@ object ScaladocConfigs { lazy val DefaultGenerationSettings = Def.task { def projectVersion = version.value def socialLinks = SocialLinks(List( - "github::https://github.com/lampepfl/dotty", + "github::https://github.com/scala/scala3", "discord::https://discord.com/invite/scala", "twitter::https://twitter.com/scala_lang", )) diff --git a/project/scripts/cmdScaladocTests b/project/scripts/cmdScaladocTests index e9403d988b98..06353af693f1 100755 --- a/project/scripts/cmdScaladocTests +++ b/project/scripts/cmdScaladocTests @@ -16,7 +16,7 @@ DOTTY_NONBOOTSTRAPPED_VERSION=$(eval $DOTTY_NONBOOTSTRAPPED_VERSION_COMMAND | ta DOTTY_BOOTSTRAPPED_VERSION_COMMAND="$SBT \"eval println(Build.dottyVersion)\"" DOTTY_BOOTSTRAPPED_VERSION=$(eval $DOTTY_BOOTSTRAPPED_VERSION_COMMAND | tail -n 2 | head -n 1) -SOURCE_LINKS_REPOSITORY="lampepfl/dotty" +SOURCE_LINKS_REPOSITORY="scala/scala3" SOURCE_LINKS_VERSION="${GITHUB_SHA:-$DOTTY_BOOTSTRAPPED_VERSION}" "$SBT" "scaladoc/generateTestcasesDocumentation" > "$tmp" 2>&1 || echo "generated testcases project with sbt" @@ -30,7 +30,7 @@ dist/target/pack/bin/scaladoc \ "-skip-by-regex:.+\.internal($|\..+)" \ "-skip-by-regex:.+\.impl($|\..+)" \ -project-logo docs/_assets/images/logo.svg \ - -social-links:github::https://github.com/lampepfl/dotty,discord::https://discord.com/invite/scala,twitter::https://twitter.com/scala_lang \ + -social-links:github::https://github.com/scala/scala3,discord::https://discord.com/invite/scala,twitter::https://twitter.com/scala_lang \ -Ygenerate-inkuire \ "-skip-by-id:scala.runtime.stdLibPatches" \ "-skip-by-id:scala.runtime.MatchCase" \ @@ -42,4 +42,4 @@ dist/target/pack/bin/scaladoc \ -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/," \ out/bootstrap/scaladoc-testcases/scala-"${DOTTY_NONBOOTSTRAPPED_VERSION}"/classes > "$tmp" 2>&1 || echo "generated testcases project with scripts" -diff -rq "$OUT1" "scaladoc/output/testcases" +diff -r "$OUT1" "scaladoc/output/testcases" From f86c0bcdfd5bc0aff99dc8a889e2a9de9c426209 Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Fri, 1 Mar 2024 20:40:08 +0100 Subject: [PATCH 174/277] Update links in the repository to scala/scala3 --- .github/ISSUE_TEMPLATE/feature.md | 4 +- .github/ISSUE_TEMPLATE/improve-error.md | 6 +- .github/workflows/scripts/publish-sdkman.sh | 4 +- MAINTENANCE.md | 6 +- NOTICE.md | 2 +- README.md | 4 +- bench/profiles/compiletime.yml | 12 ++-- bench/profiles/default.yml | 2 +- bench/profiles/empty.yml | 8 +-- bench/profiles/exhaustivity.yml | 20 +++---- bench/profiles/implicits.yml | 10 ++-- bench/profiles/misc.yml | 4 +- bench/profiles/projects.yml | 2 +- bench/profiles/pull.yml | 2 +- bench/profiles/quotes.yml | 8 +-- bench/profiles/sbt.yml | 2 +- bench/profiles/tuples.yml | 16 ++--- bench/profiles/typing.yml | 4 +- .../tools/backend/jvm/BCodeHelpers.scala | 4 +- .../tools/backend/jvm/BCodeSkelBuilder.scala | 4 +- .../backend/jvm/DottyBackendInterface.scala | 2 +- compiler/src/dotty/tools/dotc/Driver.scala | 6 +- compiler/src/dotty/tools/dotc/ast/Trees.scala | 2 +- .../tools/dotc/interactive/Interactive.scala | 2 +- .../tools/dotc/interactive/SourceTree.scala | 2 +- compiler/src/dotty/tools/dotc/report.scala | 2 +- .../tools/dotc/transform/ExpandPrivate.scala | 4 +- .../dotc/transform/InstrumentCoverage.scala | 2 +- .../dotty/tools/dotc/typer/ProtoTypes.scala | 2 +- compiler/test/dotty/tools/io/PathTest.scala | 2 +- dist/bin/scalac | 2 +- dist/bin/scalac.bat | 2 +- .../2016-02-17-scaling-dot-soundness.md | 8 +-- .../_posts/2016-05-05-multiversal-equality.md | 4 +- .../2016-12-05-implicit-function-types.md | 4 +- ...017-05-31-first-dotty-milestone-release.md | 8 +-- ...17-07-12-second-dotty-milestone-release.md | 60 +++++++++---------- ...017-09-07-third-dotty-milestone-release.md | 26 ++++---- ...17-10-16-fourth-dotty-milestone-release.md | 14 ++--- ...017-12-01-fifth-dotty-milestone-release.md | 12 ++-- ...8-03-05-seventh-dotty-milestone-release.md | 18 +++--- ...18-04-27-eighth-dotty-milestone-release.md | 16 ++--- ...018-07-06-ninth-dotty-milestone-release.md | 20 +++---- ...2018-10-10-10th-dotty-milestone-release.md | 10 ++-- ...2018-11-30-11th-dotty-milestone-release.md | 8 +-- ...2019-01-21-12th-dotty-milestone-release.md | 8 +-- ...2019-03-05-13th-dotty-milestone-release.md | 32 +++++----- ...2019-04-15-14th-dotty-milestone-release.md | 6 +- ...2019-05-23-15th-dotty-milestone-release.md | 16 ++--- ...2019-06-11-16th-dotty-milestone-release.md | 18 +++--- ...2019-07-25-17th-dotty-milestone-release.md | 14 ++--- ...2019-08-30-18th-dotty-milestone-release.md | 30 +++++----- ...2019-09-23-19th-dotty-milestone-release.md | 6 +- ...2019-11-04-20th-dotty-milestone-release.md | 12 ++-- ...2019-12-20-21th-dotty-milestone-release.md | 8 +-- ...2020-02-05-22nd-dotty-milestone-release.md | 18 +++--- ...2020-03-18-23rd-dotty-milestone-release.md | 6 +- ...2020-04-29-24th-dotty-milestone-release.md | 8 +-- ...2020-06-22-25th-dotty-milestone-release.md | 8 +-- ...2020-07-27-26th-dotty-milestone-release.md | 10 ++-- ...2020-08-31-27th-dotty-milestone-release.md | 24 ++++---- docs/_blog/_posts/2020-11-09-scala3-m1.md | 26 ++++---- docs/_blog/_posts/2020-12-18-scala3-m3.md | 42 ++++++------- docs/_blog/_posts/2021-02-17-scala3-rc1.md | 50 ++++++++-------- docs/_blog/_posts/2021-03-31-scala3-rc2.md | 24 ++++---- docs/_blog/_posts/2021-04-21-scala3-rc3.md | 24 ++++---- .../2021-06-07-scala3.0.1-rc1-release.md | 42 ++++++------- docs/_blog/_posts/2021-06-25-scala301-rc2.md | 6 +- .../contributing/architecture/context.md | 2 +- .../contributing/architecture/lifecycle.md | 16 ++--- .../_docs/contributing/architecture/phases.md | 40 ++++++------- .../contributing/architecture/symbols.md | 16 ++--- docs/_docs/contributing/architecture/time.md | 10 ++-- docs/_docs/contributing/architecture/types.md | 4 +- docs/_docs/contributing/community-build.md | 6 +- .../contributing/debugging/ide-debugging.md | 8 +-- .../contributing/debugging/inspection.md | 6 +- .../contributing/debugging/other-debugging.md | 16 ++--- docs/_docs/contributing/getting-started.md | 6 +- docs/_docs/contributing/index.md | 4 +- docs/_docs/contributing/issues/areas.md | 28 ++++----- docs/_docs/contributing/issues/cause.md | 8 +-- docs/_docs/contributing/issues/reproduce.md | 4 +- docs/_docs/contributing/procedures/release.md | 12 ++-- docs/_docs/contributing/sending-in-a-pr.md | 6 +- .../_docs/contributing/setting-up-your-ide.md | 2 +- docs/_docs/contributing/testing.md | 8 +-- docs/_docs/internals/coverage.md | 2 +- docs/_docs/internals/debug-macros.md | 2 +- docs/_docs/internals/dotc-scalac.md | 6 +- docs/_docs/internals/overall-structure.md | 14 ++--- docs/_docs/internals/periods.md | 6 +- docs/_docs/internals/type-system.md | 8 +-- .../changed-features/eta-expansion-spec.md | 2 +- .../implicit-conversions-spec.md | 2 +- .../changed-features/structural-types-spec.md | 4 +- .../contextual/by-name-context-parameters.md | 2 +- .../contextual/multiversal-equality.md | 6 +- .../reference/dropped-features/auto-apply.md | 2 +- .../dropped-features/type-projection.md | 2 +- docs/_docs/reference/enums/adts.md | 2 +- docs/_docs/reference/enums/enums.md | 6 +- .../reference/experimental/explicit-nulls.md | 2 +- .../reference/experimental/tupled-function.md | 6 +- .../reference/features-classification.md | 6 +- .../metaprogramming/compiletime-ops.md | 4 +- .../dependent-function-types-spec.md | 6 +- .../new-types/intersection-types-spec.md | 2 +- .../new-types/polymorphic-function-types.md | 2 +- .../other-new-features/open-classes.md | 2 +- .../parameter-untupling-spec.md | 2 +- .../other-new-features/parameter-untupling.md | 2 +- docs/_docs/reference/overview.md | 2 +- docs/_docs/release-notes-0.1.2.md | 40 ++++++------- .../dropped-features/auto-apply.md | 2 +- docs/_spec/APPLIEDreference/enums/enums.md | 2 +- .../APPLIEDreference/new-types/union-types.md | 4 +- .../changed-features/eta-expansion-spec.md | 2 +- .../implicit-conversions-spec.md | 2 +- .../changed-features/structural-types-spec.md | 4 +- .../contextual/by-name-context-parameters.md | 2 +- .../contextual/multiversal-equality.md | 6 +- .../dropped-features/type-projection.md | 2 +- .../experimental/explicit-nulls.md | 2 +- .../experimental/tupled-function.md | 6 +- .../TODOreference/features-classification.md | 6 +- .../metaprogramming/compiletime-ops.md | 4 +- .../dependent-function-types-spec.md | 6 +- .../new-types/polymorphic-function-types.md | 2 +- .../parameter-untupling-spec.md | 2 +- .../other-new-features/parameter-untupling.md | 2 +- docs/_spec/TODOreference/overview.md | 2 +- docs/_spec/_layouts/default.yml | 2 +- docs/_spec/_layouts/toc.yml | 2 +- .../runtime/stdLibPatches/language.scala | 2 +- .../main/dotty/tools/pc/HoverProvider.scala | 2 +- .../dotty/tools/pc/MetalsInteractive.scala | 2 +- .../src/main/dotty/tools/pc/PcCollector.scala | 6 +- .../dotty/tools/pc/SemanticdbSymbols.scala | 4 +- .../pc/completions/CompletionProvider.scala | 2 +- .../pc/tests/completion/CompletionSuite.scala | 2 +- .../tools/pc/tests/hover/HoverTermSuite.scala | 2 +- .../tools/pc/tests/hover/HoverTypeSuite.scala | 4 +- .../signaturehelp/SignatureHelpSuite.scala | 2 +- project/scripts/bootstrappedOnlyCmdTests | 4 +- .../tools/xsbt/CompilerBridgeDriver.java | 2 +- sbt-bridge/src/xsbt/CachedCompilerImpl.java | 2 +- sbt-test/sbt-bridge/zinc-13-compat/test | 2 +- .../src/main/scala/MultiversalEquality.scala | 2 +- .../inspector/src/main/scala/main.scala | 2 +- .../malformed-class-name-with-dollar/test | 2 +- .../src/tests/nonScala3Parent.scala | 2 +- .../tools/scaladoc/tasty/TypesSupport.scala | 2 +- .../dotty/tools/scaladoc/ScaladocTest.scala | 2 +- tests/explicit-nulls/pos/nn2.scala | 2 +- tests/init/pos/i9795.scala | 4 +- tests/neg/i11118.scala | 2 +- tests/neg/i4060.scala | 2 +- tests/pos-macros/i9361.scala | 2 +- .../backend/jvm/BCodeHelpers.scala | 4 +- .../backend/jvm/BCodeSkelBuilder.scala | 4 +- .../backend/jvm/DottyBackendInterface.scala | 2 +- tests/pos/erasure-array.scala | 2 +- tests/pos/i10242.scala | 2 +- tests/pos/i11681.scala | 2 +- tests/pos/i12663.scala | 2 +- tests/pos/i12679.scala | 2 +- tests/pos/i14096.scala | 2 +- tests/pos/i14271.scala | 2 +- tests/pos/i14278.scala | 2 +- tests/pos/i14642.scala | 2 +- tests/pos/i14830.scala | 2 +- tests/pos/i15546.scala | 2 +- tests/pos/i5700.scala | 2 +- tests/pos/i7414.scala | 2 +- tests/pos/i7445a.scala | 2 +- tests/pos/i7445b.scala | 2 +- tests/pos/i7653.scala | 2 +- tests/pos/i7790.scala | 2 +- tests/pos/i7807.scala | 2 +- tests/pos/i8300.scala | 2 +- tests/pos/kind-projector.scala | 2 +- tests/run-macros/f-interpolator-tests.scala | 2 +- tests/run/i11583.scala | 2 +- tests/run/i11706.scala | 2 +- tests/run/i12032.scala | 2 +- tests/run/i13216.scala | 2 +- tests/run/i13334.scala | 2 +- tests/run/i13691b.scala | 2 +- tests/run/i14582.scala | 2 +- tests/run/i15913.scala | 2 +- tests/run/i4192/TestCases.scala | 2 +- tests/run/i4496b.scala | 2 +- tests/semanticdb/expect/Advanced.expect.scala | 2 +- tests/semanticdb/expect/Advanced.scala | 2 +- 195 files changed, 672 insertions(+), 672 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md index 52f8010c372e..afbaa8020e07 100644 --- a/.github/ISSUE_TEMPLATE/feature.md +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -1,10 +1,10 @@ --- name: "\U0001F389 Suggest a feature" -about: Please create a feature request here https://github.com/lampepfl/dotty/discussions/new?category=feature-requests +about: Please create a feature request here https://github.com/scala/scala3/discussions/new?category=feature-requests title: '' labels: '' assignees: '' --- -Please create a feature request in the [Dotty Discussions](https://github.com/lampepfl/dotty/discussions/new?category=feature-requests). +Please create a feature request in the [Dotty Discussions](https://github.com/scala/scala3/discussions/new?category=feature-requests). diff --git a/.github/ISSUE_TEMPLATE/improve-error.md b/.github/ISSUE_TEMPLATE/improve-error.md index 918196e1ec53..72d556951e53 100644 --- a/.github/ISSUE_TEMPLATE/improve-error.md +++ b/.github/ISSUE_TEMPLATE/improve-error.md @@ -19,7 +19,7 @@ This code should be self-contained, reproducible (i.e. produces the expected err Ideally, we should be able to just copy this code in a file and run `scalac` (and maybe `scala`) to reproduce the issue. -For a good example, see https://github.com/lampepfl/dotty/issues/18657 +For a good example, see https://github.com/scala/scala3/issues/18657 --> ```Scala @@ -44,12 +44,12 @@ for example: ## Why this Error/Warning was not helpful - + The message was unhelpful because... ## Suggested improvement - + It could be made more helpful by... diff --git a/.github/workflows/scripts/publish-sdkman.sh b/.github/workflows/scripts/publish-sdkman.sh index 70987bff175b..f959c426e9d8 100755 --- a/.github/workflows/scripts/publish-sdkman.sh +++ b/.github/workflows/scripts/publish-sdkman.sh @@ -10,8 +10,8 @@ set -u # latest stable dotty version -DOTTY_VERSION=$(curl -s https://api.github.com/repos/lampepfl/dotty/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') -DOTTY_URL="https://github.com/lampepfl/dotty/releases/download/$DOTTY_VERSION/scala3-$DOTTY_VERSION.zip" +DOTTY_VERSION=$(curl -s https://api.github.com/repos/scala/scala3/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') +DOTTY_URL="https://github.com/scala/scala3/releases/download/$DOTTY_VERSION/scala3-$DOTTY_VERSION.zip" # checking if dotty version is available if ! curl --output /dev/null --silent --head --fail "$DOTTY_URL"; then diff --git a/MAINTENANCE.md b/MAINTENANCE.md index 5537d6648a2a..79e55e11d4a9 100644 --- a/MAINTENANCE.md +++ b/MAINTENANCE.md @@ -15,11 +15,11 @@ The issue supervisor is responsible for: - Modifying issue labels to best capture information about the issues - Attempting to reproduce the issue (or label “stat:cannot reproduce”) - Further minimizing the issue or asking the reporter of the issue to minimize it correctly (or label “stat:needs minimization”) - - Identifying which issues are of considerable importance and bringing them to the attention of the team during the Dotty meeting, where they can be filtered and added to the [Future Versions](https://github.com/lampepfl/dotty/milestone/46) milestone. + - Identifying which issues are of considerable importance and bringing them to the attention of the team during the Dotty meeting, where they can be filtered and added to the [Future Versions](https://github.com/scala/scala3/milestone/46) milestone. - Identifying if a report is really a feature request and if so, converting it to - a [feature request discussion](https://github.com/lampepfl/dotty/discussions/categories/feature-requests). + a [feature request discussion](https://github.com/scala/scala3/discussions/categories/feature-requests). - Keeping an eye on new -[discussions](https://github.com/lampepfl/dotty/discussions), making sure they +[discussions](https://github.com/scala/scala3/discussions), making sure they don't go unanswered and also correctly labeling new feature requests. Other core teammates are responsible for providing information to the issue supervisor in a timely manner when it is requested if they have that information. diff --git a/NOTICE.md b/NOTICE.md index e9b64ac262f2..fd931397a500 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -104,4 +104,4 @@ major authors were omitted by oversight. [3] https://github.com/sbt/sbt/tree/0.13/compile/interface/src/main/scala/xsbt [4] https://github.com/scoverage/scalac-scoverage-plugin [5] https://github.com/scalameta/metals -[6] https://github.com/lampepfl/dotty/pull/5783/files +[6] https://github.com/scala/scala3/pull/5783/files diff --git a/README.md b/README.md index 1e62e90a1845..6c3212f0676b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ Dotty ===== -[![Dotty CI](https://github.com/lampepfl/dotty/workflows/Dotty/badge.svg?branch=master)](https://github.com/lampepfl/dotty/actions?query=branch%3Amain) +[![Dotty CI](https://github.com/scala/scala3/workflows/Dotty/badge.svg?branch=master)](https://github.com/scala/scala3/actions?query=branch%3Amain) [![Join the chat at https://discord.com/invite/scala](https://img.shields.io/discord/632150470000902164)](https://discord.com/invite/scala) * [Documentation](https://docs.scala-lang.org/scala3/) @@ -23,7 +23,7 @@ other more direct lines of communication such as email. How to Contribute ================= * [Getting Started as Contributor](https://docs.scala-lang.org/scala3/guides/contribution/contribution-intro.html) -* [Issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) +* [Issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) License ======= diff --git a/bench/profiles/compiletime.yml b/bench/profiles/compiletime.yml index fd77df7dfe9a..520af3750aa4 100644 --- a/bench/profiles/compiletime.yml +++ b/bench/profiles/compiletime.yml @@ -1,31 +1,31 @@ charts: - name: "Compile-time sums of constant integer types (generated)" - url: https://github.com/lampepfl/dotty/blob/main/bench/src/main/scala/generateBenchmarks.scala + url: https://github.com/scala/scala3/blob/main/bench/src/main/scala/generateBenchmarks.scala lines: - key: compiletime-sum-constants label: bootstrapped - name: "Compile-time sums of term reference types (generated)" - url: https://github.com/lampepfl/dotty/blob/main/bench/src/main/scala/generateBenchmarks.scala + url: https://github.com/scala/scala3/blob/main/bench/src/main/scala/generateBenchmarks.scala lines: - key: compiletime-sum-termrefs label: bootstrapped - name: "Sums of term references, result type inferred (generated)" - url: https://github.com/lampepfl/dotty/blob/main/bench/src/main/scala/generateBenchmarks.scala + url: https://github.com/scala/scala3/blob/main/bench/src/main/scala/generateBenchmarks.scala lines: - key: compiletime-sum-termrefs-terms label: bootstrapped - name: "Compile-time sums of type applications (generated)" - url: https://github.com/lampepfl/dotty/blob/main/bench/src/main/scala/generateBenchmarks.scala + url: https://github.com/scala/scala3/blob/main/bench/src/main/scala/generateBenchmarks.scala lines: - key: compiletime-sum-applications label: bootstrapped - name: "Compile-time additions inside multiplications (generated)" - url: https://github.com/lampepfl/dotty/blob/main/bench/src/main/scala/generateBenchmarks.scala + url: https://github.com/scala/scala3/blob/main/bench/src/main/scala/generateBenchmarks.scala lines: - key: compiletime-distribute label: bootstrapped @@ -48,4 +48,4 @@ scripts: - measure 6 6 7 1 $PROG_HOME/dotty/bench/tests-generated/compiletime-ops/distribute.scala config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/default.yml b/bench/profiles/default.yml index 22ed6d5f31df..5867816217fe 100644 --- a/bench/profiles/default.yml +++ b/bench/profiles/default.yml @@ -11,4 +11,4 @@ includes: config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/empty.yml b/bench/profiles/empty.yml index ac571e64e831..108150d3934e 100644 --- a/bench/profiles/empty.yml +++ b/bench/profiles/empty.yml @@ -1,19 +1,19 @@ charts: - name: "empty class" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/empty-class.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/empty-class.scala lines: - key: empty-class label: bootstrapped - name: "empty object" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/empty-object.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/empty-object.scala lines: - key: empty-object label: bootstrapped - name: "empty file" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/empty-file.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/empty-file.scala lines: - key: empty-file label: bootstrapped @@ -30,4 +30,4 @@ scripts: - measure $PROG_HOME/dotty/tests/bench/empty-file.scala config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/exhaustivity.yml b/bench/profiles/exhaustivity.yml index af6eb4041f6c..47710f7cb39f 100644 --- a/bench/profiles/exhaustivity.yml +++ b/bench/profiles/exhaustivity.yml @@ -1,54 +1,54 @@ charts: - name: "exhaustivity check" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/patmatexhaust.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/patmatexhaust.scala lines: - key: patmatexhaust label: bootstrapped - name: "exhaustivity I" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/exhaustivity-I.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/exhaustivity-I.scala lines: - key: exhaustivity-I label: bootstrapped - name: "exhaustivity S" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/exhaustivity-S.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/exhaustivity-S.scala lines: - key: exhaustivity-S label: bootstrapped - name: "exhaustivity T" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/exhaustivity-T.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/exhaustivity-T.scala lines: - key: exhaustivity-T label: bootstrapped - name: "exhaustivity V" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/exhaustivity-V.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/exhaustivity-V.scala lines: - key: exhaustivity-V label: bootstrapped - name: "exhaustivity MIPS" - url: https://github.com/lampepfl/dotty/blob/main/tests/patmat/i7186.scala + url: https://github.com/scala/scala3/blob/main/tests/patmat/i7186.scala lines: - key: exhaustivity-mips label: bootstrapped - name: "exhaustivity i12241" - url: https://github.com/lampepfl/dotty/blob/main/tests/patmat/i12241.scala + url: https://github.com/scala/scala3/blob/main/tests/patmat/i12241.scala lines: - key: exhaustivity-i12241 label: bootstrapped - name: "exhaustivity i12358" - url: https://github.com/lampepfl/dotty/blob/main/tests/patmat/i12358.scala + url: https://github.com/scala/scala3/blob/main/tests/patmat/i12358.scala lines: - key: exhaustivity-i12358 label: bootstrapped - name: "exhaustivity i13565" - url: https://github.com/lampepfl/dotty/blob/main/tests/pos/i13565.scala + url: https://github.com/scala/scala3/blob/main/tests/pos/i13565.scala lines: - key: exhaustivity-i13565 label: bootstrapped @@ -83,4 +83,4 @@ scripts: - measure 20 40 3 $PROG_HOME/dotty/tests/pos/i13565.scala config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/implicits.yml b/bench/profiles/implicits.yml index 3e944b5be28b..ff7f8c34b872 100644 --- a/bench/profiles/implicits.yml +++ b/bench/profiles/implicits.yml @@ -1,6 +1,6 @@ charts: - name: "implicit cache I" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/implicit_cache.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/implicit_cache.scala lines: - key: implicit-cache label: bootstrapped @@ -8,7 +8,7 @@ charts: label: from tasty - name: "implicit cache II" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/implicitNums.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/implicitNums.scala lines: - key: implicitNums label: bootstrapped @@ -16,13 +16,13 @@ charts: label: from tasty - name: "implicit scope loop" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/implicit-scope-loop.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/implicit-scope-loop.scala lines: - key: implicit-scope-loop label: bootstrapped - name: "inductive implicits" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/inductive-implicits.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/inductive-implicits.scala lines: - key: inductive-implicits label: bootstrapped @@ -48,4 +48,4 @@ scripts: - source $PROG_HOME/dotty/bench/scripts/implicitNums-from-tasty config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/misc.yml b/bench/profiles/misc.yml index 668f8e60c176..7ef168a0eea9 100644 --- a/bench/profiles/misc.yml +++ b/bench/profiles/misc.yml @@ -1,13 +1,13 @@ charts: - name: "issue #1535" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/i1535.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/i1535.scala lines: - key: i1535 label: bootstrapped - name: "issue #1687" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/i1687.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/i1687.scala lines: - key: i1687 label: bootstrapped diff --git a/bench/profiles/projects.yml b/bench/profiles/projects.yml index f1133d180c54..72e506290bad 100644 --- a/bench/profiles/projects.yml +++ b/bench/profiles/projects.yml @@ -41,4 +41,4 @@ scripts: - source $PROG_HOME/dotty/bench/scripts/stdlib213 config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/pull.yml b/bench/profiles/pull.yml index 163d75a8769d..4760e27daf95 100644 --- a/bench/profiles/pull.yml +++ b/bench/profiles/pull.yml @@ -5,4 +5,4 @@ includes: - empty.yml config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/quotes.yml b/bench/profiles/quotes.yml index afd970543aa1..454cd0dc5faa 100644 --- a/bench/profiles/quotes.yml +++ b/bench/profiles/quotes.yml @@ -1,18 +1,18 @@ charts: - name: "Inline a quote" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/power-macro/PowerInlined-1.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/power-macro/PowerInlined-1.scala lines: - key: power-macro-power-inlined-1 label: bootstrapped - name: "Inline 1k quotes" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/power-macro/PowerInlined-1k.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/power-macro/PowerInlined-1k.scala lines: - key: power-macro-power-inlined-1k label: bootstrapped - name: "Quote String interpolation matching" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/string-interpolation-macro/Test.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/string-interpolation-macro/Test.scala lines: - key: quote-string-interpolation-matching label: bootstrapped @@ -29,4 +29,4 @@ scripts: - source $PROG_HOME/dotty/bench/scripts/quote-string-interpolation-matching config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/sbt.yml b/bench/profiles/sbt.yml index 3ab0e43f3db2..653b10381959 100644 --- a/bench/profiles/sbt.yml +++ b/bench/profiles/sbt.yml @@ -12,4 +12,4 @@ scripts: - measure -with-compiler -Yforce-sbt-phases -with-dotty $(find $PROG_HOME/dotty/compiler/src/dotty -name *.scala -o -name *.java) config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/tuples.yml b/bench/profiles/tuples.yml index 5e41ecf7c80d..24bf76f786cc 100644 --- a/bench/profiles/tuples.yml +++ b/bench/profiles/tuples.yml @@ -1,42 +1,42 @@ charts: - name: "Tuple22 creation with Tuple22.apply" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/tuple22-creation-apply.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/tuple22-creation-apply.scala lines: - key: tuple22-creation-apply label: bootstrapped - name: "Tuple22 creation with *:" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/tuple22-creation-cons.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/tuple22-creation-cons.scala lines: - key: tuple22-creation-cons label: bootstrapped - name: "Tuple22.tail" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/tuple22-tails.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/tuple22-tails.scala lines: - key: tuple22-tails label: bootstrapped - name: "Tuple22.apply" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/tuple22-apply.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/tuple22-apply.scala lines: - key: tuple22-apply label: bootstrapped - name: "Tuple22.size" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/tuple22-size.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/tuple22-size.scala lines: - key: tuple22-size label: bootstrapped - name: "Tuple reverse (Runtime)" - url: https://github.com/lampepfl/dotty/blob/main/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/TupleOps.scala#L59 + url: https://github.com/scala/scala3/blob/main/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/TupleOps.scala#L59 lines: - key: tuple-reverse label: bootstrapped - name: "Tuple flatMap (Runtime)" - url: https://github.com/lampepfl/dotty/blob/main/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/TupleOps.scala#L64 + url: https://github.com/scala/scala3/blob/main/bench-run/src/main/scala/dotty/tools/benchmarks/tuples/TupleOps.scala#L64 lines: - key: tuple-flatMap label: bootstrapped @@ -65,4 +65,4 @@ scripts: - measure-run TupleOps.flatMap config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/bench/profiles/typing.yml b/bench/profiles/typing.yml index f6476bca7006..929438cb5a93 100644 --- a/bench/profiles/typing.yml +++ b/bench/profiles/typing.yml @@ -1,6 +1,6 @@ charts: - name: "Find Ref" - url: https://github.com/lampepfl/dotty/blob/main/tests/bench/FindRef.scala + url: https://github.com/scala/scala3/blob/main/tests/bench/FindRef.scala lines: - key: find-ref label: bootstrapped @@ -11,4 +11,4 @@ scripts: - measure $PROG_HOME/dotty/tests/bench/FindRef.scala config: - pr_base_url: "https://github.com/lampepfl/dotty/pull/" + pr_base_url: "https://github.com/scala/scala3/pull/" diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala b/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala index 2ad58fea4cd1..385521e2785f 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala @@ -754,7 +754,7 @@ trait BCodeHelpers extends BCodeIdiomatic { case tp => report.warning( s"an unexpected type representation reached the compiler backend while compiling ${ctx.compilationUnit}: $tp. " + - "If possible, please file a bug on https://github.com/lampepfl/dotty/issues") + "If possible, please file a bug on https://github.com/scala/scala3/issues") tp match { case tp: ThisType if tp.cls == defn.ArrayClass => ObjectRef.asInstanceOf[ct.bTypes.ClassBType] // was introduced in 9b17332f11 to fix SI-999, but this code is not reached in its test, or any other test @@ -795,7 +795,7 @@ trait BCodeHelpers extends BCodeIdiomatic { report.error( em"""|compiler bug: created invalid generic signature for $sym in ${sym.denot.owner.showFullName} |signature: $sig - |if this is reproducible, please report bug at https://github.com/lampepfl/dotty/issues + |if this is reproducible, please report bug at https://github.com/scala/scala3/issues """, sym.sourcePos) throw ex } diff --git a/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala b/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala index 0ab9ed85b6cf..394700c2898e 100644 --- a/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala +++ b/compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala @@ -191,7 +191,7 @@ trait BCodeSkelBuilder extends BCodeHelpers { // Should we do this transformation earlier, say in Constructors? Or would that just cause // pain for scala-{js, native}? // - // @sjrd (https://github.com/lampepfl/dotty/pull/9181#discussion_r457458205): + // @sjrd (https://github.com/scala/scala3/pull/9181#discussion_r457458205): // moving that before the back-end would make things significantly more complicated for // Scala.js and Native. Both have a first-class concept of ModuleClass, and encode the // singleton pattern of MODULE$ in a completely different way. In the Scala.js IR, there @@ -202,7 +202,7 @@ trait BCodeSkelBuilder extends BCodeHelpers { // TODO: remove `!f.name.is(LazyBitMapName)` once we change lazy val encoding - // https://github.com/lampepfl/dotty/issues/7140 + // https://github.com/scala/scala3/issues/7140 // // Lazy val encoding assumes bitmap fields are non-static // diff --git a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index 37045bda17ec..8016c2bfc209 100644 --- a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -126,7 +126,7 @@ object DottyBackendInterface { * See also `genPlainClass` in `BCodeSkelBuilder.scala`. * * TODO: remove the special handing of `LazyBitMapName` once we swtich to - * the new lazy val encoding: https://github.com/lampepfl/dotty/issues/7140 + * the new lazy val encoding: https://github.com/scala/scala3/issues/7140 */ def isStaticModuleField(using Context): Boolean = sym.owner.isStaticModuleClass && sym.isField && !sym.name.is(LazyBitMapName) && !sym.name.is(LazyLocalName) diff --git a/compiler/src/dotty/tools/dotc/Driver.scala b/compiler/src/dotty/tools/dotc/Driver.scala index fc5367d2ccba..196752aceb29 100644 --- a/compiler/src/dotty/tools/dotc/Driver.scala +++ b/compiler/src/dotty/tools/dotc/Driver.scala @@ -126,7 +126,7 @@ class Driver { * The trade-off is that you can only pass a SimpleReporter to this method * and not a normal Reporter which is more powerful. * - * Usage example: [[https://github.com/lampepfl/dotty/tree/master/compiler/test/dotty/tools/dotc/InterfaceEntryPointTest.scala]] + * Usage example: [[https://github.com/scala/scala3/tree/master/compiler/test/dotty/tools/dotc/InterfaceEntryPointTest.scala]] * * @param args Arguments to pass to the compiler. * @param simple Used to log errors, warnings, and info messages. @@ -143,7 +143,7 @@ class Driver { /** Principal entry point to the compiler. * - * Usage example: [[https://github.com/lampepfl/dotty/tree/master/compiler/test/dotty/tools/dotc/EntryPointsTest.scala.disabled]] + * Usage example: [[https://github.com/scala/scala3/tree/master/compiler/test/dotty/tools/dotc/EntryPointsTest.scala.disabled]] * in method `runCompiler` * * @param args Arguments to pass to the compiler. @@ -182,7 +182,7 @@ class Driver { * the other overloads cannot be overridden, instead you * should override this one which they call internally. * - * Usage example: [[https://github.com/lampepfl/dotty/tree/master/compiler/test/dotty/tools/dotc/EntryPointsTest.scala.disabled]] + * Usage example: [[https://github.com/scala/scala3/tree/master/compiler/test/dotty/tools/dotc/EntryPointsTest.scala.disabled]] * in method `runCompilerWithContext` * * @param args Arguments to pass to the compiler. diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index f35acdfaaafe..41899ed661f5 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -1503,7 +1503,7 @@ object Trees { * It ensures that the source is correct, and that the local context is used if * that's necessary for transforming the whole tree. * TODO: ensure transform is always called with the correct context as argument - * @see https://github.com/lampepfl/dotty/pull/13880#discussion_r836395977 + * @see https://github.com/scala/scala3/pull/13880#discussion_r836395977 */ def transformCtx(tree: Tree)(using Context): Context = val sourced = diff --git a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala index a03ae502f2f1..16079125a434 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala @@ -250,7 +250,7 @@ object Interactive { * Note that if the given `pos` points out places for incomplete parses, * this method returns `errorTermTree` (`Literal(Consotant(null)`). * - * @see https://github.com/lampepfl/dotty/issues/15294 + * @see https://github.com/scala/scala3/issues/15294 */ def pathTo(trees: List[SourceTree], pos: SourcePosition)(using Context): List[Tree] = pathTo(trees.map(_.tree), pos.span) diff --git a/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala b/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala index 258d92a2d1a8..b950d71eb045 100644 --- a/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala +++ b/compiler/src/dotty/tools/dotc/interactive/SourceTree.scala @@ -33,7 +33,7 @@ case class SourceTree(tree: tpd.Import | tpd.NameTree, source: SourceFile) { } val position = { // FIXME: This is incorrect in some cases, like with backquoted identifiers, - // see https://github.com/lampepfl/dotty/pull/1634#issuecomment-257079436 + // see https://github.com/scala/scala3/pull/1634#issuecomment-257079436 val (start, end) = if (!treeSpan.isSynthetic) (treeSpan.point, treeSpan.point + nameLength) diff --git a/compiler/src/dotty/tools/dotc/report.scala b/compiler/src/dotty/tools/dotc/report.scala index 8e39afdd6e7d..a63b6569fefe 100644 --- a/compiler/src/dotty/tools/dotc/report.scala +++ b/compiler/src/dotty/tools/dotc/report.scala @@ -154,7 +154,7 @@ object report: | | An unhandled exception was thrown in the compiler. | Please file a crash report here: - | https://github.com/lampepfl/dotty/issues/new/choose + | https://github.com/scala/scala3/issues/new/choose | For non-enriched exceptions, compile with -Yno-enrich-error-messages. | |$info1 diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala index fa2492a261d5..9a6a04621074 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala @@ -25,8 +25,8 @@ import ValueClasses.* * This is necessary since private methods are not allowed to have the same name * as inherited public ones. * - * See discussion in https://github.com/lampepfl/dotty/pull/784 - * and https://github.com/lampepfl/dotty/issues/783 + * See discussion in https://github.com/scala/scala3/pull/784 + * and https://github.com/scala/scala3/issues/783 */ class ExpandPrivate extends MiniPhase with IdentityDenotTransformer { thisPhase => import ast.tpd.* diff --git a/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala b/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala index a76919e47164..f5e0f8c63b58 100644 --- a/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala +++ b/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala @@ -120,7 +120,7 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer: start = pos.start, end = pos.end, // +1 to account for the line number starting at 1 - // the internal line number is 0-base https://github.com/lampepfl/dotty/blob/18ada516a85532524a39a962b2ddecb243c65376/compiler/src/dotty/tools/dotc/util/SourceFile.scala#L173-L176 + // the internal line number is 0-base https://github.com/scala/scala3/blob/18ada516a85532524a39a962b2ddecb243c65376/compiler/src/dotty/tools/dotc/util/SourceFile.scala#L173-L176 line = pos.line + 1, desc = sourceFile.content.slice(pos.start, pos.end).mkString, symbolName = tree.symbol.name.toSimpleName.show, diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index 9d5c1352b106..c8012bef0904 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -126,7 +126,7 @@ object ProtoTypes { constrainResult(mt, pt) } } else { - // Best-effort to fix https://github.com/lampepfl/dotty/issues/9685 in the 3.3.x series + // Best-effort to fix https://github.com/scala/scala3/issues/9685 in the 3.3.x series // while preserving source compatibility as much as possible val methodMatchedType = constrainResult(mt, wildApprox(pt)) meth.is(Transparent) || methodMatchedType diff --git a/compiler/test/dotty/tools/io/PathTest.scala b/compiler/test/dotty/tools/io/PathTest.scala index 731d29cee8e6..a3755e0ea7dc 100644 --- a/compiler/test/dotty/tools/io/PathTest.scala +++ b/compiler/test/dotty/tools/io/PathTest.scala @@ -3,7 +3,7 @@ package dotty.tools.io import org.junit.Test class PathTest { - // Ref https://github.com/lampepfl/dotty/issues/11644#issuecomment-792457275 + // Ref https://github.com/scala/scala3/issues/11644#issuecomment-792457275 @Test def parent(): Unit = { testParent(Path(""), Directory("..")) testParent(Path("."), Directory("..")) diff --git a/dist/bin/scalac b/dist/bin/scalac index 4b888641e786..d9bd21ca425b 100644 --- a/dist/bin/scalac +++ b/dist/bin/scalac @@ -40,7 +40,7 @@ while [[ $# -gt 0 ]]; do # pass all remaining arguments to scala, e.g. to avoid interpreting them here as -D or -J while [[ $# -gt 0 ]]; do addScala "$1" && shift ; done ;; - # Optimize for short-running applications, see https://github.com/lampepfl/dotty/issues/222 + # Optimize for short-running applications, see https://github.com/scala/scala3/issues/222 -Oshort) addScala "-Oshort" && \ addJava "-XX:+TieredCompilation" && addJava "-XX:TieredStopAtLevel=1" && shift ;; diff --git a/dist/bin/scalac.bat b/dist/bin/scalac.bat index 454158c85666..cb1a76471f70 100644 --- a/dist/bin/scalac.bat +++ b/dist/bin/scalac.bat @@ -55,7 +55,7 @@ if defined _CONSUME_REMAINING ( set _SCALA_ARGS=!_SCALA_ARGS! "%__ARG%" shift ) else if "%__ARG%"=="-Oshort" ( - @rem optimize for short-running applications, see https://github.com/lampepfl/dotty/issues/222 + @rem optimize for short-running applications, see https://github.com/scala/scala3/issues/222 set _JAVA_ARGS=!_JAVA_ARGS! "-XX:+TieredCompilation" "-XX:TieredStopAtLevel=1" set _SCALA_ARGS=!_SCALA_ARGS! -Oshort shift diff --git a/docs/_blog/_posts/2016-02-17-scaling-dot-soundness.md b/docs/_blog/_posts/2016-02-17-scaling-dot-soundness.md index 7619545b844e..bc9c558e3011 100644 --- a/docs/_blog/_posts/2016-02-17-scaling-dot-soundness.md +++ b/docs/_blog/_posts/2016-02-17-scaling-dot-soundness.md @@ -69,9 +69,9 @@ categories: is not associated with a runtime value. We can in fact construct soundness issues in all of these cases. Look -at the discussion for issues [#50](https://github.com/lampepfl/dotty/issues/50) -and [#1050](https://github.com/lampepfl/dotty/issues/1050) in the -[Dotty](https://github.com/lampepfl/dotty/issues/1050) repository +at the discussion for issues [#50](https://github.com/scala/scala3/issues/50) +and [#1050](https://github.com/scala/scala3/issues/1050) in the +[Dotty](https://github.com/scala/scala3/issues/1050) repository on GitHub. All issues work fundamentally in the same way: Construct a type `S` which has a type member `T` with bad bounds, say: @@ -98,7 +98,7 @@ course. The promise is usually broken at run-time by failing with a ## Plugging the Loopholes To get back to soundness we need to plug the loopholes. Some of the -necessary measures are taken in pull request [#1051](https://github.com/lampepfl/dotty/issues/1051). +necessary measures are taken in pull request [#1051](https://github.com/scala/scala3/issues/1051). That pull request - tightens the rules for overrides of lazy values: lazy values diff --git a/docs/_blog/_posts/2016-05-05-multiversal-equality.md b/docs/_blog/_posts/2016-05-05-multiversal-equality.md index 236225eec318..d9a48a9f4424 100644 --- a/docs/_blog/_posts/2016-05-05-multiversal-equality.md +++ b/docs/_blog/_posts/2016-05-05-multiversal-equality.md @@ -6,7 +6,7 @@ authorImg: images/martin.jpg date: 2016-05-05 --- -I have been working recently on making equality tests using `==` and `!=` safer in Scala. This has led to a [Language Enhancement Proposal](https://github.com/lampepfl/dotty/issues/1247) which I summarize in this blog. +I have been working recently on making equality tests using `==` and `!=` safer in Scala. This has led to a [Language Enhancement Proposal](https://github.com/scala/scala3/issues/1247) which I summarize in this blog. ## Why Change Equality? @@ -77,7 +77,7 @@ Given a set of `Eq` instances, the idea is that the Scala compiler will check ev So this means we still keep universal equality as it is in Scala now - we don't have a choice here anyway, because of backwards compatibility. But we render it safe by checking that for each comparison the corresponding `Eq` instance exists. -What about types for which no `Eq` instance exists? To maintain backwards compatibility, we allow comparisons of such types as well, by means of a fall-back `eqAny` instance. But we do not allow comparisons between types that have an `Eq` instance and types that have none. Details are explained in the [proposal](https://github.com/lampepfl/dotty/issues/1247). +What about types for which no `Eq` instance exists? To maintain backwards compatibility, we allow comparisons of such types as well, by means of a fall-back `eqAny` instance. But we do not allow comparisons between types that have an `Eq` instance and types that have none. Details are explained in the [proposal](https://github.com/scala/scala3/issues/1247). ## Properties diff --git a/docs/_blog/_posts/2016-12-05-implicit-function-types.md b/docs/_blog/_posts/2016-12-05-implicit-function-types.md index ba28159c0fa3..0d9eae53d37f 100644 --- a/docs/_blog/_posts/2016-12-05-implicit-function-types.md +++ b/docs/_blog/_posts/2016-12-05-implicit-function-types.md @@ -6,7 +6,7 @@ authorImg: images/martin.jpg date: 2016-12-05 --- -I just made the [first pull request](https://github.com/lampepfl/dotty/pull/1775) to add _implicit function types_ to +I just made the [first pull request](https://github.com/scala/scala3/pull/1775) to add _implicit function types_ to Scala. I am pretty excited about it, because - citing the explanation of the pull request - "_This is the first step to bring contextual abstraction to Scala_". What do I mean by this? @@ -181,7 +181,7 @@ implicit Transaction => Int ``` Just like the normal function type syntax `A => B`, desugars to `scala.Function1[A, B]` the implicit function type syntax `implicit A => B` desugars to `scala.ImplicitFunction1[A, B]`. -The same holds at other function arities. With Dotty's [pull request #1758](https://github.com/lampepfl/dotty/pull/1758) +The same holds at other function arities. With Dotty's [pull request #1758](https://github.com/scala/scala3/pull/1758) merged there is no longer an upper limit of 22 for such functions. The type `ImplicitFunction1` can be thought of being defined as follows: diff --git a/docs/_blog/_posts/2017-05-31-first-dotty-milestone-release.md b/docs/_blog/_posts/2017-05-31-first-dotty-milestone-release.md index 9bfd22b2e3db..3063e658537d 100644 --- a/docs/_blog/_posts/2017-05-31-first-dotty-milestone-release.md +++ b/docs/_blog/_posts/2017-05-31-first-dotty-milestone-release.md @@ -46,7 +46,7 @@ using Dotty with sbt, see the Releases are available for download on the _Releases_ section of the Dotty repository: -https://github.com/lampepfl/dotty/releases +https://github.com/scala/scala3/releases We also provide a [homebrew](https://brew.sh/) package that can be installed by running @@ -92,9 +92,9 @@ See here for the full [version number explanation](https://dotty.epfl.ch/docs/us Over the coming weeks and months, we plan to work on the following topics: - - [Integrate Local optimizations developed in Dotty linker](https://github.com/lampepfl/dotty/pull/2513); - - [Add Language-level support for HMaps and HLists](https://github.com/lampepfl/dotty/pull/2199); - - [Port global optimizations from Dotty linker](https://github.com/lampepfl/dotty/pull/1840). + - [Integrate Local optimizations developed in Dotty linker](https://github.com/scala/scala3/pull/2513); + - [Add Language-level support for HMaps and HLists](https://github.com/scala/scala3/pull/2199); + - [Port global optimizations from Dotty linker](https://github.com/scala/scala3/pull/1840). If you want to get your hands dirty with any of this, now is a good moment to get involved! Join the team of contributors, including diff --git a/docs/_blog/_posts/2017-07-12-second-dotty-milestone-release.md b/docs/_blog/_posts/2017-07-12-second-dotty-milestone-release.md index 9172b5ad67ec..ff314eed13f2 100644 --- a/docs/_blog/_posts/2017-07-12-second-dotty-milestone-release.md +++ b/docs/_blog/_posts/2017-07-12-second-dotty-milestone-release.md @@ -34,52 +34,52 @@ The [previous technology preview](/_blog/_posts/2017-05-31-first-dotty-milestone This technology preview is geared towards improving stability and reliability. It includes: - - [Local optimizations upstreamed from the Dotty Linker](https://github.com/lampepfl/dotty/pull/2513), [2647](https://github.com/lampepfl/dotty/pull/2647) by ([@OlivierBlanvillain](https://github.com/OlivierBlanvillain)). See more details below. - - [Optimizing Pattern Matcher](https://github.com/lampepfl/dotty/pull/2829) by ([@odersky](https://github.com/odersky)) - - [Idempotency checks](https://github.com/lampepfl/dotty/pull/2756) are the first step to reproducible builds - - [Faster Base class sets](https://github.com/lampepfl/dotty/pull/2676) by ([@odersky](https://github.com/odersky)) and ([@darkdimius](https://twitter.com/darkdimius)) + - [Local optimizations upstreamed from the Dotty Linker](https://github.com/scala/scala3/pull/2513), [2647](https://github.com/scala/scala3/pull/2647) by ([@OlivierBlanvillain](https://github.com/OlivierBlanvillain)). See more details below. + - [Optimizing Pattern Matcher](https://github.com/scala/scala3/pull/2829) by ([@odersky](https://github.com/odersky)) + - [Idempotency checks](https://github.com/scala/scala3/pull/2756) are the first step to reproducible builds + - [Faster Base class sets](https://github.com/scala/scala3/pull/2676) by ([@odersky](https://github.com/odersky)) and ([@darkdimius](https://twitter.com/darkdimius)) - Numerous fixes to IDE and Dotty Language Server covering: - - [Windows support for VS Code plugin](https://github.com/lampepfl/dotty/pull/2776) - - [Fix hover-on-type for implicitly converted expressions](https://github.com/lampepfl/dotty/pull/2836) - - [Fixes to find all references in external projects](https://github.com/lampepfl/dotty/pull/2810), [2773](https://github.com/lampepfl/dotty/pull/2773/files) - - [Fix conflict with dragos-vscode-scala](https://github.com/lampepfl/dotty/pull/2777) - - [Fix ide crash on non-parsable file](https://github.com/lampepfl/dotty/pull/2752) - - [Fix hover functionality for enum classes](https://github.com/lampepfl/dotty/pull/2722) - - [Report errors on Dotty Language Server initialization](https://github.com/lampepfl/dotty/pull/2708) - - [Fixes to sbt setting up Dotty IDE](https://github.com/lampepfl/dotty/pull/2690) - - General stability improvements [2838](https://github.com/lampepfl/dotty/pull/2838), [2787](https://github.com/lampepfl/dotty/pull/2787), [2692](https://github.com/lampepfl/dotty/pull/2692) + - [Windows support for VS Code plugin](https://github.com/scala/scala3/pull/2776) + - [Fix hover-on-type for implicitly converted expressions](https://github.com/scala/scala3/pull/2836) + - [Fixes to find all references in external projects](https://github.com/scala/scala3/pull/2810), [2773](https://github.com/scala/scala3/pull/2773/files) + - [Fix conflict with dragos-vscode-scala](https://github.com/scala/scala3/pull/2777) + - [Fix ide crash on non-parsable file](https://github.com/scala/scala3/pull/2752) + - [Fix hover functionality for enum classes](https://github.com/scala/scala3/pull/2722) + - [Report errors on Dotty Language Server initialization](https://github.com/scala/scala3/pull/2708) + - [Fixes to sbt setting up Dotty IDE](https://github.com/scala/scala3/pull/2690) + - General stability improvements [2838](https://github.com/scala/scala3/pull/2838), [2787](https://github.com/scala/scala3/pull/2787), [2692](https://github.com/scala/scala3/pull/2692) - Scalac compatibility improvements: - - [Support Scala 2.12 traits](https://github.com/lampepfl/dotty/pull/2685) - - [Fixes to handling of Scala 2 classfiles](https://github.com/lampepfl/dotty/pull/2834/files) - - [Scalac parser crashes on Dotty.jar](https://github.com/lampepfl/dotty/pull/2719) + - [Support Scala 2.12 traits](https://github.com/scala/scala3/pull/2685) + - [Fixes to handling of Scala 2 classfiles](https://github.com/scala/scala3/pull/2834/files) + - [Scalac parser crashes on Dotty.jar](https://github.com/scala/scala3/pull/2719) - Java compatibility improvements: - - [Fixes to handing of Java generic signatures](https://github.com/lampepfl/dotty/pull/2831) - - [java.lang.System.out is final but that's a lie](https://github.com/lampepfl/dotty/pull/2781) + - [Fixes to handing of Java generic signatures](https://github.com/scala/scala3/pull/2831) + - [java.lang.System.out is final but that's a lie](https://github.com/scala/scala3/pull/2781) - Improved error messages: - - [Nicer error message for "implicit function type needs non-empty parameter list"](https://github.com/lampepfl/dotty/pull/2821) - - [Nicer error message for nonsensical modifier combination](https://github.com/lampepfl/dotty/pull/2807/files), [2747](https://github.com/lampepfl/dotty/pull/2747) - - [Nicer error message for supercall inside @inline method](https://github.com/lampepfl/dotty/pull/2740) - - [Check that case classes don't inherit case classes](https://github.com/lampepfl/dotty/pull/2790) - - [Check that named parameters don't conflict with positional ones](https://github.com/lampepfl/dotty/pull/2785) + - [Nicer error message for "implicit function type needs non-empty parameter list"](https://github.com/scala/scala3/pull/2821) + - [Nicer error message for nonsensical modifier combination](https://github.com/scala/scala3/pull/2807/files), [2747](https://github.com/scala/scala3/pull/2747) + - [Nicer error message for supercall inside @inline method](https://github.com/scala/scala3/pull/2740) + - [Check that case classes don't inherit case classes](https://github.com/scala/scala3/pull/2790) + - [Check that named parameters don't conflict with positional ones](https://github.com/scala/scala3/pull/2785) - Improved command line handling: - - [Support params in a file like @file.txt](https://github.com/lampepfl/dotty/pull/2765) + - [Support params in a file like @file.txt](https://github.com/scala/scala3/pull/2765) - Type system stability: - - [Handle wildcard types in unions and intersections](https://github.com/lampepfl/dotty/pull/2742) + - [Handle wildcard types in unions and intersections](https://github.com/scala/scala3/pull/2742) - Fixes to implicit search: - - [Fix shadowing of higher order implicits](https://github.com/lampepfl/dotty/pull/2739) + - [Fix shadowing of higher order implicits](https://github.com/scala/scala3/pull/2739) ### Better generated code: @@ -313,7 +313,7 @@ using Dotty with sbt, see the Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) We also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -338,10 +338,10 @@ You can try it out there without installing anything. Over the coming weeks and months, we plan to work on the following topics: - - [Add support for using Dotty generated classes with Scala 2.12](https://github.com/lampepfl/dotty/pull/2827) - - [Add Language-level support for HMaps and HLists](https://github.com/lampepfl/dotty/pull/2199); + - [Add support for using Dotty generated classes with Scala 2.12](https://github.com/scala/scala3/pull/2827) + - [Add Language-level support for HMaps and HLists](https://github.com/scala/scala3/pull/2199); - Upstream more optimizations from Dotty Linker - - [Add support for existing in the same classpath with Scala 2.12](https://github.com/lampepfl/dotty/pull/2827) + - [Add support for existing in the same classpath with Scala 2.12](https://github.com/scala/scala3/pull/2827) If you want to get your hands dirty with any of this, now is a good moment to get involved! Join the team of contributors, including diff --git a/docs/_blog/_posts/2017-09-07-third-dotty-milestone-release.md b/docs/_blog/_posts/2017-09-07-third-dotty-milestone-release.md index 236591139105..01fec156ecde 100644 --- a/docs/_blog/_posts/2017-09-07-third-dotty-milestone-release.md +++ b/docs/_blog/_posts/2017-09-07-third-dotty-milestone-release.md @@ -33,12 +33,12 @@ stability and reliability: This technology preview further improves stability and reliability. Some highlighted PRs are: - IDE bug fixes: - [#2986](https://github.com/lampepfl/dotty/pull/2986), - [#2932](https://github.com/lampepfl/dotty/pull/2932), - [#2885](https://github.com/lampepfl/dotty/pull/2885), - [#2876](https://github.com/lampepfl/dotty/pull/2876), - [#2870](https://github.com/lampepfl/dotty/pull/2870), - [#2872](https://github.com/lampepfl/dotty/pull/2872) by [@odersky] and [@smarter]. + [#2986](https://github.com/scala/scala3/pull/2986), + [#2932](https://github.com/scala/scala3/pull/2932), + [#2885](https://github.com/scala/scala3/pull/2885), + [#2876](https://github.com/scala/scala3/pull/2876), + [#2870](https://github.com/scala/scala3/pull/2870), + [#2872](https://github.com/scala/scala3/pull/2872) by [@odersky] and [@smarter]. ## How can you try it out? @@ -65,7 +65,7 @@ using Dotty with sbt, see the ### Standalone installation Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) We also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -87,16 +87,16 @@ You can try it out there without installing anything. ## What are the next steps? Over the coming weeks and months, we plan to work on the following topics: - - [Add support for using Dotty generated classes with Scala 2.12](https://github.com/lampepfl/dotty/pull/2827) - - [Add Language-level support for HMaps and HLists](https://github.com/lampepfl/dotty/pull/2199); + - [Add support for using Dotty generated classes with Scala 2.12](https://github.com/scala/scala3/pull/2827) + - [Add Language-level support for HMaps and HLists](https://github.com/scala/scala3/pull/2199); - Upstream more optimizations from Dotty Linker - - [Add support for existing in the same classpath with Scala 2.12](https://github.com/lampepfl/dotty/pull/2827) - - [Add native Dotty REPL](https://github.com/lampepfl/dotty/pull/2991) + - [Add support for existing in the same classpath with Scala 2.12](https://github.com/scala/scala3/pull/2827) + - [Add native Dotty REPL](https://github.com/scala/scala3/pull/2991) ## Questions / Reporting Bugs If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing Thank you to all the contributors who made this release possible! @@ -122,7 +122,7 @@ According to `git shortlog -sn --no-merges 0.2.0-RC1..0.3.0-RC2` these are: If you want to get your hands dirty with any of this, now is a good moment to get involved! You can have a look at our [Getting Started page](https://dotty.epfl.ch/docs/contributing/getting-started.html), our [Awesome Error Messages](http://scala-lang.org/blog/2016/10/14/dotty-errors.html) or some of -the simple [Dotty issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +the simple [Dotty issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry-points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2017-10-16-fourth-dotty-milestone-release.md b/docs/_blog/_posts/2017-10-16-fourth-dotty-milestone-release.md index 7f98c4835ee6..1edf198380c8 100644 --- a/docs/_blog/_posts/2017-10-16-fourth-dotty-milestone-release.md +++ b/docs/_blog/_posts/2017-10-16-fourth-dotty-milestone-release.md @@ -25,14 +25,14 @@ stability and reliability. ## What’s new in the 0.4.0-RC1 technology preview? -### Rewritten REPL [#2991](https://github.com/lampepfl/dotty/pull/2991) +### Rewritten REPL [#2991](https://github.com/scala/scala3/pull/2991) The original Dotty REPL was a proof of concept hacked together from -[an ancient version of the scalac REPL](https://github.com/lampepfl/dotty/pull/1082#issuecomment-183905504). +[an ancient version of the scalac REPL](https://github.com/scala/scala3/pull/1082#issuecomment-183905504). It worked by creating Scala source files from the user input using string concatenation, this made it easy to adapt it for Dotty since it did not rely on the internals of scalac, but it was also fragile and hard to reason about. -The [new REPL](https://github.com/lampepfl/dotty/pull/2991) instead works by +The [new REPL](https://github.com/scala/scala3/pull/2991) instead works by manipulating ASTs (Abstract Syntax Trees), this is more robust and will make it easier to develop new features: we have already implemented auto-completion support (by reusing the APIs we had created for @@ -42,7 +42,7 @@ Note that the user interface of the REPL has not changed: like in the old REPL we use code adapted from the [Ammonite REPL](http://ammonite.io/#Ammonite-REPL) to provide syntax highlighting, multi-line editing, history, etc. -### Scala 2.12 support [#2827](https://github.com/lampepfl/dotty/pull/2827) +### Scala 2.12 support [#2827](https://github.com/scala/scala3/pull/2827) Since our first release, it has been possible to use Scala 2 libraries in a Dotty project as explained in the [dotty-example-project](https://github.com/smarter/dotty-example-project#getting-your-project-to-compile-with-dotty). @@ -82,7 +82,7 @@ the IDE sections of the [getting-started page](https://docs.scala-lang.org/scala ### Standalone installation Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) We also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -99,7 +99,7 @@ brew upgrade dotty ## Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing Thank you to all the contributors who made this release possible! @@ -131,7 +131,7 @@ According to `git shortlog -sn --no-merges 0.3.0-RC2..0.4.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! You can have a look at our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), the [Awesome Error Messages](http://scala-lang.org/blog/2016/10/14/dotty-errors.html) project or some of -the simple [Dotty issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +the simple [Dotty issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry-points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2017-12-01-fifth-dotty-milestone-release.md b/docs/_blog/_posts/2017-12-01-fifth-dotty-milestone-release.md index 60d1062b7eac..dfc97e64f496 100644 --- a/docs/_blog/_posts/2017-12-01-fifth-dotty-milestone-release.md +++ b/docs/_blog/_posts/2017-12-01-fifth-dotty-milestone-release.md @@ -25,7 +25,7 @@ support for Scala 2.12 and came with a brand new REPL. ## What’s new in the 0.5.0-RC1 technology preview? -### Reworked implicit search [#3421](https://github.com/lampepfl/dotty/pull/3421) +### Reworked implicit search [#3421](https://github.com/scala/scala3/pull/3421) The treatment of ambiguity errors has changed. If an ambiguity is encountered in some recursive step of an implicit search, the ambiguity is propagated to the caller. Example: Say you have the following definitions: @@ -56,7 +56,7 @@ techniques no longer work. But there is now a new special type `scala.implicits. implements negation directly. For any query type `Q`: `Not[Q]` succeeds if and only if the implicit search for `Q` fails. -### Dependent function types [#3464](https://github.com/lampepfl/dotty/pull/3464) +### Dependent function types [#3464](https://github.com/scala/scala3/pull/3464) A dependent function type describes functions where the result type may depend on the function's parameter values. Example: @@ -108,7 +108,7 @@ are currently two backends using the TASTY frontend: This is the first step toward linking and whole word optimisations, recompiling code to a different backends... -### Generic java signatures [#3234](https://github.com/lampepfl/dotty/pull/3234) +### Generic java signatures [#3234](https://github.com/scala/scala3/pull/3234) Dotty now emits generic signatures for classes and methods. Those signatures are used by compilers, debuggers and to support runtime reflection. For example: @@ -144,7 +144,7 @@ the IDE sections of the [getting-started page](https://docs.scala-lang.org/scala ### Standalone installation Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) We also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -161,7 +161,7 @@ brew upgrade dotty ## Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing Thank you to all the contributors who made this release possible! @@ -198,7 +198,7 @@ According to `git shortlog -sn --no-merges 0.4.0-RC1..0.5.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! You can have a look at our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), the [Awesome Error Messages](http://scala-lang.org/blog/2016/10/14/dotty-errors.html) project or some of -the simple [Dotty issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +the simple [Dotty issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry-points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2018-03-05-seventh-dotty-milestone-release.md b/docs/_blog/_posts/2018-03-05-seventh-dotty-milestone-release.md index a72e04409ea0..a70d71bc17b8 100644 --- a/docs/_blog/_posts/2018-03-05-seventh-dotty-milestone-release.md +++ b/docs/_blog/_posts/2018-03-05-seventh-dotty-milestone-release.md @@ -19,12 +19,12 @@ You can learn more about Dotty on our [website](http://dotty.epfl.ch). This is our seventh scheduled release according to our [6-week release schedule](https://dotty.epfl.ch/docs/usage/version-numbers.html). -The [previous technology preview](https://github.com/lampepfl/dotty/releases/tag/0.6.0-RC1) focussed +The [previous technology preview](https://github.com/scala/scala3/releases/tag/0.6.0-RC1) focussed on bug fixes and stability work. ## What’s new in the 0.7.0-RC1 technology preview? -### Enum Simplification [#4003](https://github.com/lampepfl/dotty/pull/4003) +### Enum Simplification [#4003](https://github.com/scala/scala3/pull/4003) The previously introduced syntax and rules for enum were arguably too complex. We can considerably simplify them by taking away one capability: that cases can have bodies which can define members. Arguably, if we choose an ADT decomposition of a problem, it's good style to write all methods using @@ -75,7 +75,7 @@ and how to use them to model [Algebraic Data Types](https://dotty.epfl.ch/docs/r visit the respective sections in our documentation. -### Erased terms [#3342](https://github.com/lampepfl/dotty/pull/3342) +### Erased terms [#3342](https://github.com/scala/scala3/pull/3342) The `erased` modifier can be used on parameters, `val` and `def` to enforce that no reference to those terms is ever used. As they are never used, they can safely be removed during compilation. @@ -103,10 +103,10 @@ For more information, visit the [Erased Terms](https://dotty.epfl.ch/docs/refere section of our documentation. **Note**: Erased terms replace _phantom types_: they have similar semantics, but with the added -advantage that any type can be an erased parameter. See [#3410](https://github.com/lampepfl/dotty/pull/3410). +advantage that any type can be an erased parameter. See [#3410](https://github.com/scala/scala3/pull/3410). -### Improved IDE support [#3960](https://github.com/lampepfl/dotty/pull/3960) +### Improved IDE support [#3960](https://github.com/scala/scala3/pull/3960) The Dotty language server now supports context sensitive IDE completions. Completions now include local and imported definitions. Members completions take possible implicit conversions into account. @@ -183,7 +183,7 @@ compile-time. For example, writing `(eval(a), eval(a))` instead of `(eval(a), eval(b))` in the example above should be an error, but it was not caught by Scala 2 or previous versions of Dotty, whereas we now get a type mismatch error as expected. More work remains to be done to fix the remaining [GADT-related -issues](https://github.com/lampepfl/dotty/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+gadt), +issues](https://github.com/scala/scala3/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+gadt), but so far no show-stopper has been found. ## Trying out Dotty @@ -210,7 +210,7 @@ the IDE sections of the [getting-started page](https://docs.scala-lang.org/scala ### Standalone installation Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) We also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -227,7 +227,7 @@ brew upgrade dotty ## Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing Thank you to all the contributors who made this release possible! @@ -255,7 +255,7 @@ According to `git shortlog -sn --no-merges 0.6.0..0.7.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry-points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2018-04-27-eighth-dotty-milestone-release.md b/docs/_blog/_posts/2018-04-27-eighth-dotty-milestone-release.md index 72c0747e659d..d2194594edcc 100644 --- a/docs/_blog/_posts/2018-04-27-eighth-dotty-milestone-release.md +++ b/docs/_blog/_posts/2018-04-27-eighth-dotty-milestone-release.md @@ -24,12 +24,12 @@ You can learn more about Dotty on our [website](https://dotty.epfl.ch). This is our eighth scheduled release according to our [6-week release schedule](https://dotty.epfl.ch/docs/usage/version-numbers.html). -The [previous technology preview](https://github.com/lampepfl/dotty/releases/tag/0.7.0-RC1) simplified +The [previous technology preview](https://github.com/scala/scala3/releases/tag/0.7.0-RC1) simplified enums, introduced erased terms, improved IDE support and improved pattern matching for GADT. ## What’s new in the 0.8.0-RC1 technology preview? -### sbt 1 support [#3872](https://github.com/lampepfl/dotty/pull/3872) +### sbt 1 support [#3872](https://github.com/scala/scala3/pull/3872) Starting with Dotty 0.8.0, we will only support versions of sbt >= 1.1.4. Migrating to sbt 1 lets us use the new improved incremental compiler for Scala called [Zinc](https://github.com/sbt/zinc), and enables integration with tools such as [Bloop](https://scalacenter.github.io/bloop/). @@ -43,7 +43,7 @@ If you are already using Dotty with sbt 0.13, follow these simple steps to upgra ``` - replace usages of `.withDottyCompat()` by `.withDottyCompat(scalaVersion.value)` -### Unchecked warnings [#4045](https://github.com/lampepfl/dotty/pull/4045) +### Unchecked warnings [#4045](https://github.com/scala/scala3/pull/4045) Dotty now emits `unchecked` warnings like `scalac` whenever a type test is performed but cannot be fully checked at runtime because of type erasure. For example: @@ -64,7 +64,7 @@ def foo[T](x: T) = x match { } ``` -### Kind Polymorphism [#4108](https://github.com/lampepfl/dotty/pull/4108) +### Kind Polymorphism [#4108](https://github.com/scala/scala3/pull/4108) Normally type parameters in Scala are partitioned into kinds. First-level types are types of values. Higher-kinded types are type constructors such as `List` or `Map`. The kind of a type is indicated by the top type of which it is a subtype. Normal types are subtypes of `Any`, covariant single @@ -94,7 +94,7 @@ f[[X] =>> String] (i.e. `-Ykind-polymorphism`). For more information, visit the [Kind Polymorphism](https://dotty.epfl.ch/docs/reference/other-new-features/kind-polymorphism.html) section of our documentation. -### Improved support for SAM type [#4152](https://github.com/lampepfl/dotty/pull/4152) +### Improved support for SAM type [#4152](https://github.com/scala/scala3/pull/4152) This release includes fixes to [SAM types](https://www.scala-lang.org/news/2.12.0/#lambda-syntax-for-sam-types) that greatly improve interoperability with Java 8 lambdas. One can now easily write Scala code that uses Java streams: @@ -139,7 +139,7 @@ the IDE sections of the [getting-started page](https://docs.scala-lang.org/scala ### Standalone installation Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) We also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -156,7 +156,7 @@ brew upgrade dotty ## Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing Thank you to all the contributors who made this release possible! @@ -187,7 +187,7 @@ According to `git shortlog -sn --no-merges 0.7.0..0.8.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry-points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2018-07-06-ninth-dotty-milestone-release.md b/docs/_blog/_posts/2018-07-06-ninth-dotty-milestone-release.md index 914eca4d73d3..73066551300b 100644 --- a/docs/_blog/_posts/2018-07-06-ninth-dotty-milestone-release.md +++ b/docs/_blog/_posts/2018-07-06-ninth-dotty-milestone-release.md @@ -24,23 +24,23 @@ You can learn more about Dotty on our [website](https://dotty.epfl.ch). This is our ninth scheduled release according to our [6-week release schedule](https://dotty.epfl.ch/docs/usage/version-numbers.html). -The [previous technology preview](https://github.com/lampepfl/dotty/releases/tag/0.8.0-RC1) added +The [previous technology preview](https://github.com/scala/scala3/releases/tag/0.8.0-RC1) added support for sbt 1, introduced improved unchecked warnings and improved SAM type support. ## What’s new in the 0.9.0-RC1 technology preview? -### Improved REPL [#4680](https://github.com/lampepfl/dotty/pull/4680) +### Improved REPL [#4680](https://github.com/scala/scala3/pull/4680) The REPL now uses [JLine 3](https://github.com/jline/jline3) under the hood which improves on many aspects such as, auto-completions and multi-line editing. The REPL now also works on Windows! -### Documentation support in the IDE [#4461](https://github.com/lampepfl/dotty/pull/4461), [#4648](https://github.com/lampepfl/dotty/pull/4648) +### Documentation support in the IDE [#4461](https://github.com/scala/scala3/pull/4461), [#4648](https://github.com/scala/scala3/pull/4648) The Dotty IDE will now display documentation while hovering over symbols that were previously compiled by the Dotty compiler. In the future, we plan to let users query the documentation in the REPL as well. -### Drop requirement that implicit functions must be non-empty [#4549](https://github.com/lampepfl/dotty/pull/4549) +### Drop requirement that implicit functions must be non-empty [#4549](https://github.com/scala/scala3/pull/4549) We remove the arbitrary restriction that parameters of implicit functions must by non-empty. We can now write: ```scala @@ -63,7 +63,7 @@ timed { Both definitions above are equivalent. -### Emit feature warnings for implicit conversions [#4229](https://github.com/lampepfl/dotty/pull/4229) +### Emit feature warnings for implicit conversions [#4229](https://github.com/scala/scala3/pull/4229) Implicit conversions are easily the most misused feature in Scala. We now emit feature warnings when encountering an implicit conversion definition, just like Scala 2 does. @@ -76,7 +76,7 @@ unless the conversion is: (we might extend this to more conversions). -### Optimise s and raw interpolators [#3961](https://github.com/lampepfl/dotty/pull/3961) +### Optimise s and raw interpolators [#3961](https://github.com/scala/scala3/pull/3961) `s` and `raw` string interpolators were known to be slower than their not type-safe counterparts: ```scala s"Hello $name!" @@ -89,7 +89,7 @@ The compiler will now desugar the former into the latter. Special thanks to compiler! -### Support for compiler plugins [#3438](https://github.com/lampepfl/dotty/pull/3438) +### Support for compiler plugins [#3438](https://github.com/scala/scala3/pull/3438) Dotty now supports Compiler plugins. Compiler plugins let you customize the compiler pipeline without having to modify the compiler source code. A major difference compared to Scala 2 is that Dotty plugins must run after the type checker. Being able to influence normal type checking @@ -123,7 +123,7 @@ the IDE sections of the [getting-started page](https://docs.scala-lang.org/scala ### Standalone installation Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) We also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -144,7 +144,7 @@ installing anything. Note however that Scastie only supports Dotty 0.7.0-RC1. ## Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing Thank you to all the contributors who made this release possible! @@ -180,7 +180,7 @@ According to `git shortlog -sn --no-merges 0.8.0..0.9.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry-points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2018-10-10-10th-dotty-milestone-release.md b/docs/_blog/_posts/2018-10-10-10th-dotty-milestone-release.md index b583d1bd0f49..0a5ebd067391 100644 --- a/docs/_blog/_posts/2018-10-10-10th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2018-10-10-10th-dotty-milestone-release.md @@ -99,7 +99,7 @@ or the enclosing class did not change at call site. E.g. This restriction has now been removed. We also improve upon `scalac` which is not able to optimise methods that change the type of `this` on a polymorphic recursive call. -[Examples](https://github.com/lampepfl/dotty/blob/7a45a4a386d33180e5b7b21aa74271a77cce4707/tests/neg-tailcall/tailrec.scala#L43-L44) +[Examples](https://github.com/scala/scala3/blob/7a45a4a386d33180e5b7b21aa74271a77cce4707/tests/neg-tailcall/tailrec.scala#L43-L44) can be found in our test suite. ### Experimental support for generic Tuples @@ -125,7 +125,7 @@ val t2: (Int, String, Long, Int, String, Long) = (1,2,3,1,2,3) ### And much more! -Please read our [release notes](https://github.com/lampepfl/dotty/releases/tag/0.10.0-RC1) +Please read our [release notes](https://github.com/scala/scala3/releases/tag/0.10.0-RC1) for more details! ## Breaking changes @@ -160,7 +160,7 @@ the IDE sections of the [getting-started page](https://docs.scala-lang.org/scala Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) For macOS users, we also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -179,7 +179,7 @@ brew upgrade dotty If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -222,7 +222,7 @@ According to `git shortlog -sn --no-merges 0.9.0..0.10.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2018-11-30-11th-dotty-milestone-release.md b/docs/_blog/_posts/2018-11-30-11th-dotty-milestone-release.md index 344900e2e164..268d86db00c6 100644 --- a/docs/_blog/_posts/2018-11-30-11th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2018-11-30-11th-dotty-milestone-release.md @@ -115,7 +115,7 @@ information from the Scaladoc comment, then format it before we display it in th ### And much more! -Please read our [release notes](https://github.com/lampepfl/dotty/releases/tag/0.11.0-RC1) +Please read our [release notes](https://github.com/scala/scala3/releases/tag/0.11.0-RC1) for more details! ## Trying out Dotty @@ -146,7 +146,7 @@ the IDE sections of the [getting-started page](https://docs.scala-lang.org/scala Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) For macOS users, we also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -165,7 +165,7 @@ brew upgrade dotty If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -201,7 +201,7 @@ According to `git shortlog -sn --no-merges 0.10.0..0.11.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-01-21-12th-dotty-milestone-release.md b/docs/_blog/_posts/2019-01-21-12th-dotty-milestone-release.md index f9fc25375d86..d56a03b4e345 100644 --- a/docs/_blog/_posts/2019-01-21-12th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-01-21-12th-dotty-milestone-release.md @@ -106,7 +106,7 @@ This kind of reasoning is necessary for many advanced GADT usages! ### And much more! -Please read our [release notes](https://github.com/lampepfl/dotty/releases/tag/0.12.0-RC1) +Please read our [release notes](https://github.com/scala/scala3/releases/tag/0.12.0-RC1) for more details! ## Trying out Dotty @@ -137,7 +137,7 @@ the IDE sections of the [getting-started page](https://docs.scala-lang.org/scala Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) For macOS users, we also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -156,7 +156,7 @@ brew upgrade dotty If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -195,7 +195,7 @@ According to `git shortlog -sn --no-merges 0.11.0-RC1..0.12.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-03-05-13th-dotty-milestone-release.md b/docs/_blog/_posts/2019-03-05-13th-dotty-milestone-release.md index f1838847d81e..8ebb70ea59e5 100644 --- a/docs/_blog/_posts/2019-03-05-13th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-03-05-13th-dotty-milestone-release.md @@ -50,11 +50,11 @@ smoothly, but the *Parallelism and Concurrency* course given in the Spring semester teaches Spark, which means we needed to support it in Dotty! Luckily, this turned out to be mostly straightforward: we adopted the [object -serialization scheme](https://github.com/lampepfl/dotty/pull/5775) and [lambda -serialization scheme](https://github.com/lampepfl/dotty/pull/5837) pioneered by +serialization scheme](https://github.com/scala/scala3/pull/5775) and [lambda +serialization scheme](https://github.com/scala/scala3/pull/5837) pioneered by Scala 2, and that was enough to make our Spark assignments run correctly! This doesn't mean that our support is perfect however, so don't hesitate to [open an -issue](http://github.com/lampepfl/dotty/issues) if something is amiss. +issue](http://github.com/scala/scala3/issues) if something is amiss. ## Introducing top level definitions @@ -74,7 +74,7 @@ def b = a._2 You can read about [dropping package objects](https://dotty.epfl.ch/docs/reference/dropped-features/package-objects.html) at the documentation linked or at the relevant PR -[#5754](https://github.com/lampepfl/dotty/pull/5754). +[#5754](https://github.com/scala/scala3/pull/5754). ## All things impl... implied @@ -211,7 +211,7 @@ object B { **You can read more about** [implied imports](https://dotty.epfl.ch/docs/reference/contextual/import-delegate.html) from the docs or the relevant PR -[#5868](https://github.com/lampepfl/dotty/pull/5868). +[#5868](https://github.com/scala/scala3/pull/5868). As we mentioned above, *context queries* are functions with (only) inferable parameters. Here is an example of such a function: @@ -227,9 +227,9 @@ merely an alignment of IFTs into the new scheme. **You can read more about** the alternative to implicits through the *Contextual Abstractions* section of our documentation or for a deep dive from the relevant PR chain that originated from -[#5458](https://github.com/lampepfl/dotty/pull/5458). The syntax changes for new +[#5458](https://github.com/scala/scala3/pull/5458). The syntax changes for new implicits are summarized in -[#5825](https://github.com/lampepfl/dotty/pull/5825). +[#5825](https://github.com/scala/scala3/pull/5825). This release offers the support for _type class derivation_ as a language feature. Type class derivation is a way to generate instances of certain type @@ -279,8 +279,8 @@ def derived[T] given Generic[T] = ... **You can read more about** [Type class Derivation](https://dotty.epfl.ch/docs/reference/contextual/derivation.html) or have a deep dive at the relevant PRs: -[#5540](https://github.com/lampepfl/dotty/pull/5540) and -[#5839](https://github.com/lampepfl/dotty/pull/5839). +[#5540](https://github.com/scala/scala3/pull/5540) and +[#5839](https://github.com/scala/scala3/pull/5839). _Multiversal equality_ is now supported through the `Eql` marker trait (renamed from `Eq` to differentiate it from Cats' `Eq`). For example, in order to be able @@ -292,7 +292,7 @@ implied for Eql[Int, String] = Eql.derived ``` **You can read more about** how we based multiversal equality on type class derivation through -the relevant PR [#5843](https://github.com/lampepfl/dotty/pull/5843). +the relevant PR [#5843](https://github.com/scala/scala3/pull/5843). _Implicit conversions_ are now defined by implied instances of the `scala.Conversion` class. For example: @@ -311,7 +311,7 @@ important with the documentation of each feature, please consult the ## Implicit resolution rule changes -PR [#5887](https://github.com/lampepfl/dotty/pull/5887) applies the following +PR [#5887](https://github.com/scala/scala3/pull/5887) applies the following changes to implicit resolution: 1. nested implicits always take precedence over outer ones @@ -324,12 +324,12 @@ changes to implicit resolution: data model for semantic information such as symbols and types about programs in Scala and other languages. SemanticDB decouples production and consumption of semantic information, establishing documented means for communication between -tools. With PR [#5761](https://github.com/lampepfl/dotty/pull/5761) we add the +tools. With PR [#5761](https://github.com/scala/scala3/pull/5761) we add the first prototype for the generation of SemanticDB information from TASTy. ## And much more! -Please read our [release notes](https://github.com/lampepfl/dotty/releases/tag/0.13.0-RC1) +Please read our [release notes](https://github.com/scala/scala3/releases/tag/0.13.0-RC1) for more details! # Trying out Dotty @@ -360,7 +360,7 @@ the IDE sections of the [getting-started page](https://docs.scala-lang.org/scala Releases are available for download on the _Releases_ section of the Dotty repository: -[https://github.com/lampepfl/dotty/releases](https://github.com/lampepfl/dotty/releases) +[https://github.com/scala/scala3/releases](https://github.com/scala/scala3/releases) For macOS users, we also provide a [homebrew](https://brew.sh/) package that can be installed by running: @@ -379,7 +379,7 @@ brew upgrade dotty If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -417,7 +417,7 @@ According to `git shortlog -sn --no-merges 0.12.0-RC1..0.13.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-04-15-14th-dotty-milestone-release.md b/docs/_blog/_posts/2019-04-15-14th-dotty-milestone-release.md index 6724ae11cef1..1ac1c3ae9fbb 100644 --- a/docs/_blog/_posts/2019-04-15-14th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-04-15-14th-dotty-milestone-release.md @@ -72,7 +72,7 @@ For more information, please read more in the [documentation](https://dotty.epfl ## An immutable array type -A new type, `scala.IArray[T]`, is added, which is an immutable version of the `Array` type. Its implementation deserves a special attention, as it uses the new Dotty features in an elegant way (the below is an abstract from the corresponding [commit](https://github.com/lampepfl/dotty/commit/af2a0e66eb4b1204eac5dcb1d979486b92ef93d7#diff-156dc405d9f228bbc0fe406dfba63f65): +A new type, `scala.IArray[T]`, is added, which is an immutable version of the `Array` type. Its implementation deserves a special attention, as it uses the new Dotty features in an elegant way (the below is an abstract from the corresponding [commit](https://github.com/scala/scala3/commit/af2a0e66eb4b1204eac5dcb1d979486b92ef93d7#diff-156dc405d9f228bbc0fe406dfba63f65): ```scala opaque type IArray[T] = Array[T] @@ -131,7 +131,7 @@ Some of the other changes include: If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -171,7 +171,7 @@ According to `git shortlog -sn --no-merges 0.13.0-RC1..0.14.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-05-23-15th-dotty-milestone-release.md b/docs/_blog/_posts/2019-05-23-15th-dotty-milestone-release.md index 68337d78ca8c..1ffb07377da4 100644 --- a/docs/_blog/_posts/2019-05-23-15th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-05-23-15th-dotty-milestone-release.md @@ -6,7 +6,7 @@ authorImg: images/anatolii.png date: 2019-05-23 --- -Hi! We are very excited to announce the 15th release of Dotty. The most exciting thing in this release is the full bootstrap for Dotty introduced by PR [#5923](https://github.com/lampepfl/dotty/pull/5923)🎉😍. This means that we now always compile Dotty with Dotty itself, hence we can use use all the new features in the compiler code base. +Hi! We are very excited to announce the 15th release of Dotty. The most exciting thing in this release is the full bootstrap for Dotty introduced by PR [#5923](https://github.com/scala/scala3/pull/5923)🎉😍. This means that we now always compile Dotty with Dotty itself, hence we can use use all the new features in the compiler code base. With this release comes a bunch of new features and improvements, such as the ability to enforce whether an operator is intended to be used in an infix position, the type safe pattern bindings and more. @@ -36,7 +36,7 @@ This is our 15th scheduled release according to our ## Full Bootstrap Bootstrapping Dotty is a big milestone for us and in compiler construction in general. Firstly, we feel more confident that our compiler works as is (even without reusing the new features). Secondly, in the immediate future, we will be able to reuse many of the features that dotty proposes within dotty itself. For example, we have no fewer than 2641 occurrences of the text string (implicit ctx: Context) in the compiler that we can scrap with [Contextual Function types](https://www.scala-lang.org/blog/2016/12/07/implicit-function-types.html). Big milestones have high risk/high gain and we must be attentive. That is the reason that we will wait a bit until we start using new features. Consequently, at the moment we cross-compile the build with 2.12 on the CI so that we don't accidentally start using Dotty features in case we need to revise the bootstrap process (we'll start using Dotty features eventually, but let's wait until we're confident that this setup works well enough). -Check the following for more information [#5923 (comment)](https://github.com/lampepfl/dotty/pull/5923#issuecomment-485421148) and please let us know if you have any incremental compilation issues or anything else! +Check the following for more information [#5923 (comment)](https://github.com/scala/scala3/pull/5923#issuecomment-485421148) and please let us know if you have any incremental compilation issues or anything else! ## Operator Rules This change addresses the problem of the regulation of whether an operator is supposed to be used in an infix position. The motivation is for the library authors to be able to enforce whether a method or a type is supposed to be used in an infix position by the users. This ability will help to make code bases more consistent in the way the calls to methods are performed. @@ -150,7 +150,7 @@ For the migration purposes, the above change will only take effect in Scala 3.1. For more information, see the [documentation](https://dotty.epfl.ch/docs/reference/changed-features/pattern-bindings.html). ## Further improvements to Generalised Algebraic Data Types (GADTs) support -In this release, we've further improved our support for GADTs. Most notably, we now support variant GADTs, thus fixing [#2985](https://github.com/lampepfl/dotty/issues/2985): +In this release, we've further improved our support for GADTs. Most notably, we now support variant GADTs, thus fixing [#2985](https://github.com/scala/scala3/issues/2985): ```scala enum Expr[+T] { @@ -164,20 +164,20 @@ def eval[T](e: Expr[T]): T = e match { } ``` -We've also plugged a few soundness problems (e.g. [#5667](https://github.com/lampepfl/dotty/issues/5667)) caused by inferring too much when matching on abstract, union and intersection types. For more information, see PR [#5736](https://github.com/lampepfl/dotty/pull/5736). +We've also plugged a few soundness problems (e.g. [#5667](https://github.com/scala/scala3/issues/5667)) caused by inferring too much when matching on abstract, union and intersection types. For more information, see PR [#5736](https://github.com/scala/scala3/pull/5736). ## Other changes Some of the other notable changes include the following: - Singletons are now allowed in union types. E.g. the following is allowed: `object foo; type X = Int | foo.type`. -- A bunch of improvements was made for the type inference system – see, e.g., PRs [#6454](https://github.com/lampepfl/dotty/pull/6454) and [#6467](https://github.com/lampepfl/dotty/pull/6467). -- Improvements to the Scala 2 code support which, in particular, improves Cats support – see PRs [#6494](https://github.com/lampepfl/dotty/pull/6494) and [#6498](https://github.com/lampepfl/dotty/pull/6498). +- A bunch of improvements was made for the type inference system – see, e.g., PRs [#6454](https://github.com/scala/scala3/pull/6454) and [#6467](https://github.com/scala/scala3/pull/6467). +- Improvements to the Scala 2 code support which, in particular, improves Cats support – see PRs [#6494](https://github.com/scala/scala3/pull/6494) and [#6498](https://github.com/scala/scala3/pull/6498). # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -205,7 +205,7 @@ According to `git shortlog -sn --no-merges 0.14.0-RC1..0.15.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-06-11-16th-dotty-milestone-release.md b/docs/_blog/_posts/2019-06-11-16th-dotty-milestone-release.md index 41194df26625..91f63a5610b7 100644 --- a/docs/_blog/_posts/2019-06-11-16th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-06-11-16th-dotty-milestone-release.md @@ -49,7 +49,7 @@ represented by `=>>`. As a result a function from types to types is written as `[X] =>> F[X]`. For those who are interested in the discussions, -[#6558](https://github.com/lampepfl/dotty/pull/6558) introduced the new syntax. +[#6558](https://github.com/scala/scala3/pull/6558) introduced the new syntax. ## Syntax Change: Wildcard Arguments in Types @@ -92,7 +92,7 @@ delegate ListOrd[T] for Ord[List[T]] given (ord: Ord[T]) { ``` For more information, the documentation has been updated as part of the relevant -PR [#6649](https://github.com/lampepfl/dotty/pull/6649) +PR [#6649](https://github.com/scala/scala3/pull/6649) ## Polymorphic function types @@ -127,7 +127,7 @@ With PFTs we can now achieve what we want: ``` For those who are interested in the discussions and more test cases, -[#4672](https://github.com/lampepfl/dotty/pull/4672/) introduced PFTs. +[#4672](https://github.com/scala/scala3/pull/4672/) introduced PFTs. ## `lazy val`s are now thread-safe by default @@ -156,9 +156,9 @@ enum B(val gravity: Double) extends java.lang.Enum[B] { } ``` -For more information please check the [test case](https://github.com/lampepfl/dotty/tree/main/tests/run/enum-java) and -also the relevant PRs [#6602](https://github.com/lampepfl/dotty/pull/6602) and -[#6629](https://github.com/lampepfl/dotty/pull/6629). +For more information please check the [test case](https://github.com/scala/scala3/tree/main/tests/run/enum-java) and +also the relevant PRs [#6602](https://github.com/scala/scala3/pull/6602) and +[#6629](https://github.com/scala/scala3/pull/6629). In the test, the enums are defined in the `MainScala.scala` file and used from a Java source, `Test.java`. @@ -212,13 +212,13 @@ Advantages of new scheme: - Complete decoupling between derives clauses and mirror generation. For the technical details of these changes please consule the corresponding PR -[#6531](https://github.com/lampepfl/dotty/pull/6531). +[#6531](https://github.com/scala/scala3/pull/6531). # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -245,7 +245,7 @@ According to `git shortlog -sn --no-merges 0.15.0-RC1..0.16.0-RC3` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-07-25-17th-dotty-milestone-release.md b/docs/_blog/_posts/2019-07-25-17th-dotty-milestone-release.md index eea99263def9..62e0a550598d 100644 --- a/docs/_blog/_posts/2019-07-25-17th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-07-25-17th-dotty-milestone-release.md @@ -31,7 +31,7 @@ This is our 17th scheduled release according to our # What’s new in the 0.17.0-RC1 technology preview? ## New implicit scoping rules -We aim to make the implicit scoping rules clean and intuitive. In this release, the scoping rules were refactored to facilitate this goal. As specified in the [code documentation](https://github.com/lampepfl/dotty/pull/6832/files#diff-584b631c45ba6f2d4bc5d803074b8f12R474): +We aim to make the implicit scoping rules clean and intuitive. In this release, the scoping rules were refactored to facilitate this goal. As specified in the [code documentation](https://github.com/scala/scala3/pull/6832/files#diff-584b631c45ba6f2d4bc5d803074b8f12R474): The implicit scope of a type `tp` is the smallest set S of object references (i.e. TermRefs with Module symbol) such that: @@ -48,14 +48,14 @@ with Module symbol) such that: - If `tp` is some other type, its implicit scope is the union of the implicit scopes of its parts (parts defined as in the spec). -You can learn more from PR [#6832](https://github.com/lampepfl/dotty/pull/6832). +You can learn more from PR [#6832](https://github.com/scala/scala3/pull/6832). ## Metaprogramming We are making steady progress developing metaprogramming features. The highlights for this release are: -- Tasty Reflection's `Reflection` object moved inside `QuoteContext` object. This means that if previously to do Tasty Reflection you had to implicitly depend on `Reflection`, now you need to depend on `QuoteContext`. To know more, see [#6723](https://github.com/lampepfl/dotty/pull/6723). -- Progress made on quoted patterns – see [#6504](https://github.com/lampepfl/dotty/pull/6504). -- `code` string interpolator allows to obtain the code a user passes to a macro as a String. See [#6661](https://github.com/lampepfl/dotty/pull/6661). To enable this feature, do the following import: `import scala.compiletime._`. +- Tasty Reflection's `Reflection` object moved inside `QuoteContext` object. This means that if previously to do Tasty Reflection you had to implicitly depend on `Reflection`, now you need to depend on `QuoteContext`. To know more, see [#6723](https://github.com/scala/scala3/pull/6723). +- Progress made on quoted patterns – see [#6504](https://github.com/scala/scala3/pull/6504). +- `code` string interpolator allows to obtain the code a user passes to a macro as a String. See [#6661](https://github.com/scala/scala3/pull/6661). To enable this feature, do the following import: `import scala.compiletime._`. ## 2.12 build removed from the CI tests 2.12 build is removed from the test suite. The 2.12 build compiled and tested the Dotty compiler with the Scala 2.12 compiler. This means that, even though Dotty is bootstrapped (i.e. capable of compiling itself), we were not able to use any of the new Dotty features in the Dotty codebase since these features would not compile with Scala 2.12. The decision to abstain from using the new features was made to give us the time to see if something goes wrong with the bootstrap and the ability to revert to Scala 2.12 if it becomes necessary. @@ -74,7 +74,7 @@ There were some organizational and infrastructural changes worth mentioning. If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -113,7 +113,7 @@ According to `git shortlog -sn --no-merges 0.16.0-RC3..0.17.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-08-30-18th-dotty-milestone-release.md b/docs/_blog/_posts/2019-08-30-18th-dotty-milestone-release.md index 420b9103d3b7..8c06b2058230 100644 --- a/docs/_blog/_posts/2019-08-30-18th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-08-30-18th-dotty-milestone-release.md @@ -168,7 +168,7 @@ val iterator = Iterator.from(10, -1) } ``` -For more information, see PR [#6994](https://github.com/lampepfl/dotty/pull/6994). +For more information, see PR [#6994](https://github.com/scala/scala3/pull/6994). ## Brace-less syntax for control expressions This is an effort to clean-up the control expressions. Scala 2 has two ways of writing `if` statements – with and without parentheses. Parentheses can be dropped in Scala 2 `if`s inside `match` or `for` statements. We'd like to have a single style of writing all of the control expressions, and the cleaner the better. @@ -202,7 +202,7 @@ This release, hence, brings the ability to write all of the control expressions Moreover, the compiler can automatically rewrite your sources from the old syntax to the new syntax and vice versa. To rewrite the sources to the new syntax, run the compiler with the `-rewrite -new-syntax` flags, and to rewrite to the old syntax, use `-rewrite -old-syntax`. So far, both syntaxes are supported. -For more information and the precise rules, see PR [#7024](https://github.com/lampepfl/dotty/pull/7024). +For more information and the precise rules, see PR [#7024](https://github.com/scala/scala3/pull/7024). ## Significant indentation syntax Significant indentations syntax is here! A logical continuation of the brace-less syntax for control expressions described above, meant as an exploration into a better way to write Scala, it allows writing Scala programs without braces. For example: @@ -232,7 +232,7 @@ given as scala.util.FromString[Day]: So far, it is a purely experimental effort. This means there is no final decision yet on whether or not it will be included in Scala 3. However, we treat this feature seriously enough to give it an extended period of trial and see if it is viable as the new look and feel for Scala. -For more details and the discussion, see PRs [#7083](https://github.com/lampepfl/dotty/pull/7083) and [#7114](https://github.com/lampepfl/dotty/pull/7114). +For more details and the discussion, see PRs [#7083](https://github.com/scala/scala3/pull/7083) and [#7114](https://github.com/scala/scala3/pull/7114). ## Generic Number Literals It is now possible to seamlessly integrate with different number formats: that is, to write a number and get it automatically converted to your class of choice. E.g.: @@ -256,13 +256,13 @@ For precise rules, semantics and a larger example of `BigFloat`, see [the docume ## Metaprogramming Progress We are making steady progress with the language metaprogramming features. The metaprogramming spotlights of this release are as follows: -- `toExprOfTuple` method which allows converting a `Seq[Expr[Any]]` to `Expr[Tuple]`. The types of the expressions will be preserved in the tuple. See [#7037](https://github.com/lampepfl/dotty/pull/7037) and [#7076](https://github.com/lampepfl/dotty/pull/7076) for the details. -- `toExprOfTuple` method that converts a tuple of expressions to an expression of tuple – see [#7047](https://github.com/lampepfl/dotty/pull/7047). -- `toExprOfSeq` which converts an `Seq[Expr[A]]` to `Expr[Seq[A]]` – see [#6935](https://github.com/lampepfl/dotty/pull/6935). -- More `Liftable` instances – for Tuples of arity greater than 22, `BigInt` and `BigDecimal` – see [#6947](https://github.com/lampepfl/dotty/pull/6947) and [#6944](https://github.com/lampepfl/dotty/pull/6944). -- Leverage implicit lambdas to simplify `Liftable.toExpr` method – see [#6924](https://github.com/lampepfl/dotty/pull/6924) to learn how it is done. -- Runtime staging `run` moved to `scala.quoted.staging` in [#7077](https://github.com/lampepfl/dotty/pull/7077). -- Runtime staging factored out to a separate library in [#7080](https://github.com/lampepfl/dotty/pull/7080). +- `toExprOfTuple` method which allows converting a `Seq[Expr[Any]]` to `Expr[Tuple]`. The types of the expressions will be preserved in the tuple. See [#7037](https://github.com/scala/scala3/pull/7037) and [#7076](https://github.com/scala/scala3/pull/7076) for the details. +- `toExprOfTuple` method that converts a tuple of expressions to an expression of tuple – see [#7047](https://github.com/scala/scala3/pull/7047). +- `toExprOfSeq` which converts an `Seq[Expr[A]]` to `Expr[Seq[A]]` – see [#6935](https://github.com/scala/scala3/pull/6935). +- More `Liftable` instances – for Tuples of arity greater than 22, `BigInt` and `BigDecimal` – see [#6947](https://github.com/scala/scala3/pull/6947) and [#6944](https://github.com/scala/scala3/pull/6944). +- Leverage implicit lambdas to simplify `Liftable.toExpr` method – see [#6924](https://github.com/scala/scala3/pull/6924) to learn how it is done. +- Runtime staging `run` moved to `scala.quoted.staging` in [#7077](https://github.com/scala/scala3/pull/7077). +- Runtime staging factored out to a separate library in [#7080](https://github.com/scala/scala3/pull/7080). ## Type Class Derivation Type class derivation has received a major rework and an [updated documentation](https://dotty.epfl.ch/docs/reference/contextual/derivation.html). We have dropped the usage of the `Shape` type to describe the shape of a type. Instead, all the relevant information is now encoded in the `Mirror` type and its subtypes as tuples. @@ -270,15 +270,15 @@ Type class derivation has received a major rework and an [updated documentation] For more information, see the [documentation](https://dotty.epfl.ch/docs/reference/contextual/derivation.html). ## Other -- This release also features the new version of the SBT Dotty Plugin – 0.3.4. It contains some bug fixes – see [#7120](https://github.com/lampepfl/dotty/pull/7120) for details. -- Scala Days 2019 talks related to Dotty are now [mentioned](https://dotty.epfl.ch/docs/resources/talks.html) at our website – this allows to systematize the knowledge about the next generation of Scala in one place – see [#6984](https://github.com/lampepfl/dotty/pull/6984). -- ScalaJS needs your help! We would like to have robust support for ScalaJS in Dotty, which unfortunately is not the case so far. If you are interested in contributing, please see [the getting started tutorial](https://gist.github.com/sjrd/e0823a5bddbcef43999cdaa032b1220c) and [the discussion](https://github.com/lampepfl/dotty/issues/7113). +- This release also features the new version of the SBT Dotty Plugin – 0.3.4. It contains some bug fixes – see [#7120](https://github.com/scala/scala3/pull/7120) for details. +- Scala Days 2019 talks related to Dotty are now [mentioned](https://dotty.epfl.ch/docs/resources/talks.html) at our website – this allows to systematize the knowledge about the next generation of Scala in one place – see [#6984](https://github.com/scala/scala3/pull/6984). +- ScalaJS needs your help! We would like to have robust support for ScalaJS in Dotty, which unfortunately is not the case so far. If you are interested in contributing, please see [the getting started tutorial](https://gist.github.com/sjrd/e0823a5bddbcef43999cdaa032b1220c) and [the discussion](https://github.com/scala/scala3/issues/7113). # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -310,7 +310,7 @@ According to `git shortlog -sn --no-merges 0.17.0-RC1..0.18.1-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-09-23-19th-dotty-milestone-release.md b/docs/_blog/_posts/2019-09-23-19th-dotty-milestone-release.md index 0de8d87b92bb..55458b5a20c6 100644 --- a/docs/_blog/_posts/2019-09-23-19th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-09-23-19th-dotty-milestone-release.md @@ -160,7 +160,7 @@ For instance, `-project-logo dotty-logo.svg` will make `/images/dotty-logo.svg` [The front page](https://dotty.epfl.ch) has been redesigned too, with a new responsive menu and improved contrast. -Overall, every page has been updated with consistent settings of fonts and colors. A more detailed comparison between the new and the old design can be found [here](https://github.com/lampepfl/dotty/pull/7153). +Overall, every page has been updated with consistent settings of fonts and colors. A more detailed comparison between the new and the old design can be found [here](https://github.com/scala/scala3/pull/7153). ## Metaprogramming Progress We're making steady progress on the Dotty metaprogramming capability. In our previous work, we've implemented a bunch of functions for working with expressions. For example, we have a capability to convert a list of expressions into an expression of list, or a tuple of expressions into an expression of tuple. @@ -179,7 +179,7 @@ Also, `x.toExpr` syntax which lifts `x` into an expression is now deprecated. It If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -206,7 +206,7 @@ According to `git shortlog -sn --no-merges 0.18.1-RC1..0.19.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-11-04-20th-dotty-milestone-release.md b/docs/_blog/_posts/2019-11-04-20th-dotty-milestone-release.md index 78cbe171ca11..e28b2304831c 100644 --- a/docs/_blog/_posts/2019-11-04-20th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-11-04-20th-dotty-milestone-release.md @@ -127,16 +127,16 @@ It is easy to forget to put `then` at the end of the line if nothing else follow ## Metaprogramming Progress We are making a steady progress developing and improving the metaprogramming features of Dotty. Here are metaprogramming highlights of this release: -- Fix #7189: Do not try to load contents if file does not exist [#7476](https://github.com/lampepfl/dotty/pull/7476) -- Add customizable names for definitions in quotes [#7346](https://github.com/lampepfl/dotty/pull/7346) -- Rename scala.quoted.matching.{Bind => Sym} [#7332](https://github.com/lampepfl/dotty/pull/7332) -- Replace AsFunction implicit class with Expr.reduce [#7299](https://github.com/lampepfl/dotty/pull/7299) +- Fix #7189: Do not try to load contents if file does not exist [#7476](https://github.com/scala/scala3/pull/7476) +- Add customizable names for definitions in quotes [#7346](https://github.com/scala/scala3/pull/7346) +- Rename scala.quoted.matching.{Bind => Sym} [#7332](https://github.com/scala/scala3/pull/7332) +- Replace AsFunction implicit class with Expr.reduce [#7299](https://github.com/scala/scala3/pull/7299) # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -173,7 +173,7 @@ According to `git shortlog -sn --no-merges 0.19.0-RC1..0.20.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2019-12-20-21th-dotty-milestone-release.md b/docs/_blog/_posts/2019-12-20-21th-dotty-milestone-release.md index 94d8ee61bec9..794eb875e3fc 100644 --- a/docs/_blog/_posts/2019-12-20-21th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2019-12-20-21th-dotty-milestone-release.md @@ -17,7 +17,7 @@ happy to announce that we are now feature complete! # Feature Complete! This release is a HUGE milestone for us, for Dotty, for Scala 3, for our community. Since that -[initial commit](https://github.com/lampepfl/dotty/commit/90962407e72d88f8f3249ade0f6bd60ff15af5ce) +[initial commit](https://github.com/scala/scala3/commit/90962407e72d88f8f3249ade0f6bd60ff15af5ce) on the 6th December of 2012 when the only feature was the basic structure of a compiler based on the DOT calculus, we have come a long way. @@ -48,7 +48,7 @@ It means that we can now put the Scala 3 compiler under heavy load, getting it ready for industrial strength applications. At the moment we have 23 projects on our community projects and we expect this number to go up! -> https://github.com/lampepfl/dotty/tree/main/community-build/community-projects +> https://github.com/scala/scala3/tree/main/community-build/community-projects This project contains tests to build and test a corpus of open sources Scala 2.x projects against Scala 3. @@ -333,7 +333,7 @@ root for `.semanticdb` files) and `-sourceroot` to calculate a relative path for If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -378,7 +378,7 @@ According to `git shortlog -sn --no-merges 0.20.0-RC1..0.21.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2020-02-05-22nd-dotty-milestone-release.md b/docs/_blog/_posts/2020-02-05-22nd-dotty-milestone-release.md index a901e83130d8..1dc100a9a741 100644 --- a/docs/_blog/_posts/2020-02-05-22nd-dotty-milestone-release.md +++ b/docs/_blog/_posts/2020-02-05-22nd-dotty-milestone-release.md @@ -55,7 +55,7 @@ println(s"Third: ${list.third}") // 3 This syntax is a completely separate one from the `given` syntax and hence is aimed to bring more clarity and disentangle the two different concepts. -For the discussion, see [PR #7917](https://github.com/lampepfl/dotty/pull/7917). For more information on how to use extension methods in general and collective extension methods in particular, see the [documentation](https://dotty.epfl.ch/docs/reference/contextual/extension-methods.html). +For the discussion, see [PR #7917](https://github.com/scala/scala3/pull/7917). For more information on how to use extension methods in general and collective extension methods in particular, see the [documentation](https://dotty.epfl.ch/docs/reference/contextual/extension-methods.html). # Kind projector syntax support [Kind projector](https://github.com/typelevel/kind-projector) is a popular compiler plugin for Scala 2. It is especially useful in the context of purely functional programming and type class derivation – everywhere where you need to work extensively with types. @@ -90,7 +90,7 @@ object tupleFunctor extends Functor[λ[x => (x, x)]] println(squared) // (1,4) ``` -For the discussion, see [PR #7775](https://github.com/lampepfl/dotty/pull/7775). Also see the GitHub [repository](https://github.com/typelevel/kind-projector) of the kind projector Scala 2 plugin for more context. +For the discussion, see [PR #7775](https://github.com/scala/scala3/pull/7775). Also see the GitHub [repository](https://github.com/typelevel/kind-projector) of the kind projector Scala 2 plugin for more context. # Further improvements to the context parameters syntax Scala 3 context parameters are successors of Scala 2 implicits. In Scala 2, they proved useful for a wide range of applications including purely functional programming, dependency injection, type class derivation, type-level programming. Because their apparent value, one of the priorities in Scala 3 for us is to improve the conceptual framework behind them. @@ -127,7 +127,7 @@ As opposed to the previous: f(2)(given 20) ``` -For the time being, the change is experimental and the old syntax is also supported. For the discussion, see [PR #8162](https://github.com/lampepfl/dotty/pull/8162). You can browse the documentation concerning the new syntax [here](https://dotty.epfl.ch/docs/reference/contextual/motivation-new.html). +For the time being, the change is experimental and the old syntax is also supported. For the discussion, see [PR #8162](https://github.com/scala/scala3/pull/8162). You can browse the documentation concerning the new syntax [here](https://dotty.epfl.ch/docs/reference/contextual/motivation-new.html). # Semantics of inline parameters changed Inline parameters is a metaprogramming feature of Dotty which allows to splice the body of the parameter on its call site. Previously, inline parameters to methods were required to be known on compile time. With this release, this constraint has been relaxed. The following: @@ -149,7 +149,7 @@ Notice how the value of the by-name parameter `b` is not inlined but is bound to So, if previously you had a macro `inline def operationOnCode(code: => Unit) = ${ mcrImpl('code) }` which did something on the AST of the passed `code`, with this release you need to change it to `inline def operationOnCode(inline code: Unit) = ${ mcrImpl('code) }`. -This change was introduced by [PR #8060](https://github.com/lampepfl/dotty/pull/8060/). +This change was introduced by [PR #8060](https://github.com/scala/scala3/pull/8060/). Another change in the semantics of the inline parameters involves the fact that the can no longer be passed as constants to macro implementations. Previously, the following was possible: @@ -169,7 +169,7 @@ inline def power(x: Double, inline n: Int) = ${ powerCode('x, 'n) } private def powerCode(x: Expr[Double], n: Expr[Int])(given QuoteContext): Expr[Double] = ??? ``` -You can obtain the constant value of `n` from within the macro implementation by calling `n.getValue` on it which returns an `Option`. This change was introduced by [PR #8061](https://github.com/lampepfl/dotty/pull/8061). +You can obtain the constant value of `n` from within the macro implementation by calling `n.getValue` on it which returns an `Option`. This change was introduced by [PR #8061](https://github.com/scala/scala3/pull/8061). For more information about the inline capability of Dotty, see [documentation](https://dotty.epfl.ch/docs/reference/metaprogramming/inline.html). @@ -194,7 +194,7 @@ The compile-time error above will say: This feature is particularly useful for data science applications. In data science, it is very easy to make a linear algebra mistake, multiply matrices of wrong dimensions and get a runtime error – sometimes after a few hours of running the model. Hence compile-time verification of the models has a great potential for saving time. With such a type-level arithmetic, Scala becomes well-positioned to implement such type-safe data science frameworks. -For the discussion, see [PR #7628](https://github.com/lampepfl/dotty/pull/7628). The documentation is available [here](https://dotty.epfl.ch/docs/reference/metaprogramming/inline.html#the-scalacompiletimeops-package). +For the discussion, see [PR #7628](https://github.com/scala/scala3/pull/7628). The documentation is available [here](https://dotty.epfl.ch/docs/reference/metaprogramming/inline.html#the-scalacompiletimeops-package). # Suggestions on missing context parameters If there's a compile-time error due to a missing context parameter and this error can be fixed with an import, the compiler will attempt to suggest such an import in the error message. Here is an example of how this error looks like: @@ -212,7 +212,7 @@ If there's a compile-time error due to a missing context parameter and this erro One area where these suggestions will make life easier is purely functional programming with type-classes, with libraries like [cats](https://typelevel.org/cats/). Having the fix for a missing type class in the error message itself is a big time-saver. -For the discussion, see [PR #7862](https://github.com/lampepfl/dotty/pull/7862). +For the discussion, see [PR #7862](https://github.com/scala/scala3/pull/7862). # TASTy Inspector library TASTy Consumer was renamed to TASTy Inspector as of this release. It was also published in a library of its own. For more information, see the [documentation](https://dotty.epfl.ch/docs/reference/metaprogramming/tasty-inspect.html) on this library. @@ -221,7 +221,7 @@ TASTy Consumer was renamed to TASTy Inspector as of this release. It was also pu If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -267,7 +267,7 @@ According to `git shortlog -sn --no-merges 0.21.0-RC1..0.22.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2020-03-18-23rd-dotty-milestone-release.md b/docs/_blog/_posts/2020-03-18-23rd-dotty-milestone-release.md index e52db993dd19..7725d7e7d254 100644 --- a/docs/_blog/_posts/2020-03-18-23rd-dotty-milestone-release.md +++ b/docs/_blog/_posts/2020-03-18-23rd-dotty-milestone-release.md @@ -52,7 +52,7 @@ In this release, we have added an aid for the programmer to detect such mistakes 1 error found ``` -You can learn more about the feature from the [documentation](https://dotty.epfl.ch/0.23.0-RC1/docs/reference/other-new-features/safe-initialization.html). For the discussion, see PR [#7789](https://github.com/lampepfl/dotty/pull/7789). +You can learn more about the feature from the [documentation](https://dotty.epfl.ch/0.23.0-RC1/docs/reference/other-new-features/safe-initialization.html). For the discussion, see PR [#7789](https://github.com/scala/scala3/pull/7789). ## Bitwise Int compiletime operations In the previous release, Dotty has [received](https://dotty.epfl.ch/blog/2020/02/05/22nd-dotty-milestone-release.html#primitive-compiletime-operations-on-singleton-types) a support for type-level arithmetic operations on integers. In this release, we are extending this support by adding bitwise operations. For example: @@ -246,7 +246,7 @@ Notice how above, we are calling `app.fun` and `app.args`. `fun` and `args` are If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -294,7 +294,7 @@ According to `git shortlog -sn --no-merges 0.22.0-RC1..0.23.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2020-04-29-24th-dotty-milestone-release.md b/docs/_blog/_posts/2020-04-29-24th-dotty-milestone-release.md index e32df8cacc55..79148254e409 100644 --- a/docs/_blog/_posts/2020-04-29-24th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2020-04-29-24th-dotty-milestone-release.md @@ -76,13 +76,13 @@ Bar 22 Bar 22 ``` -This new change, however, comes with rather intricated rules – if you are interested to learn about them in details, see [documentation](https://dotty.epfl.ch/docs/reference/metaprogramming/inline.html#rules-for-overriding) on inlines and the PR #[8543](https://github.com/lampepfl/dotty/pull/8543/files) which introduced the change. +This new change, however, comes with rather intricated rules – if you are interested to learn about them in details, see [documentation](https://dotty.epfl.ch/docs/reference/metaprogramming/inline.html#rules-for-overriding) on inlines and the PR #[8543](https://github.com/scala/scala3/pull/8543/files) which introduced the change. # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -125,7 +125,7 @@ According to `git shortlog -sn --no-merges 0.23.0-RC1..0.24.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. @@ -134,7 +134,7 @@ We are looking forward to having you join the team of contributors. Dotty now has a set of widely-used community libraries that are built against every nightly Dotty snapshot. Currently, this includes shapeless, ScalaPB, algebra, scalatest, scopt and squants. -Join our [community build](https://github.com/lampepfl/dotty/tree/main/community-build) +Join our [community build](https://github.com/scala/scala3/tree/main/community-build) to make sure that our regression suite includes your library. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_blog/_posts/2020-06-22-25th-dotty-milestone-release.md b/docs/_blog/_posts/2020-06-22-25th-dotty-milestone-release.md index dd5def04bfe9..db73513c2413 100644 --- a/docs/_blog/_posts/2020-06-22-25th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2020-06-22-25th-dotty-milestone-release.md @@ -35,13 +35,13 @@ This default budget is configurable via a compiler flag `-Ximport-suggestion-tim This change should speed up the compiler when it comes to programming with givens. -For more information, see PR [#9167](https://github.com/lampepfl/dotty/pull/9167). +For more information, see PR [#9167](https://github.com/scala/scala3/pull/9167). # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing Thank you to all the contributors who made this release possible 🎉 @@ -89,7 +89,7 @@ According to `git shortlog -sn --no-merges 0.24.0-RC1..0.25.0-RC2` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. @@ -98,7 +98,7 @@ We are looking forward to having you join the team of contributors. Dotty now has a set of widely-used community libraries that are built against every nightly Dotty snapshot. Currently, this includes shapeless, ScalaPB, algebra, scalatest, scopt and squants. -Join our [community build](https://github.com/lampepfl/dotty/tree/main/community-build) +Join our [community build](https://github.com/scala/scala3/tree/main/community-build) to make sure that our regression suite includes your library. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_blog/_posts/2020-07-27-26th-dotty-milestone-release.md b/docs/_blog/_posts/2020-07-27-26th-dotty-milestone-release.md index b0d153dded7e..06bf6fc5dabb 100644 --- a/docs/_blog/_posts/2020-07-27-26th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2020-07-27-26th-dotty-milestone-release.md @@ -35,7 +35,7 @@ extension (ss: Seq[String]): def longestString: String = longestStrings.head ``` -You can read more about the new syntax in the [documentation](https://dotty.epfl.ch/docs/reference/contextual/extension-methods.html). For the discussion, see [PR](https://github.com/lampepfl/dotty/pull/9255). +You can read more about the new syntax in the [documentation](https://dotty.epfl.ch/docs/reference/contextual/extension-methods.html). For the discussion, see [PR](https://github.com/scala/scala3/pull/9255). # Local Selectable Instances Local and anonymous classes that extend `Selectable` get more refined types than other classes. For example: @@ -78,7 +78,7 @@ val result = constValueTuple["foo" *: "bar" *: 10 *: 2.5 *: EmptyTuple] println(result) // (foo,bar,10,2.5) ``` -This feature was introduced by PR [#9209](https://github.com/lampepfl/dotty/pull/9209). +This feature was introduced by PR [#9209](https://github.com/scala/scala3/pull/9209). # Per-run time budget for import suggestions Import suggestions is a feature useful for debugging but potentially taxing for performance. Therefore, we have added the `-Ximport-suggestion-timeout ` to allow specifying the timeout (in milliseconds) after which the suggestions mechanism should stop the lookup. The timeout budget is per-run (and not per suggestion) which ensures that the performance does not degrade in case of too many suggestions. @@ -87,7 +87,7 @@ Import suggestions is a feature useful for debugging but potentially taxing for If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing @@ -119,7 +119,7 @@ According to `git shortlog -sn --no-merges 0.25.0-RC2..0.26.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. @@ -128,7 +128,7 @@ We are looking forward to having you join the team of contributors. Dotty now has a set of widely-used community libraries that are built against every nightly Dotty snapshot. Currently, this includes shapeless, ScalaPB, algebra, scalatest, scopt and squants. -Join our [community build](https://github.com/lampepfl/dotty/tree/main/community-build) +Join our [community build](https://github.com/scala/scala3/tree/main/community-build) to make sure that our regression suite includes your library. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_blog/_posts/2020-08-31-27th-dotty-milestone-release.md b/docs/_blog/_posts/2020-08-31-27th-dotty-milestone-release.md index e42e98a1385b..7d0eebe369e2 100644 --- a/docs/_blog/_posts/2020-08-31-27th-dotty-milestone-release.md +++ b/docs/_blog/_posts/2020-08-31-27th-dotty-milestone-release.md @@ -41,30 +41,30 @@ To the best of our knowledge, cross-compiling libraries should be able to use Sc If you experience a bug with anything except the unsupported features mentioned above, please file a bug report. # Stability -As we're getting closer to the release of Scala 3, we are continuing to focus on the stability and performance of the language. In this release, we have fixed support of objects under JDK9+ (PR [#9181](https://github.com/lampepfl/dotty/pull/9181)). The issue was, due to the changes in JDK9+ compared to JDK8, our initialization scheme for objects did not work under JDK9+. The aforementioned fixed that issue, thereby unblocking JDK9+ support for Dotty. +As we're getting closer to the release of Scala 3, we are continuing to focus on the stability and performance of the language. In this release, we have fixed support of objects under JDK9+ (PR [#9181](https://github.com/scala/scala3/pull/9181)). The issue was, due to the changes in JDK9+ compared to JDK8, our initialization scheme for objects did not work under JDK9+. The aforementioned fixed that issue, thereby unblocking JDK9+ support for Dotty. -We are also continuing to work on stabilising enums. PR [#9532](https://github.com/lampepfl/dotty/pull/9532) corrects the deserialization and serialization of singleton enum values with `ObjectInputStream` and `ObjectOutputStream`. PR [#9549](https://github.com/lampepfl/dotty/pull/9549) enables overriding the `toString` method on enums – previously this was not possible because of the way enums were desugared. +We are also continuing to work on stabilising enums. PR [#9532](https://github.com/scala/scala3/pull/9532) corrects the deserialization and serialization of singleton enum values with `ObjectInputStream` and `ObjectOutputStream`. PR [#9549](https://github.com/scala/scala3/pull/9549) enables overriding the `toString` method on enums – previously this was not possible because of the way enums were desugared. # Performance We are also focusing these days on making the compiler faster and memory-efficient. For the past month, we were looking in the compiler's memory footprint. We were trying to determine what was allocated in unreasonable amounts during compilation and trying to resolve these allocation issues. The following PRs attempt to increase the performance of the compiler: -- Optimize megaphase [#9597](https://github.com/lampepfl/dotty/pull/9597) -- Cache all memberNamed results [#9633](https://github.com/lampepfl/dotty/pull/9633) -- Parallelize position pickling [#9619](https://github.com/lampepfl/dotty/pull/9619) -- Simplify TypeComparer [#9405](https://github.com/lampepfl/dotty/pull/9405) -- Optimize and simplify SourcePosition handling [#9561](https://github.com/lampepfl/dotty/pull/9561) +- Optimize megaphase [#9597](https://github.com/scala/scala3/pull/9597) +- Cache all memberNamed results [#9633](https://github.com/scala/scala3/pull/9633) +- Parallelize position pickling [#9619](https://github.com/scala/scala3/pull/9619) +- Simplify TypeComparer [#9405](https://github.com/scala/scala3/pull/9405) +- Optimize and simplify SourcePosition handling [#9561](https://github.com/scala/scala3/pull/9561) # Metaprogramming We are keeping the work on the metaprogramming API improvements. For this release, the following PRs bring better API to metaprogrammers: -- Avoid leak of internal implementation in tasty.Reflection [#9613](https://github.com/lampepfl/dotty/pull/9613) -- Redefine quoted.Expr.betaReduce [#9469](https://github.com/lampepfl/dotty/pull/9469) +- Avoid leak of internal implementation in tasty.Reflection [#9613](https://github.com/scala/scala3/pull/9613) +- Redefine quoted.Expr.betaReduce [#9469](https://github.com/scala/scala3/pull/9469) # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributing Thank you to all the contributors who made this release possible 🎉 @@ -100,7 +100,7 @@ According to `git shortlog -sn --no-merges 0.26.0-RC1..0.27.0-RC1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. @@ -109,7 +109,7 @@ We are looking forward to having you join the team of contributors. Dotty now has a set of widely-used community libraries that are built against every nightly Dotty snapshot. Currently, this includes shapeless, ScalaPB, algebra, scalatest, scopt and squants. -Join our [community build](https://github.com/lampepfl/dotty/tree/main/community-build) +Join our [community build](https://github.com/scala/scala3/tree/main/community-build) to make sure that our regression suite includes your library. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_blog/_posts/2020-11-09-scala3-m1.md b/docs/_blog/_posts/2020-11-09-scala3-m1.md index ffef5618f9ff..228a9f8eb99e 100644 --- a/docs/_blog/_posts/2020-11-09-scala3-m1.md +++ b/docs/_blog/_posts/2020-11-09-scala3-m1.md @@ -19,8 +19,8 @@ Below, you can find a short summary of the changes that took place during betwee Dotty 0.27.0-RC1 had introduced preliminary Scala.js support with the portable subset of Scala and native JavaScript types. Scala 3.0.0-M1 significantly expands on that support: -* support for non-native JS types ([#9774](https://github.com/lampepfl/dotty/pull/9774)), and -* better support for other JS interop features, notably their interactions with Scala 3 features such as top-level declarations and `enum`s (e.g, [#9725](https://github.com/lampepfl/dotty/pull/9725) and [#9955](https://github.com/lampepfl/dotty/pull/9955)). +* support for non-native JS types ([#9774](https://github.com/scala/scala3/pull/9774)), and +* better support for other JS interop features, notably their interactions with Scala 3 features such as top-level declarations and `enum`s (e.g, [#9725](https://github.com/scala/scala3/pull/9725) and [#9955](https://github.com/scala/scala3/pull/9955)). The only remaining feature of Scala.js that is not supported yet is JS exports: `@JSExport` and its siblings `@JSExportAll`, `@JSExportTopLevel` and `@JSExportStatic` are all ignored by Scala 3.0.0-M1. Support for JS exports will come in the next release. @@ -46,7 +46,7 @@ x match { As of Scala 3.1.0, the `@` syntax will be deprecated and the codebases should switch to `as` instead. -This change was implemented by PR [#9837](https://github.com/lampepfl/dotty/pull/9837). +This change was implemented by PR [#9837](https://github.com/scala/scala3/pull/9837). # Pattern-Bound Given Instances The syntax for `given` instances in patterns has also changed. In the `for`-comprehensions, the correct way of using `given`s is as follows: @@ -62,7 +62,7 @@ pair match case (ctx as given Context, y) => ... ``` -For more information, see [documentation](https://dotty.epfl.ch/docs/reference/contextual/givens.html#pattern-bound-given-instances), and for discussion, see PR [#10091](https://github.com/lampepfl/dotty/pull/10091). +For more information, see [documentation](https://dotty.epfl.ch/docs/reference/contextual/givens.html#pattern-bound-given-instances), and for discussion, see PR [#10091](https://github.com/scala/scala3/pull/10091). # Change wildcard given selectors This is another syntactic change which aims to simplify the code. Instead of: @@ -77,7 +77,7 @@ The correct version of the wildcard `given` import now becomes: import p.given ``` -This change was implemented by PR [#9949](https://github.com/lampepfl/dotty/pull/9949). +This change was implemented by PR [#9949](https://github.com/scala/scala3/pull/9949). # Final API for enumerations `enum` definitions are now released in their final design. since `0.27.0-RC1` we have made the following changes: @@ -125,22 +125,22 @@ val res1: Opt[?] = Nn # Keep `@alpha` optional for operators Following the discussion on [contributors](https://contributors.scala-lang.org/t/the-alpha-notation/4583), we now keep `@alpha` optional for operators. The checking behavior is still available when compiling with the `-Yrequire-alpha`. -`@alpha` annotations provide a way to define an alternate name for symbolic operators. You can learn more about `@alpha` annotations from the [documentation](https://dotty.epfl.ch/docs/reference/changed-features/operators.html#the-alpha-annotation). The change was implemented by PR [#10093](https://github.com/lampepfl/dotty/pull/10093). +`@alpha` annotations provide a way to define an alternate name for symbolic operators. You can learn more about `@alpha` annotations from the [documentation](https://dotty.epfl.ch/docs/reference/changed-features/operators.html#the-alpha-annotation). The change was implemented by PR [#10093](https://github.com/scala/scala3/pull/10093). # Optimizing the compiler During the last months, a considerable amount of effort went into investigating performance bottlenecks in the compiler and optimizing its workflow. We also work on stabilizing the compiler and porting relevant changes from the Scala 2 compiler to Scala 3. The following PRs are relevant to highlighting this work: -- Port classfile parsing improvements [#10037](https://github.com/lampepfl/dotty/pull/10037) -- Semanticdb usability enhancements [#9768](https://github.com/lampepfl/dotty/pull/9768) -- Optimize core and frontend [#9867](https://github.com/lampepfl/dotty/pull/9867) +- Port classfile parsing improvements [#10037](https://github.com/scala/scala3/pull/10037) +- Semanticdb usability enhancements [#9768](https://github.com/scala/scala3/pull/9768) +- Optimize core and frontend [#9867](https://github.com/scala/scala3/pull/9867) # Known issues -This release of Scala 3 doesn't work on JDK 14 because of a regression fixed in [#10135](https://github.com/lampepfl/dotty/pull/10135). JDK 15 doesn't work either because of [scala/bug#12172](https://github.com/scala/bug/issues/12172) which will be fixed in the new scala-library release. +This release of Scala 3 doesn't work on JDK 14 because of a regression fixed in [#10135](https://github.com/scala/scala3/pull/10135). JDK 15 doesn't work either because of [scala/bug#12172](https://github.com/scala/bug/issues/12172) which will be fixed in the new scala-library release. # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributors @@ -190,7 +190,7 @@ According to `git shortlog -sn --no-merges 0.27.0-RC1..3.0.0-M1` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. @@ -199,7 +199,7 @@ We are looking forward to having you join the team of contributors. Dotty now has a set of widely-used community libraries that are built against every nightly Dotty snapshot. Currently, this includes shapeless, ScalaPB, algebra, scalatest, scopt and squants. -Join our [community build](https://github.com/lampepfl/dotty/tree/main/community-build) +Join our [community build](https://github.com/scala/scala3/tree/main/community-build) to make sure that our regression suite includes your library. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_blog/_posts/2020-12-18-scala3-m3.md b/docs/_blog/_posts/2020-12-18-scala3-m3.md index 41cfa76c0265..84fa9e823bda 100644 --- a/docs/_blog/_posts/2020-12-18-scala3-m3.md +++ b/docs/_blog/_posts/2020-12-18-scala3-m3.md @@ -19,7 +19,7 @@ You can try out the M3 version online via [Scastie](https://scastie.scala-lang.o # sbt plugin update -We published a new version of the sbt plugin `sbt-dotty`, v0.5.1. Because of the changes in PR [#10607](https://github.com/lampepfl/dotty/pull/10607), this release of Scala 3 will not work with earlier versions of sbt-dotty. You will need to upgrade sbt-dotty to 0.5.1 to be able to use Scala 3.0.0-M3. +We published a new version of the sbt plugin `sbt-dotty`, v0.5.1. Because of the changes in PR [#10607](https://github.com/scala/scala3/pull/10607), this release of Scala 3 will not work with earlier versions of sbt-dotty. You will need to upgrade sbt-dotty to 0.5.1 to be able to use Scala 3.0.0-M3. # Final syntactic tweaks ## `as` dropped from the `given` syntax @@ -57,7 +57,7 @@ given global: ExecutionContext = ForkJoinContext() given Context = ctx ``` -You can find a discussion of the above change in the [PR #10538](https://github.com/lampepfl/dotty/pull/10538). +You can find a discussion of the above change in the [PR #10538](https://github.com/scala/scala3/pull/10538). ## Drop `as` in patterns Since we dropped `as` from `given`s, we lost a strong reason for having `as` at all. Therefore, we dropped `as` from patterns as well. The following syntax, valid in Scala 3.0.0-M2, is not accepted anymore: @@ -128,16 +128,16 @@ In the meantime, the compiler will emit warnings when trying to call those metho Note that the warnings are only active with language mode `3.1-migration` or higher - see the documentation on the [Language Versions](https://dotty.epfl.ch/docs/usage/language-versions.html) to learn how to enable it. -You can read the discussion of this change in the [PR #10670](https://github.com/lampepfl/dotty/pull/10670). You can also read more about it in the [documentation](https://dotty.epfl.ch/docs/reference/other-new-features/matchable.html). +You can read the discussion of this change in the [PR #10670](https://github.com/scala/scala3/pull/10670). You can also read more about it in the [documentation](https://dotty.epfl.ch/docs/reference/other-new-features/matchable.html). # Tooling improvements As we are getting closer to a stable release of Scala 3, the focus increasingly shifts on the tooling available to get started with Scala 3. For a while now, we are not using the old dottydoc documentation tool for building the documentation. We are developing an entirely new tool, scala3doc, from scratch. This new documentation tool is more robust and faster than the old one. -As part of the tooling effort, this new Scala 3 documentation tool is rapidly improved. [PR #10522](https://github.com/lampepfl/dotty/pull/10522) proves that the doctool can generate documentation for the community build projects. You can access this documentation via the following [link](https://scala3doc.virtuslab.com/pr-master-docs/index.html). +As part of the tooling effort, this new Scala 3 documentation tool is rapidly improved. [PR #10522](https://github.com/scala/scala3/pull/10522) proves that the doctool can generate documentation for the community build projects. You can access this documentation via the following [link](https://scala3doc.virtuslab.com/pr-master-docs/index.html). -[PR #10491](https://github.com/lampepfl/dotty/pull/10491) introduced scripting support in Scala 3. Consider the following source named `Main.scala`: +[PR #10491](https://github.com/scala/scala3/pull/10491) introduced scripting support in Scala 3. Consider the following source named `Main.scala`: ```scala @main def Test(name: String): Unit = @@ -157,25 +157,25 @@ The documentation for this feature is available [here](https://dotty.epfl.ch/doc # Metaprogramming changes We have been polishing the metaprogramming API and making it more uniform. The following notable changes occurred between M2 and M3: -- Add `Expr.asTerm` [#10694](https://github.com/lampepfl/dotty/pull/10694) -- Add reflect `MatchCase` `TypeRepr` [#10735](https://github.com/lampepfl/dotty/pull/10735) -- Rework reflect Symbol fields API [#10705](https://github.com/lampepfl/dotty/pull/10705) -- Remove `Expr.StringContext.unapply` [#10675](https://github.com/lampepfl/dotty/pull/10675) -- Rename `Liftable` to `ToExpr` and `Unliftable` to `FromExpr` [#10618](https://github.com/lampepfl/dotty/pull/10618) -- Remove Unliftable[Unit] [#10570](https://github.com/lampepfl/dotty/pull/10570) -- Remove reflect.LambdaType [#10548](https://github.com/lampepfl/dotty/pull/10548) -- Add `scala.quoted.Expr.unapply` as dual of `Expr.apply` [#10580](https://github.com/lampepfl/dotty/pull/10580) -- Move `Quotes` as last parameter in `ExprMap.transform` [#10519](https://github.com/lampepfl/dotty/pull/10519) -- Rework reflect Constant API [#10753](https://github.com/lampepfl/dotty/pull/10753) -- Unify quoted.report and reflect.Reporting [#10474](https://github.com/lampepfl/dotty/pull/10474) -- Fix #10359: Add GivenSelector to reflection API [#10469](https://github.com/lampepfl/dotty/pull/10469) -- Rework reflect show API [#10661](https://github.com/lampepfl/dotty/pull/10661) -- Fix #10709: Add missing level check before inlining [#10781](https://github.com/lampepfl/dotty/pull/10781) +- Add `Expr.asTerm` [#10694](https://github.com/scala/scala3/pull/10694) +- Add reflect `MatchCase` `TypeRepr` [#10735](https://github.com/scala/scala3/pull/10735) +- Rework reflect Symbol fields API [#10705](https://github.com/scala/scala3/pull/10705) +- Remove `Expr.StringContext.unapply` [#10675](https://github.com/scala/scala3/pull/10675) +- Rename `Liftable` to `ToExpr` and `Unliftable` to `FromExpr` [#10618](https://github.com/scala/scala3/pull/10618) +- Remove Unliftable[Unit] [#10570](https://github.com/scala/scala3/pull/10570) +- Remove reflect.LambdaType [#10548](https://github.com/scala/scala3/pull/10548) +- Add `scala.quoted.Expr.unapply` as dual of `Expr.apply` [#10580](https://github.com/scala/scala3/pull/10580) +- Move `Quotes` as last parameter in `ExprMap.transform` [#10519](https://github.com/scala/scala3/pull/10519) +- Rework reflect Constant API [#10753](https://github.com/scala/scala3/pull/10753) +- Unify quoted.report and reflect.Reporting [#10474](https://github.com/scala/scala3/pull/10474) +- Fix #10359: Add GivenSelector to reflection API [#10469](https://github.com/scala/scala3/pull/10469) +- Rework reflect show API [#10661](https://github.com/scala/scala3/pull/10661) +- Fix #10709: Add missing level check before inlining [#10781](https://github.com/scala/scala3/pull/10781) # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributors @@ -231,7 +231,7 @@ We are looking forward to having you join the team of contributors. ## Library authors: Join our community build -Scala 3 is regularly tested against a sample of libraries known as the "community build". You can add your library to the [community build](https://github.com/lampepfl/dotty/tree/main/community-build) by submitting a PR. +Scala 3 is regularly tested against a sample of libraries known as the "community build". You can add your library to the [community build](https://github.com/scala/scala3/tree/main/community-build) by submitting a PR. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_blog/_posts/2021-02-17-scala3-rc1.md b/docs/_blog/_posts/2021-02-17-scala3-rc1.md index 9751f7b7461e..011dc0819107 100644 --- a/docs/_blog/_posts/2021-02-17-scala3-rc1.md +++ b/docs/_blog/_posts/2021-02-17-scala3-rc1.md @@ -11,7 +11,7 @@ Greetings from the Scala 3 team! We are delighted to announce the first release This release brings some last-minute polishings, clean-ups and changes before the big release. There were a few language changes to improve the user experience, as well as the polishings of the metaprogramming framework. We have also worked on the issues that had to be fixed before the stable release. -Overall, more than [400 PRs](https://github.com/lampepfl/dotty/pulls?q=is%3Apr+is%3Aclosed+closed%3A%3E2020-12-02+sort%3Acomments-desc) were merged after the M3 release and until today! Read more below! +Overall, more than [400 PRs](https://github.com/scala/scala3/pulls?q=is%3Apr+is%3Aclosed+closed%3A%3E2020-12-02+sort%3Acomments-desc) were merged after the M3 release and until today! Read more below! ## Allow secondary type parameter list in extension methods @@ -43,7 +43,7 @@ Or, when passing both type arguments: sumBy[String](List("a", "bb", "ccc"))[Int](_.length) ``` -For discussion, see [PR #10940](https://github.com/lampepfl/dotty/pull/10940). For more information about the extension methods, see [documentation](https://dotty.epfl.ch/docs/reference/contextual/extension-methods.html). +For discussion, see [PR #10940](https://github.com/scala/scala3/pull/10940). For more information about the extension methods, see [documentation](https://dotty.epfl.ch/docs/reference/contextual/extension-methods.html). ## New `import` syntax @@ -62,11 +62,11 @@ import scala.collection.mutable as mut import NumPy as np ``` -For the details and discussion, see [PR #11244](https://github.com/lampepfl/dotty/pull/11244). Read more about this change in the [documentation](https://dotty.epfl.ch/docs/reference/changed-features/imports.html). +For the details and discussion, see [PR #11244](https://github.com/scala/scala3/pull/11244). Read more about this change in the [documentation](https://dotty.epfl.ch/docs/reference/changed-features/imports.html). ## Use `*` for vararg splices -[PR #11240](https://github.com/lampepfl/dotty/pull/11240) changed the syntax of vararg splices in patterns and function arguments. The new syntax uses a postfix `*`, instead of `: _*`, analogously to how a vararg parameter is declared. +[PR #11240](https://github.com/scala/scala3/pull/11240) changed the syntax of vararg splices in patterns and function arguments. The new syntax uses a postfix `*`, instead of `: _*`, analogously to how a vararg parameter is declared. ## Use `uninitialized` for wildcard initializers @@ -88,7 +88,7 @@ var x: A = uninitialized This way expresses the intent of the idiom in a more verbose and easy to read way than simply writing an underscore. -For discussion, see [PR #11231](https://github.com/lampepfl/dotty/pull/11231), and the [documentation](https://dotty.epfl.ch/docs/reference/dropped-features/wildcard-init.html) is available on our website. +For discussion, see [PR #11231](https://github.com/scala/scala3/pull/11231), and the [documentation](https://dotty.epfl.ch/docs/reference/dropped-features/wildcard-init.html) is available on our website. ## Eta-expand companion object if functions are expected @@ -109,49 +109,49 @@ Results in: |The method `apply` is inserted. The auto insertion will be deprecated, please write `Foo.apply` explicitly. ``` -As the warning suggests, now you should write `Foo.apply` instead of `Foo`. See [Issue #6190](https://github.com/lampepfl/dotty/issues/6190) and [PR #7207](https://github.com/lampepfl/dotty/pull/7207) for discussion. +As the warning suggests, now you should write `Foo.apply` instead of `Foo`. See [Issue #6190](https://github.com/scala/scala3/issues/6190) and [PR #7207](https://github.com/scala/scala3/pull/7207) for discussion. ## Settling on `scaladoc` as the documentation tool We have settled on using the well-known `scaladoc` as a name for the documentation tool for Scala 3 (known previously as `scala3doc`). The obsolete `dotty-doc` (or `scala3-doc`) is removed in RC1. We have also removed all the Kotlin dependencies (Dokka, etc.) from scaladoc. -For details, see [PR #11349](https://github.com/lampepfl/dotty/pull/11349). To read more about `scaladoc`, see [documentation](https://dotty.epfl.ch/docs/usage/scaladoc/index.html) +For details, see [PR #11349](https://github.com/scala/scala3/pull/11349). To read more about `scaladoc`, see [documentation](https://dotty.epfl.ch/docs/usage/scaladoc/index.html) ## Use `future` and `future-migration` to specify language versions after 3.0 in `-source` -[PR #11355](https://github.com/lampepfl/dotty/pull/11355) changes the `-source` specifier for the Scala version(s) after 3.0 from `3.1` to `future`. I.e. it is now +[PR #11355](https://github.com/scala/scala3/pull/11355) changes the `-source` specifier for the Scala version(s) after 3.0 from `3.1` to `future`. I.e. it is now `-source future` and `-source future-migration` instead of `-source 3.1` and `-source 3.1-migration`. Language imports are changed analogously. The reason for the change is that we want to keep the possibility open to ship a `3.1` version that does not yet contain all the changes enabled under `-source future`. ## Other language changes -- Warn when matching against an opaque type [#10664](https://github.com/lampepfl/dotty/pull/10664) -- Fix [#8634](https://github.com/lampepfl/dotty/issues/8634): Support -release option [#10746](https://github.com/lampepfl/dotty/pull/10746) – the same way Scala 2 does. +- Warn when matching against an opaque type [#10664](https://github.com/scala/scala3/pull/10664) +- Fix [#8634](https://github.com/scala/scala3/issues/8634): Support -release option [#10746](https://github.com/scala/scala3/pull/10746) – the same way Scala 2 does. This setting allows you to specify a version of the Java platform (8, 9 etc) and compile the code with classes specific to the that Java platform, and emit the bytecode for that version. ## Metaprogramming changes A lot of work has been done on the metaprogramming side of things. Mostly we are cleaning up and polishing the API to prepare it for the stable release. The following are the important metaprogramming changes that took place: -- Add `scala.quoted.Expr.unapply` as dual of `Expr.apply` [#10580](https://github.com/lampepfl/dotty/pull/10580) -- Remove `Expr.StringContext.unapply` [#10675](https://github.com/lampepfl/dotty/pull/10675) -- Add reflect `MatchCase` `TypeRepr` [#10735](https://github.com/lampepfl/dotty/pull/10735) -- Rename `scala.quoted.staging.{Toolbox => Compiler}` [#11129](https://github.com/lampepfl/dotty/pull/11129) -- Fix [#10863](https://github.com/lampepfl/dotty/issues/10863): Make show `AnyKind`ed [#10988](https://github.com/lampepfl/dotty/pull/10988) -- Add ParamClause to allow multiple type param clauses [#11074](https://github.com/lampepfl/dotty/pull/11074) -- Rework reflect Symbol fields API [#10705](https://github.com/lampepfl/dotty/pull/10705) -- Rename `Liftable` to `ToExpr` and `Unliftable` to `FromExpr` [#10618](https://github.com/lampepfl/dotty/pull/10618) -- Expand non-transparent macros after Typer [#9984](https://github.com/lampepfl/dotty/pull/9984) -- Rework TastyInspector API to allow inspection of all files [#10792](https://github.com/lampepfl/dotty/pull/10792) -- Allow leading context parameters in extension methods [#10940](https://github.com/lampepfl/dotty/pull/10940) -- Rename `Not` to `NotGiven` to make its purpose clearer [#10720](https://github.com/lampepfl/dotty/pull/10720) -- Fix [#10709](https://github.com/lampepfl/dotty/issues/10709): Add missing level check before inlining [#10781](https://github.com/lampepfl/dotty/pull/10781) +- Add `scala.quoted.Expr.unapply` as dual of `Expr.apply` [#10580](https://github.com/scala/scala3/pull/10580) +- Remove `Expr.StringContext.unapply` [#10675](https://github.com/scala/scala3/pull/10675) +- Add reflect `MatchCase` `TypeRepr` [#10735](https://github.com/scala/scala3/pull/10735) +- Rename `scala.quoted.staging.{Toolbox => Compiler}` [#11129](https://github.com/scala/scala3/pull/11129) +- Fix [#10863](https://github.com/scala/scala3/issues/10863): Make show `AnyKind`ed [#10988](https://github.com/scala/scala3/pull/10988) +- Add ParamClause to allow multiple type param clauses [#11074](https://github.com/scala/scala3/pull/11074) +- Rework reflect Symbol fields API [#10705](https://github.com/scala/scala3/pull/10705) +- Rename `Liftable` to `ToExpr` and `Unliftable` to `FromExpr` [#10618](https://github.com/scala/scala3/pull/10618) +- Expand non-transparent macros after Typer [#9984](https://github.com/scala/scala3/pull/9984) +- Rework TastyInspector API to allow inspection of all files [#10792](https://github.com/scala/scala3/pull/10792) +- Allow leading context parameters in extension methods [#10940](https://github.com/scala/scala3/pull/10940) +- Rename `Not` to `NotGiven` to make its purpose clearer [#10720](https://github.com/scala/scala3/pull/10720) +- Fix [#10709](https://github.com/scala/scala3/issues/10709): Add missing level check before inlining [#10781](https://github.com/scala/scala3/pull/10781) ## Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributors @@ -225,7 +225,7 @@ According to `git shortlog -sn --no-merges 3.0.0-M3..3.0.0-RC1` these are: If you want to get your hands dirty and contribute to Scala 3, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. diff --git a/docs/_blog/_posts/2021-03-31-scala3-rc2.md b/docs/_blog/_posts/2021-03-31-scala3-rc2.md index 178dfabfbffc..13170adbcfad 100644 --- a/docs/_blog/_posts/2021-03-31-scala3-rc2.md +++ b/docs/_blog/_posts/2021-03-31-scala3-rc2.md @@ -6,7 +6,7 @@ authorImg: /images/anatolii.png date: 2021-03-31 --- -Hello! We are happy to announce Scala 3.0.0-RC2. With this release, we are getting ready for 3.0.0. The significance of it is to give the community the chance and time to test all the changes meant for 3.0.0 final. A lot of bug fixes found their way into this release to ensure stability for 3.0.0 – more than [250 PRs](https://github.com/lampepfl/dotty/pulls?q=is%3Apr+is%3Aclosed+closed%3A%3E2021-02-16) were merged after the 3.0.0-RC1 release and until today! +Hello! We are happy to announce Scala 3.0.0-RC2. With this release, we are getting ready for 3.0.0. The significance of it is to give the community the chance and time to test all the changes meant for 3.0.0 final. A lot of bug fixes found their way into this release to ensure stability for 3.0.0 – more than [250 PRs](https://github.com/scala/scala3/pulls?q=is%3Apr+is%3Aclosed+closed%3A%3E2021-02-16) were merged after the 3.0.0-RC1 release and until today! Read more about this release below. @@ -28,31 +28,31 @@ As mentioned above, we are currently in an issue-fixing mode. So a lot of those There are some notable changes worth mentioning. ## Restrict experimental features to unstable releases only -PR [#11920](https://github.com/lampepfl/dotty/pull/11920) restricts usage of experimental features only to nightlies and snapshots. This change ensures that changes deemed experimental will not propagate into the wider ecosystem provided that the wider ecosystem depends on stable releases. This is needed so that if an experimental feature is modified or removed from the language, the ecosystem will not be impacted. +PR [#11920](https://github.com/scala/scala3/pull/11920) restricts usage of experimental features only to nightlies and snapshots. This change ensures that changes deemed experimental will not propagate into the wider ecosystem provided that the wider ecosystem depends on stable releases. This is needed so that if an experimental feature is modified or removed from the language, the ecosystem will not be impacted. ## New `unsafeNulls` language feature -PR [#9884](https://github.com/lampepfl/dotty/pull/9884) adds a new language feature which enables unsafe null operations under explicit nulls. This is a tool to help projects migrating to full explicit nulls gradually. From now on, you can use an import `import scala.language.unsafeNulls` to create an unsafe scope. For discussion, see the PR linked above, and for more information on the feature, see the [documentation](https://dotty.epfl.ch/docs/reference/other-new-features/explicit-nulls.html). +PR [#9884](https://github.com/scala/scala3/pull/9884) adds a new language feature which enables unsafe null operations under explicit nulls. This is a tool to help projects migrating to full explicit nulls gradually. From now on, you can use an import `import scala.language.unsafeNulls` to create an unsafe scope. For discussion, see the PR linked above, and for more information on the feature, see the [documentation](https://dotty.epfl.ch/docs/reference/other-new-features/explicit-nulls.html). ## Treat Scala.js pseudo-unions as real unions -In PR [#11671](https://github.com/lampepfl/dotty/pull/11671), we now treat the `scala.scalajs.js.|[A, B]` as if it was a real Scala 3 union `A | B`, which further boosts the support for Scala.js in Scala 3. +In PR [#11671](https://github.com/scala/scala3/pull/11671), we now treat the `scala.scalajs.js.|[A, B]` as if it was a real Scala 3 union `A | B`, which further boosts the support for Scala.js in Scala 3. ## Other API changes -`-Ycheck-init` was renamed to `-Ysafe-init`. This flag is used to check safe initialization, more about which you can read in the [documentation](https://dotty.epfl.ch/docs/reference/other-new-features/safe-initialization.html). See also PR [#11920](https://github.com/lampepfl/dotty/pull/11920). +`-Ycheck-init` was renamed to `-Ysafe-init`. This flag is used to check safe initialization, more about which you can read in the [documentation](https://dotty.epfl.ch/docs/reference/other-new-features/safe-initialization.html). See also PR [#11920](https://github.com/scala/scala3/pull/11920). -PR [#11745](https://github.com/lampepfl/dotty/pull/11745) changes the `compiletime` package API a bit. `compiletime.S` was moved to `compiletime.ops.int.S` and the package object `compiletime` was removed in favor of top-level definitions. +PR [#11745](https://github.com/scala/scala3/pull/11745) changes the `compiletime` package API a bit. `compiletime.S` was moved to `compiletime.ops.int.S` and the package object `compiletime` was removed in favor of top-level definitions. ## Metaprogramming The following are some notable metaprogramming changes included into this release: -- Add quotes.Type.valueOfConstant [#11715](https://github.com/lampepfl/dotty/pull/11715) -- Remove compiletime.Widen [#11569](https://github.com/lampepfl/dotty/pull/11569) -- Add -Xcheck-macros scalac option [#11655](https://github.com/lampepfl/dotty/pull/11655) +- Add quotes.Type.valueOfConstant [#11715](https://github.com/scala/scala3/pull/11715) +- Remove compiletime.Widen [#11569](https://github.com/scala/scala3/pull/11569) +- Add -Xcheck-macros scalac option [#11655](https://github.com/scala/scala3/pull/11655) # Let us know what you think! If you have questions or any sort of feedback, feel free to send us a message on our [Gitter channel](https://gitter.im/lampepfl/dotty). If you encounter a bug, please -[open an issue on GitHub](https://github.com/lampepfl/dotty/issues/new). +[open an issue on GitHub](https://github.com/scala/scala3/issues/new). ## Contributors @@ -107,7 +107,7 @@ According to `git shortlog -sn --no-merges 3.0.0-RC1..3.0.0-RC2` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. @@ -116,7 +116,7 @@ We are looking forward to having you join the team of contributors. Dotty now has a set of widely-used community libraries that are built against every nightly Dotty snapshot. Currently, this includes shapeless, ScalaPB, algebra, scalatest, scopt and squants. -Join our [community build](https://github.com/lampepfl/dotty/tree/main/community-build) +Join our [community build](https://github.com/scala/scala3/tree/main/community-build) to make sure that our regression suite includes your library. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_blog/_posts/2021-04-21-scala3-rc3.md b/docs/_blog/_posts/2021-04-21-scala3-rc3.md index 8651730da93a..6eddc82e7273 100644 --- a/docs/_blog/_posts/2021-04-21-scala3-rc3.md +++ b/docs/_blog/_posts/2021-04-21-scala3-rc3.md @@ -13,16 +13,16 @@ This release also impacts the release date for 3.0.0 stable. 3.0.0 stable will g # Bug fixes included -- Fix type test for trait parameter arguments [#12066](https://github.com/lampepfl/dotty/pull/12066) -- Set file filter correctly [#12119](https://github.com/lampepfl/dotty/pull/12119) -- Provide mirror support after inlining [#12079](https://github.com/lampepfl/dotty/pull/12079) -- Revert "Recursively check nonvariant arguments of base types for realizability" [#12067](https://github.com/lampepfl/dotty/pull/12067) -- When simplifying match types, ensure fully defined before reducing [#12068](https://github.com/lampepfl/dotty/pull/12068) -- sbt-dotty: the binary version is 3 for Scala >= 3.0.0 [#12084](https://github.com/lampepfl/dotty/pull/12084) -- Fix isInstanceOf[Array[?]] returning true on non-Array [#12108](https://github.com/lampepfl/dotty/pull/12108) -- Scala2Unpickler: don't unpickle the same type parameter twice [#12129](https://github.com/lampepfl/dotty/pull/12129) -- Overloading resolution: Handle SAM types more like Java and Scala 2 [#12131](https://github.com/lampepfl/dotty/pull/12131) -- Add TermParamClause.isGiven [#12042](https://github.com/lampepfl/dotty/pull/12042) +- Fix type test for trait parameter arguments [#12066](https://github.com/scala/scala3/pull/12066) +- Set file filter correctly [#12119](https://github.com/scala/scala3/pull/12119) +- Provide mirror support after inlining [#12079](https://github.com/scala/scala3/pull/12079) +- Revert "Recursively check nonvariant arguments of base types for realizability" [#12067](https://github.com/scala/scala3/pull/12067) +- When simplifying match types, ensure fully defined before reducing [#12068](https://github.com/scala/scala3/pull/12068) +- sbt-dotty: the binary version is 3 for Scala >= 3.0.0 [#12084](https://github.com/scala/scala3/pull/12084) +- Fix isInstanceOf[Array[?]] returning true on non-Array [#12108](https://github.com/scala/scala3/pull/12108) +- Scala2Unpickler: don't unpickle the same type parameter twice [#12129](https://github.com/scala/scala3/pull/12129) +- Overloading resolution: Handle SAM types more like Java and Scala 2 [#12131](https://github.com/scala/scala3/pull/12131) +- Add TermParamClause.isGiven [#12042](https://github.com/scala/scala3/pull/12042) ## Contributors Thank you to all the contributors who made this release possible 🎉 @@ -40,7 +40,7 @@ According to `git shortlog -sn --no-merges 3.0.0-RC2..3.0.0-RC3` these are: If you want to get your hands dirty and contribute to Dotty, now is a good time to get involved! Head to our [Getting Started page for new contributors](https://dotty.epfl.ch/docs/contributing/getting-started.html), -and have a look at some of the [good first issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). +and have a look at some of the [good first issues](https://github.com/scala/scala3/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%3Anovice). They make perfect entry points into hacking on the compiler. We are looking forward to having you join the team of contributors. @@ -49,7 +49,7 @@ We are looking forward to having you join the team of contributors. Dotty now has a set of widely-used community libraries that are built against every nightly Dotty snapshot. Currently, this includes shapeless, ScalaPB, algebra, scalatest, scopt and squants. -Join our [community build](https://github.com/lampepfl/dotty/tree/main/community-build) +Join our [community build](https://github.com/scala/scala3/tree/main/community-build) to make sure that our regression suite includes your library. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_blog/_posts/2021-06-07-scala3.0.1-rc1-release.md b/docs/_blog/_posts/2021-06-07-scala3.0.1-rc1-release.md index e9fac2d0447c..617f175e74b7 100644 --- a/docs/_blog/_posts/2021-06-07-scala3.0.1-rc1-release.md +++ b/docs/_blog/_posts/2021-06-07-scala3.0.1-rc1-release.md @@ -21,13 +21,13 @@ The spirit of this policy is to make sure that effectively, no library published Having said that, we still encourage people to play with the experimental features from the `NIGHTLY` compiler versions and discuss their findings. Without the curious and adventurous part of the community playing with the new features, there is no way of knowing what they are good for, and no way to decide whether they should be dropped or promoted to a stable feature. -More about this change you can read in the PR [#12102](https://github.com/lampepfl/dotty/pull/12102). +More about this change you can read in the PR [#12102](https://github.com/scala/scala3/pull/12102). # Kind-projector work -This release also brings extra features for the [Kind Projector](https://docs.scala-lang.org/scala3/guides/migration/plugin-kind-projector.html) migration support. First, PR [#12378](https://github.com/lampepfl/dotty/pull/12378) allows `_` as type lambda placeholder. Second, PR [#12341](https://github.com/lampepfl/dotty/pull/12341) brings support for the variance annotations on the placeholder. This work enhances the ability to cross-compile Scala 2 code that uses the Kind Projector plugin to Scala 3. +This release also brings extra features for the [Kind Projector](https://docs.scala-lang.org/scala3/guides/migration/plugin-kind-projector.html) migration support. First, PR [#12378](https://github.com/scala/scala3/pull/12378) allows `_` as type lambda placeholder. Second, PR [#12341](https://github.com/scala/scala3/pull/12341) brings support for the variance annotations on the placeholder. This work enhances the ability to cross-compile Scala 2 code that uses the Kind Projector plugin to Scala 3. # Improved error reporting -Down the error reporting lane, match type reduction errors were improved. When using a match type, it may or may not reduce to one of its cases. If it doesn't match type is used as specified, e.g. if `M[T]` is a match type and it didn't reduce for `M[Int]`, `M[Int]` will be used. This behavior, however, is frequently not what you want: there is a lot of cases where you would expect a match type to reduce but it doesn't. In such cases, it would be nice to have some diagnostic regarding why it didn't reduce. PR [#12053](https://github.com/lampepfl/dotty/pull/12053/) adds just such a diagnostic. E.g. the following code: +Down the error reporting lane, match type reduction errors were improved. When using a match type, it may or may not reduce to one of its cases. If it doesn't match type is used as specified, e.g. if `M[T]` is a match type and it didn't reduce for `M[Int]`, `M[Int]` will be used. This behavior, however, is frequently not what you want: there is a lot of cases where you would expect a match type to reduce but it doesn't. In such cases, it would be nice to have some diagnostic regarding why it didn't reduce. PR [#12053](https://github.com/scala/scala3/pull/12053/) adds just such a diagnostic. E.g. the following code: ```scala trait A @@ -58,32 +58,32 @@ will report the following error: ``` # Scaladoc -We have updated the [documentation](http://dotty.epfl.ch/docs/usage/scaladoc/index.html) for Scaladoc making it easier for you to get started. Also, PR [#11582](https://github.com/lampepfl/dotty/pull/11582) has added the snippet compiler to ensure the snippets in your scaladoc documentation comments aren't broken. You can read more about this feature on the [mailing list](https://contributors.scala-lang.org/t/snippet-validation-in-scaladoc-for-scala-3/4976). +We have updated the [documentation](http://dotty.epfl.ch/docs/usage/scaladoc/index.html) for Scaladoc making it easier for you to get started. Also, PR [#11582](https://github.com/scala/scala3/pull/11582) has added the snippet compiler to ensure the snippets in your scaladoc documentation comments aren't broken. You can read more about this feature on the [mailing list](https://contributors.scala-lang.org/t/snippet-validation-in-scaladoc-for-scala-3/4976). # Metaprogramming A lot of metaprogramming work was focused on improving the performance. Some of the notable PRs include: -- Cache quote unpickling [#12242](https://github.com/lampepfl/dotty/pull/12242) -- Avoid pickled tasty for some captured quote reference [#12248](https://github.com/lampepfl/dotty/pull/12248) -- Improve quote matcher performance [#12418](https://github.com/lampepfl/dotty/pull/12418) -- Port scala.quoted.runtime.impl.QuoteMatcher [#12402](https://github.com/lampepfl/dotty/pull/12402) +- Cache quote unpickling [#12242](https://github.com/scala/scala3/pull/12242) +- Avoid pickled tasty for some captured quote reference [#12248](https://github.com/scala/scala3/pull/12248) +- Improve quote matcher performance [#12418](https://github.com/scala/scala3/pull/12418) +- Port scala.quoted.runtime.impl.QuoteMatcher [#12402](https://github.com/scala/scala3/pull/12402) # Issue fixing Otherwise, we are making an effort to reduce our issue tracker. Among others, the following are some of the PRs dedicated to issue fixing: -- IArray.toArray: Deprecate broken method [#12598](https://github.com/lampepfl/dotty/pull/12598) -- Fix comparison of dependent function types [#12214](https://github.com/lampepfl/dotty/pull/12214) -- Make translucentSuperType handle match types [#12153](https://github.com/lampepfl/dotty/pull/12153) -- Harden Type Inference [#12560](https://github.com/lampepfl/dotty/pull/12560) -- Reject references to self in super constructor calls [#12567](https://github.com/lampepfl/dotty/pull/12567) -- Provide mirror support after inlining [#12062](https://github.com/lampepfl/dotty/pull/12062) -- Allow export paths to see imports [#12134](https://github.com/lampepfl/dotty/pull/12134) -- Streamline given syntax [#12107](https://github.com/lampepfl/dotty/pull/12107) -- Export constructor proxies [#12311](https://github.com/lampepfl/dotty/pull/12311) -- Identify package and nested package object in isSubPrefix [#12297](https://github.com/lampepfl/dotty/pull/12297) -- Treat Refinements more like AndTypes [#12317](https://github.com/lampepfl/dotty/pull/12317) -- Fix [#9871](https://github.com/lampepfl/dotty/pull/9871): use toNestedPairs in provablyDisjoint [#10560](https://github.com/lampepfl/dotty/pull/10560) +- IArray.toArray: Deprecate broken method [#12598](https://github.com/scala/scala3/pull/12598) +- Fix comparison of dependent function types [#12214](https://github.com/scala/scala3/pull/12214) +- Make translucentSuperType handle match types [#12153](https://github.com/scala/scala3/pull/12153) +- Harden Type Inference [#12560](https://github.com/scala/scala3/pull/12560) +- Reject references to self in super constructor calls [#12567](https://github.com/scala/scala3/pull/12567) +- Provide mirror support after inlining [#12062](https://github.com/scala/scala3/pull/12062) +- Allow export paths to see imports [#12134](https://github.com/scala/scala3/pull/12134) +- Streamline given syntax [#12107](https://github.com/scala/scala3/pull/12107) +- Export constructor proxies [#12311](https://github.com/scala/scala3/pull/12311) +- Identify package and nested package object in isSubPrefix [#12297](https://github.com/scala/scala3/pull/12297) +- Treat Refinements more like AndTypes [#12317](https://github.com/scala/scala3/pull/12317) +- Fix [#9871](https://github.com/scala/scala3/pull/9871): use toNestedPairs in provablyDisjoint [#10560](https://github.com/scala/scala3/pull/10560) # Contributors @@ -147,7 +147,7 @@ According to `git shortlog -sn --no-merges 3.0.0-RC2..3.0.1-RC1`† these are: ## Library authors: Join our community build Scala 3 now has a set of widely-used community libraries that are built against every nightly Scala 3 snapshot. -Join our [community build](https://github.com/lampepfl/dotty/tree/main/community-build) +Join our [community build](https://github.com/scala/scala3/tree/main/community-build) to make sure that our regression suite includes your library. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_blog/_posts/2021-06-25-scala301-rc2.md b/docs/_blog/_posts/2021-06-25-scala301-rc2.md index 76257d1a8664..054a8dfc9d56 100644 --- a/docs/_blog/_posts/2021-06-25-scala301-rc2.md +++ b/docs/_blog/_posts/2021-06-25-scala301-rc2.md @@ -6,9 +6,9 @@ authorImg: /images/anatolii.png date: 2021-06-25 --- -This post is a quick announcement of Scala 3.0.1-RC2. This is the second release candidate for 3.0.1. The reason for this release is that a regression with respect to 3.0.0 was introduced by PR [#12519](https://github.com/lampepfl/dotty/pull/12519) which caused the compiler to fail where it shouldn't. We have fixed this regression in PR [#12827](https://github.com/lampepfl/dotty/pull/12827) and backported it to 3.0.1. This is the main reason for having 3.0.1-RC2 before 3.0.1 which is due in one week. +This post is a quick announcement of Scala 3.0.1-RC2. This is the second release candidate for 3.0.1. The reason for this release is that a regression with respect to 3.0.0 was introduced by PR [#12519](https://github.com/scala/scala3/pull/12519) which caused the compiler to fail where it shouldn't. We have fixed this regression in PR [#12827](https://github.com/scala/scala3/pull/12827) and backported it to 3.0.1. This is the main reason for having 3.0.1-RC2 before 3.0.1 which is due in one week. -Besides this main change, taking advantage of the fact that RC2 is happening, we have also included various SBT reporting improvements (PR [#12845](https://github.com/lampepfl/dotty/pull/12845)) which should improve interaction with [Metals](https://scalameta.org/metals/). Also we've backported a few infrastructural fixes even though they aren't a regression from 3.0.0. +Besides this main change, taking advantage of the fact that RC2 is happening, we have also included various SBT reporting improvements (PR [#12845](https://github.com/scala/scala3/pull/12845)) which should improve interaction with [Metals](https://scalameta.org/metals/). Also we've backported a few infrastructural fixes even though they aren't a regression from 3.0.0. @@ -29,7 +29,7 @@ According to `git shortlog -sn --no-merges 3.0.1-RC1..3.0.1-RC2` these are: ## Library authors: Join our community build Scala 3 now has a set of widely-used community libraries that are built against every nightly Scala 3 snapshot. -Join our [community build](https://github.com/lampepfl/dotty/tree/main/community-build) +Join our [community build](https://github.com/scala/scala3/tree/main/community-build) to make sure that our regression suite includes your library. [Scastie]: https://scastie.scala-lang.org/?target=dotty diff --git a/docs/_docs/contributing/architecture/context.md b/docs/_docs/contributing/architecture/context.md index cd38ee437867..61cb88ad5494 100644 --- a/docs/_docs/contributing/architecture/context.md +++ b/docs/_docs/contributing/architecture/context.md @@ -50,4 +50,4 @@ convention is that the `Context` be an explicit parameter, to track its usage. | ... | and so on | -[Contexts]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Contexts.scala +[Contexts]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/Contexts.scala diff --git a/docs/_docs/contributing/architecture/lifecycle.md b/docs/_docs/contributing/architecture/lifecycle.md index 2cf58f477da3..30ca934ede71 100644 --- a/docs/_docs/contributing/architecture/lifecycle.md +++ b/docs/_docs/contributing/architecture/lifecycle.md @@ -78,13 +78,13 @@ tools // contains helpers and the `scala` generic runner ``` -[Phases]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Phases.scala -[CompilationUnit]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/CompilationUnit.scala +[Phases]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/Phases.scala +[CompilationUnit]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/CompilationUnit.scala -[dotty.tools]: https://github.com/lampepfl/dotty/tree/master/compiler/src/dotty/tools -[ScalaSettings]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +[dotty.tools]: https://github.com/scala/scala3/tree/master/compiler/src/dotty/tools +[ScalaSettings]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala [syntax]: https://docs.scala-lang.org/scala3/reference/syntax.html -[Main]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Main.scala -[Driver]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Driver.scala -[Compiler]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Compiler.scala -[Run]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Run.scala \ No newline at end of file +[Main]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/Main.scala +[Driver]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/Driver.scala +[Compiler]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/Compiler.scala +[Run]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/Run.scala \ No newline at end of file diff --git a/docs/_docs/contributing/architecture/phases.md b/docs/_docs/contributing/architecture/phases.md index 844ae144dddb..8e63de04dadb 100644 --- a/docs/_docs/contributing/architecture/phases.md +++ b/docs/_docs/contributing/architecture/phases.md @@ -85,24 +85,24 @@ suitable for the runtime system, with two sub-groupings: ### `backendPhases` These map the transformed trees to Java classfiles or SJSIR files. -[CompilationUnit]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/CompilationUnit.scala -[Compiler]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Compiler.scala -[Phase]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Phases.scala -[MiniPhase]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala -[Run]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Run.scala -[parser]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/parsing/ParserPhase.scala -[typer]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/typer/TyperPhase.scala -[posttyper]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/PostTyper.scala -[prepjsinterop]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/sjs/PrepJSInterop.scala -[pickler]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/Pickler.scala -[inlining]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/Inlining.scala -[postInlining]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/PostInlining.scala -[staging]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/Staging.scala -[pickleQuotes]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala -[refchecks]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/typer/RefChecks.scala -[initChecker]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/init/Checker.scala -[firstTransform]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala -[patternMatcher]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala -[erasure]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/Erasure.scala -[Mirror]: https://github.com/lampepfl/dotty/blob/master/library/src/scala/deriving/Mirror.scala +[CompilationUnit]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/CompilationUnit.scala +[Compiler]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/Compiler.scala +[Phase]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/Phases.scala +[MiniPhase]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/MegaPhase.scala +[Run]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/Run.scala +[parser]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/parsing/ParserPhase.scala +[typer]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/typer/TyperPhase.scala +[posttyper]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +[prepjsinterop]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/sjs/PrepJSInterop.scala +[pickler]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/Pickler.scala +[inlining]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/Inlining.scala +[postInlining]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/PostInlining.scala +[staging]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/Staging.scala +[pickleQuotes]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala +[refchecks]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +[initChecker]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/init/Checker.scala +[firstTransform]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala +[patternMatcher]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +[erasure]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/Erasure.scala +[Mirror]: https://github.com/scala/scala3/blob/master/library/src/scala/deriving/Mirror.scala [PCP]: ../../reference/metaprogramming/macros.md#the-phase-consistency-principle diff --git a/docs/_docs/contributing/architecture/symbols.md b/docs/_docs/contributing/architecture/symbols.md index c19588a4ff12..c11c054b4967 100644 --- a/docs/_docs/contributing/architecture/symbols.md +++ b/docs/_docs/contributing/architecture/symbols.md @@ -60,11 +60,11 @@ All definition symbols will contain a `SymDenotation`. The denotation, in turn, A class symbol will instead be associated with a `ClassDenotation`, which extends `SymDenotation` with some additional fields specific for classes. -[Signature1]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Signature.scala#L9-L33 -[Symbols]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Symbols.scala -[flatten]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/Flatten.scala -[lambdaLift]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala -[CompilationUnit]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/CompilationUnit.scala -[Denotations]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Denotations.scala -[SymDenotations]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/SymDenotations.scala -[flags]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Flags.scala +[Signature1]: https://github.com/scala/scala3/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Signature.scala#L9-L33 +[Symbols]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/Symbols.scala +[flatten]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/Flatten.scala +[lambdaLift]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala +[CompilationUnit]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/CompilationUnit.scala +[Denotations]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/Denotations.scala +[SymDenotations]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +[flags]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/Flags.scala diff --git a/docs/_docs/contributing/architecture/time.md b/docs/_docs/contributing/architecture/time.md index 588b1ce40bb2..56a6cf7447a1 100644 --- a/docs/_docs/contributing/architecture/time.md +++ b/docs/_docs/contributing/architecture/time.md @@ -61,8 +61,8 @@ method foo after typer => (b: Box)(x: b.X): scala.collection.immutable.List[b. method foo after erasure => (b: Box, x: Object): scala.collection.immutable.List ``` -[runs]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/Run.scala -[periods]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Periods.scala -[Contexts]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Contexts.scala -[typer]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/typer/TyperPhase.scala -[erasure]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/Erasure.scala +[runs]: https://github.com/scala/scala3/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/Run.scala +[periods]: https://github.com/scala/scala3/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Periods.scala +[Contexts]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/Contexts.scala +[typer]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/typer/TyperPhase.scala +[erasure]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/Erasure.scala diff --git a/docs/_docs/contributing/architecture/types.md b/docs/_docs/contributing/architecture/types.md index 2dfdc33101a0..ed8995c08643 100644 --- a/docs/_docs/contributing/architecture/types.md +++ b/docs/_docs/contributing/architecture/types.md @@ -143,5 +143,5 @@ Type -+- proxy_type --+- NamedType --------+- TypeRef ``` -[Types.scala]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Types.scala -[DottyTypeStealer]: https://github.com/lampepfl/dotty/blob/master/compiler/test/dotty/tools/DottyTypeStealer.scala +[Types.scala]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/Types.scala +[DottyTypeStealer]: https://github.com/scala/scala3/blob/master/compiler/test/dotty/tools/DottyTypeStealer.scala diff --git a/docs/_docs/contributing/community-build.md b/docs/_docs/contributing/community-build.md index b382786c614e..e333e4985e36 100644 --- a/docs/_docs/contributing/community-build.md +++ b/docs/_docs/contributing/community-build.md @@ -32,14 +32,14 @@ project to the community build you can follow these steps: check out the [Scala 3 Migration Guide](https://docs.scala-lang.org/scala3/guides/migration/compatibility-intro.html). You can see the submodules in - [community-projects](https://github.com/lampepfl/dotty/tree/main/community-build/community-projects/) + [community-projects](https://github.com/scala/scala3/tree/main/community-build/community-projects/) for examples of projects that compile with Scala 3. 2. Open a PR against this repo that: - Adds your project as a new git submodule - `git submodule add https://github.com/dotty-staging/XYZ.git community-build/community-projects/XYZ` - - Add the project to [projects.scala](https://github.com/lampepfl/dotty/blob/main/community-build/src/scala/dotty/communitybuild/projects.scala) - - Adds a test in [CommunityBuildTest.scala](https://github.com/lampepfl/dotty/blob/main/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala) + - Add the project to [projects.scala](https://github.com/scala/scala3/blob/main/community-build/src/scala/dotty/communitybuild/projects.scala) + - Adds a test in [CommunityBuildTest.scala](https://github.com/scala/scala3/blob/main/community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala) 3. Once the CI is green, someone from the Dotty team will fork your repo and add it to [dotty-staging](https://github.com/dotty-staging). This enables us to diff --git a/docs/_docs/contributing/debugging/ide-debugging.md b/docs/_docs/contributing/debugging/ide-debugging.md index af817826565a..8548235672af 100644 --- a/docs/_docs/contributing/debugging/ide-debugging.md +++ b/docs/_docs/contributing/debugging/ide-debugging.md @@ -74,7 +74,7 @@ To locate them on your filesystem you can run the `export scala3-library-bootstr ``` $ sbt > export scala3-library-bootstrapped/fullClasspath -/home/user/lampepfl/dotty/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar +/home/user/scala/scala3/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar [success] Total time: 1 s, completed Mar 10, 2023, 4:37:43 PM ``` @@ -93,7 +93,7 @@ Here is the final configuration: "../tests/pos/HelloWorld.scala", "-classpath", // To replace with your own paths - "/home/user/lampepfl/dotty/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar", + "/home/user/scala/scala3/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar", "-color", "never" ], @@ -112,7 +112,7 @@ You can compile more than one Scala file, by adding them in the `args`: "file1.scala", "file2.scala", "-classpath", - "/home/user/lampepfl/dotty/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar" + "/home/user/scala/scala3/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar" ] ``` @@ -132,7 +132,7 @@ And concatenate the output into the classpath argument, which should already con "args": [ "using-cats.scala", "-classpath", - "/home/user/lampepfl/dotty/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/typelevel/cats-core_3/2.9.0/cats-core_3-2.9.0.jar:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/typelevel/cats-kernel_3/2.9.0/cats-kernel_3-2.9.0.jar" + "/home/user/scala/scala3/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/typelevel/cats-core_3/2.9.0/cats-core_3-2.9.0.jar:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/typelevel/cats-kernel_3/2.9.0/cats-kernel_3-2.9.0.jar" ] ``` diff --git a/docs/_docs/contributing/debugging/inspection.md b/docs/_docs/contributing/debugging/inspection.md index a80c3d3462ae..7cb1fa68abff 100644 --- a/docs/_docs/contributing/debugging/inspection.md +++ b/docs/_docs/contributing/debugging/inspection.md @@ -181,6 +181,6 @@ class StealBox: assert(empty.name.toString == "") ``` -[DottyTypeStealer]: https://github.com/lampepfl/dotty/blob/master/compiler/test/dotty/tools/DottyTypeStealer.scala -[ScalaSettings]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala -[symbols]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +[DottyTypeStealer]: https://github.com/scala/scala3/blob/master/compiler/test/dotty/tools/DottyTypeStealer.scala +[ScalaSettings]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +[symbols]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/SymDenotations.scala diff --git a/docs/_docs/contributing/debugging/other-debugging.md b/docs/_docs/contributing/debugging/other-debugging.md index 50be43db51ab..e8b72bcca656 100644 --- a/docs/_docs/contributing/debugging/other-debugging.md +++ b/docs/_docs/contributing/debugging/other-debugging.md @@ -152,7 +152,7 @@ To print out the trees after all phases: scalac -Xprint:all ../issues/Playground.scala ``` -To find out the list of all the phases and their names, check out [this](https://github.com/lampepfl/dotty/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/Compiler.scala#L34) line in `Compiler.scala`. Each `Phase` object has `phaseName` defined on it, this is the phase name. +To find out the list of all the phases and their names, check out [this](https://github.com/scala/scala3/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/Compiler.scala#L34) line in `Compiler.scala`. Each `Phase` object has `phaseName` defined on it, this is the phase name. ## Printing out stack traces of compile time errors You can use the flag `-Ydebug-error` to get the stack trace of all the compile-time errors. Consider the following file: @@ -207,7 +207,7 @@ val YshowVarBounds = BooleanSetting("-Yshow-var-bounds" , "Print type varia val YtestPickler = BooleanSetting("-Ytest-pickler" , "self-test for pickling functionality; should be used with -Ystop-after:pickler") ``` -They are defined in [ScalaSettings.scala](https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala). E.g. `YprintPos` is defined as: +They are defined in [ScalaSettings.scala](https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala). E.g. `YprintPos` is defined as: ```scala val YprintPos: Setting[Boolean] = BooleanSetting("-Yprint-pos", "show tree positions.") @@ -244,7 +244,7 @@ package @ { ### Figuring out an object creation site #### Via ID -Every [Positioned](https://github.com/lampepfl/dotty/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/ast/Positioned.scala) (a parent class of `Tree`) object has a `uniqueId` field. It is an integer that is unique for that tree and doesn't change from compile run to compile run. You can output these IDs from any printer (such as the ones used by `.show` and `-Xprint`) via `-Yshow-tree-ids` flag, e.g.: +Every [Positioned](https://github.com/scala/scala3/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/ast/Positioned.scala) (a parent class of `Tree`) object has a `uniqueId` field. It is an integer that is unique for that tree and doesn't change from compile run to compile run. You can output these IDs from any printer (such as the ones used by `.show` and `-Xprint`) via `-Yshow-tree-ids` flag, e.g.: ```shell scalac -Xprint:typer -Yshow-tree-ids ../issues/Playground.scala @@ -355,7 +355,7 @@ if (tree.show == """println("Hello World")""") { } ``` -In other words, you have a reference to the object and want to know were it was created. To do so, go to the class definition of that object. In our case, `tree` is a [`Tree`](https://github.com/lampepfl/dotty/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/ast/Trees.scala#L52). Now, create a new `val` member of that type: +In other words, you have a reference to the object and want to know were it was created. To do so, go to the class definition of that object. In our case, `tree` is a [`Tree`](https://github.com/scala/scala3/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/ast/Trees.scala#L52). Now, create a new `val` member of that type: ```scala val tracer = Thread.currentThread.getStackTrace.mkString("\n") @@ -380,7 +380,7 @@ Dotty has a lot of debug calls scattered throughout the code, most of which are These do not follow any particular system and so probably it will be easier to go with `println` most of the times instead. #### Printers -Defined in [Printers.scala](https://github.com/lampepfl/dotty/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/config/Printers.scala) as a set of variables, each responsible for its own domain. To enable them, replace `noPrinter` with `default`. [Example](https://github.com/lampepfl/dotty/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/typer/Typer.scala#L2226) from the code: +Defined in [Printers.scala](https://github.com/scala/scala3/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/config/Printers.scala) as a set of variables, each responsible for its own domain. To enable them, replace `noPrinter` with `default`. [Example](https://github.com/scala/scala3/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/typer/Typer.scala#L2226) from the code: ```scala typr.println(i"make contextual function $tree / $pt ---> $ifun") @@ -389,13 +389,13 @@ typr.println(i"make contextual function $tree / $pt ---> $ifun") `typr` is a printer. #### Tracing -Defined in [trace.scala](https://github.com/lampepfl/dotty/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/reporting/trace.scala). [Example](https://github.com/lampepfl/dotty/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/typer/Typer.scala#L2232) from the code: +Defined in [trace.scala](https://github.com/scala/scala3/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/reporting/trace.scala). [Example](https://github.com/scala/scala3/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/typer/Typer.scala#L2232) from the code: ```scala trace(i"typing $tree", typr, show = true) { // ... ``` -To enable globally, change [tracingEnabled](https://github.com/lampepfl/dotty/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/config/Config.scala#L164) to `true` (will recompile a lot of code). +To enable globally, change [tracingEnabled](https://github.com/scala/scala3/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/config/Config.scala#L164) to `true` (will recompile a lot of code). You also need to set the printer referenced in the call (in the example, `typr`) to `default` as explained in the section on printers. @@ -406,4 +406,4 @@ trace.force(i"typing $tree", typr, show = true) { // ... ``` #### Reporter -Defined in [Reporter.scala](https://github.com/lampepfl/dotty/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/reporting/Reporter.scala). Enables calls such as `report.log`. To enable, run scalac with `-Ylog:typer` option. +Defined in [Reporter.scala](https://github.com/scala/scala3/blob/10526a7d0aa8910729b6036ee51942e05b71abf6/compiler/src/dotty/tools/dotc/reporting/Reporter.scala). Enables calls such as `report.log`. To enable, run scalac with `-Ylog:typer` option. diff --git a/docs/_docs/contributing/getting-started.md b/docs/_docs/contributing/getting-started.md index 938e7ff36d42..63e968902600 100644 --- a/docs/_docs/contributing/getting-started.md +++ b/docs/_docs/contributing/getting-started.md @@ -127,7 +127,7 @@ For more information, see the [scaladoc section](./scaladoc.md). ## Community The main development discussion channels are: -- [github.com/lampepfl/dotty/discussions](https://github.com/lampepfl/dotty/discussions) +- [github.com/scala/scala3/discussions](https://github.com/scala/scala3/discussions) - [contributors.scala-lang.org](https://contributors.scala-lang.org) - [gitter.im/scala/contributors](https://gitter.im/scala/contributors) @@ -141,5 +141,5 @@ The main development discussion channels are: [adopt]: https://adoptopenjdk.net/ [compat]: https://docs.scala-lang.org/overviews/jdk-compatibility/overview.html [scala-cla]: https://www.lightbend.com/contribute/cla/scala -[dotty-issue]: https://github.com/lampepfl/dotty/issues -[dotty-discussion]: https://github.com/lampepfl/dotty/discussions +[dotty-issue]: https://github.com/scala/scala3/issues +[dotty-discussion]: https://github.com/scala/scala3/discussions diff --git a/docs/_docs/contributing/index.md b/docs/_docs/contributing/index.md index 507149340941..965847e39a94 100644 --- a/docs/_docs/contributing/index.md +++ b/docs/_docs/contributing/index.md @@ -12,9 +12,9 @@ also documents the inner workings of the Scala 3 compiler, `dotc`. Keep in mind that the code for `dotc` is continually changing, so the ideas discussed in this guide may fall out of date. This is a living document, so please consider contributing to it on -[GitHub](https://github.com/lampepfl/dotty/tree/main/docs/_docs/contributing) if +[GitHub](https://github.com/scala/scala3/tree/main/docs/_docs/contributing) if you notice anything out of date, or report any issues -[here](https://github.com/lampepfl/dotty/issues). +[here](https://github.com/scala/scala3/issues). ### Get the most from This Guide diff --git a/docs/_docs/contributing/issues/areas.md b/docs/_docs/contributing/issues/areas.md index ce27e9c0a5aa..9206d608ffbb 100644 --- a/docs/_docs/contributing/issues/areas.md +++ b/docs/_docs/contributing/issues/areas.md @@ -55,17 +55,17 @@ See [Inliner]. #### Compiletime Ops Types See `tryCompiletimeConstantFold` in [Types]. -[Showable]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/printing/Showable.scala -[PlainPrinter]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala -[RefinedPrinter]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala -[ErrorMessageID]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala -[messages]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/reporting/messages.scala -[Synthesizer]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala -[SyntheticMembers]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala -[quotes-impl]: https://github.com/lampepfl/dotty/tree/master/compiler/src/scala/quoted/runtime/impl -[Inliner]: https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/inlines/Inliner.scala -[Types]: https://github.com/lampepfl/dotty/tree/master/compiler/src/dotty/tools/dotc/core/Types.scala -[Completion]: https://github.com/lampepfl/dotty/tree/master/compiler/src/dotty/tools/dotc/interactive/Completion.scala -[DesugarEnums]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala -[Desugar]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/ast/Desugar.scala -[Space]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala +[Showable]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/printing/Showable.scala +[PlainPrinter]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +[RefinedPrinter]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +[ErrorMessageID]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala +[messages]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/reporting/messages.scala +[Synthesizer]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/typer/Synthesizer.scala +[SyntheticMembers]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala +[quotes-impl]: https://github.com/scala/scala3/tree/master/compiler/src/scala/quoted/runtime/impl +[Inliner]: https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/inlines/Inliner.scala +[Types]: https://github.com/scala/scala3/tree/master/compiler/src/dotty/tools/dotc/core/Types.scala +[Completion]: https://github.com/scala/scala3/tree/master/compiler/src/dotty/tools/dotc/interactive/Completion.scala +[DesugarEnums]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala +[Desugar]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/ast/Desugar.scala +[Space]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala diff --git a/docs/_docs/contributing/issues/cause.md b/docs/_docs/contributing/issues/cause.md index e23f6d1f747f..f96d3b6d2f8a 100644 --- a/docs/_docs/contributing/issues/cause.md +++ b/docs/_docs/contributing/issues/cause.md @@ -116,7 +116,7 @@ def myInfo: Type = myInfo_debug, def myInfo_=(x: Type) = { tracer = Thread.currentThread.getStackTrace.mkString("\n"); myInfo_debug = x } ``` -[Printers]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/config/Printers.scala -[Denotation]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Denotations.scala -[PostTyper]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/PostTyper.scala -[ScalaSettings]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +[Printers]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/config/Printers.scala +[Denotation]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/core/Denotations.scala +[PostTyper]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +[ScalaSettings]: https://github.com/scala/scala3/blob/master/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala diff --git a/docs/_docs/contributing/issues/reproduce.md b/docs/_docs/contributing/issues/reproduce.md index ca5da324a867..ae031a44d76f 100644 --- a/docs/_docs/contributing/issues/reproduce.md +++ b/docs/_docs/contributing/issues/reproduce.md @@ -159,7 +159,7 @@ scala -classpath $here/out Test # Run main method of `Test` generated by the co In this section, you have seen how to reproduce an issue locally, and next you will see how to try and detect its root cause. -[lampepfl/dotty]: https://github.com/lampepfl/dotty/issues -[#7710]: https://github.com/lampepfl/dotty/issues/7710 +[lampepfl/dotty]: https://github.com/scala/scala3/issues +[#7710]: https://github.com/scala/scala3/issues/7710 [dotty-issue-workspace]: https://github.com/anatoliykmetyuk/dotty-issue-workspace [workspace-readme]: https://github.com/anatoliykmetyuk/dotty-issue-workspace#getting-started diff --git a/docs/_docs/contributing/procedures/release.md b/docs/_docs/contributing/procedures/release.md index c54bb637aff5..88e1beb1b93b 100644 --- a/docs/_docs/contributing/procedures/release.md +++ b/docs/_docs/contributing/procedures/release.md @@ -28,7 +28,7 @@ Say we want to release the 0.14.0 version. In this section we describe the proce CI is set to automatically detect the tags of the format discussed above and perform the required release operations. Precisely, it will do two things for the release tags: - Publish the release jars to Maven -- Create the drafts at the GitHub [release](https://github.com/lampepfl/dotty/releases) page of the repository with the artefacts of the release. +- Create the drafts at the GitHub [release](https://github.com/scala/scala3/releases) page of the repository with the artefacts of the release. The CI operation is entirely automatic provided you have tagged the release correctly. No need to do anything here. @@ -50,11 +50,11 @@ However, you may end up with as many as 6 tasks being run. The auxiliary tasks m ### Release Procedure Checklist Before we start the release procedure, we create an issue with a release checklist. As we go through the release, we update the checklist. To generate the checklist, run the following command: -`bash <(curl -sL https://raw.githubusercontent.com/lampepfl/dotty/main/docs/docs/contributing/checklist.sh) ` +`bash <(curl -sL https://raw.githubusercontent.com/scala/scala3/main/docs/docs/contributing/checklist.sh) ` Above, `` is the stable version being released. For example, if you are releasing `0.14.0` and `0.15.0-RC1`, this variable is `14` and the command is as follows: -`bash <(curl -sL https://raw.githubusercontent.com/lampepfl/dotty/main/docs/docs/contributing/checklist.sh) 14` +`bash <(curl -sL https://raw.githubusercontent.com/scala/scala3/main/docs/docs/contributing/checklist.sh) 14` Copy and paste the output into the release issue. @@ -73,10 +73,10 @@ After the release is done, we document it as follows: During the release process we ensure that various parts of the community are also prepared for the new version of Scala so that users can hit the ground running when the new release is announced. You can see an example of this -[here](https://github.com/lampepfl/dotty/issues/17559). +[here](https://github.com/scala/scala3/issues/17559). # Procedure in Bash Scripts -The below procedure is compiled from [this](https://github.com/lampepfl/dotty/issues/5907#issue-409313505) and [this](https://github.com/lampepfl/dotty/issues/6235#issue-429265748) checklists. It assumes we want to publish the `0.14.0` given the `0.14.0-RC1` release candidate. +The below procedure is compiled from [this](https://github.com/scala/scala3/issues/5907#issue-409313505) and [this](https://github.com/scala/scala3/issues/6235#issue-429265748) checklists. It assumes we want to publish the `0.14.0` given the `0.14.0-RC1` release candidate. Note that at the same time we will also publish the `0.15.0-RC1` release. We publish two releases at the same time as per the logic outlined at the [Example/At the Dotty Repo](#at-the-dotty-repo) and the [Model](#model) sections above: the step (5) in the algorithm outlined in the [Example](#at-the-dotty-repo) for the release cycle of `0.14.0` is the step (1) in the release cycle of `0.15.0`. @@ -101,7 +101,7 @@ git merge 0.14.x git push origin main ######## Publish the 0.15.0-RC1 unstable version – begin the release cycle for 0.15.0 ######## -# Move all the unfinished tasks from Milestone 15 to Milestone 16 on GitHub – see https://github.com/lampepfl/dotty/milestones +# Move all the unfinished tasks from Milestone 15 to Milestone 16 on GitHub – see https://github.com/scala/scala3/milestones git checkout -b 0.15.x diff --git a/docs/_docs/contributing/sending-in-a-pr.md b/docs/_docs/contributing/sending-in-a-pr.md index c99e6a28172b..0c276e2c9287 100644 --- a/docs/_docs/contributing/sending-in-a-pr.md +++ b/docs/_docs/contributing/sending-in-a-pr.md @@ -104,7 +104,7 @@ every part of CI. For example, maybe you're just updating some documentation and there is no need to run the community build for this. We skip parts of the CI by utilizing keywords inside of brackets. The most up-to-date way to see this are by looking in the `if` statements of jobs. For example you can see some -[here](https://github.com/lampepfl/dotty/blob/5d2812a5937389f8a46f9e97ab9cbfbb3f298d87/.github/workflows/ci.yaml#L54-L64). +[here](https://github.com/scala/scala3/blob/5d2812a5937389f8a46f9e97ab9cbfbb3f298d87/.github/workflows/ci.yaml#L54-L64). Below are commonly used ones: @@ -160,8 +160,8 @@ you're PR will be merged in! [pull-request]: https://docs.github.com/en?query=pull+requests [lampepfl/dotty]: https://github.com/lampepfl/dotty [cla]: http://typesafe.com/contribute/cla/scala -[issues]: https://github.com/lampepfl/dotty/issues -[full-list]: https://github.com/lampepfl/dotty/blob/master/CONTRIBUTING.md +[issues]: https://github.com/scala/scala3/issues +[full-list]: https://github.com/scala/scala3/blob/master/CONTRIBUTING.md [discord]: https://discord.gg/TSmY9zkHar [dry]: https://www.oreilly.com/library/view/97-things-every/9780596809515/ch30.html [scouts]: https://www.oreilly.com/library/view/97-things-every/9780596809515/ch08.html diff --git a/docs/_docs/contributing/setting-up-your-ide.md b/docs/_docs/contributing/setting-up-your-ide.md index 3bb7d329d50c..a02c1dee63cb 100644 --- a/docs/_docs/contributing/setting-up-your-ide.md +++ b/docs/_docs/contributing/setting-up-your-ide.md @@ -34,7 +34,7 @@ want to make sure you do two things: 1. You'll want to find and change the following under `commonBootstrappedSettings` which is found in the - [`Build.scala`](https://github.com/lampepfl/dotty/blob/main/project/Build.scala) + [`Build.scala`](https://github.com/scala/scala3/blob/main/project/Build.scala) file. ```diff diff --git a/docs/_docs/contributing/testing.md b/docs/_docs/contributing/testing.md index 6c9ea7616e0b..9ea02f071cb6 100644 --- a/docs/_docs/contributing/testing.md +++ b/docs/_docs/contributing/testing.md @@ -251,7 +251,7 @@ can enter an inconsistent state and cause spurious test failures. If you suspect you can run `rm -rf out/*` from the root of the repository and run your tests again. If that fails, you can try `git clean -xfd`. -[CompilationTests]: https://github.com/lampepfl/dotty/blob/master/compiler/test/dotty/tools/dotc/CompilationTests.scala -[compiler/test]: https://github.com/lampepfl/dotty/blob/master/compiler/test/ -[compiler/test/dotc]: https://github.com/lampepfl/dotty/tree/master/compiler/test/dotc -[SemanticdbTests]: https://github.com/lampepfl/dotty/blob/master/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala +[CompilationTests]: https://github.com/scala/scala3/blob/master/compiler/test/dotty/tools/dotc/CompilationTests.scala +[compiler/test]: https://github.com/scala/scala3/blob/master/compiler/test/ +[compiler/test/dotc]: https://github.com/scala/scala3/tree/master/compiler/test/dotc +[SemanticdbTests]: https://github.com/scala/scala3/blob/master/compiler/test/dotty/tools/dotc/semanticdb/SemanticdbTests.scala diff --git a/docs/_docs/internals/coverage.md b/docs/_docs/internals/coverage.md index 162aa182a1e0..923908683721 100644 --- a/docs/_docs/internals/coverage.md +++ b/docs/_docs/internals/coverage.md @@ -5,7 +5,7 @@ title: "Code Coverage for Scala 3" ## Instrument code for coverage analysis -[PR#13880](https://github.com/lampepfl/dotty/pull/13880) has implemented code coverage support for Dotty. +[PR#13880](https://github.com/scala/scala3/pull/13880) has implemented code coverage support for Dotty. In general, code coverage "instruments" the program at compile time: code is inserted to record which statement are called. This does not change the behavior of the program. Also, a list of all the coverable statements is produced. To use this feature, add the compile option `-coverage-out:DIR`, where `DIR` is the destination of the measurement files. diff --git a/docs/_docs/internals/debug-macros.md b/docs/_docs/internals/debug-macros.md index 4d5cab52c568..a085ebbde355 100644 --- a/docs/_docs/internals/debug-macros.md +++ b/docs/_docs/internals/debug-macros.md @@ -34,7 +34,7 @@ the stack trace, we will be able to figure out where the tree is created. If the position is in the compiler, then either report a compiler bug or fix the problem with `.withSpan(tree.span)`. The following fix is an example: -- https://github.com/lampepfl/dotty/pull/6581 +- https://github.com/scala/scala3/pull/6581 ## unresolved symbols in pickling diff --git a/docs/_docs/internals/dotc-scalac.md b/docs/_docs/internals/dotc-scalac.md index 03baad375eb1..e5335c734891 100644 --- a/docs/_docs/internals/dotc-scalac.md +++ b/docs/_docs/internals/dotc-scalac.md @@ -133,6 +133,6 @@ if (sym is Flags.PackageClass) // Scala 3 (*) * `MethodType(paramSyms, resultType)` from scalac => `mt @ MethodType(paramNames, paramTypes)`. Result type is `mt.resultType` -[Denotations1]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Denotations.scala#L27-L72 -[Denotations2]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Denotations.scala#L77-L103 -[Signature1]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Signature.scala#L9-L33 +[Denotations1]: https://github.com/scala/scala3/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Denotations.scala#L27-L72 +[Denotations2]: https://github.com/scala/scala3/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Denotations.scala#L77-L103 +[Signature1]: https://github.com/scala/scala3/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Signature.scala#L9-L33 diff --git a/docs/_docs/internals/overall-structure.md b/docs/_docs/internals/overall-structure.md index ab936ddd8512..a25c287e16c9 100644 --- a/docs/_docs/internals/overall-structure.md +++ b/docs/_docs/internals/overall-structure.md @@ -235,10 +235,10 @@ Phases fall into four categories: * Code generators: These map the transformed trees to Java classfiles or .sjsir files. -[dotty.tools]: https://github.com/lampepfl/dotty/tree/main/compiler/src/dotty/tools -[dotc]: https://github.com/lampepfl/dotty/tree/main/compiler/src/dotty/tools/dotc -[Main]: https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/Main.scala -[Driver]: https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/Driver.scala -[Compiler]: https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/Compiler.scala -[Run]: https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/Run.scala -[Context]: https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/core/Contexts.scala +[dotty.tools]: https://github.com/scala/scala3/tree/main/compiler/src/dotty/tools +[dotc]: https://github.com/scala/scala3/tree/main/compiler/src/dotty/tools/dotc +[Main]: https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/Main.scala +[Driver]: https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/Driver.scala +[Compiler]: https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/Compiler.scala +[Run]: https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/Run.scala +[Context]: https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/core/Contexts.scala diff --git a/docs/_docs/internals/periods.md b/docs/_docs/internals/periods.md index 46241da0bb17..bf9c4a5fe786 100644 --- a/docs/_docs/internals/periods.md +++ b/docs/_docs/internals/periods.md @@ -88,6 +88,6 @@ object Period { As a sentinel value there's `Nowhere`, a period that is empty. -[runs]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/Run.scala -[phases]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Phases.scala -[period]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Periods.scala +[runs]: https://github.com/scala/scala3/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/Run.scala +[phases]: https://github.com/scala/scala3/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Phases.scala +[period]: https://github.com/scala/scala3/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Periods.scala diff --git a/docs/_docs/internals/type-system.md b/docs/_docs/internals/type-system.md index 8fa8912a7118..d2c0cd869e61 100644 --- a/docs/_docs/internals/type-system.md +++ b/docs/_docs/internals/type-system.md @@ -95,7 +95,7 @@ checks if `tp1` is a subtype of `tp2`. ### Type rebasing ### **FIXME**: This section is no longer accurate because -https://github.com/lampepfl/dotty/pull/331 changed the handling of refined +https://github.com/scala/scala3/pull/331 changed the handling of refined types. Consider [tests/pos/refinedSubtyping.scala][5] @@ -132,8 +132,8 @@ TODO ## Type inference via constraint solving ## TODO -[1]: https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/core/Types.scala +[1]: https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/core/Types.scala [2]: https://github.com/samuelgruetter/dotty/blob/classdiagrampdf/dotty-types.pdf [3]: https://github.com/samuelgruetter/scaladiagrams/tree/print-descendants -[4]: https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/core/TypeComparer.scala -[5]: https://github.com/lampepfl/dotty/blob/main/tests/pos/refinedSubtyping.scala +[4]: https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +[5]: https://github.com/scala/scala3/blob/main/tests/pos/refinedSubtyping.scala diff --git a/docs/_docs/reference/changed-features/eta-expansion-spec.md b/docs/_docs/reference/changed-features/eta-expansion-spec.md index 714ab37ae11a..516764ef5370 100644 --- a/docs/_docs/reference/changed-features/eta-expansion-spec.md +++ b/docs/_docs/reference/changed-features/eta-expansion-spec.md @@ -74,4 +74,4 @@ The method value syntax `m _` is deprecated. ## Reference -For more information, see [PR #2701](https://github.com/lampepfl/dotty/pull/2701). +For more information, see [PR #2701](https://github.com/scala/scala3/pull/2701). diff --git a/docs/_docs/reference/changed-features/implicit-conversions-spec.md b/docs/_docs/reference/changed-features/implicit-conversions-spec.md index dc19e10c8b8f..a70321b70c15 100644 --- a/docs/_docs/reference/changed-features/implicit-conversions-spec.md +++ b/docs/_docs/reference/changed-features/implicit-conversions-spec.md @@ -114,4 +114,4 @@ changes to implicit resolution, refer to the [Changes in Implicit Resolution](im ## Reference For more information about implicit resolution, see [Changes in Implicit Resolution](implicit-resolution.md). -Other details are available in [PR #2065](https://github.com/lampepfl/dotty/pull/2065). +Other details are available in [PR #2065](https://github.com/scala/scala3/pull/2065). diff --git a/docs/_docs/reference/changed-features/structural-types-spec.md b/docs/_docs/reference/changed-features/structural-types-spec.md index 18d0f31ee6fe..216b738ae61c 100644 --- a/docs/_docs/reference/changed-features/structural-types-spec.md +++ b/docs/_docs/reference/changed-features/structural-types-spec.md @@ -16,7 +16,7 @@ RefineStat ::= ‘val’ VarDcl | ‘def’ DefDcl | ‘type’ {nl} TypeDcl ## Implementation of Structural Types The standard library defines a universal marker trait -[`scala.Selectable`](https://github.com/lampepfl/dotty/blob/main/library/src/scala/Selectable.scala): +[`scala.Selectable`](https://github.com/scala/scala3/blob/main/library/src/scala/Selectable.scala): ```scala trait Selectable extends Any @@ -150,4 +150,4 @@ conversion that can turn `v` into a `Selectable`, and the selection methods coul ## Context -For more information, see [Rethink Structural Types](https://github.com/lampepfl/dotty/issues/1886). +For more information, see [Rethink Structural Types](https://github.com/scala/scala3/issues/1886). diff --git a/docs/_docs/reference/contextual/by-name-context-parameters.md b/docs/_docs/reference/contextual/by-name-context-parameters.md index 3515efd78fa5..7c517abe9406 100644 --- a/docs/_docs/reference/contextual/by-name-context-parameters.md +++ b/docs/_docs/reference/contextual/by-name-context-parameters.md @@ -61,5 +61,5 @@ No local given instance was generated because the synthesized argument is not re ## Reference -For more information, see [Issue #1998](https://github.com/lampepfl/dotty/issues/1998) +For more information, see [Issue #1998](https://github.com/scala/scala3/issues/1998) and the associated [Scala SIP](https://docs.scala-lang.org/sips/byname-implicits.html). diff --git a/docs/_docs/reference/contextual/multiversal-equality.md b/docs/_docs/reference/contextual/multiversal-equality.md index b51d03b10963..6258973c0cda 100644 --- a/docs/_docs/reference/contextual/multiversal-equality.md +++ b/docs/_docs/reference/contextual/multiversal-equality.md @@ -25,7 +25,7 @@ the program will still typecheck, since values of all types can be compared with But it will probably give unexpected results and fail at runtime. Multiversal equality is an opt-in way to make universal equality safer. -It uses a binary type class [`scala.CanEqual`](https://github.com/lampepfl/dotty/blob/main/library/src/scala/CanEqual.scala) +It uses a binary type class [`scala.CanEqual`](https://github.com/scala/scala3/blob/main/library/src/scala/CanEqual.scala) to indicate that values of two given types can be compared with each other. The example above would not typecheck if `S` or `T` was a class that derives `CanEqual`, e.g. @@ -71,7 +71,7 @@ given CanEqual[A, B] = CanEqual.derived given CanEqual[B, A] = CanEqual.derived ``` -The [`scala.CanEqual`](https://github.com/lampepfl/dotty/blob/main/library/src/scala/CanEqual.scala) +The [`scala.CanEqual`](https://github.com/scala/scala3/blob/main/library/src/scala/CanEqual.scala) object defines a number of `CanEqual` given instances that together define a rule book for what standard types can be compared (more details below). @@ -225,4 +225,4 @@ work under `-language:strictEquality`, since otherwise the universal `Eq[Any]` i More on multiversal equality is found in a [blog post](http://www.scala-lang.org/blog/2016/05/06/multiversal-equality.html) -and a [GitHub issue](https://github.com/lampepfl/dotty/issues/1247). +and a [GitHub issue](https://github.com/scala/scala3/issues/1247). diff --git a/docs/_docs/reference/dropped-features/auto-apply.md b/docs/_docs/reference/dropped-features/auto-apply.md index eadfe2f429ea..1a809275d4d0 100644 --- a/docs/_docs/reference/dropped-features/auto-apply.md +++ b/docs/_docs/reference/dropped-features/auto-apply.md @@ -93,4 +93,4 @@ stricter checking. ## Reference -For more information, see [Issue #2570](https://github.com/lampepfl/dotty/issues/2570) and [PR #2716](https://github.com/lampepfl/dotty/pull/2716). +For more information, see [Issue #2570](https://github.com/scala/scala3/issues/2570) and [PR #2716](https://github.com/scala/scala3/pull/2716). diff --git a/docs/_docs/reference/dropped-features/type-projection.md b/docs/_docs/reference/dropped-features/type-projection.md index 08b5ffb34eca..2c3e82ce99b8 100644 --- a/docs/_docs/reference/dropped-features/type-projection.md +++ b/docs/_docs/reference/dropped-features/type-projection.md @@ -9,7 +9,7 @@ and `A` names a type member of `T`. Scala 3 disallows this if `T` is an abstract type (class types and type aliases are fine). This change was made because unrestricted type projection -is [unsound](https://github.com/lampepfl/dotty/issues/1050). +is [unsound](https://github.com/scala/scala3/issues/1050). This restriction rules out the [type-level encoding of a combinator calculus](https://michid.wordpress.com/2010/01/29/scala-type-level-encoding-of-the-ski-calculus/). diff --git a/docs/_docs/reference/enums/adts.md b/docs/_docs/reference/enums/adts.md index 5219e062a633..36dd1daf0b59 100644 --- a/docs/_docs/reference/enums/adts.md +++ b/docs/_docs/reference/enums/adts.md @@ -170,4 +170,4 @@ The changes are specified below as deltas with respect to the Scala syntax given ## Reference -For more information, see [Issue #1970](https://github.com/lampepfl/dotty/issues/1970). +For more information, see [Issue #1970](https://github.com/scala/scala3/issues/1970). diff --git a/docs/_docs/reference/enums/enums.md b/docs/_docs/reference/enums/enums.md index 65051bdfb39f..8d4fca3268b0 100644 --- a/docs/_docs/reference/enums/enums.md +++ b/docs/_docs/reference/enums/enums.md @@ -180,7 +180,7 @@ scala> Color.Red.compareTo(Color.Green) val res15: Int = -1 ``` -For a more in-depth example of using Scala 3 enums from Java, see [this test](https://github.com/lampepfl/dotty/tree/main/tests/run/enum-java). In the test, the enums are defined in the `MainScala.scala` file and used from a Java source, `Test.java`. +For a more in-depth example of using Scala 3 enums from Java, see [this test](https://github.com/scala/scala3/tree/main/tests/run/enum-java). In the test, the enums are defined in the `MainScala.scala` file and used from a Java source, `Test.java`. ## Implementation @@ -218,5 +218,5 @@ val Red: Color = $new(0, "Red") ## Reference -For more information, see [Issue #1970](https://github.com/lampepfl/dotty/issues/1970) and -[PR #4003](https://github.com/lampepfl/dotty/pull/4003). +For more information, see [Issue #1970](https://github.com/scala/scala3/issues/1970) and +[PR #4003](https://github.com/scala/scala3/pull/4003). diff --git a/docs/_docs/reference/experimental/explicit-nulls.md b/docs/_docs/reference/experimental/explicit-nulls.md index 47b21d3a5e23..1925b0b3c925 100644 --- a/docs/_docs/reference/experimental/explicit-nulls.md +++ b/docs/_docs/reference/experimental/explicit-nulls.md @@ -431,7 +431,7 @@ When dealing with local mutable variables, there are two questions: x = null ``` -See [more examples](https://github.com/lampepfl/dotty/blob/main/tests/explicit-nulls/neg/flow-varref-in-closure.scala). +See [more examples](https://github.com/scala/scala3/blob/main/tests/explicit-nulls/neg/flow-varref-in-closure.scala). Currently, we are unable to track paths with a mutable variable prefix. For example, `x.a` if `x` is mutable. diff --git a/docs/_docs/reference/experimental/tupled-function.md b/docs/_docs/reference/experimental/tupled-function.md index 0cc016953a80..de683128fb0c 100644 --- a/docs/_docs/reference/experimental/tupled-function.md +++ b/docs/_docs/reference/experimental/tupled-function.md @@ -35,7 +35,7 @@ The compiler will synthesize an instance of `TupledFunction[F, G]` if: Examples -------- `TupledFunction` can be used to generalize the `Function1.tupled`, ... `Function22.tupled` methods to functions of any arities. -The following defines `tupled` as [extension method](../contextual/extension-methods.html) ([full example](https://github.com/lampepfl/dotty/blob/main/tests/run/tupled-function-tupled.scala)). +The following defines `tupled` as [extension method](../contextual/extension-methods.html) ([full example](https://github.com/scala/scala3/blob/main/tests/run/tupled-function-tupled.scala)). ```scala /** Creates a tupled version of this function: instead of N arguments, @@ -49,7 +49,7 @@ extension [F, Args <: Tuple, R](f: F) def tupled(using tf: TupledFunction[F, Args => R]): Args => R = tf.tupled(f) ``` -`TupledFunction` can be used to generalize the `Function.untupled` to a function of any arities ([full example](https://github.com/lampepfl/dotty/blob/main/tests/run/tupled-function-untupled.scala)) +`TupledFunction` can be used to generalize the `Function.untupled` to a function of any arities ([full example](https://github.com/scala/scala3/blob/main/tests/run/tupled-function-untupled.scala)) ```scala /** Creates an untupled version of this function: instead of a single argument of type [[scala.Tuple]] with N elements, @@ -65,7 +65,7 @@ extension [F, Args <: Tuple, R](f: Args => R) def untupled(using tf: TupledFunction[F, Args => R]): F = tf.untupled(f) ``` -`TupledFunction` can also be used to generalize the [`Tuple1.compose`](https://github.com/lampepfl/dotty/blob/main/tests/run/tupled-function-compose.scala) and [`Tuple1.andThen`](https://github.com/lampepfl/dotty/blob/main/tests/run/tupled-function-andThen.scala) methods to compose functions of larger arities and with functions that return tuples. +`TupledFunction` can also be used to generalize the [`Tuple1.compose`](https://github.com/scala/scala3/blob/main/tests/run/tupled-function-compose.scala) and [`Tuple1.andThen`](https://github.com/scala/scala3/blob/main/tests/run/tupled-function-andThen.scala) methods to compose functions of larger arities and with functions that return tuples. ```scala /** Composes two instances of TupledFunction into a new TupledFunction, with this function applied last. diff --git a/docs/_docs/reference/features-classification.md b/docs/_docs/reference/features-classification.md index 36cea3b9e72d..550130780b44 100644 --- a/docs/_docs/reference/features-classification.md +++ b/docs/_docs/reference/features-classification.md @@ -72,7 +72,7 @@ These constructs are restricted to make the language safer. - [Given Imports](contextual/given-imports.md): implicits now require a special form of import, to make the import clearly visible. - [Type Projection](dropped-features/type-projection.md): only classes can be used as prefix `C` of a type projection `C#A`. Type projection on abstract types is no longer supported since it is unsound. - [Multiversal equality](contextual/multiversal-equality.md) implements an "opt-in" scheme to rule out nonsensical comparisons with `==` and `!=`. - - [infix](https://github.com/lampepfl/dotty/pull/5975) + - [infix](https://github.com/scala/scala3/pull/5975) makes method application syntax uniform across code bases. Unrestricted implicit conversions continue to be available in Scala 3.0, but will be deprecated and removed later. Unrestricted versions of the other constructs in the list above are available only under `-source 3.0-migration`. @@ -100,7 +100,7 @@ These constructs are proposed to be dropped without a new construct replacing th - [Auto application](dropped-features/auto-apply.md), - [Weak conformance](dropped-features/weak-conformance.md), - [Compound types](new-types/intersection-types.md), - - [Auto tupling](https://github.com/lampepfl/dotty/pull/4311) (implemented, but not merged). + - [Auto tupling](https://github.com/scala/scala3/pull/4311) (implemented, but not merged). The date when these constructs are dropped varies. The current status is: @@ -148,7 +148,7 @@ These are additions to the language that make it more powerful or pleasant to us - [Enums](enums/enums.md) provide concise syntax for enumerations and [algebraic data types](enums/adts.md). - [Parameter untupling](other-new-features/parameter-untupling.md) avoids having to use `case` for tupled parameter destructuring. - [Dependent function types](new-types/dependent-function-types.md) generalize dependent methods to dependent function values and types. - - [Polymorphic function types](https://github.com/lampepfl/dotty/pull/4672) generalize polymorphic methods to dependent function values and types. _Current status_: There is a proposal, and a prototype implementation, but the implementation has not been finalized or merged yet. + - [Polymorphic function types](https://github.com/scala/scala3/pull/4672) generalize polymorphic methods to dependent function values and types. _Current status_: There is a proposal, and a prototype implementation, but the implementation has not been finalized or merged yet. - [Kind polymorphism](other-new-features/kind-polymorphism.md) allows the definition of operators working equally on types and type constructors. **Status: mixed** diff --git a/docs/_docs/reference/metaprogramming/compiletime-ops.md b/docs/_docs/reference/metaprogramming/compiletime-ops.md index 048c6b6165bb..dcefb3a16ed3 100644 --- a/docs/_docs/reference/metaprogramming/compiletime-ops.md +++ b/docs/_docs/reference/metaprogramming/compiletime-ops.md @@ -259,5 +259,5 @@ val notMissing : NotMissing = summonInlineCheck(3) ## Reference -For more information about compile-time operations, see [PR #4768](https://github.com/lampepfl/dotty/pull/4768), -which explains how `summonFrom`'s predecessor (implicit matches) can be used for typelevel programming and code specialization and [PR #7201](https://github.com/lampepfl/dotty/pull/7201) which explains the new `summonFrom` syntax. +For more information about compile-time operations, see [PR #4768](https://github.com/scala/scala3/pull/4768), +which explains how `summonFrom`'s predecessor (implicit matches) can be used for typelevel programming and code specialization and [PR #7201](https://github.com/scala/scala3/pull/7201) which explains the new `summonFrom` syntax. diff --git a/docs/_docs/reference/new-types/dependent-function-types-spec.md b/docs/_docs/reference/new-types/dependent-function-types-spec.md index f603200b1ae0..3084ff4de71c 100644 --- a/docs/_docs/reference/new-types/dependent-function-types-spec.md +++ b/docs/_docs/reference/new-types/dependent-function-types-spec.md @@ -4,7 +4,7 @@ title: "Dependent Function Types - More Details" nightlyOf: https://docs.scala-lang.org/scala3/reference/new-types/dependent-function-types-spec.html --- -Initial implementation in [PR #3464](https://github.com/lampepfl/dotty/pull/3464). +Initial implementation in [PR #3464](https://github.com/scala/scala3/pull/3464). ## Syntax @@ -46,7 +46,7 @@ same way that other functions do, see The example below defines a trait `C` and the two dependent function types `DF` and `IDF` and prints the results of the respective function applications: -[depfuntype.scala]: https://github.com/lampepfl/dotty/blob/main/tests/pos/depfuntype.scala +[depfuntype.scala]: https://github.com/scala/scala3/blob/main/tests/pos/depfuntype.scala ```scala trait C { type M; val m: M } @@ -70,7 +70,7 @@ type IDF = (x: C) ?=> x.M In the following example the depend type `f.Eff` refers to the effect type `CanThrow`: -[eff-dependent.scala]: https://github.com/lampepfl/dotty/blob/main/tests/run/eff-dependent.scala +[eff-dependent.scala]: https://github.com/scala/scala3/blob/main/tests/run/eff-dependent.scala ```scala trait Effect diff --git a/docs/_docs/reference/new-types/intersection-types-spec.md b/docs/_docs/reference/new-types/intersection-types-spec.md index 4e26626c0b36..723720fdef89 100644 --- a/docs/_docs/reference/new-types/intersection-types-spec.md +++ b/docs/_docs/reference/new-types/intersection-types-spec.md @@ -97,7 +97,7 @@ glb(A, _) = A // use first In the above, `|T|` means the erased type of `T`, `JArray` refers to the type of Java Array. -See also: [`TypeErasure#erasedGlb`](https://github.com/lampepfl/dotty/blob/main/compiler/src/dotty/tools/dotc/core/TypeErasure.scala#L289). +See also: [`TypeErasure#erasedGlb`](https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/core/TypeErasure.scala#L289). ## Relationship with Compound Type (`with`) diff --git a/docs/_docs/reference/new-types/polymorphic-function-types.md b/docs/_docs/reference/new-types/polymorphic-function-types.md index 1754bf844831..04f4a3483896 100644 --- a/docs/_docs/reference/new-types/polymorphic-function-types.md +++ b/docs/_docs/reference/new-types/polymorphic-function-types.md @@ -33,7 +33,7 @@ In Scala 3 this is now possible. The type of the `bar` value above is This type describes function values which take a type `A` as a parameter, then take a list of type `List[A]`, and return a list of the same type `List[A]`. -[More details](https://github.com/lampepfl/dotty/pull/4672) +[More details](https://github.com/scala/scala3/pull/4672) ## Example Usage diff --git a/docs/_docs/reference/other-new-features/open-classes.md b/docs/_docs/reference/other-new-features/open-classes.md index 10af6ead669e..ff2dbac27b3b 100644 --- a/docs/_docs/reference/other-new-features/open-classes.md +++ b/docs/_docs/reference/other-new-features/open-classes.md @@ -77,4 +77,4 @@ A class that is neither `abstract` nor `open` is similar to a `sealed` class: it ## Migration -`open` is a new modifier in Scala 3. To allow cross compilation between Scala 2.13 and Scala 3.0 without warnings, the feature warning for ad-hoc extensions is produced only under `-source future`. It will be produced by default [from Scala 3.4 on](https://github.com/lampepfl/dotty/issues/16334). +`open` is a new modifier in Scala 3. To allow cross compilation between Scala 2.13 and Scala 3.0 without warnings, the feature warning for ad-hoc extensions is produced only under `-source future`. It will be produced by default [from Scala 3.4 on](https://github.com/scala/scala3/issues/16334). diff --git a/docs/_docs/reference/other-new-features/parameter-untupling-spec.md b/docs/_docs/reference/other-new-features/parameter-untupling-spec.md index fd462dd610c8..c9e1033f5ea6 100644 --- a/docs/_docs/reference/other-new-features/parameter-untupling-spec.md +++ b/docs/_docs/reference/other-new-features/parameter-untupling-spec.md @@ -56,4 +56,4 @@ Obsolete conversions could be detected and fixed by [`Scalafix`](https://scalace ## Reference -For more information, see [Issue #897](https://github.com/lampepfl/dotty/issues/897). +For more information, see [Issue #897](https://github.com/scala/scala3/issues/897). diff --git a/docs/_docs/reference/other-new-features/parameter-untupling.md b/docs/_docs/reference/other-new-features/parameter-untupling.md index e1e7afcad8fe..27e3850b309c 100644 --- a/docs/_docs/reference/other-new-features/parameter-untupling.md +++ b/docs/_docs/reference/other-new-features/parameter-untupling.md @@ -75,4 +75,4 @@ cannot subvert untupling. For more information see: * [More details](./parameter-untupling-spec.md) -* [Issue #897](https://github.com/lampepfl/dotty/issues/897). +* [Issue #897](https://github.com/scala/scala3/issues/897). diff --git a/docs/_docs/reference/overview.md b/docs/_docs/reference/overview.md index b1e8281dfc16..bdb8aa74c1aa 100644 --- a/docs/_docs/reference/overview.md +++ b/docs/_docs/reference/overview.md @@ -91,7 +91,7 @@ These constructs are proposed to be dropped without a new construct replacing th - [Auto application](dropped-features/auto-apply.md), - [Weak conformance](dropped-features/weak-conformance.md), - Compound types (replaced by [Intersection types](new-types/intersection-types.md)), -- [Auto tupling](https://github.com/lampepfl/dotty/pull/4311) (implemented, but not merged). +- [Auto tupling](https://github.com/scala/scala3/pull/4311) (implemented, but not merged). The date when these constructs are dropped varies. The current status is: diff --git a/docs/_docs/release-notes-0.1.2.md b/docs/_docs/release-notes-0.1.2.md index 98f359c83a15..c6bc9846bf07 100644 --- a/docs/_docs/release-notes-0.1.2.md +++ b/docs/_docs/release-notes-0.1.2.md @@ -18,7 +18,7 @@ Dotty 0.1.2 targets Java 8. We don't have plans to add support for earlier versi # Reporting Bugs / Known Issues -Please [file](https://github.com/lampepfl/dotty/issues) any bugs you encounter. If you’re unsure whether something is a bug, +Please [file](https://github.com/scala/scala3/issues) any bugs you encounter. If you’re unsure whether something is a bug, please ask on the Dotty [gitter channel](https://github.com/lampepfl/dotty). # Dotty Doc @@ -86,27 +86,27 @@ This release ships with the following features: [9]: http://docs.scala-lang.org/sips/pending/static-members.html [10]: http://docs.scala-lang.org/sips/pending/improved-lazy-val-initialization.html [11]: http://magarciaepfl.github.io/scala/ -[12]: https://github.com/lampepfl/dotty/commit/b2215ed23311b2c99ea638f9d7fcad9737dba588 -[13]: https://github.com/lampepfl/dotty/pull/187 -[14]: https://github.com/lampepfl/dotty/pull/217 +[12]: https://github.com/scala/scala3/commit/b2215ed23311b2c99ea638f9d7fcad9737dba588 +[13]: https://github.com/scala/scala3/pull/187 +[14]: https://github.com/scala/scala3/pull/217 [15]: reference/other-new-features/trait-parameters.html -[16]: https://github.com/lampepfl/dotty/commit/89540268e6c49fb92b9ca61249e46bb59981bf5a -[17]: https://github.com/lampepfl/dotty/pull/174 -[18]: https://github.com/lampepfl/dotty/pull/488 -[19]: https://github.com/lampepfl/dotty/pull/174 -[20]: https://github.com/lampepfl/dotty/pull/411 -[21]: https://github.com/lampepfl/dotty/pull/1364 -[22]: https://github.com/lampepfl/dotty/pull/1227 -[23]: https://github.com/lampepfl/dotty/pull/117 -[24]: https://github.com/lampepfl/dotty/pull/2532 -[25]: https://github.com/lampepfl/dotty/pull/2194 -[26]: https://github.com/lampepfl/dotty/pull/213 -[27]: https://github.com/lampepfl/dotty/pull/2513 -[28]: https://github.com/lampepfl/dotty/pull/2361 -[29]: https://github.com/lampepfl/dotty/pull/1453 +[16]: https://github.com/scala/scala3/commit/89540268e6c49fb92b9ca61249e46bb59981bf5a +[17]: https://github.com/scala/scala3/pull/174 +[18]: https://github.com/scala/scala3/pull/488 +[19]: https://github.com/scala/scala3/pull/174 +[20]: https://github.com/scala/scala3/pull/411 +[21]: https://github.com/scala/scala3/pull/1364 +[22]: https://github.com/scala/scala3/pull/1227 +[23]: https://github.com/scala/scala3/pull/117 +[24]: https://github.com/scala/scala3/pull/2532 +[25]: https://github.com/scala/scala3/pull/2194 +[26]: https://github.com/scala/scala3/pull/213 +[27]: https://github.com/scala/scala3/pull/2513 +[28]: https://github.com/scala/scala3/pull/2361 +[29]: https://github.com/scala/scala3/pull/1453 [30]: reference/contextual/context-functions.html -[31]: https://github.com/lampepfl/dotty/pull/2136 -[32]: https://github.com/lampepfl/dotty/pull/1758 +[31]: https://github.com/scala/scala3/pull/2136 +[32]: https://github.com/scala/scala3/pull/1758 [33]: reference/metaprogramming/inline.html # Contributors diff --git a/docs/_spec/APPLIEDreference/dropped-features/auto-apply.md b/docs/_spec/APPLIEDreference/dropped-features/auto-apply.md index b9aedb9f046b..95366b5e8f78 100644 --- a/docs/_spec/APPLIEDreference/dropped-features/auto-apply.md +++ b/docs/_spec/APPLIEDreference/dropped-features/auto-apply.md @@ -93,4 +93,4 @@ stricter checking. ## Reference -For more information, see [Issue #2570](https://github.com/lampepfl/dotty/issues/2570) and [PR #2716](https://github.com/lampepfl/dotty/pull/2716). +For more information, see [Issue #2570](https://github.com/scala/scala3/issues/2570) and [PR #2716](https://github.com/scala/scala3/pull/2716). diff --git a/docs/_spec/APPLIEDreference/enums/enums.md b/docs/_spec/APPLIEDreference/enums/enums.md index bcab50d3a36d..d8fdbe9f1db2 100644 --- a/docs/_spec/APPLIEDreference/enums/enums.md +++ b/docs/_spec/APPLIEDreference/enums/enums.md @@ -178,5 +178,5 @@ scala> Color.Red.compareTo(Color.Green) val res15: Int = -1 ``` -For a more in-depth example of using Scala 3 enums from Java, see [this test](https://github.com/lampepfl/dotty/tree/main/tests/run/enum-java). +For a more in-depth example of using Scala 3 enums from Java, see [this test](https://github.com/scala/scala3/tree/main/tests/run/enum-java). In the test, the enums are defined in the `MainScala.scala` file and used from a Java source, `Test.java`. diff --git a/docs/_spec/APPLIEDreference/new-types/union-types.md b/docs/_spec/APPLIEDreference/new-types/union-types.md index 152505d7fc8d..f59bb6f6b851 100644 --- a/docs/_spec/APPLIEDreference/new-types/union-types.md +++ b/docs/_spec/APPLIEDreference/new-types/union-types.md @@ -59,8 +59,8 @@ be changed in the future. For example by not widening unions that have been explicitly written down by the user and not inferred, or by not widening a type argument when the corresponding type parameter is covariant. -See [PR #2330](https://github.com/lampepfl/dotty/pull/2330) and -[Issue #4867](https://github.com/lampepfl/dotty/issues/4867) for further discussions. +See [PR #2330](https://github.com/scala/scala3/pull/2330) and +[Issue #4867](https://github.com/scala/scala3/issues/4867) for further discussions. ### Example diff --git a/docs/_spec/TODOreference/changed-features/eta-expansion-spec.md b/docs/_spec/TODOreference/changed-features/eta-expansion-spec.md index a62d45df9e11..fa5c1e57a066 100644 --- a/docs/_spec/TODOreference/changed-features/eta-expansion-spec.md +++ b/docs/_spec/TODOreference/changed-features/eta-expansion-spec.md @@ -74,4 +74,4 @@ The method value syntax `m _` is deprecated. ## Reference -For more information, see [PR #2701](https://github.com/lampepfl/dotty/pull/2701). +For more information, see [PR #2701](https://github.com/scala/scala3/pull/2701). diff --git a/docs/_spec/TODOreference/changed-features/implicit-conversions-spec.md b/docs/_spec/TODOreference/changed-features/implicit-conversions-spec.md index dc19e10c8b8f..a70321b70c15 100644 --- a/docs/_spec/TODOreference/changed-features/implicit-conversions-spec.md +++ b/docs/_spec/TODOreference/changed-features/implicit-conversions-spec.md @@ -114,4 +114,4 @@ changes to implicit resolution, refer to the [Changes in Implicit Resolution](im ## Reference For more information about implicit resolution, see [Changes in Implicit Resolution](implicit-resolution.md). -Other details are available in [PR #2065](https://github.com/lampepfl/dotty/pull/2065). +Other details are available in [PR #2065](https://github.com/scala/scala3/pull/2065). diff --git a/docs/_spec/TODOreference/changed-features/structural-types-spec.md b/docs/_spec/TODOreference/changed-features/structural-types-spec.md index d456932649fb..cb48a593e831 100644 --- a/docs/_spec/TODOreference/changed-features/structural-types-spec.md +++ b/docs/_spec/TODOreference/changed-features/structural-types-spec.md @@ -16,7 +16,7 @@ RefineStat ::= ‘val’ VarDcl | ‘def’ DefDcl | ‘type’ {nl} TypeDcl ## Implementation of Structural Types The standard library defines a universal marker trait -[`scala.Selectable`](https://github.com/lampepfl/dotty/blob/main/library/src/scala/Selectable.scala): +[`scala.Selectable`](https://github.com/scala/scala3/blob/main/library/src/scala/Selectable.scala): ```scala trait Selectable extends Any @@ -150,4 +150,4 @@ conversion that can turn `v` into a `Selectable`, and the selection methods coul ## Context -For more information, see [Rethink Structural Types](https://github.com/lampepfl/dotty/issues/1886). +For more information, see [Rethink Structural Types](https://github.com/scala/scala3/issues/1886). diff --git a/docs/_spec/TODOreference/contextual/by-name-context-parameters.md b/docs/_spec/TODOreference/contextual/by-name-context-parameters.md index 3004bfb2c4c2..7a80b20592ea 100644 --- a/docs/_spec/TODOreference/contextual/by-name-context-parameters.md +++ b/docs/_spec/TODOreference/contextual/by-name-context-parameters.md @@ -61,5 +61,5 @@ No local given instance was generated because the synthesized argument is not re ## Reference -For more information, see [Issue #1998](https://github.com/lampepfl/dotty/issues/1998) +For more information, see [Issue #1998](https://github.com/scala/scala3/issues/1998) and the associated [Scala SIP](https://docs.scala-lang.org/sips/byname-implicits.html). diff --git a/docs/_spec/TODOreference/contextual/multiversal-equality.md b/docs/_spec/TODOreference/contextual/multiversal-equality.md index e9a81b95f472..fa729fda8e61 100644 --- a/docs/_spec/TODOreference/contextual/multiversal-equality.md +++ b/docs/_spec/TODOreference/contextual/multiversal-equality.md @@ -25,7 +25,7 @@ the program will still typecheck, since values of all types can be compared with But it will probably give unexpected results and fail at runtime. Multiversal equality is an opt-in way to make universal equality safer. -It uses a binary type class [`scala.CanEqual`](https://github.com/lampepfl/dotty/blob/main/library/src/scala/CanEqual.scala) +It uses a binary type class [`scala.CanEqual`](https://github.com/scala/scala3/blob/main/library/src/scala/CanEqual.scala) to indicate that values of two given types can be compared with each other. The example above would not typecheck if `S` or `T` was a class that derives `CanEqual`, e.g. @@ -70,7 +70,7 @@ given CanEqual[A, B] = CanEqual.derived given CanEqual[B, A] = CanEqual.derived ``` -The [`scala.CanEqual`](https://github.com/lampepfl/dotty/blob/main/library/src/scala/CanEqual.scala) +The [`scala.CanEqual`](https://github.com/scala/scala3/blob/main/library/src/scala/CanEqual.scala) object defines a number of `CanEqual` given instances that together define a rule book for what standard types can be compared (more details below). @@ -224,4 +224,4 @@ work under `-language:strictEquality`, since otherwise the universal `Eq[Any]` i More on multiversal equality is found in a [blog post](http://www.scala-lang.org/blog/2016/05/06/multiversal-equality.html) -and a [GitHub issue](https://github.com/lampepfl/dotty/issues/1247). +and a [GitHub issue](https://github.com/scala/scala3/issues/1247). diff --git a/docs/_spec/TODOreference/dropped-features/type-projection.md b/docs/_spec/TODOreference/dropped-features/type-projection.md index 08b5ffb34eca..2c3e82ce99b8 100644 --- a/docs/_spec/TODOreference/dropped-features/type-projection.md +++ b/docs/_spec/TODOreference/dropped-features/type-projection.md @@ -9,7 +9,7 @@ and `A` names a type member of `T`. Scala 3 disallows this if `T` is an abstract type (class types and type aliases are fine). This change was made because unrestricted type projection -is [unsound](https://github.com/lampepfl/dotty/issues/1050). +is [unsound](https://github.com/scala/scala3/issues/1050). This restriction rules out the [type-level encoding of a combinator calculus](https://michid.wordpress.com/2010/01/29/scala-type-level-encoding-of-the-ski-calculus/). diff --git a/docs/_spec/TODOreference/experimental/explicit-nulls.md b/docs/_spec/TODOreference/experimental/explicit-nulls.md index b3fa53429cfe..3be83afe967e 100644 --- a/docs/_spec/TODOreference/experimental/explicit-nulls.md +++ b/docs/_spec/TODOreference/experimental/explicit-nulls.md @@ -431,7 +431,7 @@ When dealing with local mutable variables, there are two questions: x = null ``` -See [more examples](https://github.com/lampepfl/dotty/blob/main/tests/explicit-nulls/neg/flow-varref-in-closure.scala). +See [more examples](https://github.com/scala/scala3/blob/main/tests/explicit-nulls/neg/flow-varref-in-closure.scala). Currently, we are unable to track paths with a mutable variable prefix. For example, `x.a` if `x` is mutable. diff --git a/docs/_spec/TODOreference/experimental/tupled-function.md b/docs/_spec/TODOreference/experimental/tupled-function.md index da108fc832ad..e01570e9e8a6 100644 --- a/docs/_spec/TODOreference/experimental/tupled-function.md +++ b/docs/_spec/TODOreference/experimental/tupled-function.md @@ -34,7 +34,7 @@ The compiler will synthesize an instance of `TupledFunction[F, G]` if: Examples -------- `TupledFunction` can be used to generalize the `Function1.tupled`, ... `Function22.tupled` methods to functions of any arities. -The following defines `tupled` as [extension method](../contextual/extension-methods.html) ([full example](https://github.com/lampepfl/dotty/blob/main/tests/run/tupled-function-tupled.scala)). +The following defines `tupled` as [extension method](../contextual/extension-methods.html) ([full example](https://github.com/scala/scala3/blob/main/tests/run/tupled-function-tupled.scala)). ```scala /** Creates a tupled version of this function: instead of N arguments, @@ -48,7 +48,7 @@ extension [F, Args <: Tuple, R](f: F) def tupled(using tf: TupledFunction[F, Args => R]): Args => R = tf.tupled(f) ``` -`TupledFunction` can be used to generalize the `Function.untupled` to a function of any arities ([full example](https://github.com/lampepfl/dotty/blob/main/tests/run/tupled-function-untupled.scala)) +`TupledFunction` can be used to generalize the `Function.untupled` to a function of any arities ([full example](https://github.com/scala/scala3/blob/main/tests/run/tupled-function-untupled.scala)) ```scala /** Creates an untupled version of this function: instead of a single argument of type [[scala.Tuple]] with N elements, @@ -64,7 +64,7 @@ extension [F, Args <: Tuple, R](f: Args => R) def untupled(using tf: TupledFunction[F, Args => R]): F = tf.untupled(f) ``` -`TupledFunction` can also be used to generalize the [`Tuple1.compose`](https://github.com/lampepfl/dotty/blob/main/tests/run/tupled-function-compose.scala) and [`Tuple1.andThen`](https://github.com/lampepfl/dotty/blob/main/tests/run/tupled-function-andThen.scala) methods to compose functions of larger arities and with functions that return tuples. +`TupledFunction` can also be used to generalize the [`Tuple1.compose`](https://github.com/scala/scala3/blob/main/tests/run/tupled-function-compose.scala) and [`Tuple1.andThen`](https://github.com/scala/scala3/blob/main/tests/run/tupled-function-andThen.scala) methods to compose functions of larger arities and with functions that return tuples. ```scala /** Composes two instances of TupledFunction into a new TupledFunction, with this function applied last. diff --git a/docs/_spec/TODOreference/features-classification.md b/docs/_spec/TODOreference/features-classification.md index 36cea3b9e72d..550130780b44 100644 --- a/docs/_spec/TODOreference/features-classification.md +++ b/docs/_spec/TODOreference/features-classification.md @@ -72,7 +72,7 @@ These constructs are restricted to make the language safer. - [Given Imports](contextual/given-imports.md): implicits now require a special form of import, to make the import clearly visible. - [Type Projection](dropped-features/type-projection.md): only classes can be used as prefix `C` of a type projection `C#A`. Type projection on abstract types is no longer supported since it is unsound. - [Multiversal equality](contextual/multiversal-equality.md) implements an "opt-in" scheme to rule out nonsensical comparisons with `==` and `!=`. - - [infix](https://github.com/lampepfl/dotty/pull/5975) + - [infix](https://github.com/scala/scala3/pull/5975) makes method application syntax uniform across code bases. Unrestricted implicit conversions continue to be available in Scala 3.0, but will be deprecated and removed later. Unrestricted versions of the other constructs in the list above are available only under `-source 3.0-migration`. @@ -100,7 +100,7 @@ These constructs are proposed to be dropped without a new construct replacing th - [Auto application](dropped-features/auto-apply.md), - [Weak conformance](dropped-features/weak-conformance.md), - [Compound types](new-types/intersection-types.md), - - [Auto tupling](https://github.com/lampepfl/dotty/pull/4311) (implemented, but not merged). + - [Auto tupling](https://github.com/scala/scala3/pull/4311) (implemented, but not merged). The date when these constructs are dropped varies. The current status is: @@ -148,7 +148,7 @@ These are additions to the language that make it more powerful or pleasant to us - [Enums](enums/enums.md) provide concise syntax for enumerations and [algebraic data types](enums/adts.md). - [Parameter untupling](other-new-features/parameter-untupling.md) avoids having to use `case` for tupled parameter destructuring. - [Dependent function types](new-types/dependent-function-types.md) generalize dependent methods to dependent function values and types. - - [Polymorphic function types](https://github.com/lampepfl/dotty/pull/4672) generalize polymorphic methods to dependent function values and types. _Current status_: There is a proposal, and a prototype implementation, but the implementation has not been finalized or merged yet. + - [Polymorphic function types](https://github.com/scala/scala3/pull/4672) generalize polymorphic methods to dependent function values and types. _Current status_: There is a proposal, and a prototype implementation, but the implementation has not been finalized or merged yet. - [Kind polymorphism](other-new-features/kind-polymorphism.md) allows the definition of operators working equally on types and type constructors. **Status: mixed** diff --git a/docs/_spec/TODOreference/metaprogramming/compiletime-ops.md b/docs/_spec/TODOreference/metaprogramming/compiletime-ops.md index a43c941ae943..782cd72886d5 100644 --- a/docs/_spec/TODOreference/metaprogramming/compiletime-ops.md +++ b/docs/_spec/TODOreference/metaprogramming/compiletime-ops.md @@ -290,5 +290,5 @@ val notMissing : NotMissing = summonInlineCheck(3) ## Reference -For more information about compile-time operations, see [PR #4768](https://github.com/lampepfl/dotty/pull/4768), -which explains how `summonFrom`'s predecessor (implicit matches) can be used for typelevel programming and code specialization and [PR #7201](https://github.com/lampepfl/dotty/pull/7201) which explains the new `summonFrom` syntax. +For more information about compile-time operations, see [PR #4768](https://github.com/scala/scala3/pull/4768), +which explains how `summonFrom`'s predecessor (implicit matches) can be used for typelevel programming and code specialization and [PR #7201](https://github.com/scala/scala3/pull/7201) which explains the new `summonFrom` syntax. diff --git a/docs/_spec/TODOreference/new-types/dependent-function-types-spec.md b/docs/_spec/TODOreference/new-types/dependent-function-types-spec.md index f3237ddf7b9a..b27346a687d6 100644 --- a/docs/_spec/TODOreference/new-types/dependent-function-types-spec.md +++ b/docs/_spec/TODOreference/new-types/dependent-function-types-spec.md @@ -4,7 +4,7 @@ title: "Dependent Function Types - More Details" nightlyOf: https://docs.scala-lang.org/scala3/reference/new-types/dependent-function-types-spec.html --- -Initial implementation in [PR #3464](https://github.com/lampepfl/dotty/pull/3464). +Initial implementation in [PR #3464](https://github.com/scala/scala3/pull/3464). ## Syntax @@ -46,7 +46,7 @@ same way that other functions do, see The example below defines a trait `C` and the two dependent function types `DF` and `IDF` and prints the results of the respective function applications: -[depfuntype.scala]: https://github.com/lampepfl/dotty/blob/main/tests/pos/depfuntype.scala +[depfuntype.scala]: https://github.com/scala/scala3/blob/main/tests/pos/depfuntype.scala ```scala trait C { type M; val m: M } @@ -70,7 +70,7 @@ type IDF = (x: C) ?=> x.M In the following example the depend type `f.Eff` refers to the effect type `CanThrow`: -[eff-dependent.scala]: https://github.com/lampepfl/dotty/blob/main/tests/run/eff-dependent.scala +[eff-dependent.scala]: https://github.com/scala/scala3/blob/main/tests/run/eff-dependent.scala ```scala trait Effect diff --git a/docs/_spec/TODOreference/new-types/polymorphic-function-types.md b/docs/_spec/TODOreference/new-types/polymorphic-function-types.md index 1754bf844831..04f4a3483896 100644 --- a/docs/_spec/TODOreference/new-types/polymorphic-function-types.md +++ b/docs/_spec/TODOreference/new-types/polymorphic-function-types.md @@ -33,7 +33,7 @@ In Scala 3 this is now possible. The type of the `bar` value above is This type describes function values which take a type `A` as a parameter, then take a list of type `List[A]`, and return a list of the same type `List[A]`. -[More details](https://github.com/lampepfl/dotty/pull/4672) +[More details](https://github.com/scala/scala3/pull/4672) ## Example Usage diff --git a/docs/_spec/TODOreference/other-new-features/parameter-untupling-spec.md b/docs/_spec/TODOreference/other-new-features/parameter-untupling-spec.md index e5165550fc0d..6133012463a1 100644 --- a/docs/_spec/TODOreference/other-new-features/parameter-untupling-spec.md +++ b/docs/_spec/TODOreference/other-new-features/parameter-untupling-spec.md @@ -86,4 +86,4 @@ Obsolete conversions could be detected and fixed by [`Scalafix`](https://scalace ## Reference -For more information, see [Issue #897](https://github.com/lampepfl/dotty/issues/897). +For more information, see [Issue #897](https://github.com/scala/scala3/issues/897). diff --git a/docs/_spec/TODOreference/other-new-features/parameter-untupling.md b/docs/_spec/TODOreference/other-new-features/parameter-untupling.md index fcc1fa11d519..09806fc169eb 100644 --- a/docs/_spec/TODOreference/other-new-features/parameter-untupling.md +++ b/docs/_spec/TODOreference/other-new-features/parameter-untupling.md @@ -74,4 +74,4 @@ cannot subvert untupling. For more information see: * [More details](./parameter-untupling-spec.md) -* [Issue #897](https://github.com/lampepfl/dotty/issues/897). +* [Issue #897](https://github.com/scala/scala3/issues/897). diff --git a/docs/_spec/TODOreference/overview.md b/docs/_spec/TODOreference/overview.md index b1e8281dfc16..bdb8aa74c1aa 100644 --- a/docs/_spec/TODOreference/overview.md +++ b/docs/_spec/TODOreference/overview.md @@ -91,7 +91,7 @@ These constructs are proposed to be dropped without a new construct replacing th - [Auto application](dropped-features/auto-apply.md), - [Weak conformance](dropped-features/weak-conformance.md), - Compound types (replaced by [Intersection types](new-types/intersection-types.md)), -- [Auto tupling](https://github.com/lampepfl/dotty/pull/4311) (implemented, but not merged). +- [Auto tupling](https://github.com/scala/scala3/pull/4311) (implemented, but not merged). The date when these constructs are dropped varies. The current status is: diff --git a/docs/_spec/_layouts/default.yml b/docs/_spec/_layouts/default.yml index 5d597cb5ea96..0f7fb24d7ce2 100644 --- a/docs/_spec/_layouts/default.yml +++ b/docs/_spec/_layouts/default.yml @@ -27,7 +27,7 @@
diff --git a/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 a583e31a9e0c..2beb4460db56 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala @@ -155,7 +155,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 addd86fc32ab..eadadd484089 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 ac63ef92aef5..9e223cb094e3 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 49942d8af4d5b4bdbf8e4ee86d0d62c67c70d8fe Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 5 Mar 2024 11:50:15 +0100 Subject: [PATCH 175/277] Support snippet that refers to experimental definitions on stable releases We add `-YnoExperimental` to simulate a releases version of the compile. Then fix the issue by allowing experimental code with `-experimental`. --- .../src/dotty/tools/scaladoc/snippets/SnippetCompiler.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompiler.scala b/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompiler.scala index 0ab5086e09d0..b47b15676c57 100644 --- a/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompiler.scala +++ b/scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompiler.scala @@ -27,6 +27,8 @@ class SnippetCompiler( object SnippetDriver extends Driver: val currentCtx = val rootCtx = initCtx.fresh.addMode(Mode.ReadPositions).addMode(Mode.Interactive) + rootCtx.setSetting(rootCtx.settings.YnoExperimental, true) + rootCtx.setSetting(rootCtx.settings.experimental, true) rootCtx.setSetting(rootCtx.settings.YretainTrees, true) rootCtx.setSetting(rootCtx.settings.YcookComments, true) rootCtx.setSetting(rootCtx.settings.YreadComments, true) From 579493f2a94a6ea9ce3b8c5e5784202d7ee223fb Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 5 Mar 2024 11:38:50 +0100 Subject: [PATCH 176/277] Remove `Feature.globalOnlyImports` This is dead code. This logic is now handled by `Features.handleGlobalLanguageImport`. --- compiler/src/dotty/tools/dotc/config/Feature.scala | 2 -- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/Feature.scala b/compiler/src/dotty/tools/dotc/config/Feature.scala index 0ab090ac5899..7eb95badd4d0 100644 --- a/compiler/src/dotty/tools/dotc/config/Feature.scala +++ b/compiler/src/dotty/tools/dotc/config/Feature.scala @@ -33,8 +33,6 @@ object Feature: val captureChecking = experimental("captureChecking") val into = experimental("into") - val globalOnlyImports: Set[TermName] = Set(pureFunctions, captureChecking) - /** Is `feature` enabled by by a command-line setting? The enabling setting is * * -language:feature diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 6c2e69658927..4ee27ba15527 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -30,7 +30,7 @@ import scala.annotation.tailrec import rewrites.Rewrites.{patch, overlapsPatch} import reporting.* import config.Feature -import config.Feature.{sourceVersion, migrateTo3, globalOnlyImports} +import config.Feature.{sourceVersion, migrateTo3} import config.SourceVersion.* import config.SourceVersion import dotty.tools.dotc.config.MigrationVersion From 92b27d264689dbe4779341041edaa15077fdfc68 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 4 Mar 2024 15:39:57 +0100 Subject: [PATCH 177/277] Disallow ill-staged references to local classes Fixes #19856 --- .../dotty/tools/dotc/staging/HealType.scala | 5 ++- tests/neg-macros/i19856.scala | 9 +++++ tests/neg-macros/i19856b.scala | 34 +++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 tests/neg-macros/i19856.scala create mode 100644 tests/neg-macros/i19856b.scala diff --git a/compiler/src/dotty/tools/dotc/staging/HealType.scala b/compiler/src/dotty/tools/dotc/staging/HealType.scala index 8b77f0774cdc..08e1e91b0bad 100644 --- a/compiler/src/dotty/tools/dotc/staging/HealType.scala +++ b/compiler/src/dotty/tools/dotc/staging/HealType.scala @@ -47,7 +47,10 @@ class HealType(pos: SrcPos)(using Context) extends TypeMap { checkNotWildcardSplice(tp) if level == 0 then tp else getTagRef(prefix) case _: TermRef | _: ThisType | NoPrefix => - if levelInconsistentRootOfPath(tp).exists then + val inconsistentRoot = levelInconsistentRootOfPath(tp) + if inconsistentRoot.isClass && inconsistentRoot.isLocal then + levelError(inconsistentRoot, tp, pos) + else if inconsistentRoot.exists then tryHeal(tp) else tp diff --git a/tests/neg-macros/i19856.scala b/tests/neg-macros/i19856.scala new file mode 100644 index 000000000000..990ae31d8db8 --- /dev/null +++ b/tests/neg-macros/i19856.scala @@ -0,0 +1,9 @@ +import scala.quoted.* + +def test(using Quotes): Any = + class Foo { + class IdxWrapper + def foo(using Type[IdxWrapper]): Expr[Any] = + '{ new IdxWrapper } // error + } + () diff --git a/tests/neg-macros/i19856b.scala b/tests/neg-macros/i19856b.scala new file mode 100644 index 000000000000..814b230a7ad0 --- /dev/null +++ b/tests/neg-macros/i19856b.scala @@ -0,0 +1,34 @@ +import scala.deriving.Mirror +import scala.quoted.{Expr, Quotes, Type} + +trait macroTest[A] { + type ElemTop <: A + type Index[_] + + case class IdxWrapper[X](idx: Index[X]) + + def indexOf[X <: ElemTop: Type](x: Expr[X]): Expr[Index[X]] + + def indexOfA(a: Expr[A]): Expr[IdxWrapper[_ <: ElemTop]] +} +object macroTest { + + def derivedImpl[A: Type, ElemTypes <: Tuple: Type, Label <: String: Type, Labels <: Tuple: Type]( + using m: Expr[ + Mirror.SumOf[A] { + type MirroredElemTypes = ElemTypes + type MirroredLabel = Label + type MirroredElemLabels = Labels + } + ], + q: Quotes, + ): macroTest[A] = new macroTest[A]: + override type Index[_] = Int + + override def indexOf[X <: ElemTop: Type](x: Expr[X]): Expr[Index[X]] = '{ $m.ordinal($x) } + + override def indexOfA(a: Expr[A]): Expr[IdxWrapper[_ <: ElemTop]] = + given Type[IdxWrapper] = Type.of[IdxWrapper] // error + given Type[ElemTop] = Type.of[ElemTop] // error + '{ new IdxWrapper(${ indexOf(a.asInstanceOf[Expr[ElemTop]]) }) } // error // error +} From a543e8f97ce647ac1705a0b0199adfe4f32df724 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 4 Mar 2024 11:04:12 +0100 Subject: [PATCH 178/277] Cleanup unnecessary language flag At some point `scala.compiletime.erasedValue` was defined as erased and therefore we needed this flag. Now we special case `erasedValue` in the compiler to give it erased semantics without defining it as such. --- compiler/test/dotty/tools/dotc/TastyBootstrapTests.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/test/dotty/tools/dotc/TastyBootstrapTests.scala b/compiler/test/dotty/tools/dotc/TastyBootstrapTests.scala index 50e07f388dc4..27311497de9c 100644 --- a/compiler/test/dotty/tools/dotc/TastyBootstrapTests.scala +++ b/compiler/test/dotty/tools/dotc/TastyBootstrapTests.scala @@ -60,7 +60,6 @@ class TastyBootstrapTests { val lib = compileList("lib", librarySources, defaultOptions.and("-Ycheck-reentrant", - "-language:experimental.erasedDefinitions", // support declaration of scala.compiletime.erasedValue // "-source", "future", // TODO: re-enable once library uses updated syntax for vararg splices, wildcard imports, and import renaming ))(libGroup) From 1f2448cdc6c0cbb2a377ac60c6b04c59e858ee76 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 1 Feb 2024 11:27:32 +0100 Subject: [PATCH 179/277] Publish `scala2-library-tasty` --- project/Build.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Build.scala b/project/Build.scala index ba6fe5a555fd..8e0ef0ad3093 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -2121,7 +2121,7 @@ object Build { // FIXME: we do not aggregate `bin` because its tests delete jars, thus breaking other tests def asDottyRoot(implicit mode: Mode): Project = project.withCommonSettings. aggregate(`scala3-interfaces`, dottyLibrary, dottyCompiler, tastyCore, `scala3-sbt-bridge`, scala3PresentationCompiler). - bootstrappedAggregate(`scala3-language-server`, `scala3-staging`, + bootstrappedAggregate(`scala2-library-tasty`, `scala3-language-server`, `scala3-staging`, `scala3-tasty-inspector`, `scala3-library-bootstrappedJS`, scaladoc). dependsOn(tastyCore). dependsOn(dottyCompiler). From 00f11a3b782b84068808ffdd0e4fe16c69f646a8 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 19 Jan 2024 10:03:35 +0100 Subject: [PATCH 180/277] Fix `TypeTreeTypeTest` to not match `TypeBoundsTree`s Also see `TypeBoundsTreeTypeTest` in `QuotesImpl` and `Quotes` spec ``` * +- TypeTree ----+- Inferred * | +- ... * | ... * +- TypeBoundsTree ``` Fixes #19480 --- .../src/scala/quoted/runtime/impl/QuotesImpl.scala | 2 +- tests/pos-macros/i19480/Macro_1.scala | 11 +++++++++++ tests/pos-macros/i19480/Test_2.scala | 1 + tests/pos-macros/i19480b/Macro_1.scala | 11 +++++++++++ tests/pos-macros/i19480b/Test_2.scala | 1 + 5 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 tests/pos-macros/i19480/Macro_1.scala create mode 100644 tests/pos-macros/i19480/Test_2.scala create mode 100644 tests/pos-macros/i19480b/Macro_1.scala create mode 100644 tests/pos-macros/i19480b/Test_2.scala diff --git a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala index 04d8d7bc51a0..c802d2a9201d 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala @@ -1105,7 +1105,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler object TypeTreeTypeTest extends TypeTest[Tree, TypeTree]: def unapply(x: Tree): Option[TypeTree & x.type] = x match - case x: (tpd.TypeBoundsTree & x.type) => None + case TypeBoundsTreeTypeTest(_) => None case x: (tpd.Tree & x.type) if x.isType => Some(x) case _ => None end TypeTreeTypeTest diff --git a/tests/pos-macros/i19480/Macro_1.scala b/tests/pos-macros/i19480/Macro_1.scala new file mode 100644 index 000000000000..bf3ea577a20e --- /dev/null +++ b/tests/pos-macros/i19480/Macro_1.scala @@ -0,0 +1,11 @@ +import scala.quoted.* + +inline def whatever: Int = ${whateverImpl} + +def whateverImpl(using Quotes): Expr[Int] = { + import quotes.reflect.* + val t = '{class K[T]}.asTerm + object mapper extends TreeMap + mapper.transformTree(t)(Symbol.spliceOwner) + '{42} +} diff --git a/tests/pos-macros/i19480/Test_2.scala b/tests/pos-macros/i19480/Test_2.scala new file mode 100644 index 000000000000..f12d2935bb9a --- /dev/null +++ b/tests/pos-macros/i19480/Test_2.scala @@ -0,0 +1 @@ +def test = whatever diff --git a/tests/pos-macros/i19480b/Macro_1.scala b/tests/pos-macros/i19480b/Macro_1.scala new file mode 100644 index 000000000000..150c0e93002d --- /dev/null +++ b/tests/pos-macros/i19480b/Macro_1.scala @@ -0,0 +1,11 @@ +import scala.quoted.* + +inline def whatever: Int = ${whateverImpl} + +def whateverImpl(using Quotes): Expr[Int] = { + import quotes.reflect.* + val t = '{class K[T[_]]}.asTerm + object mapper extends TreeMap + mapper.transformTree(t)(Symbol.spliceOwner) + '{42} +} diff --git a/tests/pos-macros/i19480b/Test_2.scala b/tests/pos-macros/i19480b/Test_2.scala new file mode 100644 index 000000000000..f12d2935bb9a --- /dev/null +++ b/tests/pos-macros/i19480b/Test_2.scala @@ -0,0 +1 @@ +def test = whatever From 05eb7f7ae514d1db5e0bece30d63cf5a30164ee8 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 6 Mar 2024 15:41:27 +0100 Subject: [PATCH 181/277] Remove `-Yforce-inline-while-typing` This flag only existed to help the migration to 3.0.0 from preview builds older than `3.0.0-M3`. This was only relevant for the 3.0.X versions. --- compiler/src/dotty/tools/dotc/config/ScalaSettings.scala | 2 -- compiler/src/dotty/tools/dotc/inlines/Inlines.scala | 1 - 2 files changed, 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 3dafedd8e2e0..07efc18a772b 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -435,8 +435,6 @@ private sealed trait YSettings: val Yinstrument: Setting[Boolean] = BooleanSetting("-Yinstrument", "Add instrumentation code that counts allocations and closure creations.") val YinstrumentDefs: Setting[Boolean] = BooleanSetting("-Yinstrument-defs", "Add instrumentation code that counts method calls; needs -Yinstrument to be set, too.") - val YforceInlineWhileTyping: Setting[Boolean] = BooleanSetting("-Yforce-inline-while-typing", "Make non-transparent inline methods inline when typing. Emulates the old inlining behavior of 3.0.0-M3.") - val YdebugMacros: Setting[Boolean] = BooleanSetting("-Ydebug-macros", "Show debug info when quote pattern match fails") // Pipeline compilation options diff --git a/compiler/src/dotty/tools/dotc/inlines/Inlines.scala b/compiler/src/dotty/tools/dotc/inlines/Inlines.scala index a97917e28771..866cf771d1e6 100644 --- a/compiler/src/dotty/tools/dotc/inlines/Inlines.scala +++ b/compiler/src/dotty/tools/dotc/inlines/Inlines.scala @@ -81,7 +81,6 @@ object Inlines: private def needsTransparentInlining(tree: Tree)(using Context): Boolean = tree.symbol.is(Transparent) || ctx.mode.is(Mode.ForceInline) - || ctx.settings.YforceInlineWhileTyping.value /** Try to inline a call to an inline method. Fail with error if the maximal * inline depth is exceeded. From d2d2af5f5fb9e7c9b7873aa3a41012badaa94976 Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Wed, 6 Mar 2024 16:01:18 +0100 Subject: [PATCH 182/277] Increase coverage of stdlib-cc to all compilation tests --- .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 80960212f8c1..baf894edd009 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -200,7 +200,7 @@ jobs: # TODO increase coverage to `scala3-bootstrapped/test` - name: Test with Scala 2 library with CC TASTy - run: ./project/scripts/sbt ";set ThisBuild/Build.scala2Library := Build.Scala2LibraryCCTasty ;scala3-bootstrapped/testCompilation pos" + run: ./project/scripts/sbt ";set ThisBuild/Build.scala2Library := Build.Scala2LibraryCCTasty ;scala3-bootstrapped/testCompilation" test_windows_fast: From f806ed84bfec45cd0fc4f9d489b584282e257449 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 7 Mar 2024 13:44:11 +0100 Subject: [PATCH 183/277] Tag experimental API tests Followup of https://github.com/scala/scala3/pull/19811 --- tests/init-global/pos/global-region1.scala | 2 ++ tests/init-global/warn/i18628_3.scala | 2 ++ tests/neg-macros/i19842/Macro.scala | 1 + tests/neg/inline-unstable-accessors.scala | 2 +- tests/neg/publicInBinaryOverride.check | 10 +++++----- tests/neg/publicInBinaryOverride.scala | 2 ++ tests/pos/TupleReverseOnto.scala | 3 +++ tests/pos/i7851.scala | 2 ++ tests/pos/tupled-function-instances.scala | 2 ++ tests/run-deep-subtype/Tuple-reverse.scala | 2 ++ tests/run-macros/i12021/Macro_1.scala | 2 ++ tests/run/i13215.scala | 2 +- tests/run/noProtectedSuper.scala | 2 ++ tests/run/publicInBinary/Lib_1.scala | 2 +- tests/run/quotes-add-erased/Macro_1.scala | 2 ++ tests/run/quotes-reflection/Macros_1.scala | 2 ++ 16 files changed, 32 insertions(+), 8 deletions(-) diff --git a/tests/init-global/pos/global-region1.scala b/tests/init-global/pos/global-region1.scala index db56fe45e1a4..0797d22aa5bf 100644 --- a/tests/init-global/pos/global-region1.scala +++ b/tests/init-global/pos/global-region1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.init.region trait B { def foo(): Int } diff --git a/tests/init-global/warn/i18628_3.scala b/tests/init-global/warn/i18628_3.scala index 0a14c7d4c73e..e7a057ded0d8 100644 --- a/tests/init-global/warn/i18628_3.scala +++ b/tests/init-global/warn/i18628_3.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.init.widen object Test: diff --git a/tests/neg-macros/i19842/Macro.scala b/tests/neg-macros/i19842/Macro.scala index 481c0b2468b0..78b1f576f1b4 100644 --- a/tests/neg-macros/i19842/Macro.scala +++ b/tests/neg-macros/i19842/Macro.scala @@ -1,3 +1,4 @@ +//> using options -experimental -Yno-experimental import scala.annotation.{experimental, targetName} import scala.quoted.* diff --git a/tests/neg/inline-unstable-accessors.scala b/tests/neg/inline-unstable-accessors.scala index a7fa75c2c6c9..d40f69819a2e 100644 --- a/tests/neg/inline-unstable-accessors.scala +++ b/tests/neg/inline-unstable-accessors.scala @@ -1,4 +1,4 @@ -//> using options -Werror -WunstableInlineAccessors -explain +//> using options -experimental -Yno-experimental -Werror -WunstableInlineAccessors -explain package foo import scala.annotation.publicInBinary diff --git a/tests/neg/publicInBinaryOverride.check b/tests/neg/publicInBinaryOverride.check index e44692c78525..73c60fa55d6a 100644 --- a/tests/neg/publicInBinaryOverride.check +++ b/tests/neg/publicInBinaryOverride.check @@ -1,5 +1,5 @@ --- [E164] Declaration Error: tests/neg/publicInBinaryOverride.scala:8:15 ----------------------------------------------- -8 | override def f(): Unit = () // error - | ^ - | error overriding method f in class A of type (): Unit; - | method f of type (): Unit also needs to be declared with @publicInBinary +-- [E164] Declaration Error: tests/neg/publicInBinaryOverride.scala:10:15 ---------------------------------------------- +10 | override def f(): Unit = () // error + | ^ + | error overriding method f in class A of type (): Unit; + | method f of type (): Unit also needs to be declared with @publicInBinary diff --git a/tests/neg/publicInBinaryOverride.scala b/tests/neg/publicInBinaryOverride.scala index 4b9144d27540..342e4773c56f 100644 --- a/tests/neg/publicInBinaryOverride.scala +++ b/tests/neg/publicInBinaryOverride.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.publicInBinary class A: diff --git a/tests/pos/TupleReverseOnto.scala b/tests/pos/TupleReverseOnto.scala index bef2d0949b29..09d5a323cb29 100644 --- a/tests/pos/TupleReverseOnto.scala +++ b/tests/pos/TupleReverseOnto.scala @@ -1,4 +1,7 @@ +//> using options -experimental -Yno-experimental + import scala.Tuple.* + def test[T1, T2, T3, T4] = summon[ReverseOnto[(T1, T2), (T3, T4)] =:= ReverseOnto[(T1, T2), (T3, T4)]] summon[ReverseOnto[(T1, T2), (T3, T4)] =:= (T2, T1, T3, T4)] diff --git a/tests/pos/i7851.scala b/tests/pos/i7851.scala index 7be04c45a257..5a6408cbe12a 100644 --- a/tests/pos/i7851.scala +++ b/tests/pos/i7851.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + trait Wrappable[T] { } given Wrappable[Float] with { } diff --git a/tests/pos/tupled-function-instances.scala b/tests/pos/tupled-function-instances.scala index 3b2d2aae40b2..3a3bc81b7426 100644 --- a/tests/pos/tupled-function-instances.scala +++ b/tests/pos/tupled-function-instances.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.util.TupledFunction object Test { def main(args: Array[String]): Unit = { diff --git a/tests/run-deep-subtype/Tuple-reverse.scala b/tests/run-deep-subtype/Tuple-reverse.scala index b0461d167fab..230800062bb5 100644 --- a/tests/run-deep-subtype/Tuple-reverse.scala +++ b/tests/run-deep-subtype/Tuple-reverse.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.reflect.ClassTag object Test { diff --git a/tests/run-macros/i12021/Macro_1.scala b/tests/run-macros/i12021/Macro_1.scala index 25cab1786146..4c36c1fc4cf0 100644 --- a/tests/run-macros/i12021/Macro_1.scala +++ b/tests/run-macros/i12021/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.quoted.* inline def inspect[A]: String = diff --git a/tests/run/i13215.scala b/tests/run/i13215.scala index 738eb25d598a..56cd3517d6ac 100644 --- a/tests/run/i13215.scala +++ b/tests/run/i13215.scala @@ -1,4 +1,4 @@ -//> using options -Werror -WunstableInlineAccessors +//> using options -experimental -Yno-experimental -Werror -WunstableInlineAccessors import scala.annotation.publicInBinary diff --git a/tests/run/noProtectedSuper.scala b/tests/run/noProtectedSuper.scala index 41b0615d12ab..999a8a06c4fa 100644 --- a/tests/run/noProtectedSuper.scala +++ b/tests/run/noProtectedSuper.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.publicInBinary package p { diff --git a/tests/run/publicInBinary/Lib_1.scala b/tests/run/publicInBinary/Lib_1.scala index a3c6ccea8427..86895ba40706 100644 --- a/tests/run/publicInBinary/Lib_1.scala +++ b/tests/run/publicInBinary/Lib_1.scala @@ -1,4 +1,4 @@ -//> using options -Werror -WunstableInlineAccessors +//> using options -experimental -Yno-experimental -Werror -WunstableInlineAccessors package foo diff --git a/tests/run/quotes-add-erased/Macro_1.scala b/tests/run/quotes-add-erased/Macro_1.scala index 56247d45cd23..5b95051a3744 100644 --- a/tests/run/quotes-add-erased/Macro_1.scala +++ b/tests/run/quotes-add-erased/Macro_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.annotation.MacroAnnotation import scala.annotation.internal.ErasedParam import scala.quoted._ diff --git a/tests/run/quotes-reflection/Macros_1.scala b/tests/run/quotes-reflection/Macros_1.scala index 5945d39a097a..c9fe6eb38c99 100644 --- a/tests/run/quotes-reflection/Macros_1.scala +++ b/tests/run/quotes-reflection/Macros_1.scala @@ -1,3 +1,5 @@ +//> using options -experimental -Yno-experimental + import scala.quoted.* inline def inspect[A]: String = From 229062cd555517413b6fa3162d1c70d8b420e74f Mon Sep 17 00:00:00 2001 From: EnzeXing Date: Thu, 7 Mar 2024 17:24:35 -0500 Subject: [PATCH 184/277] address comments --- .../dotty/tools/dotc/transform/init/Objects.scala | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala index 5c876206b111..19570f13c519 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala @@ -602,11 +602,12 @@ object Objects: case _ => a def filterType(tpe: Type)(using Context): Value = - val baseClasses = tpe.baseClasses - if baseClasses.isEmpty then a - else tpe match + tpe match case t @ SAMType(_, _) if a.isInstanceOf[Fun] => a // if tpe is SAMType and a is Fun, allow it - case _ => filterClass(baseClasses.head) // could have called ClassSymbol, but it does not handle OrType and AndType + case _ => + val baseClasses = tpe.baseClasses + if baseClasses.isEmpty then a + else filterClass(baseClasses.head) // could have called ClassSymbol, but it does not handle OrType and AndType def filterClass(sym: Symbol)(using Context): Value = if !sym.isClass then a @@ -614,8 +615,7 @@ object Objects: val klass = sym.asClass a match case Cold => Cold - case ref: Ref if ref.klass.isSubClass(klass) => ref - case ref: Ref => Bottom + case ref: Ref => if ref.klass.isSubClass(klass) then ref else Bottom case ValueSet(values) => values.map(v => v.filterClass(klass)).join case arr: OfArray => if defn.ArrayClass.isSubClass(klass) then arr else Bottom case fun: Fun => @@ -1572,7 +1572,7 @@ object Objects: report.warning("The argument should be a constant integer value", arg) res.widen(1) case _ => - if res.isInstanceOf[Fun] then res.widen(2) else res.widen(1) // TODO: changing to widen(2) causes standard library analysis to loop infinitely + if res.isInstanceOf[Fun] then res.widen(2) else res.widen(1) argInfos += ArgInfo(widened, trace.add(arg.tree), arg.tree) } From 1e56ca0ed1bcd9917dd1a4192e5c482367ab7d1a Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 8 Mar 2024 08:57:31 +0100 Subject: [PATCH 185/277] Port tasty inspector test from scala2-library-tasty-tests Part of #19379 The new test is run on all available configurations. Now it also runs on Windows. --- .../test/BootstrappedStdLibTASYyTest.scala | 32 ----------- .../scala2-library-test.scala | 53 +++++++++++++++++++ 2 files changed, 53 insertions(+), 32 deletions(-) create mode 100644 tests/run-tasty-inspector/scala2-library-test.scala diff --git a/scala2-library-tasty-tests/test/BootstrappedStdLibTASYyTest.scala b/scala2-library-tasty-tests/test/BootstrappedStdLibTASYyTest.scala index db810cd87f26..f05accd8c2ba 100644 --- a/scala2-library-tasty-tests/test/BootstrappedStdLibTASYyTest.scala +++ b/scala2-library-tasty-tests/test/BootstrappedStdLibTASYyTest.scala @@ -17,10 +17,6 @@ class BootstrappedStdLibTASYyTest: import BootstrappedStdLibTASYyTest._ - /** Test that we can load trees from TASTy */ - @Test def testTastyInspector: Unit = - loadWithTastyInspector(loadBlacklisted) - /** Test that we can load and compile trees from TASTy in a Jar */ @Test def testFromTastyInJar: Unit = compileFromTastyInJar(loadBlacklisted.union(compileBlacklisted)) @@ -52,23 +48,6 @@ class BootstrappedStdLibTASYyTest: compileBlacklisted.diff(scalaLibTastyPathsSet).mkString( "`loadBlacklisted` contains names that are not in `scalaLibTastyPaths`: \n ", "\n ", "\n\n")) - @Ignore - @Test def testLoadBacklistIsMinimal = - var shouldBeWhitelisted = List.empty[String] - val size = loadBlacklisted.size - for (notBlacklisted, i) <- loadBlacklist.zipWithIndex do - val blacklist = loadBlacklisted - notBlacklisted - println(s"Trying without $notBlacklisted in the blacklist (${i+1}/$size)") - try { - loadWithTastyInspector(blacklist) - shouldBeWhitelisted = notBlacklisted :: shouldBeWhitelisted - } - catch { - case ex: Throwable => // ok - } - assert(shouldBeWhitelisted.isEmpty, - shouldBeWhitelisted.mkString("Some classes do not need to be blacklisted in `loadBlacklisted`\n ", "\n ", "\n\n")) - @Ignore @Test def testCompileBlacklistIsMinimal = var shouldBeWhitelisted = List.empty[String] @@ -101,17 +80,6 @@ object BootstrappedStdLibTASYyTest: .map(_.normalize.path.stripPrefix(scalaLibClassesPath.toString + "/")) .toList - def loadWithTastyInspector(blacklisted: Set[String]): Unit = - val inspector = new scala.tasty.inspector.Inspector { - def inspect(using Quotes)(tastys: List[Tasty[quotes.type]]): Unit = - for tasty <- tastys do - tasty.ast.show(using quotes.reflect.Printer.TreeStructure) // Check that we can traverse the full tree - () - } - val tastyFiles = scalaLibTastyPaths.filterNot(blacklisted) - val isSuccess = TastyInspector.inspectTastyFiles(tastyFiles.map(x => scalaLibClassesPath.resolve(x).toString))(inspector) - assert(isSuccess, "Errors reported while loading from TASTy") - def compileFromTastyInJar(blacklisted: Set[String]): Unit = { val driver = new dotty.tools.dotc.Driver val yFromTastyBlacklist = diff --git a/tests/run-tasty-inspector/scala2-library-test.scala b/tests/run-tasty-inspector/scala2-library-test.scala new file mode 100644 index 000000000000..15a251427d70 --- /dev/null +++ b/tests/run-tasty-inspector/scala2-library-test.scala @@ -0,0 +1,53 @@ +import scala.quoted._ +import scala.tasty.inspector._ + +import dotty.tools.io.Directory + +import java.io.File.pathSeparator +import java.io.File.separator + +@main def Test: Unit = + blacklistsOnlyContainsClassesThatExist() + testTastyInspector() + +/** Test that we can load trees from TASTy */ +def testTastyInspector(): Unit = + loadWithTastyInspector(loadBlacklisted) + +def blacklistsOnlyContainsClassesThatExist() = + val scalaLibTastyPathsSet = scalaLibTastyPaths.toSet + assert(loadBlacklisted.diff(scalaLibTastyPathsSet).isEmpty, + loadBlacklisted.diff(scalaLibTastyPathsSet).mkString( + "`loadBlacklisted` contains names that are not in `scalaLibTastyPaths`: \n ", "\n ", "\n\n")) + +def dottyVersion = + System.getProperty("java.class.path").nn.split(pathSeparator).collectFirst { + case path if path.endsWith(".jar") && path.contains("scala3-library_3-") => + path.split("scala3-library_3-").last.stripSuffix(".jar") + }.get + +def scalaLibClassesPath = + java.nio.file.Paths.get( + s"out/bootstrap/scala2-library-bootstrapped/scala-$dottyVersion-nonbootstrapped/classes".replace("/", separator)) + +lazy val scalaLibTastyPaths = + new Directory(scalaLibClassesPath).deepFiles + .filter(_.`extension` == "tasty") + .map(_.normalize.path.stripPrefix(scalaLibClassesPath.toString + separator)) + .toList + +def loadWithTastyInspector(blacklisted: Set[String]): Unit = + val inspector = new scala.tasty.inspector.Inspector { + def inspect(using Quotes)(tastys: List[Tasty[quotes.type]]): Unit = + for tasty <- tastys do + tasty.ast.show(using quotes.reflect.Printer.TreeStructure) // Check that we can traverse the full tree + () + } + val tastyFiles = scalaLibTastyPaths.filterNot(blacklisted) + val isSuccess = TastyInspector.inspectTastyFiles(tastyFiles.map(x => scalaLibClassesPath.resolve(x).toString))(inspector) + assert(isSuccess, "Errors reported while loading from TASTy") + +/** Set of tasty files that cannot be loaded from TASTy */ +def loadBlacklisted = Set[String]( + // No issues :) +) From 5c98f222a6758c82f8fe3e51b39d37ff23ac28cb Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 8 Mar 2024 10:34:45 +0100 Subject: [PATCH 186/277] Enable all tests `scala2-library-cc-tasty` --- .github/workflows/ci.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index baf894edd009..71a2c4ed6eb0 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -198,9 +198,8 @@ jobs: - name: Test with Scala 2 library TASTy run: ./project/scripts/sbt ";set ThisBuild/Build.scala2Library := Build.Scala2LibraryTasty ;scala3-bootstrapped/test" - # TODO increase coverage to `scala3-bootstrapped/test` - name: Test with Scala 2 library with CC TASTy - run: ./project/scripts/sbt ";set ThisBuild/Build.scala2Library := Build.Scala2LibraryCCTasty ;scala3-bootstrapped/testCompilation" + run: ./project/scripts/sbt ";set ThisBuild/Build.scala2Library := Build.Scala2LibraryCCTasty ;scala3-bootstrapped/test" test_windows_fast: From 442170c5940264644d6fc09775a7cd16cdae063a Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 8 Mar 2024 11:03:49 +0100 Subject: [PATCH 187/277] Re-enable lost tests Found in https://github.com/scala/scala3/pull/7906#discussion_r1516298628 --- tests/{pos-custom-args => pos}/i4125.scala | 2 ++ tests/{pos-custom-args => pos}/i4509.scala | 2 ++ tests/{pos-custom-args => pos}/i5938.scala | 7 +++++-- tests/{pos-custom-args => pos}/i6009a.scala | 2 ++ tests/{pos-custom-args => pos}/i6009b.scala | 2 ++ tests/{pos-custom-args => pos}/i6009c.scala | 2 ++ tests/{pos-custom-args => pos}/i6419.scala | 2 ++ tests/{pos-custom-args => pos}/i7741.scala | 2 ++ .../{pos-custom-args => pos}/inline-match-gadt.scala | 2 ++ tests/{pos-custom-args => pos}/matchtype.scala | 12 +++++++----- tests/{pos-custom-args => pos}/phantom-Eq.scala | 2 ++ .../phantom-Eq2/Phantom-Eq_1.scala | 1 + .../phantom-Eq2/Phantom-Eq_2.scala | 0 .../{pos-custom-args => pos}/phantom-Evidence.scala | 4 +++- 14 files changed, 34 insertions(+), 8 deletions(-) rename tests/{pos-custom-args => pos}/i4125.scala (73%) rename tests/{pos-custom-args => pos}/i4509.scala (58%) rename tests/{pos-custom-args => pos}/i5938.scala (60%) rename tests/{pos-custom-args => pos}/i6009a.scala (63%) rename tests/{pos-custom-args => pos}/i6009b.scala (63%) rename tests/{pos-custom-args => pos}/i6009c.scala (64%) rename tests/{pos-custom-args => pos}/i6419.scala (78%) rename tests/{pos-custom-args => pos}/i7741.scala (69%) rename tests/{pos-custom-args => pos}/inline-match-gadt.scala (81%) rename tests/{pos-custom-args => pos}/matchtype.scala (86%) rename tests/{pos-custom-args => pos}/phantom-Eq.scala (93%) rename tests/{pos-custom-args => pos}/phantom-Eq2/Phantom-Eq_1.scala (93%) rename tests/{pos-custom-args => pos}/phantom-Eq2/Phantom-Eq_2.scala (100%) rename tests/{pos-custom-args => pos}/phantom-Evidence.scala (88%) diff --git a/tests/pos-custom-args/i4125.scala b/tests/pos/i4125.scala similarity index 73% rename from tests/pos-custom-args/i4125.scala rename to tests/pos/i4125.scala index 70d03fbf3d77..80634076c1b9 100644 --- a/tests/pos-custom-args/i4125.scala +++ b/tests/pos/i4125.scala @@ -1,3 +1,5 @@ +import scala.language.experimental.erasedDefinitions + object Test { def foo: ((erased x: Int, y: Int) => Int) = (erased x, y) => 1 def bar: ((erased x: Int, y: Int) ?=> Int) = (erased x, y) ?=> 1 diff --git a/tests/pos-custom-args/i4509.scala b/tests/pos/i4509.scala similarity index 58% rename from tests/pos-custom-args/i4509.scala rename to tests/pos/i4509.scala index 2e394ef296ed..400cc984c2c2 100644 --- a/tests/pos-custom-args/i4509.scala +++ b/tests/pos/i4509.scala @@ -1,3 +1,5 @@ +import scala.language.experimental.erasedDefinitions + object Main { def fun[T](op: (erased Int) ?=> T) = op(using 0) fun { } diff --git a/tests/pos-custom-args/i5938.scala b/tests/pos/i5938.scala similarity index 60% rename from tests/pos-custom-args/i5938.scala rename to tests/pos/i5938.scala index c650fca779d7..17a20dcd0f1f 100644 --- a/tests/pos-custom-args/i5938.scala +++ b/tests/pos/i5938.scala @@ -1,8 +1,11 @@ +import scala.language.experimental.erasedDefinitions + import compiletime.summonFrom +import compiletime.erasedValue trait Link[T, A] -inline def link[T] = +transparent inline def link[T] = summonFrom { case _: Link[T, s] => summonFrom { @@ -12,7 +15,7 @@ inline def link[T] = class Foo object Foo { - erased implicit val barLink: Link[Foo, Bar.type] = null + erased implicit val barLink: Link[Foo, Bar.type] = erasedValue } implicit object Bar { diff --git a/tests/pos-custom-args/i6009a.scala b/tests/pos/i6009a.scala similarity index 63% rename from tests/pos-custom-args/i6009a.scala rename to tests/pos/i6009a.scala index 41360d845116..63a6039a88a3 100644 --- a/tests/pos-custom-args/i6009a.scala +++ b/tests/pos/i6009a.scala @@ -1,3 +1,5 @@ +import scala.language.experimental.erasedDefinitions + class Foo { def foo(f: (erased Int) => Int): Int = { erased val ctx = 1 diff --git a/tests/pos-custom-args/i6009b.scala b/tests/pos/i6009b.scala similarity index 63% rename from tests/pos-custom-args/i6009b.scala rename to tests/pos/i6009b.scala index 41360d845116..63a6039a88a3 100644 --- a/tests/pos-custom-args/i6009b.scala +++ b/tests/pos/i6009b.scala @@ -1,3 +1,5 @@ +import scala.language.experimental.erasedDefinitions + class Foo { def foo(f: (erased Int) => Int): Int = { erased val ctx = 1 diff --git a/tests/pos-custom-args/i6009c.scala b/tests/pos/i6009c.scala similarity index 64% rename from tests/pos-custom-args/i6009c.scala rename to tests/pos/i6009c.scala index 02f2ced70cec..e09a56203fcf 100644 --- a/tests/pos-custom-args/i6009c.scala +++ b/tests/pos/i6009c.scala @@ -1,3 +1,5 @@ +import scala.language.experimental.erasedDefinitions + class Foo { def foo(f: (erased Int) ?=> Int): Int = { implicit erased val ctx = 1 diff --git a/tests/pos-custom-args/i6419.scala b/tests/pos/i6419.scala similarity index 78% rename from tests/pos-custom-args/i6419.scala rename to tests/pos/i6419.scala index b398e9856dee..550922f48d76 100644 --- a/tests/pos-custom-args/i6419.scala +++ b/tests/pos/i6419.scala @@ -1,3 +1,5 @@ +import scala.language.experimental.erasedDefinitions + class Foo { inline def foo: Unit = { @scala.annotation.compileTimeOnly("some message") val res = ??? diff --git a/tests/pos-custom-args/i7741.scala b/tests/pos/i7741.scala similarity index 69% rename from tests/pos-custom-args/i7741.scala rename to tests/pos/i7741.scala index 72b83b172552..237616d04d2a 100644 --- a/tests/pos-custom-args/i7741.scala +++ b/tests/pos/i7741.scala @@ -1,3 +1,5 @@ +import scala.language.experimental.erasedDefinitions + class A1 { @native private def a: Unit } diff --git a/tests/pos-custom-args/inline-match-gadt.scala b/tests/pos/inline-match-gadt.scala similarity index 81% rename from tests/pos-custom-args/inline-match-gadt.scala rename to tests/pos/inline-match-gadt.scala index f63d0fb5b68c..cf2aae00b402 100644 --- a/tests/pos-custom-args/inline-match-gadt.scala +++ b/tests/pos/inline-match-gadt.scala @@ -1,3 +1,5 @@ +import scala.language.experimental.erasedDefinitions + object `inline-match-gadt` { class Exactly[T] erased def exactType[T]: Exactly[T] = compiletime.erasedValue diff --git a/tests/pos-custom-args/matchtype.scala b/tests/pos/matchtype.scala similarity index 86% rename from tests/pos-custom-args/matchtype.scala rename to tests/pos/matchtype.scala index 746301622864..21c074deafd7 100644 --- a/tests/pos-custom-args/matchtype.scala +++ b/tests/pos/matchtype.scala @@ -1,4 +1,6 @@ -import compiletime.* +import scala.language.experimental.erasedDefinitions +import compiletime.erasedValue +import compiletime.ops.int.S object Test { type T[X] = X match { case String => Int @@ -6,7 +8,7 @@ object Test { } type Len[X] <: Int = X match { - case Unit => 0 + case EmptyTuple => 0 case x *: xs => S[Len[xs]] } @@ -28,7 +30,7 @@ object Test { erased val z1: Head[(Int, String)] = 22 type Concat[X <: Tuple, Y <: Tuple] <: Tuple = X match { - case Unit => Y + case EmptyTuple => Y case x1 *: xs1 => x1 *: Concat[xs1, Y] } @@ -55,8 +57,8 @@ object Test { erased val y4: Elem[(String, Int, Boolean), 2] = erasedValue[Boolean] erased val z4: Boolean = erasedValue[Elem[(String, Int, Boolean), 2]] - erased val y5: Concat[Unit, (String, Int)] = erasedValue[(String, Int)] - erased val z5: (String, Int) = erasedValue[Concat[Unit, (String, Int)]] + erased val y5: Concat[EmptyTuple, (String, Int)] = erasedValue[(String, Int)] + erased val z5: (String, Int) = erasedValue[Concat[EmptyTuple, (String, Int)]] erased val y6: Concat[(Boolean, Boolean), (String, Int)] = erasedValue[Boolean *: Boolean *: (String, Int)] erased val z6: Boolean *: Boolean *: (String, Int) = erasedValue[Concat[(Boolean, Boolean), (String, Int)]] erased val y7: (Boolean, Boolean, String, Int) = erasedValue[Concat[(Boolean, Boolean), String *: Int *: EmptyTuple]] diff --git a/tests/pos-custom-args/phantom-Eq.scala b/tests/pos/phantom-Eq.scala similarity index 93% rename from tests/pos-custom-args/phantom-Eq.scala rename to tests/pos/phantom-Eq.scala index 6ec5f77676ce..9f892d353b41 100644 --- a/tests/pos-custom-args/phantom-Eq.scala +++ b/tests/pos/phantom-Eq.scala @@ -1,3 +1,5 @@ +import scala.language.experimental.erasedDefinitions + object PhantomEq { import EqUtil.* diff --git a/tests/pos-custom-args/phantom-Eq2/Phantom-Eq_1.scala b/tests/pos/phantom-Eq2/Phantom-Eq_1.scala similarity index 93% rename from tests/pos-custom-args/phantom-Eq2/Phantom-Eq_1.scala rename to tests/pos/phantom-Eq2/Phantom-Eq_1.scala index cb4f8aa6821f..120c68174898 100644 --- a/tests/pos-custom-args/phantom-Eq2/Phantom-Eq_1.scala +++ b/tests/pos/phantom-Eq2/Phantom-Eq_1.scala @@ -1,3 +1,4 @@ +import scala.language.experimental.erasedDefinitions /* This is a version of ../pos/phantomEq.scala that tests phantom with separate compilation */ object EqUtil { diff --git a/tests/pos-custom-args/phantom-Eq2/Phantom-Eq_2.scala b/tests/pos/phantom-Eq2/Phantom-Eq_2.scala similarity index 100% rename from tests/pos-custom-args/phantom-Eq2/Phantom-Eq_2.scala rename to tests/pos/phantom-Eq2/Phantom-Eq_2.scala diff --git a/tests/pos-custom-args/phantom-Evidence.scala b/tests/pos/phantom-Evidence.scala similarity index 88% rename from tests/pos-custom-args/phantom-Evidence.scala rename to tests/pos/phantom-Evidence.scala index 3a82cfe0c6e8..ecdd84cbc481 100644 --- a/tests/pos-custom-args/phantom-Evidence.scala +++ b/tests/pos/phantom-Evidence.scala @@ -1,3 +1,5 @@ +import scala.language.experimental.erasedDefinitions + /** In this implementation variant of =:= (called =::=) we erase all instantiations and definitions of =::= */ object WithNormalState { import Utils.* @@ -24,5 +26,5 @@ object WithNormalState { object Utils { type =::=[From, To] - erased given tpEquals[A]: A =::= A = compiletime.erasedValue + erased given tpEquals[A]: (A =::= A) = compiletime.erasedValue } From ac40aa63e7430d8ece56c38b3c321383e2e432e5 Mon Sep 17 00:00:00 2001 From: willerf Date: Fri, 8 Mar 2024 08:36:42 -0500 Subject: [PATCH 188/277] suppress warnings in global init checker --- .../tools/dotc/transform/init/Checker.scala | 3 ++- .../tools/dotc/transform/init/Objects.scala | 22 +++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Checker.scala b/compiler/src/dotty/tools/dotc/transform/init/Checker.scala index 7cf028c95064..692b3177786d 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Checker.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Checker.scala @@ -50,7 +50,8 @@ class Checker extends Phase: Semantic.checkClasses(classes)(using checkCtx) if ctx.settings.YcheckInitGlobal.value then - Objects.checkClasses(classes)(using checkCtx) + val obj = new Objects + obj.checkClasses(classes)(using checkCtx) } units0 diff --git a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala index 763b71619de8..39ce09ccfa23 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala @@ -65,7 +65,7 @@ import scala.annotation.constructorOnly * whole-program analysis. However, the check is not modular in terms of project boundaries. * */ -object Objects: +class Objects: // ----------------------------- abstract domain ----------------------------- @@ -1734,16 +1734,20 @@ object Objects: if cls.isAllOf(Flags.JavaInterface) then Bottom else evalType(tref.prefix, thisV, klass, elideObjectAccess = cls.isStatic) + val mutateErrorSet: mutable.Set[(ClassSymbol, ClassSymbol)] = mutable.Set.empty def errorMutateOtherStaticObject(currentObj: ClassSymbol, otherObj: ClassSymbol)(using Trace, Context) = - val msg = - s"Mutating ${otherObj.show} during initialization of ${currentObj.show}.\n" + - "Mutating other static objects during the initialization of one static object is forbidden. " + Trace.show + if mutateErrorSet.add((currentObj, otherObj)) then + val msg = + s"Mutating ${otherObj.show} during initialization of ${currentObj.show}.\n" + + "Mutating other static objects during the initialization of one static object is forbidden. " + Trace.show - report.warning(msg, Trace.position) + report.warning(msg, Trace.position) + val readErrorSet: mutable.Set[(ClassSymbol, ClassSymbol)] = mutable.Set.empty def errorReadOtherStaticObject(currentObj: ClassSymbol, otherObj: ClassSymbol)(using Trace, Context) = - val msg = - "Reading mutable state of " + otherObj.show + " during initialization of " + currentObj.show + ".\n" + - "Reading mutable state of other static objects is forbidden as it breaks initialization-time irrelevance. " + Trace.show + if readErrorSet.add((currentObj, otherObj)) then + val msg = + "Reading mutable state of " + otherObj.show + " during initialization of " + currentObj.show + ".\n" + + "Reading mutable state of other static objects is forbidden as it breaks initialization-time irrelevance. " + Trace.show - report.warning(msg, Trace.position) + report.warning(msg, Trace.position) From e2c65e6d9ad2f64bda4bd7f4693526a9f75ca334 Mon Sep 17 00:00:00 2001 From: Katarzyna Marek Date: Fri, 8 Mar 2024 15:25:27 +0100 Subject: [PATCH 189/277] add `info` implementation to pc (#19812) --- .../tools/pc/ScalaPresentationCompiler.scala | 18 +++ .../tools/pc/SymbolInformationProvider.scala | 122 ++++++++++++++++++ .../dotty/tools/pc/tests/info/InfoSuite.scala | 56 ++++++++ project/Build.scala | 2 +- 4 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 presentation-compiler/src/main/dotty/tools/pc/SymbolInformationProvider.scala create mode 100644 presentation-compiler/test/dotty/tools/pc/tests/info/InfoSuite.scala diff --git a/presentation-compiler/src/main/dotty/tools/pc/ScalaPresentationCompiler.scala b/presentation-compiler/src/main/dotty/tools/pc/ScalaPresentationCompiler.scala index f3dc8d1658c4..378564d90bc1 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/ScalaPresentationCompiler.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/ScalaPresentationCompiler.scala @@ -19,12 +19,14 @@ import scala.meta.internal.metals.EmptyReportContext import scala.meta.internal.metals.ReportContext import scala.meta.internal.metals.ReportLevel import scala.meta.internal.metals.StdReportContext +import scala.meta.internal.mtags.CommonMtagsEnrichments.* import scala.meta.internal.pc.CompilerAccess import scala.meta.internal.pc.DefinitionResultImpl import scala.meta.internal.pc.EmptyCompletionList import scala.meta.internal.pc.EmptySymbolSearch import scala.meta.internal.pc.PresentationCompilerConfigImpl import scala.meta.pc.* +import scala.meta.pc.{PcSymbolInformation as IPcSymbolInformation} import dotty.tools.dotc.reporting.StoreReporter import dotty.tools.pc.completions.CompletionProvider @@ -34,6 +36,7 @@ import dotty.tools.pc.buildinfo.BuildInfo import org.eclipse.lsp4j.DocumentHighlight import org.eclipse.lsp4j.TextEdit import org.eclipse.lsp4j as l +import scala.meta.internal.pc.SymbolInformationProvider case class ScalaPresentationCompiler( buildTargetIdentifier: String = "", @@ -184,6 +187,21 @@ case class ScalaPresentationCompiler( def diagnosticsForDebuggingPurposes(): ju.List[String] = List[String]().asJava + override def info( + symbol: String + ): CompletableFuture[Optional[IPcSymbolInformation]] = + compilerAccess.withNonInterruptableCompiler[Optional[IPcSymbolInformation]]( + None + )( + Optional.empty(), + EmptyCancelToken, + ) { access => + SymbolInformationProvider(using access.compiler().currentCtx) + .info(symbol) + .map(_.asJava) + .asJava + } + def semanticdbTextDocument( filename: URI, code: String diff --git a/presentation-compiler/src/main/dotty/tools/pc/SymbolInformationProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/SymbolInformationProvider.scala new file mode 100644 index 000000000000..aa1508f89313 --- /dev/null +++ b/presentation-compiler/src/main/dotty/tools/pc/SymbolInformationProvider.scala @@ -0,0 +1,122 @@ +package scala.meta.internal.pc + +import scala.util.control.NonFatal + +import scala.meta.pc.PcSymbolKind +import scala.meta.pc.PcSymbolProperty + +import dotty.tools.dotc.core.Contexts.Context +import dotty.tools.dotc.core.Denotations.Denotation +import dotty.tools.dotc.core.Denotations.MultiDenotation +import dotty.tools.dotc.core.Flags +import dotty.tools.dotc.core.Names.* +import dotty.tools.dotc.core.StdNames.nme +import dotty.tools.dotc.core.Symbols.* +import dotty.tools.pc.utils.MtagsEnrichments.metalsDealias +import dotty.tools.pc.SemanticdbSymbols +import dotty.tools.pc.utils.MtagsEnrichments.allSymbols + +class SymbolInformationProvider(using Context): + private def toSymbols( + pkg: String, + parts: List[(String, Boolean)], + ): List[Symbol] = + def loop( + owners: List[Symbol], + parts: List[(String, Boolean)], + ): List[Symbol] = + parts match + case (head, isClass) :: tl => + val foundSymbols = + owners.flatMap { owner => + val next = + if isClass then owner.info.member(typeName(head)) + else owner.info.member(termName(head)) + next.allSymbols + } + if foundSymbols.nonEmpty then loop(foundSymbols, tl) + else Nil + case Nil => owners + + val pkgSym = + if pkg == "_empty_" then requiredPackage(nme.EMPTY_PACKAGE) + else requiredPackage(pkg) + loop(List(pkgSym), parts) + end toSymbols + + def info(symbol: String): Option[PcSymbolInformation] = + val index = symbol.lastIndexOf("/") + val pkg = normalizePackage(symbol.take(index + 1)) + + def loop( + symbol: String, + acc: List[(String, Boolean)], + ): List[(String, Boolean)] = + if symbol.isEmpty() then acc.reverse + else + val newSymbol = symbol.takeWhile(c => c != '.' && c != '#') + val rest = symbol.drop(newSymbol.size) + loop(rest.drop(1), (newSymbol, rest.headOption.exists(_ == '#')) :: acc) + val names = + loop(symbol.drop(index + 1).takeWhile(_ != '('), List.empty) + + val foundSymbols = + try toSymbols(pkg, names) + catch case NonFatal(e) => Nil + + val (searchedSymbol, alternativeSymbols) = + foundSymbols.partition: compilerSymbol => + SemanticdbSymbols.symbolName(compilerSymbol) == symbol + + searchedSymbol match + case Nil => None + case sym :: _ => + val classSym = if sym.isClass then sym else sym.moduleClass + val parents = + if classSym.isClass + then classSym.asClass.parentSyms.map(SemanticdbSymbols.symbolName) + else Nil + val dealisedSymbol = + if sym.isAliasType then sym.info.metalsDealias.typeSymbol else sym + val classOwner = + sym.ownersIterator.drop(1).find(s => s.isClass || s.is(Flags.Module)) + val overridden = sym.denot.allOverriddenSymbols.toList + + val pcSymbolInformation = + PcSymbolInformation( + symbol = SemanticdbSymbols.symbolName(sym), + kind = getSymbolKind(sym), + parents = parents, + dealiasedSymbol = SemanticdbSymbols.symbolName(dealisedSymbol), + classOwner = classOwner.map(SemanticdbSymbols.symbolName), + overriddenSymbols = overridden.map(SemanticdbSymbols.symbolName), + alternativeSymbols = + alternativeSymbols.map(SemanticdbSymbols.symbolName), + properties = + if sym.is(Flags.Abstract) then List(PcSymbolProperty.ABSTRACT) + else Nil, + ) + + Some(pcSymbolInformation) + end match + end info + + private def getSymbolKind(sym: Symbol): PcSymbolKind = + if sym.isAllOf(Flags.JavaInterface) then PcSymbolKind.INTERFACE + else if sym.is(Flags.Trait) then PcSymbolKind.TRAIT + else if sym.isConstructor then PcSymbolKind.CONSTRUCTOR + else if sym.isPackageObject then PcSymbolKind.PACKAGE_OBJECT + else if sym.isClass then PcSymbolKind.CLASS + else if sym.is(Flags.Macro) then PcSymbolKind.MACRO + else if sym.is(Flags.Local) then PcSymbolKind.LOCAL + else if sym.is(Flags.Method) then PcSymbolKind.METHOD + else if sym.is(Flags.Param) then PcSymbolKind.PARAMETER + else if sym.is(Flags.Package) then PcSymbolKind.PACKAGE + else if sym.is(Flags.TypeParam) then PcSymbolKind.TYPE_PARAMETER + else if sym.isType then PcSymbolKind.TYPE + else PcSymbolKind.UNKNOWN_KIND + + private def normalizePackage(pkg: String): String = + pkg.replace("/", ".").nn.stripSuffix(".") + +end SymbolInformationProvider diff --git a/presentation-compiler/test/dotty/tools/pc/tests/info/InfoSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/info/InfoSuite.scala new file mode 100644 index 000000000000..8464c4d69da4 --- /dev/null +++ b/presentation-compiler/test/dotty/tools/pc/tests/info/InfoSuite.scala @@ -0,0 +1,56 @@ +package dotty.tools.pc.tests.info + +import scala.meta.internal.jdk.CollectionConverters._ +import scala.meta.pc.PcSymbolKind +import scala.meta.pc.PcSymbolProperty + +import scala.meta.pc.PcSymbolInformation +import dotty.tools.pc.base.BasePCSuite +import scala.language.unsafeNulls +import org.junit.Test + +class InfoSuite extends BasePCSuite { + + def getInfo(symbol: String): PcSymbolInformation = { + val result = presentationCompiler.info(symbol).get() + assertEquals(true, result.isPresent(), s"no info returned for symbol $symbol") + assertNoDiff(result.get().symbol(), symbol) + result.get() + } + + @Test def `list` = + val info = getInfo("scala/collection/immutable/List#") + assertEquals(true, info.properties().contains(PcSymbolProperty.ABSTRACT), s"class List should be abstract") + assertEquals( + true, + info.parents().contains("scala/collection/immutable/LinearSeq#"), + "class List should extend LinearSeq" + ) + + @Test def `empty-list-constructor` = + val info = getInfo("scala/collection/immutable/List.empty().") + assertNoDiff(info.classOwner(), "scala/collection/immutable/List.") + assertEquals(info.kind(), PcSymbolKind.METHOD, "List.empty() should be a method") + + @Test def `assert` = + val info = getInfo("scala/Predef.assert().") + assertEquals(info.kind(), PcSymbolKind.METHOD, "assert() should be a method") + assertNoDiff(info.classOwner(), "scala/Predef.") + assertEquals( + info.alternativeSymbols().asScala.mkString("\n"), + "scala/Predef.assert(+1).", + "there should be a single alternative symbol to assert()" + ) + + @Test def `flatMap` = + val info = getInfo("scala/collection/immutable/List#flatMap().") + assertEquals(info.kind(), PcSymbolKind.METHOD, "List.flatMap() should be a method") + assertNoDiff(info.classOwner(), "scala/collection/immutable/List#") + assertNoDiff( + info.overriddenSymbols().asScala.mkString("\n"), + """|scala/collection/StrictOptimizedIterableOps#flatMap(). + |scala/collection/IterableOps#flatMap(). + |scala/collection/IterableOnceOps#flatMap(). + |""".stripMargin + ) +} diff --git a/project/Build.scala b/project/Build.scala index ba6fe5a555fd..df418a7fbab5 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1340,7 +1340,7 @@ object Build { BuildInfoPlugin.buildInfoDefaultSettings lazy val presentationCompilerSettings = { - val mtagsVersion = "1.2.2+25-bb9dfbb9-SNAPSHOT" + val mtagsVersion = "1.2.2+44-42e0515a-SNAPSHOT" Seq( resolvers ++= Resolver.sonatypeOssRepos("snapshots"), From cb253f8d7c542e7845c99754c5c8430961643cc2 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 8 Mar 2024 17:09:36 +0100 Subject: [PATCH 190/277] Improve message when tree cannot be shown as source Closes #19905 --- .../runtime/impl/printers/SourceCode.scala | 17 +++++----- tests/run-macros/i19905.check | 3 ++ tests/run-macros/i19905/Macro_1.scala | 31 +++++++++++++++++++ tests/run-macros/i19905/Test_2.scala | 5 +++ 4 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 tests/run-macros/i19905.check create mode 100644 tests/run-macros/i19905/Macro_1.scala create mode 100644 tests/run-macros/i19905/Test_2.scala diff --git a/compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala b/compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala index b27016045051..9aec7fc17ed7 100644 --- a/compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala +++ b/compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala @@ -188,7 +188,7 @@ object SourceCode { case Select(newTree: New, _) => printType(newTree.tpe)(using Some(cdef.symbol)) case parent: Term => - throw new MatchError(parent.show(using Printer.TreeStructure)) + cannotBeShownAsSource(parent.show(using Printer.TreeStructure)) } def printSeparated(list: List[Tree /* Term | TypeTree */]): Unit = list match { @@ -536,7 +536,7 @@ object SourceCode { printCaseDef(tree) case _ => - throw new MatchError(tree.show(using Printer.TreeStructure)) + cannotBeShownAsSource(tree.show(using Printer.TreeStructure)) } @@ -934,7 +934,7 @@ object SourceCode { case Ident("unapply" | "unapplySeq") => this += fun.symbol.owner.fullName.stripSuffix("$") case _ => - throw new MatchError(fun.show(using Printer.TreeStructure)) + cannotBeShownAsSource(fun.show(using Printer.TreeStructure)) } inParens(printPatterns(patterns, ", ")) @@ -953,7 +953,7 @@ object SourceCode { printTree(v) case _ => - throw new MatchError(pattern.show(using Printer.TreeStructure)) + cannotBeShownAsSource(pattern.show(using Printer.TreeStructure)) } @@ -1079,7 +1079,7 @@ object SourceCode { printTypeTree(tpt) case _ => - throw new MatchError(tree.show(using Printer.TreeStructure)) + cannotBeShownAsSource(tree.show(using Printer.TreeStructure)) } @@ -1248,7 +1248,7 @@ object SourceCode { printType(rhs) case _ => - throw new MatchError(tpe.show(using Printer.TypeReprStructure)) + cannotBeShownAsSource(tpe.show(using Printer.TypeReprStructure)) } private def printSelector(sel: Selector): this.type = sel match { @@ -1287,7 +1287,7 @@ object SourceCode { val sym = annot.tpe.typeSymbol sym != Symbol.requiredClass("scala.forceInline") && sym.maybeOwner != Symbol.requiredPackage("scala.annotation.internal") - case x => throw new MatchError(x.show(using Printer.TreeStructure)) + case x => cannotBeShownAsSource(x.show(using Printer.TreeStructure)) } printAnnotations(annots) if (annots.nonEmpty) this += " " @@ -1458,6 +1458,9 @@ object SourceCode { } } + private def cannotBeShownAsSource(x: String): Nothing = + throw new Exception(s"$x does not have a source representation") + private object SpecialOp { def unapply(arg: Tree): Option[(String, List[Term])] = arg match { case arg @ Apply(fn, args) => diff --git a/tests/run-macros/i19905.check b/tests/run-macros/i19905.check new file mode 100644 index 000000000000..36ba7772bfdb --- /dev/null +++ b/tests/run-macros/i19905.check @@ -0,0 +1,3 @@ +java.lang.Exception: NoPrefix() does not have a source representation +java.lang.Exception: NoPrefix() does not have a source representation +NoPrefix() diff --git a/tests/run-macros/i19905/Macro_1.scala b/tests/run-macros/i19905/Macro_1.scala new file mode 100644 index 000000000000..dc2351f32864 --- /dev/null +++ b/tests/run-macros/i19905/Macro_1.scala @@ -0,0 +1,31 @@ +import scala.quoted.* + +inline def noPrefixShortCode: String = + ${ noPrefixShortCodeImpl } + +inline def noPrefixCode: String = + ${ noPrefixCodeImpl } + +inline def noPrefixStructure: String = + ${ noPrefixStructure } + +def noPrefix(using Quotes): quotes.reflect.TypeRepr = + import quotes.reflect.* + TypeRepr.of[Unit] match + case TypeRef(ThisType(TypeRef(prefix, _)), _) => prefix + +def noPrefixShortCodeImpl(using Quotes): Expr[String] = + import quotes.reflect.* + try Expr(Printer.TypeReprShortCode.show(noPrefix)) + catch case ex: Exception => + Expr(s"${ex.getClass.getName}: ${ex.getMessage}") + +def noPrefixCodeImpl(using Quotes): Expr[String] = + import quotes.reflect.* + try Expr(Printer.TypeReprCode.show(noPrefix)) + catch case ex: Exception => + Expr(s"${ex.getClass.getName}: ${ex.getMessage}") + +def noPrefixStructure(using Quotes): Expr[String] = + import quotes.reflect.* + Expr(Printer.TypeReprStructure.show(noPrefix)) diff --git a/tests/run-macros/i19905/Test_2.scala b/tests/run-macros/i19905/Test_2.scala new file mode 100644 index 000000000000..9363beb64e6d --- /dev/null +++ b/tests/run-macros/i19905/Test_2.scala @@ -0,0 +1,5 @@ +@main +def Test: Unit = + println(noPrefixShortCode) + println(noPrefixCode) + println(noPrefixStructure) From 157ed43c74c72cf31db4da3889befd891bc65041 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sat, 9 Mar 2024 18:48:10 -0500 Subject: [PATCH 191/277] Fix undercompilation upon ctor change **Problem** Scala 3 compiler registers special `zincMangledName` for constructors for the purpose of incremental compilation. Currently the `zincMangledName` contains the package name, which does not match the use site tracking, thereby causing undercompilation during incremental compilation after a ctor change, like adding a parameter. There is an existing scripted test, but coincidentally the test class does NOT include packages, so the test ends up passing. **Solution** This PR reproduces the issue by adding package name to the test. This also fixes the problem by changing the `zincMangedName` to `sym.owner.name ++ ";init;"`. --- compiler/src/dotty/tools/dotc/sbt/package.scala | 2 +- sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala | 2 +- sbt-test/source-dependencies/constructors/A.scala | 2 ++ sbt-test/source-dependencies/constructors/B.scala | 2 ++ sbt-test/source-dependencies/constructors/changes/A2.scala | 2 ++ sbt-test/source-dependencies/constructors/changes/B2.scala | 2 ++ 6 files changed, 10 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/package.scala b/compiler/src/dotty/tools/dotc/sbt/package.scala index 379a2e45ce40..7c24319005ed 100644 --- a/compiler/src/dotty/tools/dotc/sbt/package.scala +++ b/compiler/src/dotty/tools/dotc/sbt/package.scala @@ -12,7 +12,7 @@ inline val InlineParamHash = 1997 // 302nd prime extension (sym: Symbol) def constructorName(using Context) = - sym.owner.fullName ++ ";init;" + sym.owner.name ++ ";init;" /** Mangle a JVM symbol name in a format better suited for internal uses by sbt. */ def zincMangledName(using Context): Name = diff --git a/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala b/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala index 2b2b7d26c716..d6cc3ac6339d 100644 --- a/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala +++ b/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala @@ -306,7 +306,7 @@ class ExtractUsedNamesSpecification { // All classes extend Object "Object", // All classes have a default constructor called - "java.lang.Object;init;", + "Object;init;", // the return type of the default constructor is Unit "Unit" ) diff --git a/sbt-test/source-dependencies/constructors/A.scala b/sbt-test/source-dependencies/constructors/A.scala index b81025bada4d..0c5a5efa5b25 100644 --- a/sbt-test/source-dependencies/constructors/A.scala +++ b/sbt-test/source-dependencies/constructors/A.scala @@ -1 +1,3 @@ +package example + class A(a: Int) diff --git a/sbt-test/source-dependencies/constructors/B.scala b/sbt-test/source-dependencies/constructors/B.scala index e44b1d4c7852..b66f04320f13 100644 --- a/sbt-test/source-dependencies/constructors/B.scala +++ b/sbt-test/source-dependencies/constructors/B.scala @@ -1 +1,3 @@ +package example + class B { val y = new A(2) } diff --git a/sbt-test/source-dependencies/constructors/changes/A2.scala b/sbt-test/source-dependencies/constructors/changes/A2.scala index edd9e160e7bf..5f72892e6f26 100644 --- a/sbt-test/source-dependencies/constructors/changes/A2.scala +++ b/sbt-test/source-dependencies/constructors/changes/A2.scala @@ -1 +1,3 @@ +package example + class A(a: String) diff --git a/sbt-test/source-dependencies/constructors/changes/B2.scala b/sbt-test/source-dependencies/constructors/changes/B2.scala index 701f0514685f..7b1399a8ac49 100644 --- a/sbt-test/source-dependencies/constructors/changes/B2.scala +++ b/sbt-test/source-dependencies/constructors/changes/B2.scala @@ -1 +1,3 @@ +package example + class B { val y = new A("a") } From 2a97cb4b0fcc0da6491cf085171f0396a224d2ad Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 11 Mar 2024 09:23:22 +0100 Subject: [PATCH 192/277] Add regression test for #19909 Closes #19909 Probably fixed by #19645 --- tests/pos-macros/i19909/Macro_1.scala | 12 ++++++++++++ tests/pos-macros/i19909/Test_2.scala | 15 +++++++++++++++ tests/pos-macros/i19909b/Macro.scala | 12 ++++++++++++ tests/pos-macros/i19909b/Test.scala | 15 +++++++++++++++ 4 files changed, 54 insertions(+) create mode 100644 tests/pos-macros/i19909/Macro_1.scala create mode 100644 tests/pos-macros/i19909/Test_2.scala create mode 100644 tests/pos-macros/i19909b/Macro.scala create mode 100644 tests/pos-macros/i19909b/Test.scala diff --git a/tests/pos-macros/i19909/Macro_1.scala b/tests/pos-macros/i19909/Macro_1.scala new file mode 100644 index 000000000000..d7f0bedf7ed8 --- /dev/null +++ b/tests/pos-macros/i19909/Macro_1.scala @@ -0,0 +1,12 @@ +package examples.select + +import scala.language.dynamics +import scala.quoted.* + +case class Wrapper[A](inner: A) extends Dynamic: + transparent inline def selectDynamic(inline name: String) = + ${selectDynamicImpl('inner, 'name)} + +def selectDynamicImpl[A:Type](inner: Expr[A], name: Expr[String])(using quotes: Quotes): Expr[Any] = + import quotes.reflect.* + Select.unique(inner.asTerm, name.valueOrAbort).asExpr diff --git a/tests/pos-macros/i19909/Test_2.scala b/tests/pos-macros/i19909/Test_2.scala new file mode 100644 index 000000000000..8d38bd0da2cf --- /dev/null +++ b/tests/pos-macros/i19909/Test_2.scala @@ -0,0 +1,15 @@ +package examples.select + + +import scala.language.dynamics +import examples.select.Wrapper + +object Dynamic0: + + @main + def runTimeError = + + val w = Wrapper(Option(1)) + println(w.isEmpty) + +end Dynamic0 diff --git a/tests/pos-macros/i19909b/Macro.scala b/tests/pos-macros/i19909b/Macro.scala new file mode 100644 index 000000000000..d7f0bedf7ed8 --- /dev/null +++ b/tests/pos-macros/i19909b/Macro.scala @@ -0,0 +1,12 @@ +package examples.select + +import scala.language.dynamics +import scala.quoted.* + +case class Wrapper[A](inner: A) extends Dynamic: + transparent inline def selectDynamic(inline name: String) = + ${selectDynamicImpl('inner, 'name)} + +def selectDynamicImpl[A:Type](inner: Expr[A], name: Expr[String])(using quotes: Quotes): Expr[Any] = + import quotes.reflect.* + Select.unique(inner.asTerm, name.valueOrAbort).asExpr diff --git a/tests/pos-macros/i19909b/Test.scala b/tests/pos-macros/i19909b/Test.scala new file mode 100644 index 000000000000..8d38bd0da2cf --- /dev/null +++ b/tests/pos-macros/i19909b/Test.scala @@ -0,0 +1,15 @@ +package examples.select + + +import scala.language.dynamics +import examples.select.Wrapper + +object Dynamic0: + + @main + def runTimeError = + + val w = Wrapper(Option(1)) + println(w.isEmpty) + +end Dynamic0 From c26740cb0fe06d61e0e5aeeec1efca9f98d0fe67 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 11 Mar 2024 13:57:26 +0100 Subject: [PATCH 193/277] Use `concurrent.Map` in `MacroAnnotation` example This is much safer if users copy-paste the example blindly into their code. --- library/src/scala/annotation/MacroAnnotation.scala | 10 +++++----- tests/run-macros/annot-memo/Macro_1.scala | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/library/src/scala/annotation/MacroAnnotation.scala b/library/src/scala/annotation/MacroAnnotation.scala index a76289ecea61..02e9470f06fd 100644 --- a/library/src/scala/annotation/MacroAnnotation.scala +++ b/library/src/scala/annotation/MacroAnnotation.scala @@ -42,7 +42,7 @@ trait MacroAnnotation extends StaticAnnotation: * This example shows how to modify a `def` and add a `val` next to it using a macro annotation. * ```scala * import scala.quoted.* - * import scala.collection.mutable + * import scala.collection.concurrent * * class memoize extends MacroAnnotation: * def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = @@ -52,14 +52,14 @@ trait MacroAnnotation extends StaticAnnotation: * (param.tpt.tpe.asType, tpt.tpe.asType) match * case ('[t], '[u]) => * val cacheName = Symbol.freshName(name + "Cache") - * val cacheSymbol = Symbol.newVal(Symbol.spliceOwner, cacheName, TypeRepr.of[mutable.Map[t, u]], Flags.Private, Symbol.noSymbol) + * val cacheSymbol = Symbol.newVal(Symbol.spliceOwner, cacheName, TypeRepr.of[concurrent.Map[t, u]], Flags.Private, Symbol.noSymbol) * val cacheRhs = * given Quotes = cacheSymbol.asQuotes - * '{ mutable.Map.empty[t, u] }.asTerm + * '{ concurrent.TrieMap.empty[t, u] }.asTerm * val cacheVal = ValDef(cacheSymbol, Some(cacheRhs)) * val newRhs = * given Quotes = tree.symbol.asQuotes - * val cacheRefExpr = Ref(cacheSymbol).asExprOf[mutable.Map[t, u]] + * val cacheRefExpr = Ref(cacheSymbol).asExprOf[concurrent.Map[t, u]] * val paramRefExpr = Ref(param.symbol).asExprOf[t] * val rhsExpr = rhsTree.asExprOf[u] * '{ $cacheRefExpr.getOrElseUpdate($paramRefExpr, $rhsExpr) }.asTerm @@ -82,7 +82,7 @@ trait MacroAnnotation extends StaticAnnotation: * and the macro will modify the definition to create * ```scala * val fibCache$macro$1 = - * scala.collection.mutable.Map.empty[Int, Int] + * scala.collection.concurrent.TrieMap.empty[Int, Int] * def fib(n: Int): Int = * fibCache$macro$1.getOrElseUpdate( * n, diff --git a/tests/run-macros/annot-memo/Macro_1.scala b/tests/run-macros/annot-memo/Macro_1.scala index c18260cc0f95..cd990e1d6cce 100644 --- a/tests/run-macros/annot-memo/Macro_1.scala +++ b/tests/run-macros/annot-memo/Macro_1.scala @@ -2,7 +2,7 @@ import scala.annotation.{experimental, MacroAnnotation} import scala.quoted._ -import scala.collection.mutable +import scala.collection.concurrent @experimental class memoize extends MacroAnnotation: @@ -13,14 +13,14 @@ class memoize extends MacroAnnotation: (param.tpt.tpe.asType, tpt.tpe.asType) match case ('[t], '[u]) => val cacheName = Symbol.freshName(name + "Cache") - val cacheSymbol = Symbol.newVal(Symbol.spliceOwner, cacheName, TypeRepr.of[mutable.Map[t, u]], Flags.Private, Symbol.noSymbol) + val cacheSymbol = Symbol.newVal(Symbol.spliceOwner, cacheName, TypeRepr.of[concurrent.Map[t, u]], Flags.Private, Symbol.noSymbol) val cacheRhs = given Quotes = cacheSymbol.asQuotes - '{ mutable.Map.empty[t, u] }.asTerm + '{ concurrent.TrieMap.empty[t, u] }.asTerm val cacheVal = ValDef(cacheSymbol, Some(cacheRhs)) val newRhs = given Quotes = tree.symbol.asQuotes - val cacheRefExpr = Ref(cacheSymbol).asExprOf[mutable.Map[t, u]] + val cacheRefExpr = Ref(cacheSymbol).asExprOf[concurrent.Map[t, u]] val paramRefExpr = Ref(param.symbol).asExprOf[t] val rhsExpr = rhsTree.asExprOf[u] '{ $cacheRefExpr.getOrElseUpdate($paramRefExpr, $rhsExpr) }.asTerm From 799a431640086c8357ba8da122f90167020cce5b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 13:06:54 +0000 Subject: [PATCH 194/277] Bump burnett01/rsync-deployments from 6.0.0 to 7.0.0 Bumps [burnett01/rsync-deployments](https://github.com/burnett01/rsync-deployments) from 6.0.0 to 7.0.0. - [Release notes](https://github.com/burnett01/rsync-deployments/releases) - [Commits](https://github.com/burnett01/rsync-deployments/compare/6.0.0...7.0.0) --- updated-dependencies: - dependency-name: burnett01/rsync-deployments dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/spec.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/spec.yml b/.github/workflows/spec.yml index 0c09ec170986..94b99e81e044 100644 --- a/.github/workflows/spec.yml +++ b/.github/workflows/spec.yml @@ -45,7 +45,7 @@ jobs: env: USER_FOR_TEST: ${{ secrets.SPEC_DEPLOY_USER }} if: ${{ env.USER_FOR_TEST != '' }} - uses: burnett01/rsync-deployments@6.0.0 + uses: burnett01/rsync-deployments@7.0.0 with: switches: -rzv path: docs/_spec/_site/ From 5966f75e1c091026b90f0c9b0bed43895adb684d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 13:06:58 +0000 Subject: [PATCH 195/277] Bump VirtusLab/scala-cli-setup from 1.1.3 to 1.2.0 Bumps [VirtusLab/scala-cli-setup](https://github.com/virtuslab/scala-cli-setup) from 1.1.3 to 1.2.0. - [Release notes](https://github.com/virtuslab/scala-cli-setup/releases) - [Commits](https://github.com/virtuslab/scala-cli-setup/compare/v1.1.3...v1.2.0) --- updated-dependencies: - dependency-name: VirtusLab/scala-cli-setup dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/lts-backport.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lts-backport.yaml b/.github/workflows/lts-backport.yaml index 2dbfedbc447b..7e8564a634c4 100644 --- a/.github/workflows/lts-backport.yaml +++ b/.github/workflows/lts-backport.yaml @@ -15,7 +15,7 @@ jobs: with: fetch-depth: 0 - uses: coursier/cache-action@v6 - - uses: VirtusLab/scala-cli-setup@v1.1.3 + - uses: VirtusLab/scala-cli-setup@v1.2.0 - run: scala-cli ./project/scripts/addToBackportingProject.scala -- ${{ github.sha }} env: GRAPHQL_API_TOKEN: ${{ secrets.GRAPHQL_API_TOKEN }} From 11a6f0a9e853a9b0cca14bcb02d9d93f0f9ae57b Mon Sep 17 00:00:00 2001 From: 110416 Date: Mon, 11 Mar 2024 22:14:15 +0900 Subject: [PATCH 196/277] fix(#16610): warn ignored Scaladoc on multiple enum cases (#19555) close #16610 Before this commit, the compiler ignored Scaladoc comment on multiple enum cases without warning. This is partly expected because the case to which the doc is attached is ambiguous, but we should at least warn users that the comment is ignored by compiler due to ambiguity and they should take an action if they want the doc to be displayed. --- .../dotty/tools/dotc/config/ScalaSettings.scala | 1 + .../src/dotty/tools/dotc/parsing/Parsers.scala | 8 ++++++++ tests/warn/i16610.check | 5 +++++ tests/warn/i16610.scala | 16 ++++++++++++++++ 4 files changed, 30 insertions(+) create mode 100644 tests/warn/i16610.check create mode 100644 tests/warn/i16610.scala diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 07efc18a772b..1129d6bbe0e3 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -168,6 +168,7 @@ private sealed trait WarningSettings: val XfatalWarnings: Setting[Boolean] = BooleanSetting("-Werror", "Fail the compilation if there are any warnings.", aliases = List("-Xfatal-warnings")) val WvalueDiscard: Setting[Boolean] = BooleanSetting("-Wvalue-discard", "Warn when non-Unit expression results are unused.") val WNonUnitStatement = BooleanSetting("-Wnonunit-statement", "Warn when block statements are non-Unit expressions.") + val WenumCommentDiscard = BooleanSetting("-Wenum-comment-discard", "Warn when a comment ambiguously assigned to multiple enum cases is discarded.") val WimplausiblePatterns = BooleanSetting("-Wimplausible-patterns", "Warn if comparison with a pattern value looks like it might always fail.") val WunstableInlineAccessors = BooleanSetting("-WunstableInlineAccessors", "Warn an inline methods has references to non-stable binary APIs.") val Wunused: Setting[List[ChoiceWithHelp[String]]] = MultiChoiceHelpSetting( diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 6c2e69658927..4880c7704f0e 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -3997,6 +3997,14 @@ object Parsers { if (in.token == COMMA) { in.nextToken() val ids = commaSeparated(() => termIdent()) + if ctx.settings.WenumCommentDiscard.value then + in.getDocComment(start).foreach: comm => + warning( + em"""Ambiguous Scaladoc comment on multiple cases is ignored. + |Remove the comment or make separate cases to add Scaladoc comments to each of them.""", + comm.span.start + ) + PatDef(mods1, id :: ids, TypeTree(), EmptyTree) } else { diff --git a/tests/warn/i16610.check b/tests/warn/i16610.check new file mode 100644 index 000000000000..4eb69b5c551a --- /dev/null +++ b/tests/warn/i16610.check @@ -0,0 +1,5 @@ +-- Warning: tests/warn/i16610.scala:12:2 ------------------------------------------------------------------------------- +12 | /** // warn + | ^ + | Ambiguous Scaladoc comment on multiple cases is ignored. + | Remove the comment or make separate cases to add Scaladoc comments to each of them. diff --git a/tests/warn/i16610.scala b/tests/warn/i16610.scala new file mode 100644 index 000000000000..7657d23b7fd2 --- /dev/null +++ b/tests/warn/i16610.scala @@ -0,0 +1,16 @@ +//> using options -Wenum-comment-discard +/** + * Description of enum + */ +enum MyEnum { + + /** + * Description of case 1 + */ + case MyCase1 + + /** // warn + * Description of case 2 and 3 + */ + case MyCase2, MyCase3 +} \ No newline at end of file From 373e8e9788a9f11c0214cd6817966025e3a93f74 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Mon, 11 Mar 2024 14:53:02 +0100 Subject: [PATCH 197/277] fix name of Ident and Select trees for module class from java --- .../dotty/tools/dotc/core/ContextOps.scala | 5 +-- .../src/dotty/tools/dotc/typer/Typer.scala | 38 +++++++++++-------- tests/run/i17255/J.java | 37 ++++++++++++------ tests/run/i17255/Module.scala | 10 +++-- 4 files changed, 55 insertions(+), 35 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/ContextOps.scala b/compiler/src/dotty/tools/dotc/core/ContextOps.scala index 427cfa47c7c1..57c369a08de6 100644 --- a/compiler/src/dotty/tools/dotc/core/ContextOps.scala +++ b/compiler/src/dotty/tools/dotc/core/ContextOps.scala @@ -64,10 +64,7 @@ object ContextOps: val directSearch = def asModule = if name.isTypeName && name.endsWith(StdNames.str.MODULE_SUFFIX) then - pre.findMember(name.stripModuleClassSuffix.moduleClassName, pre, required, excluded) match - case NoDenotation => NoDenotation - case symDenot: SymDenotation => - symDenot.companionModule.denot + pre.findMember(name.stripModuleClassSuffix.moduleClassName, pre, required, excluded) else NoDenotation pre.findMember(name, pre, required, excluded) match case NoDenotation => asModule diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 6d537ea62c7c..5b176a7797ee 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -631,7 +631,13 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer case checkedType: NamedType if !prefixIsElidable(checkedType) => ref(checkedType).withSpan(tree.span) case _ => - tree.withType(checkedType) + def isScalaModuleRef = checkedType match + case moduleRef: TypeRef if moduleRef.symbol.is(ModuleClass, butNot = JavaDefined) => true + case _ => false + if ctx.isJava && isScalaModuleRef then + cpy.Ident(tree)(tree.name.unmangleClassName).withType(checkedType) + else + tree.withType(checkedType) val tree2 = toNotNullTermRef(tree1, pt) checkLegalValue(tree2, pt) tree2 @@ -688,11 +694,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer report.error(StableIdentPattern(tree, pt), tree.srcPos) def typedSelect(tree0: untpd.Select, pt: Type, qual: Tree)(using Context): Tree = - val selName = - if ctx.isJava && tree0.name.isTypeName && tree0.name.endsWith(StdNames.str.MODULE_SUFFIX) then - tree0.name.stripModuleClassSuffix.moduleClassName - else - tree0.name + val selName = tree0.name val tree = cpy.Select(tree0)(qual, selName) val superAccess = qual.isInstanceOf[Super] val rawType = selectionType(tree, qual) @@ -769,26 +771,30 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer def typeSelectOnTerm(using Context): Tree = val qual = typedExpr(tree.qualifier, shallowSelectionProto(tree.name, pt, this, tree.nameSpan)) - typedSelect(tree, pt, qual).withSpan(tree.span).computeNullable() - - def javaSelectOnType(qual: Tree)(using Context) = - // semantic name conversion for `O$` in java code - if !qual.symbol.is(JavaDefined) then - val tree2 = untpd.cpy.Select(tree)(qual, tree.name.unmangleClassName) - assignType(tree2, qual) + if ctx.isJava then + javaSelection(qual) else - assignType(cpy.Select(tree)(qual, tree.name), qual) + typedSelect(tree, pt, qual).withSpan(tree.span).computeNullable() + + def javaSelection(qual: Tree)(using Context) = + val tree1 = assignType(cpy.Select(tree)(qual, tree.name), qual) + tree1.tpe match + case moduleRef: TypeRef if moduleRef.symbol.is(ModuleClass, butNot = JavaDefined) => + // handle unmangling of module names (Foo$ -> Foo[ModuleClass]) + cpy.Select(tree)(qual, tree.name.unmangleClassName).withType(moduleRef) + case _ => + tree1 def tryJavaSelectOnType(using Context): Tree = tree.qualifier match { case sel @ Select(qual, name) => val qual1 = untpd.cpy.Select(sel)(qual, name.toTypeName) val qual2 = typedType(qual1, WildcardType) - javaSelectOnType(qual2) + javaSelection(qual2) case id @ Ident(name) => val qual1 = untpd.cpy.Ident(id)(name.toTypeName) val qual2 = typedType(qual1, WildcardType) - javaSelectOnType(qual2) + javaSelection(qual2) case _ => errorTree(tree, em"cannot convert to type selection") // will never be printed due to fallback diff --git a/tests/run/i17255/J.java b/tests/run/i17255/J.java index 3c6d64d75ab9..3706e53cbbc3 100644 --- a/tests/run/i17255/J.java +++ b/tests/run/i17255/J.java @@ -1,16 +1,29 @@ package p; public class J { - public static J j = new J(); - public static p.J f() { - return p.J.j; - } - public static Module$ module2() { - return p.Module$.MODULE$; - } - public static p.Module$ module() { - return p.Module$.MODULE$; - } + public static J j = new J(); - public String toString() { return "J"; } -} \ No newline at end of file + public static p.J f() { + return p.J.j; + } + + public static Module$ module2() { + return p.Module$.MODULE$; + } + + public static p.Module$ module() { + return p.Module$.MODULE$; + } + + public static Module.InnerModule$ innermodule2() { + return p.Module.InnerModule$.MODULE$; + } + + public static p.Module.InnerModule$ innermodule() { + return p.Module.InnerModule$.MODULE$; + } + + public String toString() { + return "J"; + } +} diff --git a/tests/run/i17255/Module.scala b/tests/run/i17255/Module.scala index e681264093da..936e78e8e4ce 100644 --- a/tests/run/i17255/Module.scala +++ b/tests/run/i17255/Module.scala @@ -1,8 +1,10 @@ -// scalajs: --skip - package p { object Module { override def toString = "Module" + + object InnerModule { + override def toString = "InnerModule" + } } } @@ -10,4 +12,6 @@ object Test extends App { assert(p.J.f().toString == "J") assert(p.J.module().toString == "Module") assert(p.J.module2().toString == "Module") -} \ No newline at end of file + assert(p.J.innermodule().toString == "InnerModule") + assert(p.J.innermodule2().toString == "InnerModule") +} From 24215819d4ab1e708936118b56c46bbafaba83be Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 11 Mar 2024 15:29:16 +0100 Subject: [PATCH 198/277] Revert "Followup fix to transparent inline conversion (#18130)" This reverts commit 3de184c8dde00948641b8eee8a9988afb3328ab4. --- .../dotty/tools/dotc/typer/ProtoTypes.scala | 20 +++----------- tests/neg/i9685bis.check | 9 ------- tests/neg/i9685bis.scala | 25 ----------------- tests/pos-macros/i18123.scala | 27 ------------------- 4 files changed, 3 insertions(+), 78 deletions(-) delete mode 100644 tests/neg/i9685bis.check delete mode 100644 tests/neg/i9685bis.scala delete mode 100644 tests/pos-macros/i18123.scala diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index c8012bef0904..96b0be6d9bd8 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -18,7 +18,6 @@ import ErrorReporting.* import util.SourceFile import TypeComparer.necessarySubType import dotty.tools.dotc.core.Flags.Transparent -import dotty.tools.dotc.config.{ Feature, SourceVersion } import scala.annotation.internal.sharable import dotty.tools.dotc.util.Spans.{NoSpan, Span} @@ -115,22 +114,9 @@ object ProtoTypes { * achieved by replacing expected type parameters with wildcards. */ def constrainResult(meth: Symbol, mt: Type, pt: Type)(using Context): Boolean = - if (Inlines.isInlineable(meth)) { - // Stricter behaviour in 3.4+: do not apply `wildApprox` to non-transparent inlines - if (Feature.sourceVersion.isAtLeast(SourceVersion.`3.4`)) { - if (meth.is(Transparent)) { - constrainResult(mt, wildApprox(pt)) - // do not constrain the result type of transparent inline methods - true - } else { - constrainResult(mt, pt) - } - } else { - // Best-effort to fix https://github.com/scala/scala3/issues/9685 in the 3.3.x series - // while preserving source compatibility as much as possible - val methodMatchedType = constrainResult(mt, wildApprox(pt)) - meth.is(Transparent) || methodMatchedType - } + if (Inlines.isInlineable(meth) && meth.is(Transparent)) { + constrainResult(mt, wildApprox(pt)) + true } else constrainResult(mt, pt) } diff --git a/tests/neg/i9685bis.check b/tests/neg/i9685bis.check deleted file mode 100644 index 1cc81df9987c..000000000000 --- a/tests/neg/i9685bis.check +++ /dev/null @@ -1,9 +0,0 @@ --- [E008] Not Found Error: tests/neg/i9685bis.scala:25:4 --------------------------------------------------------------- -25 | 1.asdf // error - | ^^^^^^ - | value asdf is not a member of Int, but could be made available as an extension method. - | - | The following import might make progress towards fixing the problem: - | - | import foo.Baz.toBaz - | diff --git a/tests/neg/i9685bis.scala b/tests/neg/i9685bis.scala deleted file mode 100644 index 0a3e245fe738..000000000000 --- a/tests/neg/i9685bis.scala +++ /dev/null @@ -1,25 +0,0 @@ -//> using options -source future - -package foo - -import scala.language.implicitConversions - -class Foo - -object Foo: - - inline implicit def toFoo(x: Int): Foo = Foo() - -class Bar - -object Bar: - inline given Conversion[Int, Bar] with - def apply(x: Int): Bar = Bar() - -class Baz - -object Baz: - transparent inline implicit def toBaz(x: Int): Baz = Baz() - -object Usage: - 1.asdf // error diff --git a/tests/pos-macros/i18123.scala b/tests/pos-macros/i18123.scala deleted file mode 100644 index d9127a918ee8..000000000000 --- a/tests/pos-macros/i18123.scala +++ /dev/null @@ -1,27 +0,0 @@ -// may not compile anymore in Scala 3.4+ -package pkg - -import scala.language.`3.3` - -trait P[+T] - -extension [T](inline parse0: P[T]) - inline def | [V >: T](inline other: P[V]): P[V] = ??? - -extension [T](inline parse0: => P[T]) - inline def rep[V](inline min: Int = 0)(using repeater: Implicits.Repeater[T, V]): P[V] = ??? - -object Implicits: - trait Repeater[-T, R] - object Repeater: - implicit def GenericRepeaterImplicit[T]: Repeater[T, Seq[T]] = ??? - -sealed trait RegexTree -abstract class Node extends RegexTree -class CharClassIntersection() extends Node - -def classItem: P[RegexTree] = ??? -def charClassIntersection: P[CharClassIntersection] = ??? - -def x = - (charClassIntersection.rep() | classItem.rep()) From b28d4c1cbe0a552091be7c83ea82924db636d7b2 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 11 Mar 2024 15:37:08 +0100 Subject: [PATCH 199/277] Revert "Take into account the result type of inline implicit conversions unless they are transparent" This reverts commit eb38e1f0fc38313ab17969a74664618900ace2e9. --- community-build/community-projects/munit | 2 +- community-build/community-projects/specs2 | 2 +- .../dotty/tools/dotc/typer/ProtoTypes.scala | 5 ++-- tests/neg-macros/i18174.scala | 27 ------------------- tests/neg-macros/i9685bis.check | 9 ------- tests/neg-macros/i9685bis.scala | 23 ---------------- 6 files changed, 4 insertions(+), 64 deletions(-) delete mode 100644 tests/neg-macros/i18174.scala delete mode 100644 tests/neg-macros/i9685bis.check delete mode 100644 tests/neg-macros/i9685bis.scala diff --git a/community-build/community-projects/munit b/community-build/community-projects/munit index c18fddb143b9..5c77d7316fc6 160000 --- a/community-build/community-projects/munit +++ b/community-build/community-projects/munit @@ -1 +1 @@ -Subproject commit c18fddb143b98e4c026dc118687410d52b187d88 +Subproject commit 5c77d7316fc66adaed64e9532ee0a45a668b01ec diff --git a/community-build/community-projects/specs2 b/community-build/community-projects/specs2 index ba01cca013d9..a618330aa808 160000 --- a/community-build/community-projects/specs2 +++ b/community-build/community-projects/specs2 @@ -1 +1 @@ -Subproject commit ba01cca013d9d99e390d17619664bdedd716e0d7 +Subproject commit a618330aa80833787859dae805d02e45d4304c42 diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index 96b0be6d9bd8..46c12b244fbb 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -17,7 +17,6 @@ import Inferencing.* import ErrorReporting.* import util.SourceFile import TypeComparer.necessarySubType -import dotty.tools.dotc.core.Flags.Transparent import scala.annotation.internal.sharable import dotty.tools.dotc.util.Spans.{NoSpan, Span} @@ -107,14 +106,14 @@ object ProtoTypes { if !res then ctx.typerState.constraint = savedConstraint res - /** Constrain result with special case if `meth` is a transparent inlineable method in an inlineable context. + /** Constrain result with special case if `meth` is an inlineable method in an inlineable context. * In that case, we should always succeed and not constrain type parameters in the expected type, * because the actual return type can be a subtype of the currently known return type. * However, we should constrain parameters of the declared return type. This distinction is * achieved by replacing expected type parameters with wildcards. */ def constrainResult(meth: Symbol, mt: Type, pt: Type)(using Context): Boolean = - if (Inlines.isInlineable(meth) && meth.is(Transparent)) { + if (Inlines.isInlineable(meth)) { constrainResult(mt, wildApprox(pt)) true } diff --git a/tests/neg-macros/i18174.scala b/tests/neg-macros/i18174.scala deleted file mode 100644 index 8bb5ffd51a3f..000000000000 --- a/tests/neg-macros/i18174.scala +++ /dev/null @@ -1,27 +0,0 @@ -// does not compile anymore in Scala 3.4+ -package pkg - -import scala.language.`3.4` - -trait P[+T] - -extension [T](inline parse0: P[T]) - inline def | [V >: T](inline other: P[V]): P[V] = ??? - -extension [T](inline parse0: => P[T]) - inline def rep[V](inline min: Int = 0)(using repeater: Implicits.Repeater[T, V]): P[V] = ??? - -object Implicits: - trait Repeater[-T, R] - object Repeater: - implicit def GenericRepeaterImplicit[T]: Repeater[T, Seq[T]] = ??? - -sealed trait RegexTree -abstract class Node extends RegexTree -class CharClassIntersection() extends Node - -def classItem: P[RegexTree] = ??? -def charClassIntersection: P[CharClassIntersection] = ??? - -def x = - (charClassIntersection.rep() | classItem.rep()) // error diff --git a/tests/neg-macros/i9685bis.check b/tests/neg-macros/i9685bis.check deleted file mode 100644 index 45e7f85aa30d..000000000000 --- a/tests/neg-macros/i9685bis.check +++ /dev/null @@ -1,9 +0,0 @@ --- [E008] Not Found Error: tests/neg-macros/i9685bis.scala:23:4 -------------------------------------------------------- -23 | 1.asdf // error - | ^^^^^^ - | value asdf is not a member of Int, but could be made available as an extension method. - | - | The following import might make progress towards fixing the problem: - | - | import foo.Baz.toBaz - | diff --git a/tests/neg-macros/i9685bis.scala b/tests/neg-macros/i9685bis.scala deleted file mode 100644 index 0023d4d719b4..000000000000 --- a/tests/neg-macros/i9685bis.scala +++ /dev/null @@ -1,23 +0,0 @@ -package foo - -import scala.language.implicitConversions - -class Foo - -object Foo: - - inline implicit def toFoo(x: Int): Foo = Foo() - -class Bar - -object Bar: - inline given Conversion[Int, Bar] with - def apply(x: Int): Bar = Bar() - -class Baz - -object Baz: - transparent inline implicit def toBaz(x: Int): Baz = Baz() - -object Usage: - 1.asdf // error From 5bc43d317cd571eac3b6c1a2c5ae41c1a693678f Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 11 Mar 2024 15:46:28 +0100 Subject: [PATCH 200/277] Add regression tests for #18123 --- tests/pos/i18123.scala | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tests/pos/i18123.scala diff --git a/tests/pos/i18123.scala b/tests/pos/i18123.scala new file mode 100644 index 000000000000..714850004d2c --- /dev/null +++ b/tests/pos/i18123.scala @@ -0,0 +1,25 @@ +// may not compile anymore in Scala 3.4+ +package pkg + +trait P[+T] + +extension [T](inline parse0: P[T]) + inline def | [V >: T](inline other: P[V]): P[V] = ??? + +extension [T](inline parse0: => P[T]) + inline def rep[V](inline min: Int = 0)(using repeater: Implicits.Repeater[T, V]): P[V] = ??? + +object Implicits: + trait Repeater[-T, R] + object Repeater: + implicit def GenericRepeaterImplicit[T]: Repeater[T, Seq[T]] = ??? + +sealed trait RegexTree +abstract class Node extends RegexTree +class CharClassIntersection() extends Node + +def classItem: P[RegexTree] = ??? +def charClassIntersection: P[CharClassIntersection] = ??? + +def x = + (charClassIntersection.rep() | classItem.rep()) From 0942eef54c6c2eb31118175d9777a344c79275f7 Mon Sep 17 00:00:00 2001 From: Eugene Flesselle Date: Mon, 11 Mar 2024 18:36:48 +0100 Subject: [PATCH 201/277] Cover patterns using `reflet.TypeTest` in isMatchTypeShaped --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 4 +++- tests/pos/i19692.scala | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i19692.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 47bd25e5d45e..41fc50b1ec4a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1814,7 +1814,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer // check `pat` here and throw away the result. val gadtCtx: Context = ctx.fresh.setFreshGADTBounds val pat1 = typedPattern(pat, selType)(using gadtCtx) - val Typed(_, tpt) = tpd.unbind(tpd.unsplice(pat1)): @unchecked + val tpt = tpd.unbind(tpd.unsplice(pat1)) match + case Typed(_, tpt) => tpt + case UnApply(fun, _, p1 :: _) if fun.symbol == defn.TypeTest_unapply => p1 instantiateMatchTypeProto(pat1, pt) match { case defn.MatchCase(patternTp, _) => tpt.tpe frozen_=:= patternTp case _ => false diff --git a/tests/pos/i19692.scala b/tests/pos/i19692.scala new file mode 100644 index 000000000000..7cc64e59ff07 --- /dev/null +++ b/tests/pos/i19692.scala @@ -0,0 +1,8 @@ + +trait UsingTypeTest[B](using reflect.TypeTest[Int, B]): + + type M[U <: Int] = U match + case B => String + + def m(t: Int): M[Int] = t match + case _: B => "hello" \ No newline at end of file From 3694d9540c0d36a2783da3d0a59c7456965cf7d8 Mon Sep 17 00:00:00 2001 From: Katarzyna Marek Date: Tue, 12 Mar 2024 09:49:34 +0100 Subject: [PATCH 202/277] Weekly metals backport (#19921) https://github.com/scalameta/metals/pull/6176 https://github.com/scalameta/metals/pull/6173 --- .../dotty/tools/pc/PcInlayHintsProvider.scala | 7 +- .../pc/printer/ShortenedTypePrinter.scala | 3 +- .../tools/pc/tests/hover/HoverTermSuite.scala | 16 +++ ...tionsSuite.scala => InlayHintsSuite.scala} | 126 ++++++++++++++++-- 4 files changed, 136 insertions(+), 16 deletions(-) rename presentation-compiler/test/dotty/tools/pc/tests/inlayHints/{SyntheticDecorationsSuite.scala => InlayHintsSuite.scala} (83%) diff --git a/presentation-compiler/src/main/dotty/tools/pc/PcInlayHintsProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/PcInlayHintsProvider.scala index 3a17d30bc024..9b40f1e6777a 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/PcInlayHintsProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/PcInlayHintsProvider.scala @@ -83,7 +83,7 @@ class PcInlayHintsProvider( if params.implicitParameters() => val labelParts = symbols.map(s => List(labelPart(s, s.decodedName))) val label = - if allImplicit then labelParts.separated("(", ", ", ")") + if allImplicit then labelParts.separated("(using ", ", ", ")") else labelParts.separated(", ") inlayHints.add( adjustPos(pos).toLsp, @@ -218,7 +218,10 @@ object ImplicitParameters: case Apply(fun, args) if args.exists(isSyntheticArg) && !tree.sourcePos.span.isZeroExtent => val (implicitArgs, providedArgs) = args.partition(isSyntheticArg) - val allImplicit = providedArgs.isEmpty + val allImplicit = providedArgs.isEmpty || providedArgs.forall { + case Ident(name) => name == nme.MISSING + case _ => false + } val pos = implicitArgs.head.sourcePos Some(implicitArgs.map(_.symbol), pos, allImplicit) case _ => None diff --git a/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala b/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala index ed37e133372b..a7cf1a703a1f 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala @@ -66,7 +66,8 @@ class ShortenedTypePrinter( private val foundRenames = collection.mutable.LinkedHashMap.empty[Symbol, String] - def getUsedRenames: Map[Symbol, String] = foundRenames.toMap + def getUsedRenames: Map[Symbol, String] = + foundRenames.toMap.filter { case (k, v) => k.showName != v } def getUsedRenamesInfo(using Context): List[String] = foundRenames.map { (from, to) => 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 82fd0c657e67..d1e90241e639 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala @@ -637,3 +637,19 @@ class HoverTermSuite extends BaseHoverSuite: |def test(d: S[Int], f: S[Char]): AB[Int, String] |```""".stripMargin, ) + + @Test def `import-no-rename` = + check( + """ + |import scala.collection + | + |object O { + | < 2)>> + |} + |""".stripMargin, + """ + |```scala + |val abc: scala.collection.Map[Int, Int] + |``` + |""".stripMargin + ) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/inlayHints/SyntheticDecorationsSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/inlayHints/InlayHintsSuite.scala similarity index 83% rename from presentation-compiler/test/dotty/tools/pc/tests/inlayHints/SyntheticDecorationsSuite.scala rename to presentation-compiler/test/dotty/tools/pc/tests/inlayHints/InlayHintsSuite.scala index 0e32e5cf0682..da7601e3c746 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/inlayHints/SyntheticDecorationsSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/inlayHints/InlayHintsSuite.scala @@ -19,7 +19,7 @@ class InlayHintsSuite extends BaseInlayHintsSuite { | def foo()/*: Unit<>*/ = { | implicit val imp: Int = 2 | def addOne(x: Int)(implicit one: Int)/*: Int<>*/ = x + one - | val x/*: Int<>*/ = addOne(1)/*(imp<<(3:17)>>)*/ + | val x/*: Int<>*/ = addOne(1)/*(using imp<<(3:17)>>)*/ | } |} |""".stripMargin @@ -66,7 +66,7 @@ class InlayHintsSuite extends BaseInlayHintsSuite { |object Main { | implicit val imp: Int = 2 | def addOne(x: Int)(implicit one: Int)/*: Int<>*/ = x + one - | val x/*: Int<>*/ = addOne(1)/*(imp<<(3:15)>>)*/ + | val x/*: Int<>*/ = addOne(1)/*(using imp<<(3:15)>>)*/ |} |""".stripMargin ) @@ -100,7 +100,7 @@ class InlayHintsSuite extends BaseInlayHintsSuite { |object Main { | implicit val imp: Int = 2 | def addOne(x: Int)(using one: Int)/*: Int<>*/ = x + one - | val x/*: Int<>*/ = addOne(1)/*(imp<<(3:15)>>)*/ + | val x/*: Int<>*/ = addOne(1)/*(using imp<<(3:15)>>)*/ |} |""".stripMargin ) @@ -502,7 +502,7 @@ class InlayHintsSuite extends BaseInlayHintsSuite { |} |""".stripMargin, """|object Main { - | val ordered/*: String<>*/ = /*augmentString<>(*/"acb"/*)*/.sorted/*[Char<>]*//*(Char<>)*/ + | val ordered/*: String<>*/ = /*augmentString<>(*/"acb"/*)*/.sorted/*[Char<>]*//*(using Char<>)*/ |} |""".stripMargin ) @@ -608,18 +608,18 @@ class InlayHintsSuite extends BaseInlayHintsSuite { | | /*StringTestOps<<(6:17)>>(*/"foo"/*)*/ should { | /*StringTestOps<<(6:17)>>(*/"checkThing1"/*)*/ in { - | checkThing1[String]/*(instancesString<<(10:15)>>)*/ - | }/*(here<<(5:15)>>)*/ + | checkThing1[String]/*(using instancesString<<(10:15)>>)*/ + | }/*(using here<<(5:15)>>)*/ | /*StringTestOps<<(6:17)>>(*/"checkThing2"/*)*/ in { - | checkThing2[String]/*(instancesString<<(10:15)>>, instancesString<<(10:15)>>)*/ - | }/*(here<<(5:15)>>)*/ - | }/*(subjectRegistrationFunction<<(3:15)>>)*/ + | checkThing2[String]/*(using instancesString<<(10:15)>>, instancesString<<(10:15)>>)*/ + | }/*(using here<<(5:15)>>)*/ + | }/*(using subjectRegistrationFunction<<(3:15)>>)*/ | | /*StringTestOps<<(6:17)>>(*/"bar"/*)*/ should { | /*StringTestOps<<(6:17)>>(*/"checkThing1"/*)*/ in { - | checkThing1[String]/*(instancesString<<(10:15)>>)*/ - | }/*(here<<(5:15)>>)*/ - | }/*(subjectRegistrationFunction<<(3:15)>>)*/ + | checkThing1[String]/*(using instancesString<<(10:15)>>)*/ + | }/*(using here<<(5:15)>>)*/ + | }/*(using subjectRegistrationFunction<<(3:15)>>)*/ | | def checkThing1[A](implicit ev: Eq[A])/*: Nothing<>*/ = ??? | def checkThing2[A](implicit ev: Eq[A], sem: Semigroup[A])/*: Nothing<>*/ = ??? @@ -664,4 +664,104 @@ class InlayHintsSuite extends BaseInlayHintsSuite { |case class ErrorMessage(error) |""".stripMargin ) -} \ No newline at end of file + + @Test def `anonymous-given` = + check( + """|package example + | + |trait Ord[T]: + | def compare(x: T, y: T): Int + | + |given intOrd: Ord[Int] with + | def compare(x: Int, y: Int) = + | if x < y then -1 else if x > y then +1 else 0 + | + |given Ord[String] with + | def compare(x: String, y: String) = + | x.compare(y) + | + |""".stripMargin, + """|package example + | + |trait Ord[T]: + | def compare(x: T, y: T): Int + | + |given intOrd: Ord[Int] with + | def compare(x: Int, y: Int)/*: Int<>*/ = + | if x < y then -1 else if x > y then +1 else 0 + | + |given Ord[String] with + | def compare(x: String, y: String)/*: Int<>*/ = + | /*augmentString<>(*/x/*)*/.compare(y) + | + |""".stripMargin + ) + + @Test def `context-bounds1` = + check( + """|package example + |object O { + | given Int = 1 + | def test[T: Ordering](x: T)(using Int) = ??? + | test(1) + |} + |""".stripMargin, + """|package example + |object O { + | given Int = 1 + | def test[T: Ordering](x: T)(using Int)/*: Nothing<>*/ = ??? + | test/*[Int<>]*/(1)/*(using Int<>, given_Int<<(2:8)>>)*/ + |} + |""".stripMargin + ) + + @Test def `context-bounds2` = + check( + """|package example + |object O { + | def test[T: Ordering](x: T) = ??? + | test(1) + |} + |""".stripMargin, + """|package example + |object O { + | def test[T: Ordering](x: T)/*: Nothing<>*/ = ??? + | test/*[Int<>]*/(1)/*(using Int<>)*/ + |} + |""".stripMargin + ) + + @Test def `context-bounds3` = + check( + """|package example + |object O { + | def test[T: Ordering](x: T)(using Int) = ??? + | test(1) + |} + |""".stripMargin, + """|package example + |object O { + | def test[T: Ordering](x: T)(using Int)/*: Nothing<>*/ = ??? + | test/*[Int<>]*/(1)/*(using Int<>)*/ + |} + |""".stripMargin + ) + + @Test def `context-bounds4` = + check( + """|package example + |object O { + | implicit val i: Int = 123 + | def test[T: Ordering](x: T)(implicit v: Int) = ??? + | test(1) + |} + |""".stripMargin, + """|package example + |object O { + | implicit val i: Int = 123 + | def test[T: Ordering](x: T)(implicit v: Int)/*: Nothing<>*/ = ??? + | test/*[Int<>]*/(1)/*(using Int<>, i<<(2:15)>>)*/ + |} + |""".stripMargin + ) +} From 4c0a644a6aa814544dceff6822d2f3e7be930252 Mon Sep 17 00:00:00 2001 From: Jan Chyb Date: Tue, 12 Mar 2024 15:02:25 +0100 Subject: [PATCH 203/277] Fix quotes.reflect.Ref incorrectly casting `This`` to `RefTree` --- .../quoted/runtime/impl/QuotesImpl.scala | 9 +++- tests/run-macros/i19732.check | 1 + tests/run-macros/i19732/Macro_1.scala | 42 +++++++++++++++++++ tests/run-macros/i19732/Test_2.scala | 7 ++++ 4 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 tests/run-macros/i19732.check create mode 100644 tests/run-macros/i19732/Macro_1.scala create mode 100644 tests/run-macros/i19732/Test_2.scala diff --git a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala index 04d8d7bc51a0..2569698122ff 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala @@ -466,7 +466,14 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler withDefaultPos(tpd.ref(tp).asInstanceOf[tpd.RefTree]) def apply(sym: Symbol): Ref = assert(sym.isTerm) - withDefaultPos(tpd.ref(sym).asInstanceOf[tpd.RefTree]) + val refTree = tpd.ref(sym) match + case t @ tpd.This(ident) => // not a RefTree, so we need to work around this - issue #19732 + // ident in `This` can be a TypeIdent of sym, so we manually prepare the ref here, + // knowing that the owner is actually `This`. + val term = Select(This(sym.owner), sym) + term.asInstanceOf[tpd.RefTree] + case other => other.asInstanceOf[tpd.RefTree] + withDefaultPos(refTree) end Ref type Ident = tpd.Ident diff --git a/tests/run-macros/i19732.check b/tests/run-macros/i19732.check new file mode 100644 index 000000000000..a5a57e7eb466 --- /dev/null +++ b/tests/run-macros/i19732.check @@ -0,0 +1 @@ +Map(b -> 23) diff --git a/tests/run-macros/i19732/Macro_1.scala b/tests/run-macros/i19732/Macro_1.scala new file mode 100644 index 000000000000..31564fdcf77f --- /dev/null +++ b/tests/run-macros/i19732/Macro_1.scala @@ -0,0 +1,42 @@ +// package dummy + +import scala.quoted.* + +trait Defaults[A]: + def defaults: Map[String, Any] + +object Defaults: + inline def derived[A <: Product]: Defaults[A] = ${ defaultsImpl[A] } + + def defaultsImpl[A <: Product: Type](using Quotes): Expr[Defaults[A]] = + '{ + new Defaults[A]: + def defaults: Map[String, Any] = ${ defaultParmasImpl[A] } + } + +def defaultParmasImpl[T](using quotes: Quotes, tpe: Type[T]): Expr[Map[String, Any]] = + import quotes.reflect.* + + TypeRepr.of[T].classSymbol match + case None => '{ Map.empty[String, Any] } + case Some(sym) => + val comp = sym.companionClass + val mod = Ref(sym.companionModule) + val names = + for p <- sym.caseFields if p.flags.is(Flags.HasDefault) + yield p.name + val namesExpr: Expr[List[String]] = + Expr.ofList(names.map(Expr(_))) + + val body = comp.tree.asInstanceOf[ClassDef].body + val idents: List[Ref] = + for + case deff @ DefDef(name, _, _, _) <- body + if name.startsWith("$lessinit$greater$default") + yield mod.select(deff.symbol) + val typeArgs = TypeRepr.of[T].typeArgs + val identsExpr: Expr[List[Any]] = + if typeArgs.isEmpty then Expr.ofList(idents.map(_.asExpr)) + else Expr.ofList(idents.map(_.appliedToTypes(typeArgs).asExpr)) + + '{ $namesExpr.zip($identsExpr).toMap } diff --git a/tests/run-macros/i19732/Test_2.scala b/tests/run-macros/i19732/Test_2.scala new file mode 100644 index 000000000000..04efd3a6015b --- /dev/null +++ b/tests/run-macros/i19732/Test_2.scala @@ -0,0 +1,7 @@ +class Outer: + case class Inner(a: String, b: Int = 23) derives Defaults + +object Test: + def main(args: Array[String]): Unit = + val outer = Outer() + println(summon[Defaults[outer.Inner]].defaults) From 1efe9efe7bc4ba34083f42fc21c8871e21861dd2 Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Mon, 4 Mar 2024 16:31:13 +0100 Subject: [PATCH 204/277] Add check for parents in Quotes (#i19842) --- .../tools/dotc/transform/TreeChecker.scala | 20 +++++++----- .../quoted/runtime/impl/QuotesImpl.scala | 2 ++ .../{i19842.check => i19842-a.check} | 26 +++++----------- .../{i19842 => i19842-a}/Macro.scala | 1 - .../{i19842 => i19842-a}/Test.scala | 0 tests/neg-macros/i19842-b.check | 22 +++++++++++++ tests/neg-macros/i19842-b/Macro.scala | 31 +++++++++++++++++++ tests/neg-macros/i19842-b/Test.scala | 9 ++++++ 8 files changed, 84 insertions(+), 27 deletions(-) rename tests/neg-macros/{i19842.check => i19842-a.check} (53%) rename tests/neg-macros/{i19842 => i19842-a}/Macro.scala (86%) rename tests/neg-macros/{i19842 => i19842-a}/Test.scala (100%) create mode 100644 tests/neg-macros/i19842-b.check create mode 100644 tests/neg-macros/i19842-b/Macro.scala create mode 100644 tests/neg-macros/i19842-b/Test.scala diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index d0736564957b..4a7548f40f43 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -198,6 +198,17 @@ object TreeChecker { } }.apply(tp0) + def checkParents(sym: ClassSymbol, parents: List[tpd.Tree])(using Context): Unit = + val symbolParents = sym.classInfo.parents.map(_.dealias.typeSymbol) + val treeParents = parents.map(_.tpe.dealias.typeSymbol) + assert(symbolParents == treeParents, + i"""Parents of class symbol differs from the parents in the tree for $sym + | + |Parents in symbol: $symbolParents + |Parents in tree: $treeParents + |""".stripMargin) + end checkParents + /** Run some additional checks on the nodes of the trees. Specifically: * * - TypeTree can only appear in TypeApply args, New, Typed tpt, Closure @@ -570,14 +581,7 @@ object TreeChecker { assert(ctx.owner.isClass) val sym = ctx.owner.asClass if !sym.isPrimitiveValueClass then - val symbolParents = sym.classInfo.parents.map(_.dealias.typeSymbol) - val treeParents = impl.parents.map(_.tpe.dealias.typeSymbol) - assert(symbolParents == treeParents, - i"""Parents of class symbol differs from the parents in the tree for $sym - | - |Parents in symbol: $symbolParents - |Parents in tree: $treeParents - |""".stripMargin) + TreeChecker.checkParents(sym, impl.parents) } override def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(using Context): Tree = { diff --git a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala index c802d2a9201d..6dfa00dde59f 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala @@ -24,6 +24,7 @@ import scala.quoted.runtime.impl.printers.* import scala.reflect.TypeTest import dotty.tools.dotc.core.NameKinds.ExceptionBinderName +import dotty.tools.dotc.transform.TreeChecker object QuotesImpl { @@ -253,6 +254,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler (cdef.name.toString, cdef.constructor, cdef.parents, cdef.self, rhs.body) def module(module: Symbol, parents: List[Tree /* Term | TypeTree */], body: List[Statement]): (ValDef, ClassDef) = { + if xCheckMacro then TreeChecker.checkParents(module.moduleClass.asClass, parents) val cls = module.moduleClass val clsDef = ClassDef(cls, parents, body) val newCls = Apply(Select(New(TypeIdent(cls)), cls.primaryConstructor), Nil) diff --git a/tests/neg-macros/i19842.check b/tests/neg-macros/i19842-a.check similarity index 53% rename from tests/neg-macros/i19842.check rename to tests/neg-macros/i19842-a.check index b22efc51a94a..af5dbc604f93 100644 --- a/tests/neg-macros/i19842.check +++ b/tests/neg-macros/i19842-a.check @@ -1,28 +1,18 @@ --- Error: tests/neg-macros/i19842/Test.scala:9:50 ---------------------------------------------------------------------- +-- Error: tests/neg-macros/i19842-a/Test.scala:9:50 -------------------------------------------------------------------- 9 |@main def Test = summon[Serializer[ValidationCls]] // error | ^ - |Malformed tree was found while expanding macro with -Xcheck-macros. - |The tree does not conform to the compiler's tree invariants. - | - |Macro was: - |scala.quoted.runtime.Expr.splice[Serializer[ValidationCls]](((contextual$2: scala.quoted.Quotes) ?=> Macros.makeSerializer[ValidationCls](scala.quoted.Type.of[ValidationCls](contextual$2), contextual$2))) - | - |The macro returned: - |{ - | object objectSerializer$macro$1 extends Serializer[ValidationCls] { this: objectSerializer$macro$1.type => - | - | } - | objectSerializer$macro$1 - |} - | - |Error: - |assertion failed: Parents of class symbol differs from the parents in the tree for object objectSerializer$macro$1 + |Exception occurred while executing macro expansion. + |java.lang.AssertionError: assertion failed: Parents of class symbol differs from the parents in the tree for object objectSerializer$macro$1 | |Parents in symbol: [class Object, trait Serializer] |Parents in tree: [trait Serializer] | + | at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8) + | at dotty.tools.dotc.transform.TreeChecker$.checkParents(TreeChecker.scala:209) + | at scala.quoted.runtime.impl.QuotesImpl$reflect$ClassDef$.module(QuotesImpl.scala:257) + | at scala.quoted.runtime.impl.QuotesImpl$reflect$ClassDef$.module(QuotesImpl.scala:256) + | at Macros$.makeSerializer(Macro.scala:25) | - |stacktrace available when compiling with `-Ydebug` |--------------------------------------------------------------------------------------------------------------------- |Inline stack trace |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/neg-macros/i19842/Macro.scala b/tests/neg-macros/i19842-a/Macro.scala similarity index 86% rename from tests/neg-macros/i19842/Macro.scala rename to tests/neg-macros/i19842-a/Macro.scala index 78b1f576f1b4..936e08b02592 100644 --- a/tests/neg-macros/i19842/Macro.scala +++ b/tests/neg-macros/i19842-a/Macro.scala @@ -16,7 +16,6 @@ object Macros { name, Flags.Implicit, Flags.EmptyFlags, - // Without TypeRep.of[Object] it would fail with java.lang.AssertionError: assertion failed: First parent must be a class List(TypeRepr.of[Object], TypeRepr.of[Serializer[T]]), _ => Nil, Symbol.noSymbol diff --git a/tests/neg-macros/i19842/Test.scala b/tests/neg-macros/i19842-a/Test.scala similarity index 100% rename from tests/neg-macros/i19842/Test.scala rename to tests/neg-macros/i19842-a/Test.scala diff --git a/tests/neg-macros/i19842-b.check b/tests/neg-macros/i19842-b.check new file mode 100644 index 000000000000..95a71fb9f98d --- /dev/null +++ b/tests/neg-macros/i19842-b.check @@ -0,0 +1,22 @@ +-- Error: tests/neg-macros/i19842-b/Test.scala:9:50 -------------------------------------------------------------------- +9 |@main def Test = summon[Serializer[ValidationCls]] // error + | ^ + |Exception occurred while executing macro expansion. + |java.lang.AssertionError: assertion failed: Parents of class symbol differs from the parents in the tree for object objectSerializer$macro$1 + | + |Parents in symbol: [class Object, trait Serializer] + |Parents in tree: [class Object, trait Serializer, trait Foo] + | + | at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8) + | at dotty.tools.dotc.transform.TreeChecker$.checkParents(TreeChecker.scala:209) + | at scala.quoted.runtime.impl.QuotesImpl$reflect$ClassDef$.module(QuotesImpl.scala:257) + | at scala.quoted.runtime.impl.QuotesImpl$reflect$ClassDef$.module(QuotesImpl.scala:256) + | at Macros$.makeSerializer(Macro.scala:27) + | + |--------------------------------------------------------------------------------------------------------------------- + |Inline stack trace + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + |This location contains code that was inlined from Test.scala:5 +5 | implicit inline def implicitMakeSerializer[T]: Serializer[T] = ${ Macros.makeSerializer[T] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --------------------------------------------------------------------------------------------------------------------- diff --git a/tests/neg-macros/i19842-b/Macro.scala b/tests/neg-macros/i19842-b/Macro.scala new file mode 100644 index 000000000000..d46ff758342b --- /dev/null +++ b/tests/neg-macros/i19842-b/Macro.scala @@ -0,0 +1,31 @@ +//> using options -experimental -Yno-experimental + +import scala.annotation.{experimental, targetName} +import scala.quoted.* +import scala.util.Try + +trait Foo + +object Macros { + def makeSerializer[T: Type](using Quotes): Expr[Serializer[T]] = { + import quotes.reflect.* + + val tpe: TypeRepr = TypeRepr.of[T] + val name: String = Symbol.freshName("objectSerializer") + + val modSym: Symbol = Symbol.newModule( + Symbol.spliceOwner, + name, + Flags.Implicit, + Flags.EmptyFlags, + List(TypeRepr.of[Object], TypeRepr.of[Serializer[T]]), + _ => Nil, + Symbol.noSymbol + ) + + val (modValDef: ValDef, modClassDef: ClassDef) = + ClassDef.module(modSym, List(TypeTree.of[Object], TypeTree.of[Serializer[T]], TypeTree.of[Foo]), Nil) + + Block(List(modValDef, modClassDef), Ref(modSym)).asExprOf[Serializer[T]] + } +} \ No newline at end of file diff --git a/tests/neg-macros/i19842-b/Test.scala b/tests/neg-macros/i19842-b/Test.scala new file mode 100644 index 000000000000..ba1611d97696 --- /dev/null +++ b/tests/neg-macros/i19842-b/Test.scala @@ -0,0 +1,9 @@ + +trait Serializer[@specialized T] + +object Serializer: + implicit inline def implicitMakeSerializer[T]: Serializer[T] = ${ Macros.makeSerializer[T] } + +case class ValidationCls(string: String) + +@main def Test = summon[Serializer[ValidationCls]] // error \ No newline at end of file From 46bfe909afd0a0607ce327063b5332d788d809e9 Mon Sep 17 00:00:00 2001 From: odersky Date: Tue, 12 Mar 2024 22:11:44 +0100 Subject: [PATCH 205/277] Don't allow implicit conversions on prefixes of type selections Fixes #19888 --- .../src/dotty/tools/dotc/typer/Typer.scala | 6 ++-- tests/neg/i11994.check | 34 ++++++------------- tests/neg/i19888.scala | 16 +++++++++ 3 files changed, 30 insertions(+), 26 deletions(-) create mode 100644 tests/neg/i19888.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 47bd25e5d45e..549ebcdc49a1 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -714,9 +714,11 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer val elems = qual.tpe.widenTermRefExpr.tupleElementTypes.getOrElse(Nil) typedSelect(tree, pt, qual.cast(defn.tupleType(elems))) else - val tree1 = tryExtensionOrConversion( + val tree1 = { + if selName.isTypeName then EmptyTree + else tryExtensionOrConversion( tree, pt, IgnoredProto(pt), qual, ctx.typerState.ownedVars, this, inSelect = true) - .orElse { + }.orElse { if ctx.gadt.isNarrowing then // try GADT approximation if we're trying to select a member // Member lookup cannot take GADTs into account b/c of cache, so we diff --git a/tests/neg/i11994.check b/tests/neg/i11994.check index 76860af70a39..8895515898c2 100644 --- a/tests/neg/i11994.check +++ b/tests/neg/i11994.check @@ -1,26 +1,12 @@ --- [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 - | - | The error occurred while trying to compute the signature of method foo - | which required to compute the signature of type T - | which required to compute the signature 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 ----------------------------------------------------------------- +-- [E046] Cyclic 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 compute the signature of given instance given_Unit + | which required to compute the signature of type T + | which required to compute the signature of given instance given_Unit + | + | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. | - | Cyclic reference involving method given_Unit - | - | The error occurred while trying to compute the signature of given instance given_Unit - | which required to compute the signature of type T - | which required to compute the signature of given instance given_Unit - | - | 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/i19888.scala b/tests/neg/i19888.scala new file mode 100644 index 000000000000..d258672feed6 --- /dev/null +++ b/tests/neg/i19888.scala @@ -0,0 +1,16 @@ +object Main{ + object Foo + object Bar{ type Qux = Unit } + + + implicit def conv(f: Foo.type): Bar.type = Bar + + def B: Bar.type = Bar + + def main(args: Array[String]): Unit = { + val x: Foo.Qux = null // error + val y: B.Qux = null + println(x) + println(y) + } +} \ No newline at end of file From 779886261af52416a673641e27830576bb9c404d Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 12 Mar 2024 11:30:39 +0100 Subject: [PATCH 206/277] Load but not enter case accessors fields in Scala2Unpickler Fixes #19421 --- .../tools/dotc/core/unpickleScala2/Scala2Unpickler.scala | 7 ++++--- sbt-test/scala2-compat/i19421/S3SnapshotStoreSpec.scala | 8 ++++++++ sbt-test/scala2-compat/i19421/build.sbt | 5 +++++ sbt-test/scala2-compat/i19421/test | 3 +++ 4 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 sbt-test/scala2-compat/i19421/S3SnapshotStoreSpec.scala create mode 100644 sbt-test/scala2-compat/i19421/build.sbt create mode 100644 sbt-test/scala2-compat/i19421/test diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 521306eb73fc..611fda9c1d41 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -445,8 +445,6 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas // Scala 2 sometimes pickle the same type parameter symbol multiple times // (see i11173 for an example), but we should only unpickle it once. || tag == TYPEsym && flags.is(TypeParam) && symScope(owner).lookup(name.asTypeName).exists - // We discard the private val representing a case accessor. We only load the case accessor def. - || flags.isAllOf(CaseAccessor| PrivateLocal, butNot = Method) then // skip this member return NoSymbol @@ -534,7 +532,10 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas // parameter unpickling and try to emulate it. !completer.areParamsInitialized case _ => - true) + true) && + // We discard the private val representing a case accessor. We only enter the case accessor def. + // We do need to load these symbols to read properly unpickle the annotations on the symbol (see sbt-test/scala2-compat/i19421). + !flags.isAllOf(CaseAccessor | PrivateLocal, butNot = Method) if (canEnter) owner.asClass.enter(sym, symScope(owner)) diff --git a/sbt-test/scala2-compat/i19421/S3SnapshotStoreSpec.scala b/sbt-test/scala2-compat/i19421/S3SnapshotStoreSpec.scala new file mode 100644 index 000000000000..9dce07d206fc --- /dev/null +++ b/sbt-test/scala2-compat/i19421/S3SnapshotStoreSpec.scala @@ -0,0 +1,8 @@ +import com.typesafe.config.Config +import akka.persistence.snapshot.SnapshotStoreSpec + +object ConfigHelper { + def config(): Config = ??? +} + +class S3SnapshotStoreSpec extends SnapshotStoreSpec(null) diff --git a/sbt-test/scala2-compat/i19421/build.sbt b/sbt-test/scala2-compat/i19421/build.sbt new file mode 100644 index 000000000000..fa553d80d273 --- /dev/null +++ b/sbt-test/scala2-compat/i19421/build.sbt @@ -0,0 +1,5 @@ +scalaVersion := sys.props("plugin.scalaVersion") + +libraryDependencies ++= Seq( + "com.typesafe.akka" %% "akka-persistence-tck" % "2.8.0" +).map(_.cross(CrossVersion.for3Use2_13)) diff --git a/sbt-test/scala2-compat/i19421/test b/sbt-test/scala2-compat/i19421/test new file mode 100644 index 000000000000..fb936bd5ecaf --- /dev/null +++ b/sbt-test/scala2-compat/i19421/test @@ -0,0 +1,3 @@ +> compile +> clean +> compile From 89201623875bc363cf7bec2a745649df1d9c8168 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Mon, 11 Mar 2024 16:57:31 +0100 Subject: [PATCH 207/277] Test -print-tasty output of Java sources --- .../tools/dotc/config/ScalaSettings.scala | 1 + .../dotc/core/tasty/TastyAnsiiPrinter.scala | 5 +- .../tools/dotc/core/tasty/TastyPrinter.scala | 26 ++- .../tools/dotc/printing/RefinedPrinter.scala | 5 +- .../dotty/tools/dotc/transform/Pickler.scala | 37 +++- tests/pos/i19806/J.tastycheck | 161 ++++++++++++++++++ tests/pos/i19806/J_SCALA_ONLY.java | 22 +++ tests/pos/i19806/Module.scala | 9 + tests/run/i17255/Module.scala | 1 + 9 files changed, 256 insertions(+), 11 deletions(-) create mode 100644 tests/pos/i19806/J.tastycheck create mode 100644 tests/pos/i19806/J_SCALA_ONLY.java create mode 100644 tests/pos/i19806/Module.scala diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 3dafedd8e2e0..0cb508ce1272 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -388,6 +388,7 @@ private sealed trait YSettings: val YshowPrintErrors: Setting[Boolean] = BooleanSetting("-Yshow-print-errors", "Don't suppress exceptions thrown during tree printing.") val YprintTasty: Setting[Boolean] = BooleanSetting("-Yprint-tasty", "Prints the generated TASTY to stdout.") val YtestPickler: Setting[Boolean] = BooleanSetting("-Ytest-pickler", "Self-test for pickling functionality; should be used with -Ystop-after:pickler.") + val YtestPicklerCheck: Setting[Boolean] = BooleanSetting("-Ytest-pickler-check", "Self-test for pickling -print-tasty output; should be used with -Ytest-pickler.") val YcheckReentrant: Setting[Boolean] = BooleanSetting("-Ycheck-reentrant", "Check that compiled program does not contain vars that can be accessed from a global root.") val YdropComments: Setting[Boolean] = BooleanSetting("-Ydrop-docs", "Drop documentation when scanning source files.", aliases = List("-Ydrop-comments")) val YcookComments: Setting[Boolean] = BooleanSetting("-Ycook-docs", "Cook the documentation (type check `@usecase`, etc.)", aliases = List("-Ycook-comments")) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyAnsiiPrinter.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyAnsiiPrinter.scala index d8d72a4e651e..a3d8cedacb4a 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyAnsiiPrinter.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyAnsiiPrinter.scala @@ -2,7 +2,10 @@ package dotty.tools.dotc package core package tasty -class TastyAnsiiPrinter(bytes: Array[Byte]) extends TastyPrinter(bytes) { +class TastyAnsiiPrinter(bytes: Array[Byte], testPickler: Boolean) extends TastyPrinter(bytes, testPickler) { + + def this(bytes: Array[Byte]) = this(bytes, testPickler = false) + override protected def nameStr(str: String): String = Console.MAGENTA + str + Console.RESET override protected def treeStr(str: String): String = Console.YELLOW + str + Console.RESET override protected def lengthStr(str: String): String = Console.CYAN + str + Console.RESET diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala index a74607dbc9d5..a4818e8d6fd5 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala @@ -20,9 +20,12 @@ import dotty.tools.tasty.TastyBuffer.Addr object TastyPrinter: def showContents(bytes: Array[Byte], noColor: Boolean): String = + showContents(bytes, noColor, testPickler = false) + + def showContents(bytes: Array[Byte], noColor: Boolean, testPickler: Boolean = false): String = val printer = - if noColor then new TastyPrinter(bytes) - else new TastyAnsiiPrinter(bytes) + if noColor then new TastyPrinter(bytes, testPickler) + else new TastyAnsiiPrinter(bytes, testPickler) printer.showContents() def main(args: Array[String]): Unit = { @@ -62,7 +65,9 @@ object TastyPrinter: println(line) } -class TastyPrinter(bytes: Array[Byte]) { +class TastyPrinter(bytes: Array[Byte], val testPickler: Boolean) { + + def this(bytes: Array[Byte]) = this(bytes, testPickler = false) class TastyPrinterUnpickler extends TastyUnpickler(bytes) { var namesStart: Addr = uninitialized @@ -84,9 +89,16 @@ class TastyPrinter(bytes: Array[Byte]) { private def printHeader(sb: StringBuilder): Unit = val header = unpickler.header sb.append("Header:\n") - sb.append(s" version: ${header.majorVersion}.${header.minorVersion}.${header.experimentalVersion}\n") - sb.append(" tooling: ").append(header.toolingVersion).append("\n") - sb.append(" UUID: ").append(header.uuid).append("\n") + if testPickler then + // these fields are not stable when the TASTy/compiler versions change, so not useful for testing + sb.append(" version: \n") + sb.append(" tooling: \n") + sb.append(" UUID: \n") + else + sb.append(s" version: ${header.majorVersion}.${header.minorVersion}.${header.experimentalVersion}\n") + sb.append(" tooling: ").append(header.toolingVersion).append("\n") + sb.append(" UUID: ").append(header.uuid).append("\n") + end if sb.append("\n") private def printNames(sb: StringBuilder): Unit = @@ -230,6 +242,8 @@ class TastyPrinter(bytes: Array[Byte]) { import reader.* sb.append(s"\n\nAttributes (${reader.endAddr.index - reader.startAddr.index} bytes, starting from $base):\n") while !isAtEnd do + // TODO: Should we elide attributes under testPickler? (i.e. + // if we add new attributes many check files will need to be updated) val tag = readByte() sb.append(" ").append(attributeTagToString(tag)) if isBooleanAttrTag(tag) then () diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 893b34f48396..93e280f8a13c 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -1010,7 +1010,10 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { var modsText = modText(constr.mods, constr.symbol, "", isType = false) if (!modsText.isEmpty) modsText = " " ~ modsText if (constr.mods.hasAnnotations && !constr.mods.hasFlags) modsText = modsText ~~ " this" - withEnclosingDef(constr) { addParamssText(tparamsTxt ~~ modsText, constr.trailingParamss) } + val ctorParamss = + // for fake `(x$1: Unit): Foo` constructor, don't print the param (span is not reconstructed correctly) + if constr.symbol.isAllOf(JavaParsers.fakeFlags) then Nil else constr.trailingParamss + withEnclosingDef(constr) { addParamssText(tparamsTxt ~~ modsText, ctorParamss) } } val parentsText = Text(impl.parents.map(constrText), if (ofNew) keywordStr(" with ") else ", ") val derivedText = Text(impl.derived.map(toText(_)), ", ") diff --git a/compiler/src/dotty/tools/dotc/transform/Pickler.scala b/compiler/src/dotty/tools/dotc/transform/Pickler.scala index 27b5d53e25dc..0ce3be9c1c4e 100644 --- a/compiler/src/dotty/tools/dotc/transform/Pickler.scala +++ b/compiler/src/dotty/tools/dotc/transform/Pickler.scala @@ -69,6 +69,7 @@ class Pickler extends Phase { // Maps that keep a record if -Ytest-pickler is set. private val beforePickling = new mutable.HashMap[ClassSymbol, String] + private val printedTasty = new mutable.HashMap[ClassSymbol, String] private val pickledBytes = new mutable.HashMap[ClassSymbol, (CompilationUnit, Array[Byte])] /** Drop any elements of this list that are linked module classes of other elements in the list */ @@ -184,7 +185,10 @@ class Pickler extends Phase { else val pickled = computePickled() reportPositionWarnings() - if ctx.settings.YtestPickler.value then pickledBytes(cls) = (unit, pickled) + if ctx.settings.YtestPickler.value then + pickledBytes(cls) = (unit, pickled) + if ctx.settings.YtestPicklerCheck.value then + printedTasty(cls) = TastyPrinter.showContents(pickled, noColor = true, testPickler = true) () => pickled unit.pickled += (cls -> demandPickled) @@ -251,15 +255,22 @@ class Pickler extends Phase { private def testUnpickler(using Context): Unit = pickling.println(i"testing unpickler at run ${ctx.runId}") ctx.initialize() + val resolveCheck = ctx.settings.YtestPicklerCheck.value val unpicklers = for ((cls, (unit, bytes)) <- pickledBytes) yield { val unpickler = new DottyUnpickler(unit.source.file, bytes) unpickler.enter(roots = Set.empty) - cls -> (unit, unpickler) + val optCheck = + if resolveCheck then + val resolved = unit.source.file.resolveSibling(s"${cls.name.mangledString}.tastycheck") + if resolved == null then None + else Some(resolved) + else None + cls -> (unit, unpickler, optCheck) } pickling.println("************* entered toplevel ***********") val rootCtx = ctx - for ((cls, (unit, unpickler)) <- unpicklers) do + for ((cls, (unit, unpickler, optCheck)) <- unpicklers) do val testJava = unit.typedAsJava if testJava then if unpickler.unpickler.nameAtRef.contents.exists(_ == nme.FromJavaObject) then @@ -268,6 +279,15 @@ class Pickler extends Phase { val freshUnit = CompilationUnit(rootCtx.compilationUnit.source) freshUnit.needsCaptureChecking = unit.needsCaptureChecking freshUnit.knowsPureFuns = unit.knowsPureFuns + optCheck match + case Some(check) => + import java.nio.charset.StandardCharsets.UTF_8 + val checkContents = String(check.toByteArray, UTF_8) + inContext(rootCtx.fresh.setCompilationUnit(freshUnit)): + testSamePrinted(printedTasty(cls), checkContents, cls, check) + case None => + () + inContext(printerContext(testJava)(using rootCtx.fresh.setCompilationUnit(freshUnit))): testSame(i"$unpickled%\n%", beforePickling(cls), cls) @@ -283,4 +303,15 @@ class Pickler extends Phase { | | diff before-pickling.txt after-pickling.txt""") end testSame + + private def testSamePrinted(printed: String, checkContents: String, cls: ClassSymbol, check: AbstractFile)(using Context) = + import java.nio.charset.StandardCharsets.UTF_8 + def normal(s: String) = new String(s.getBytes(UTF_8), UTF_8) + val unequal = printed.length() != checkContents.length() || normal(printed) != normal(checkContents) + if unequal then + output("after-printing.txt", printed) + report.error(em"""TASTy printer difference for $cls in ${cls.source}, for details: + | + | diff ${check.toString} after-printing.txt""") + end testSamePrinted } diff --git a/tests/pos/i19806/J.tastycheck b/tests/pos/i19806/J.tastycheck new file mode 100644 index 000000000000..900530e80965 --- /dev/null +++ b/tests/pos/i19806/J.tastycheck @@ -0,0 +1,161 @@ +Header: + version: + tooling: + UUID: + +Names (217 bytes, starting from 80): + 0: ASTs + 1: p + 2: J + 3: J[ModuleClass] + 4: Object + 5: java + 6: lang + 7: java[Qualified . lang] + 8: _ + 9: + 10: Unit + 11: scala + 12: module2 + 13: Module + 14: Module[ModuleClass] + 15: module + 16: innermodule2 + 17: InnerModule + 18: InnerModule[ModuleClass] + 19: innermodule + 20: T + 21: Nothing + 22: Positions + 23: tests/pos/i19806/J_SCALA_ONLY.java + 24: Comments + 25: Attributes + + +Trees (145 bytes, starting from 300): + 0: PACKAGE(142) + 3: TERMREFpkg 1 [p] + 5: VALDEF(11) 2 [J] + 8: IDENTtpt 3 [J[ModuleClass]] + 10: TYPEREFsymbol 18 + 12: TERMREFpkg 1 [p] + 14: ELIDED + 15: SHAREDtype 10 + 17: OBJECT + 18: TYPEDEF(86) 3 [J[ModuleClass]] + 21: TEMPLATE(82) + 23: TYPEREF 4 [Object] + 25: TERMREFpkg 7 [java[Qualified . lang]] + 27: SELFDEF 8 [_] + 29: SINGLETONtpt + 30: TERMREFsymbol 5 + 32: SHAREDtype 12 + 34: DEFDEF(7) 9 [] + 37: EMPTYCLAUSE + 38: TYPEREF 10 [Unit] + 40: TERMREFpkg 11 [scala] + 42: STABLE + 43: DEFDEF(12) 12 [module2] + 46: EMPTYCLAUSE + 47: IDENTtpt 14 [Module[ModuleClass]] + 49: TYPEREF 14 [Module[ModuleClass]] + 51: SHAREDtype 12 + 53: ELIDED + 54: SHAREDtype 49 + 56: STATIC + 57: DEFDEF(12) 15 [module] + 60: EMPTYCLAUSE + 61: SELECTtpt 14 [Module[ModuleClass]] + 63: SHAREDtype 3 + 65: ELIDED + 66: TYPEREF 14 [Module[ModuleClass]] + 68: SHAREDtype 3 + 70: STATIC + 71: DEFDEF(14) 16 [innermodule2] + 74: EMPTYCLAUSE + 75: SELECTtpt 18 [InnerModule[ModuleClass]] + 77: TERMREF 13 [Module] + 79: SHAREDtype 12 + 81: ELIDED + 82: TYPEREF 18 [InnerModule[ModuleClass]] + 84: SHAREDtype 77 + 86: STATIC + 87: DEFDEF(16) 19 [innermodule] + 90: EMPTYCLAUSE + 91: SELECTtpt 18 [InnerModule[ModuleClass]] + 93: SELECT 13 [Module] + 95: SHAREDtype 3 + 97: ELIDED + 98: TYPEREF 18 [InnerModule[ModuleClass]] + 100: TERMREF 13 [Module] + 102: SHAREDtype 3 + 104: STATIC + 105: OBJECT + 106: TYPEDEF(37) 2 [J] + 109: TEMPLATE(34) + 111: TYPEPARAM(11) 20 [T] + 114: TYPEBOUNDS(6) + 116: TYPEREF 21 [Nothing] + 118: SHAREDtype 40 + 120: SHAREDtype 23 + 122: PRIVATE + 123: LOCAL + 124: SHAREDtype 120 + 126: SPLITCLAUSE + 127: DEFDEF(16) 9 [] + 130: TYPEPARAM(7) 20 [T] + 133: TYPEBOUNDStpt(4) + 135: SHAREDtype 116 + 137: SHAREDtype 120 + 139: EMPTYCLAUSE + 140: SHAREDtype 38 + 142: ELIDED + 143: SHAREDtype 38 + 145: + +Positions (145 bytes, starting from 448): + lines: 23 + line sizes: + 10, 0, 19, 0, 15, 0, 35, 29, 3, 0, 36, 29, 3, 0, 52, 41, 3, 0, 53, 41 + 3, 1, 0 + positions: + 0: 0 .. 394 + 5: 12 .. 12 + 8: 12 .. 12 + 18: 12 .. 394 + 21: 52 .. 392 + 23: 25 .. 25 + 30: 52 .. 52 + 34: 52 .. 52 + 38: 52 .. 52 + 43: 52 .. 119 + 47: 66 .. 73 + 57: 123 .. 191 + 61: 137 .. 146 + 63: 137 .. 138 + 71: 195 .. 291 + 75: 209 .. 228 + 77: 209 .. 215 + 87: 295 .. 392 + 91: 309 .. 330 + 93: 309 .. 317 + 95: 309 .. 310 + 106: 12 .. 394 + 109: 27 .. 48 + 111: 27 .. 28 + 114: 27 .. 27 + 124: 28 .. 28 + 127: 35 .. 48 + 130: 27 .. 28 + 135: 27 .. 27 + 137: 27 .. 27 + 140: 46 .. 46 + + source paths: + 0: 23 [tests/pos/i19806/J_SCALA_ONLY.java] + + +Attributes (4 bytes, starting from 597): + JAVAattr + OUTLINEattr + SOURCEFILEattr 23 [tests/pos/i19806/J_SCALA_ONLY.java] diff --git a/tests/pos/i19806/J_SCALA_ONLY.java b/tests/pos/i19806/J_SCALA_ONLY.java new file mode 100644 index 000000000000..abbc6c0e9d57 --- /dev/null +++ b/tests/pos/i19806/J_SCALA_ONLY.java @@ -0,0 +1,22 @@ +package p; + +public class J { + + public J() {} + + public static Module$ module2() { + return p.Module$.MODULE$; + } + + public static p.Module$ module() { + return p.Module$.MODULE$; + } + + public static Module.InnerModule$ innermodule2() { + return p.Module.InnerModule$.MODULE$; + } + + public static p.Module.InnerModule$ innermodule() { + return p.Module.InnerModule$.MODULE$; + } +} diff --git a/tests/pos/i19806/Module.scala b/tests/pos/i19806/Module.scala new file mode 100644 index 000000000000..d0142fc24682 --- /dev/null +++ b/tests/pos/i19806/Module.scala @@ -0,0 +1,9 @@ +//> using options -Yjava-tasty -Ytest-pickler-check + +package p + +object Module: + object InnerModule + +class Outer: + object InnerModule diff --git a/tests/run/i17255/Module.scala b/tests/run/i17255/Module.scala index 936e78e8e4ce..9b7153edbfd1 100644 --- a/tests/run/i17255/Module.scala +++ b/tests/run/i17255/Module.scala @@ -1,3 +1,4 @@ +// scalajs: --skip package p { object Module { override def toString = "Module" From 090b6473e68d8d0e89d0a659803db25fcb2ea026 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Wed, 13 Mar 2024 11:36:57 +0100 Subject: [PATCH 208/277] elide source file names --- .../tools/dotc/core/tasty/TastyPrinter.scala | 76 ++++++++++++++----- tests/pos/i19806/J.tastycheck | 6 +- 2 files changed, 60 insertions(+), 22 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala index a4818e8d6fd5..e63ac4737a09 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala @@ -13,9 +13,11 @@ import dotty.tools.tasty.TastyFormat.{ASTsSection, PositionsSection, CommentsSec import java.nio.file.{Files, Paths} import dotty.tools.io.{JarArchive, Path} import dotty.tools.tasty.TastyFormat.header +import scala.collection.immutable.BitSet import scala.compiletime.uninitialized import dotty.tools.tasty.TastyBuffer.Addr +import dotty.tools.dotc.core.Names.TermName object TastyPrinter: @@ -82,10 +84,6 @@ class TastyPrinter(bytes: Array[Byte], val testPickler: Boolean) { private val unpickler: TastyPrinterUnpickler = new TastyPrinterUnpickler import unpickler.{nameAtRef, unpickle} - private def nameToString(name: Name): String = name.debugString - - private def nameRefToString(ref: NameRef): String = nameToString(nameAtRef(ref)) - private def printHeader(sb: StringBuilder): Unit = val header = unpickler.header sb.append("Header:\n") @@ -101,27 +99,34 @@ class TastyPrinter(bytes: Array[Byte], val testPickler: Boolean) { end if sb.append("\n") - private def printNames(sb: StringBuilder): Unit = + private def printNames(sb: StringBuilder)(using refs: NameRefs): Unit = sb.append(s"Names (${unpickler.namesEnd.index - unpickler.namesStart.index} bytes, starting from ${unpickler.namesStart.index}):\n") for ((name, idx) <- nameAtRef.contents.zipWithIndex) { val index = nameStr("%6d".format(idx)) - sb.append(index).append(": ").append(nameToString(name)).append("\n") + sb.append(index).append(": ").append(refs.nameRefToString(NameRef(idx))).append("\n") } def showContents(): String = { val sb: StringBuilder = new StringBuilder + given NameRefs = unpickle0(new SourceFileUnpickler)(using NameRefs.empty).getOrElse(NameRefs.empty) printHeader(sb) printNames(sb) - unpickle(new TreeSectionUnpickler(sb)) - unpickle(new PositionSectionUnpickler(sb)) - unpickle(new CommentSectionUnpickler(sb)) - unpickle(new AttributesSectionUnpickler(sb)) + unpickle0(new TreeSectionUnpickler(sb)) + unpickle0(new PositionSectionUnpickler(sb)) + unpickle0(new CommentSectionUnpickler(sb)) + unpickle0(new AttributesSectionUnpickler(sb)) sb.result } - class TreeSectionUnpickler(sb: StringBuilder) extends SectionUnpickler[Unit](ASTsSection) { + def unpickle0[R](sec: PrinterSectionUnpickler[R])(using NameRefs): Option[R] = + unpickle(new SectionUnpickler[R](sec.name) { + def unpickle(reader: TastyReader, nameAtRef: NameTable): R = + sec.unpickle0(reader.subReader(reader.startAddr, reader.endAddr)) // fork so we can visit multiple times + }) + + class TreeSectionUnpickler(sb: StringBuilder) extends PrinterSectionUnpickler[Unit](ASTsSection) { import dotty.tools.tasty.TastyFormat.* - def unpickle(reader: TastyReader, tastyName: NameTable): Unit = { + def unpickle0(reader: TastyReader)(using refs: NameRefs): Unit = { import reader.* var indent = 0 def newLine() = { @@ -131,7 +136,7 @@ class TastyPrinter(bytes: Array[Byte], val testPickler: Boolean) { def printNat() = sb.append(treeStr(" " + readNat())) def printName() = { val idx = readNat() - sb.append(nameStr(" " + idx + " [" + nameRefToString(NameRef(idx)) + "]")) + sb.append(nameStr(" " + idx + " [" + refs.nameRefToString(NameRef(idx)) + "]")) } def printTree(): Unit = { newLine() @@ -190,8 +195,8 @@ class TastyPrinter(bytes: Array[Byte], val testPickler: Boolean) { } } - class PositionSectionUnpickler(sb: StringBuilder) extends SectionUnpickler[Unit](PositionsSection) { - def unpickle(reader: TastyReader, tastyName: NameTable): Unit = { + class PositionSectionUnpickler(sb: StringBuilder) extends PrinterSectionUnpickler[Unit](PositionsSection) { + def unpickle0(reader: TastyReader)(using tastyName: NameRefs): Unit = { import reader.* val posUnpickler = new PositionUnpickler(reader, tastyName) sb.append(s"\n\nPositions (${reader.endAddr.index - reader.startAddr.index} bytes, starting from $base):\n") @@ -222,8 +227,8 @@ class TastyPrinter(bytes: Array[Byte], val testPickler: Boolean) { } } - class CommentSectionUnpickler(sb: StringBuilder) extends SectionUnpickler[Unit](CommentsSection) { - def unpickle(reader: TastyReader, tastyName: NameTable): Unit = { + class CommentSectionUnpickler(sb: StringBuilder) extends PrinterSectionUnpickler[Unit](CommentsSection) { + def unpickle0(reader: TastyReader)(using NameRefs): Unit = { import reader.* val comments = new CommentUnpickler(reader).comments if !comments.isEmpty then @@ -236,9 +241,9 @@ class TastyPrinter(bytes: Array[Byte], val testPickler: Boolean) { } } - class AttributesSectionUnpickler(sb: StringBuilder) extends SectionUnpickler[Unit](AttributesSection) { + class AttributesSectionUnpickler(sb: StringBuilder) extends PrinterSectionUnpickler[Unit](AttributesSection) { import dotty.tools.tasty.TastyFormat.* - def unpickle(reader: TastyReader, tastyName: NameTable): Unit = { + def unpickle0(reader: TastyReader)(using nameAtRef: NameRefs): Unit = { import reader.* sb.append(s"\n\nAttributes (${reader.endAddr.index - reader.startAddr.index} bytes, starting from $base):\n") while !isAtEnd do @@ -256,6 +261,39 @@ class TastyPrinter(bytes: Array[Byte], val testPickler: Boolean) { } } + class NameRefs(sourceFileRefs: Set[NameRef]) extends (NameRef => TermName): + private val isSourceFile = sourceFileRefs.map(_.index).to(BitSet) + + def nameRefToString(ref: NameRef): String = this(ref).debugString + + def apply(ref: NameRef): TermName = + if isSourceFile(ref.index) then NameRefs.elidedSourceFile + else nameAtRef(ref) + + object NameRefs: + import dotty.tools.dotc.core.Names.termName + + private val elidedSourceFile = termName("") + val empty = NameRefs(Set.empty) + + + class SourceFileUnpickler extends PrinterSectionUnpickler[NameRefs](PositionsSection) { + def unpickle0(reader: TastyReader)(using nameAtRef: NameRefs): NameRefs = { + if !testPickler then return NameRefs.empty + val buf = Set.newBuilder[NameRef] + val posUnpickler = new PositionUnpickler(reader, nameAtRef) + val sources = posUnpickler.sourceNameRefs + for ((_, nameRef) <- sources.iterator) { + buf += nameRef + } + NameRefs(buf.result) + } + } + + abstract class PrinterSectionUnpickler[T](val name: String) { + def unpickle0(reader: TastyReader)(using refs: NameRefs): T + } + protected def nameStr(str: String): String = str protected def treeStr(str: String): String = str protected def lengthStr(str: String): String = str diff --git a/tests/pos/i19806/J.tastycheck b/tests/pos/i19806/J.tastycheck index 900530e80965..7fe7970c5099 100644 --- a/tests/pos/i19806/J.tastycheck +++ b/tests/pos/i19806/J.tastycheck @@ -27,7 +27,7 @@ Names (217 bytes, starting from 80): 20: T 21: Nothing 22: Positions - 23: tests/pos/i19806/J_SCALA_ONLY.java + 23: 24: Comments 25: Attributes @@ -152,10 +152,10 @@ Positions (145 bytes, starting from 448): 140: 46 .. 46 source paths: - 0: 23 [tests/pos/i19806/J_SCALA_ONLY.java] + 0: 23 [] Attributes (4 bytes, starting from 597): JAVAattr OUTLINEattr - SOURCEFILEattr 23 [tests/pos/i19806/J_SCALA_ONLY.java] + SOURCEFILEattr 23 [] From 923f63f04d0c57ffbdfa26cd5198ffb5ba998858 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Wed, 13 Mar 2024 12:05:37 +0100 Subject: [PATCH 209/277] check lines not whole file --- .../dotty/tools/dotc/transform/Pickler.scala | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/Pickler.scala b/compiler/src/dotty/tools/dotc/transform/Pickler.scala index 0ce3be9c1c4e..e467635f25bc 100644 --- a/compiler/src/dotty/tools/dotc/transform/Pickler.scala +++ b/compiler/src/dotty/tools/dotc/transform/Pickler.scala @@ -304,14 +304,33 @@ class Pickler extends Phase { | diff before-pickling.txt after-pickling.txt""") end testSame - private def testSamePrinted(printed: String, checkContents: String, cls: ClassSymbol, check: AbstractFile)(using Context) = - import java.nio.charset.StandardCharsets.UTF_8 - def normal(s: String) = new String(s.getBytes(UTF_8), UTF_8) - val unequal = printed.length() != checkContents.length() || normal(printed) != normal(checkContents) - if unequal then + private def testSamePrinted(printed: String, checkContents: String, cls: ClassSymbol, check: AbstractFile)(using Context): Unit = { + if hasDiff(printed, checkContents) then output("after-printing.txt", printed) report.error(em"""TASTy printer difference for $cls in ${cls.source}, for details: | | diff ${check.toString} after-printing.txt""") - end testSamePrinted + } + + /** Reuse diff logic from compiler/test/dotty/tools/vulpix/FileDiff.scala */ + private def hasDiff(actual: String, expect: String): Boolean = + import scala.util.Using + import scala.io.Source + val actualLines = Using(Source.fromString(actual))(_.getLines().toList).get + val expectLines = Using(Source.fromString(expect))(_.getLines().toList).get + !matches(actualLines, expectLines) + + private def matches(actual: String, expect: String): Boolean = { + import java.io.File + val actual1 = actual.stripLineEnd + val expect1 = expect.stripLineEnd + + // handle check file path mismatch on windows + actual1 == expect1 || File.separatorChar == '\\' && actual1.replace('\\', '/') == expect1 + } + + private def matches(actual: Seq[String], expect: Seq[String]): Boolean = { + actual.length == expect.length + && actual.lazyZip(expect).forall(matches) + } } From 85ddd961b03d79e572580dde727e4161dfa50b1d Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Wed, 13 Mar 2024 12:41:36 +0100 Subject: [PATCH 210/277] Add sbt test for `scala2-library-cc-tasty` --- project/Build.scala | 1 + sbt-test/sbt-dotty/scala2-library-cc-tasty/build.sbt | 4 ++++ .../scala2-library-cc-tasty/src/main/scala/hello/Hello.scala | 4 ++++ sbt-test/sbt-dotty/scala2-library-cc-tasty/test | 1 + 4 files changed, 10 insertions(+) create mode 100644 sbt-test/sbt-dotty/scala2-library-cc-tasty/build.sbt create mode 100644 sbt-test/sbt-dotty/scala2-library-cc-tasty/src/main/scala/hello/Hello.scala create mode 100644 sbt-test/sbt-dotty/scala2-library-cc-tasty/test diff --git a/project/Build.scala b/project/Build.scala index 2b24746e4ca4..ea56039fa401 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1920,6 +1920,7 @@ object Build { (`scala3-compiler-bootstrapped` / publishLocalBin), (`scala3-library-bootstrapped` / publishLocalBin), (`scala2-library-tasty` / publishLocal), + (`scala2-library-cc-tasty` / publishLocal), (`scala3-library-bootstrappedJS` / publishLocalBin), (`tasty-core-bootstrapped` / publishLocalBin), (`scala3-staging` / publishLocalBin), diff --git a/sbt-test/sbt-dotty/scala2-library-cc-tasty/build.sbt b/sbt-test/sbt-dotty/scala2-library-cc-tasty/build.sbt new file mode 100644 index 000000000000..db059b501d77 --- /dev/null +++ b/sbt-test/sbt-dotty/scala2-library-cc-tasty/build.sbt @@ -0,0 +1,4 @@ +scalaVersion := sys.props("plugin.scalaVersion") + +libraryDependencies += "org.scala-lang" %% "scala2-library-cc-tasty-experimental" % scalaVersion.value +scalacOptions += "-Yscala2-unpickler:never" // check that we do not load symbol from the Scala 2 library classfiles (use TASTy) diff --git a/sbt-test/sbt-dotty/scala2-library-cc-tasty/src/main/scala/hello/Hello.scala b/sbt-test/sbt-dotty/scala2-library-cc-tasty/src/main/scala/hello/Hello.scala new file mode 100644 index 000000000000..87277631f69b --- /dev/null +++ b/sbt-test/sbt-dotty/scala2-library-cc-tasty/src/main/scala/hello/Hello.scala @@ -0,0 +1,4 @@ +package hello + +@main def hello: Unit = + println(Some("Hello world!")) // load Some form the Scala 2 library TASTy diff --git a/sbt-test/sbt-dotty/scala2-library-cc-tasty/test b/sbt-test/sbt-dotty/scala2-library-cc-tasty/test new file mode 100644 index 000000000000..62ea636c177f --- /dev/null +++ b/sbt-test/sbt-dotty/scala2-library-cc-tasty/test @@ -0,0 +1 @@ +> run From 6e1bba5793474a8390f7d989b0a6dd475a71f989 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Wed, 13 Mar 2024 13:16:34 +0100 Subject: [PATCH 211/277] print what is the diff --- compiler/src/dotty/tools/dotc/transform/Pickler.scala | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/Pickler.scala b/compiler/src/dotty/tools/dotc/transform/Pickler.scala index e467635f25bc..cd5461880655 100644 --- a/compiler/src/dotty/tools/dotc/transform/Pickler.scala +++ b/compiler/src/dotty/tools/dotc/transform/Pickler.scala @@ -307,9 +307,10 @@ class Pickler extends Phase { private def testSamePrinted(printed: String, checkContents: String, cls: ClassSymbol, check: AbstractFile)(using Context): Unit = { if hasDiff(printed, checkContents) then output("after-printing.txt", printed) - report.error(em"""TASTy printer difference for $cls in ${cls.source}, for details: - | - | diff ${check.toString} after-printing.txt""") + report.error(em"""TASTy printer difference for $cls in ${cls.source}, did not match ${check}, + | output dumped in after-printing.txt, check diff with `git diff --no-index -- after-printing.txt ${check}` + | actual output: + |$printed""") } /** Reuse diff logic from compiler/test/dotty/tools/vulpix/FileDiff.scala */ From 1d5db004270b07d25f902aaba9da96e0c0d6005f Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Wed, 13 Mar 2024 13:57:09 +0100 Subject: [PATCH 212/277] elide base index of sections --- .../tools/dotc/core/tasty/TastyPrinter.scala | 28 +++++++++++++++---- .../dotty/tools/dotc/transform/Pickler.scala | 10 +++---- tests/pos/i19806/J.tastycheck | 10 +++---- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala index e63ac4737a09..af2097f347ba 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala @@ -97,10 +97,14 @@ class TastyPrinter(bytes: Array[Byte], val testPickler: Boolean) { sb.append(" tooling: ").append(header.toolingVersion).append("\n") sb.append(" UUID: ").append(header.uuid).append("\n") end if - sb.append("\n") private def printNames(sb: StringBuilder)(using refs: NameRefs): Unit = - sb.append(s"Names (${unpickler.namesEnd.index - unpickler.namesStart.index} bytes, starting from ${unpickler.namesStart.index}):\n") + sb.append(sectionHeader( + name = "Names", + count = (unpickler.namesEnd.index - unpickler.namesStart.index).toString, + base = showBase(unpickler.namesStart.index), + lineEnd = true + )) for ((name, idx) <- nameAtRef.contents.zipWithIndex) { val index = nameStr("%6d".format(idx)) sb.append(index).append(": ").append(refs.nameRefToString(NameRef(idx))).append("\n") @@ -187,11 +191,12 @@ class TastyPrinter(bytes: Array[Byte], val testPickler: Boolean) { } indent -= 2 } - sb.append(s"\n\nTrees (${endAddr.index - startAddr.index} bytes, starting from $base):") + sb.append(sectionHeader("Trees", reader, lineEnd = false)) while (!isAtEnd) { printTree() newLine() } + sb.append("\n") } } @@ -199,7 +204,7 @@ class TastyPrinter(bytes: Array[Byte], val testPickler: Boolean) { def unpickle0(reader: TastyReader)(using tastyName: NameRefs): Unit = { import reader.* val posUnpickler = new PositionUnpickler(reader, tastyName) - sb.append(s"\n\nPositions (${reader.endAddr.index - reader.startAddr.index} bytes, starting from $base):\n") + sb.append(sectionHeader("Positions", reader)) val lineSizes = posUnpickler.lineSizes sb.append(s" lines: ${lineSizes.length}\n") sb.append(s" line sizes:\n") @@ -232,7 +237,7 @@ class TastyPrinter(bytes: Array[Byte], val testPickler: Boolean) { import reader.* val comments = new CommentUnpickler(reader).comments if !comments.isEmpty then - sb.append(s"\n\nComments (${reader.endAddr.index - reader.startAddr.index} bytes, starting from $base):\n") + sb.append(sectionHeader("Comments", reader)) val sorted = comments.toSeq.sortBy(_._1.index) for ((addr, cmt) <- sorted) { sb.append(treeStr("%6d".format(addr.index))) @@ -245,7 +250,7 @@ class TastyPrinter(bytes: Array[Byte], val testPickler: Boolean) { import dotty.tools.tasty.TastyFormat.* def unpickle0(reader: TastyReader)(using nameAtRef: NameRefs): Unit = { import reader.* - sb.append(s"\n\nAttributes (${reader.endAddr.index - reader.startAddr.index} bytes, starting from $base):\n") + sb.append(sectionHeader("Attributes", reader)) while !isAtEnd do // TODO: Should we elide attributes under testPickler? (i.e. // if we add new attributes many check files will need to be updated) @@ -290,6 +295,17 @@ class TastyPrinter(bytes: Array[Byte], val testPickler: Boolean) { } } + private final def showBase(index: Int): String = + if testPickler then "" else index.toString() + + private final def sectionHeader(name: String, reader: TastyReader, lineEnd: Boolean = true): String = + val count = reader.endAddr.index - reader.startAddr.index + sectionHeader(name, count.toString, {showBase(reader.base)}, lineEnd) + + private final def sectionHeader(name: String, count: String, base: String, lineEnd: Boolean): String = + val suffix = if lineEnd then "\n" else "" + s"\n$name ($count bytes, starting from $base):$suffix" + abstract class PrinterSectionUnpickler[T](val name: String) { def unpickle0(reader: TastyReader)(using refs: NameRefs): T } diff --git a/compiler/src/dotty/tools/dotc/transform/Pickler.scala b/compiler/src/dotty/tools/dotc/transform/Pickler.scala index cd5461880655..b0aed580e824 100644 --- a/compiler/src/dotty/tools/dotc/transform/Pickler.scala +++ b/compiler/src/dotty/tools/dotc/transform/Pickler.scala @@ -305,21 +305,21 @@ class Pickler extends Phase { end testSame private def testSamePrinted(printed: String, checkContents: String, cls: ClassSymbol, check: AbstractFile)(using Context): Unit = { - if hasDiff(printed, checkContents) then + for lines <- diff(printed, checkContents) do output("after-printing.txt", printed) report.error(em"""TASTy printer difference for $cls in ${cls.source}, did not match ${check}, - | output dumped in after-printing.txt, check diff with `git diff --no-index -- after-printing.txt ${check}` + | output dumped in after-printing.txt, check diff with `git diff --no-index -- $check after-printing.txt` | actual output: - |$printed""") + |$lines%\n%""") } /** Reuse diff logic from compiler/test/dotty/tools/vulpix/FileDiff.scala */ - private def hasDiff(actual: String, expect: String): Boolean = + private def diff(actual: String, expect: String): Option[Seq[String]] = import scala.util.Using import scala.io.Source val actualLines = Using(Source.fromString(actual))(_.getLines().toList).get val expectLines = Using(Source.fromString(expect))(_.getLines().toList).get - !matches(actualLines, expectLines) + Option.when(!matches(actualLines, expectLines))(actualLines) private def matches(actual: String, expect: String): Boolean = { import java.io.File diff --git a/tests/pos/i19806/J.tastycheck b/tests/pos/i19806/J.tastycheck index 7fe7970c5099..110c33310e43 100644 --- a/tests/pos/i19806/J.tastycheck +++ b/tests/pos/i19806/J.tastycheck @@ -3,7 +3,7 @@ Header: tooling: UUID: -Names (217 bytes, starting from 80): +Names (217 bytes, starting from ): 0: ASTs 1: p 2: J @@ -31,8 +31,7 @@ Names (217 bytes, starting from 80): 24: Comments 25: Attributes - -Trees (145 bytes, starting from 300): +Trees (145 bytes, starting from ): 0: PACKAGE(142) 3: TERMREFpkg 1 [p] 5: VALDEF(11) 2 [J] @@ -113,7 +112,7 @@ Trees (145 bytes, starting from 300): 143: SHAREDtype 38 145: -Positions (145 bytes, starting from 448): +Positions (145 bytes, starting from ): lines: 23 line sizes: 10, 0, 19, 0, 15, 0, 35, 29, 3, 0, 36, 29, 3, 0, 52, 41, 3, 0, 53, 41 @@ -154,8 +153,7 @@ Positions (145 bytes, starting from 448): source paths: 0: 23 [] - -Attributes (4 bytes, starting from 597): +Attributes (4 bytes, starting from ): JAVAattr OUTLINEattr SOURCEFILEattr 23 [] From 23d0ce3ab8461fe7faae38194385dadf390a6d17 Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Thu, 22 Feb 2024 17:18:58 +0100 Subject: [PATCH 213/277] Refactor settings & improve dx --- .../tools/backend/jvm/BackendUtils.scala | 39 +- compiler/src/dotty/tools/dotc/Driver.scala | 2 + .../tools/dotc/config/CompilerCommand.scala | 6 +- .../tools/dotc/config/ScalaSettings.scala | 441 +++++++++--------- .../dotty/tools/dotc/config/Settings.scala | 200 ++++---- .../src/dotty/tools/dotc/core/Contexts.scala | 5 +- .../dotty/tools/dotc/ScalaCommandTest.scala | 4 +- .../test/dotty/tools/dotc/SettingsTests.scala | 30 +- .../dotc/config/ScalaSettingsTests.scala | 12 +- 9 files changed, 393 insertions(+), 346 deletions(-) diff --git a/compiler/src/dotty/tools/backend/jvm/BackendUtils.scala b/compiler/src/dotty/tools/backend/jvm/BackendUtils.scala index 2f8a469169cc..459f1b2b2613 100644 --- a/compiler/src/dotty/tools/backend/jvm/BackendUtils.scala +++ b/compiler/src/dotty/tools/backend/jvm/BackendUtils.scala @@ -20,24 +20,7 @@ class BackendUtils(val postProcessor: PostProcessor) { import bTypes.* import coreBTypes.jliLambdaMetaFactoryAltMetafactoryHandle - // Keep synchronized with `minTargetVersion` and `maxTargetVersion` in ScalaSettings - lazy val classfileVersion: Int = compilerSettings.target match { - case "8" => asm.Opcodes.V1_8 - case "9" => asm.Opcodes.V9 - case "10" => asm.Opcodes.V10 - case "11" => asm.Opcodes.V11 - case "12" => asm.Opcodes.V12 - case "13" => asm.Opcodes.V13 - case "14" => asm.Opcodes.V14 - case "15" => asm.Opcodes.V15 - case "16" => asm.Opcodes.V16 - case "17" => asm.Opcodes.V17 - case "18" => asm.Opcodes.V18 - case "19" => asm.Opcodes.V19 - case "20" => asm.Opcodes.V20 - case "21" => asm.Opcodes.V21 - case "22" => asm.Opcodes.V22 - } + lazy val classfileVersion: Int = BackendUtils.classfileVersionMap(compilerSettings.target) lazy val extraProc: Int = { import GenBCodeOps.addFlagIf @@ -184,3 +167,23 @@ class BackendUtils(val postProcessor: PostProcessor) { } } } + +object BackendUtils { + lazy val classfileVersionMap = Map( + "8" -> asm.Opcodes.V1_8, + "9" -> asm.Opcodes.V9, + "10" -> asm.Opcodes.V10, + "11" -> asm.Opcodes.V11, + "12" -> asm.Opcodes.V12, + "13" -> asm.Opcodes.V13, + "14" -> asm.Opcodes.V14, + "15" -> asm.Opcodes.V15, + "16" -> asm.Opcodes.V16, + "17" -> asm.Opcodes.V17, + "18" -> asm.Opcodes.V18, + "19" -> asm.Opcodes.V19, + "20" -> asm.Opcodes.V20, + "21" -> asm.Opcodes.V21, + "22" -> asm.Opcodes.V22, + ) +} \ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/Driver.scala b/compiler/src/dotty/tools/dotc/Driver.scala index 196752aceb29..82a9f5850bb6 100644 --- a/compiler/src/dotty/tools/dotc/Driver.scala +++ b/compiler/src/dotty/tools/dotc/Driver.scala @@ -10,6 +10,7 @@ import dotty.tools.io.AbstractFile import reporting.* import core.Decorators.* import config.Feature +import dotty.tools.dotc.config.ScalaSettings import scala.util.control.NonFatal import fromtasty.{TASTYCompiler, TastyFileUtil} @@ -199,6 +200,7 @@ class Driver { } def main(args: Array[String]): Unit = { + println("settings: " + ScalaSettings.allSettings) // Preload scala.util.control.NonFatal. Otherwise, when trying to catch a StackOverflowError, // we may try to load it but fail with another StackOverflowError and lose the original exception, // see . diff --git a/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala b/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala index 2ffe900fbdbf..2e82c6a3cd67 100644 --- a/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala +++ b/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala @@ -5,9 +5,9 @@ import Settings.* import core.Contexts.* abstract class CompilerCommand extends CliCommand: - type ConcreteSettings = ScalaSettings + type ConcreteSettings = ScalaSettings.type - final def helpMsg(using settings: ScalaSettings)(using SettingsState, Context): String = + final def helpMsg(using settings: ConcreteSettings)(using SettingsState, Context): String = settings.allSettings.find(isHelping) match case Some(s) => s.description case _ => @@ -20,7 +20,7 @@ abstract class CompilerCommand extends CliCommand: else if (settings.XshowPhases.value) phasesMessage else "" - final def isHelpFlag(using settings: ScalaSettings)(using SettingsState): Boolean = + final def isHelpFlag(using settings: ConcreteSettings)(using SettingsState): Boolean = import settings.* val flags = Set(help, Vhelp, Whelp, Xhelp, Yhelp, showPlugins, XshowPhases) flags.exists(_.value) || allSettings.exists(isHelping) diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index e970e148f615..92150ae6e426 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package config import scala.language.unsafeNulls - +import dotty.tools.backend.jvm.BackendUtils.classfileVersionMap import dotty.tools.dotc.config.PathResolver.Defaults import dotty.tools.dotc.config.Settings.{Setting, SettingGroup} import dotty.tools.dotc.config.SourceVersion @@ -10,17 +10,35 @@ import dotty.tools.dotc.core.Contexts.* import dotty.tools.dotc.rewrites.Rewrites import dotty.tools.io.{AbstractFile, Directory, JDK9Reflectors, PlainDirectory, NoAbstractFile} import Setting.ChoiceWithHelp +import ScalaSettingCategories.* import scala.util.chaining.* import java.util.zip.Deflater -class ScalaSettings extends SettingGroup with AllScalaSettings - -object ScalaSettings: - // Keep synchronized with `classfileVersion` in `BackendUtils` - private val minTargetVersion = 8 - private val maxTargetVersion = 22 +object ScalaSettingCategories: + val RootSetting = "" + val WarningSetting = "W" + val ForkSetting = "Y" + val AdvancedSetting = "X" + val VerboseSetting = "V" + +object ScalaSettings extends SettingGroup with AllScalaSettings: + + val settingsByCategory: Map[String, List[Setting[_]]] = + allSettings.groupBy(_.category) + .view.mapValues(_.toList).toMap + .withDefaultValue(Nil) + def categories: List[String] = settingsByCategory.keys.toList + val rootSettings: List[Setting[_]] = settingsByCategory(RootSetting) + val warningSettings: List[Setting[_]] = settingsByCategory(WarningSetting) + val forkSettings: List[Setting[_]] = settingsByCategory(ForkSetting) + val advancedSettings: List[Setting[_]] = settingsByCategory(AdvancedSetting) + val verboseSettings: List[Setting[_]] = settingsByCategory(VerboseSetting) + val settingsByAliases: Map[String, Setting[_]] = allSettings.flatMap(s => s.aliases.map(_ -> s)).toMap + + private lazy val minTargetVersion = classfileVersionMap.keysIterator.map(_.toInt).min + private lazy val maxTargetVersion = classfileVersionMap.keysIterator.map(_.toInt).max def supportedTargetVersions: List[String] = (minTargetVersion to maxTargetVersion).toList.map(_.toString) @@ -56,38 +74,38 @@ trait AllScalaSettings extends CommonScalaSettings, PluginSettings, VerboseSetti self: SettingGroup => /* Path related settings */ - val semanticdbTarget: Setting[String] = PathSetting("-semanticdb-target", "Specify an alternative output directory for SemanticDB files.", "") - val semanticdbText: Setting[Boolean] = BooleanSetting("-semanticdb-text", "Specifies whether to include source code in SemanticDB files or not.") + val semanticdbTarget: Setting[String] = PathSetting(RootSetting, "semanticdb-target", "Specify an alternative output directory for SemanticDB files.", "") + val semanticdbText: Setting[Boolean] = BooleanSetting(RootSetting, "semanticdb-text", "Specifies whether to include source code in SemanticDB files or not.") - val source: Setting[String] = ChoiceSetting("-source", "source version", "source version", ScalaSettings.supportedSourceVersions, SourceVersion.defaultSourceVersion.toString, aliases = List("--source")) - val uniqid: Setting[Boolean] = BooleanSetting("-uniqid", "Uniquely tag all identifiers in debugging output.", aliases = List("--unique-id")) - val rewrite: Setting[Option[Rewrites]] = OptionSetting[Rewrites]("-rewrite", "When used in conjunction with a `...-migration` source version, rewrites sources to migrate to new version.", aliases = List("--rewrite")) - val fromTasty: Setting[Boolean] = BooleanSetting("-from-tasty", "Compile classes from tasty files. The arguments are .tasty or .jar files.", aliases = List("--from-tasty")) + val source: Setting[String] = ChoiceSetting(RootSetting, "source", "source version", "source version", ScalaSettings.supportedSourceVersions, SourceVersion.defaultSourceVersion.toString, aliases = List("--source")) + val uniqid: Setting[Boolean] = BooleanSetting(RootSetting, "uniqid", "Uniquely tag all identifiers in debugging output.", aliases = List("--unique-id")) + val rewrite: Setting[Option[Rewrites]] = OptionSetting[Rewrites](RootSetting, "rewrite", "When used in conjunction with a `...-migration` source version, rewrites sources to migrate to new version.", aliases = List("--rewrite")) + val fromTasty: Setting[Boolean] = BooleanSetting(RootSetting, "from-tasty", "Compile classes from tasty files. The arguments are .tasty or .jar files.", aliases = List("--from-tasty")) - val newSyntax: Setting[Boolean] = BooleanSetting("-new-syntax", "Require `then` and `do` in control expressions.") - val oldSyntax: Setting[Boolean] = BooleanSetting("-old-syntax", "Require `(...)` around conditions.") - val indent: Setting[Boolean] = BooleanSetting("-indent", "Together with -rewrite, remove {...} syntax when possible due to significant indentation.") - val noindent: Setting[Boolean] = BooleanSetting("-no-indent", "Require classical {...} syntax, indentation is not significant.", aliases = List("-noindent")) + val newSyntax: Setting[Boolean] = BooleanSetting(RootSetting, "new-syntax", "Require `then` and `do` in control expressions.") + val oldSyntax: Setting[Boolean] = BooleanSetting(RootSetting, "old-syntax", "Require `(...)` around conditions.") + val indent: Setting[Boolean] = BooleanSetting(RootSetting, "indent", "Together with -rewrite, remove {...} syntax when possible due to significant indentation.") + val noindent: Setting[Boolean] = BooleanSetting(RootSetting, "no-indent", "Require classical {...} syntax, indentation is not significant.", aliases = List("-noindent")) /* Decompiler settings */ - val printTasty: Setting[Boolean] = BooleanSetting("-print-tasty", "Prints the raw tasty.", aliases = List("--print-tasty")) - val printLines: Setting[Boolean] = BooleanSetting("-print-lines", "Show source code line numbers.", aliases = List("--print-lines")) + val printTasty: Setting[Boolean] = BooleanSetting(RootSetting, "print-tasty", "Prints the raw tasty.", aliases = List("--print-tasty")) + val printLines: Setting[Boolean] = BooleanSetting(RootSetting, "print-lines", "Show source code line numbers.", aliases = List("--print-lines")) /* Scala.js-related settings */ - val scalajsGenStaticForwardersForNonTopLevelObjects: Setting[Boolean] = BooleanSetting("-scalajs-genStaticForwardersForNonTopLevelObjects", "Generate static forwarders even for non-top-level objects (Scala.js only).") - val scalajsMapSourceURI: Setting[List[String]] = MultiStringSetting("-scalajs-mapSourceURI", "uri1[->uri2]", "rebases source URIs from uri1 to uri2 (or to a relative URI) for source maps (Scala.js only).") + val scalajsGenStaticForwardersForNonTopLevelObjects: Setting[Boolean] = BooleanSetting(RootSetting, "scalajs-genStaticForwardersForNonTopLevelObjects", "Generate static forwarders even for non-top-level objects (Scala.js only).") + val scalajsMapSourceURI: Setting[List[String]] = MultiStringSetting(RootSetting, "scalajs-mapSourceURI", "uri1[->uri2]", "rebases source URIs from uri1 to uri2 (or to a relative URI) for source maps (Scala.js only).") val projectUrl: Setting[String] = StringSetting ( - "-project-url", + RootSetting, + "project-url", "project repository homepage", "The source repository of your project.", "" ) - val wikiSyntax: Setting[Boolean] = BooleanSetting("-Xwiki-syntax", "Retains the Scala2 behavior of using Wiki Syntax in Scaladoc.") - - val jvmargs = PrefixSetting("-J", "-J", "Pass directly to the runtime system.") - val defines = PrefixSetting("-Dproperty=value", "-D", "Pass -Dproperty=value directly to the runtime system.") + val wikiSyntax: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xwiki-syntax", "Retains the Scala2 behavior of using Wiki Syntax in Scaladoc.") + val jvmargs = PrefixSetting(RootSetting, "J", "Pass -J directly to the runtime system.") + val defines = PrefixSetting(RootSetting, "D", "Pass -D directly to the runtime system.") end AllScalaSettings /** Settings shared by compiler and scaladoc */ @@ -95,84 +113,85 @@ trait CommonScalaSettings: self: SettingGroup => /* Path related settings */ - val bootclasspath: Setting[String] = PathSetting("-bootclasspath", "Override location of bootstrap class files.", Defaults.scalaBootClassPath, aliases = List("--boot-class-path")) - val extdirs: Setting[String] = PathSetting("-extdirs", "Override location of installed extensions.", Defaults.scalaExtDirs, aliases = List("--extension-directories")) - val javabootclasspath: Setting[String] = PathSetting("-javabootclasspath", "Override java boot classpath.", Defaults.javaBootClassPath, aliases = List("--java-boot-class-path")) - val javaextdirs: Setting[String] = PathSetting("-javaextdirs", "Override java extdirs classpath.", Defaults.javaExtDirs, aliases = List("--java-extension-directories")) - val sourcepath: Setting[String] = PathSetting("-sourcepath", "Specify location(s) of source files.", Defaults.scalaSourcePath, aliases = List("--source-path")) - val sourceroot: Setting[String] = PathSetting("-sourceroot", "Specify workspace root directory.", ".") - - val classpath: Setting[String] = PathSetting("-classpath", "Specify where to find user class files.", ScalaSettings.defaultClasspath, aliases = List("-cp", "--class-path")) - val outputDir: Setting[AbstractFile] = OutputSetting("-d", "directory|jar", "Destination for generated classfiles.", + val bootclasspath: Setting[String] = PathSetting(RootSetting, "bootclasspath", "Override location of bootstrap class files.", Defaults.scalaBootClassPath, aliases = List("--boot-class-path")) + val extdirs: Setting[String] = PathSetting(RootSetting, "extdirs", "Override location of installed extensions.", Defaults.scalaExtDirs, aliases = List("--extension-directories")) + val javabootclasspath: Setting[String] = PathSetting(RootSetting, "javabootclasspath", "Override java boot classpath.", Defaults.javaBootClassPath, aliases = List("--java-boot-class-path")) + val javaextdirs: Setting[String] = PathSetting(RootSetting, "javaextdirs", "Override java extdirs classpath.", Defaults.javaExtDirs, aliases = List("--java-extension-directories")) + val sourcepath: Setting[String] = PathSetting(RootSetting, "sourcepath", "Specify location(s) of source files.", Defaults.scalaSourcePath, aliases = List("--source-path")) + val sourceroot: Setting[String] = PathSetting(RootSetting, "sourceroot", "Specify workspace root directory.", ".") + + val classpath: Setting[String] = PathSetting(RootSetting, "classpath", "Specify where to find user class files.", ScalaSettings.defaultClasspath, aliases = List("-cp", "--class-path")) + val outputDir: Setting[AbstractFile] = OutputSetting(RootSetting, "d", "directory|jar", "Destination for generated classfiles.", new PlainDirectory(Directory("."))) - val color: Setting[String] = ChoiceSetting("-color", "mode", "Colored output", List("always", "never"/*, "auto"*/), "always"/* "auto"*/, aliases = List("--color")) - val verbose: Setting[Boolean] = BooleanSetting("-verbose", "Output messages about what the compiler is doing.", aliases = List("--verbose")) - val version: Setting[Boolean] = BooleanSetting("-version", "Print product version and exit.", aliases = List("--version")) - val help: Setting[Boolean] = BooleanSetting("-help", "Print a synopsis of standard options.", aliases = List("--help", "-h")) - val pageWidth: Setting[Int] = IntSetting("-pagewidth", "Set page width", ScalaSettings.defaultPageWidth, aliases = List("--page-width")) - val silentWarnings: Setting[Boolean] = BooleanSetting("-nowarn", "Silence all warnings.", aliases = List("--no-warnings")) - - val javaOutputVersion: Setting[String] = ChoiceSetting("-java-output-version", "version", "Compile code with classes specific to the given version of the Java platform available on the classpath and emit bytecode for this version. Corresponds to -release flag in javac.", ScalaSettings.supportedReleaseVersions, "", aliases = List("-release", "--release")) - - val deprecation: Setting[Boolean] = BooleanSetting("-deprecation", "Emit warning and location for usages of deprecated APIs.", aliases = List("--deprecation")) - val feature: Setting[Boolean] = BooleanSetting("-feature", "Emit warning and location for usages of features that should be imported explicitly.", aliases = List("--feature")) - val explain: Setting[Boolean] = BooleanSetting("-explain", "Explain errors in more detail.", aliases = List("--explain")) + val color: Setting[String] = ChoiceSetting(RootSetting, "color", "mode", "Colored output", List("always", "never"/*, "auto"*/), "always"/* "auto"*/, aliases = List("--color")) + val verbose: Setting[Boolean] = BooleanSetting(RootSetting, "verbose", "Output messages about what the compiler is doing.", aliases = List("--verbose")) + val version: Setting[Boolean] = BooleanSetting(RootSetting, "version", "Print product version and exit.", aliases = List("--version")) + val help: Setting[Boolean] = BooleanSetting(RootSetting, "help", "Print a synopsis of standard options.", aliases = List("--help", "-h")) + val pageWidth: Setting[Int] = IntSetting(RootSetting, "pagewidth", "Set page width", ScalaSettings.defaultPageWidth, aliases = List("--page-width")) + val silentWarnings: Setting[Boolean] = BooleanSetting(RootSetting, "nowarn", "Silence all warnings.", aliases = List("--no-warnings")) + + val javaOutputVersion: Setting[String] = ChoiceSetting(RootSetting, "java-output-version", "version", "Compile code with classes specific to the given version of the Java platform available on the classpath and emit bytecode for this version. Corresponds to -release flag in javac.", ScalaSettings.supportedReleaseVersions, "", aliases = List("-release", "--release")) + + val deprecation: Setting[Boolean] = BooleanSetting(RootSetting, "deprecation", "Emit warning and location for usages of deprecated APIs.", aliases = List("--deprecation")) + val feature: Setting[Boolean] = BooleanSetting(RootSetting, "feature", "Emit warning and location for usages of features that should be imported explicitly.", aliases = List("--feature")) + val explain: Setting[Boolean] = BooleanSetting(RootSetting, "explain", "Explain errors in more detail.", aliases = List("--explain")) // -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.") + val explainTypes: Setting[Boolean] = BooleanSetting(RootSetting, "explain-types", "Explain type errors in more detail (deprecated, use -explain instead).", aliases = List("--explain-types", "-explaintypes")) + val explainCyclic: Setting[Boolean] = BooleanSetting(RootSetting, "explain-cyclic", "Explain cyclic reference errors in more detail.", aliases = List("--explain-cyclic")) + val unchecked: Setting[Boolean] = BooleanSetting(RootSetting, "unchecked", "Enable additional warnings where generated code depends on assumptions.", initialValue = true, aliases = List("--unchecked")) + val language: Setting[List[String]] = MultiStringSetting(RootSetting, "language", "feature", "Enable one or more language features.", aliases = List("--language")) + val experimental: Setting[Boolean] = BooleanSetting(RootSetting, "experimental", "Annotate all top-level definitions with @experimental. This enables the use of experimental features anywhere in the project.") /* Coverage settings */ - val coverageOutputDir = PathSetting("-coverage-out", "Destination for coverage classfiles and instrumentation data.", "", aliases = List("--coverage-out")) - val coverageExcludeClasslikes: Setting[List[String]] = MultiStringSetting("-coverage-exclude-classlikes", "packages, classes and modules", "List of regexes for packages, classes and modules to exclude from coverage.", aliases = List("--coverage-exclude-classlikes")) - val coverageExcludeFiles: Setting[List[String]] = MultiStringSetting("-coverage-exclude-files", "files", "List of regexes for files to exclude from coverage.", aliases = List("--coverage-exclude-files")) + val coverageOutputDir = PathSetting(RootSetting, "coverage-out", "Destination for coverage classfiles and instrumentation data.", "", aliases = List("--coverage-out")) + val coverageExcludeClasslikes: Setting[List[String]] = MultiStringSetting(RootSetting, "coverage-exclude-classlikes", "packages, classes and modules", "List of regexes for packages, classes and modules to exclude from coverage.", aliases = List("--coverage-exclude-classlikes")) + val coverageExcludeFiles: Setting[List[String]] = MultiStringSetting(RootSetting, "coverage-exclude-files", "files", "List of regexes for files to exclude from coverage.", aliases = List("--coverage-exclude-files")) /* Other settings */ - val encoding: Setting[String] = StringSetting("-encoding", "encoding", "Specify character encoding used by source files.", Properties.sourceEncoding, aliases = List("--encoding")) - val usejavacp: Setting[Boolean] = BooleanSetting("-usejavacp", "Utilize the java.class.path in classpath resolution.", aliases = List("--use-java-class-path")) - val scalajs: Setting[Boolean] = BooleanSetting("-scalajs", "Compile in Scala.js mode (requires scalajs-library.jar on the classpath).", aliases = List("--scalajs")) + val encoding: Setting[String] = StringSetting(RootSetting, "encoding", "encoding", "Specify character encoding used by source files.", Properties.sourceEncoding, aliases = List("--encoding")) + val usejavacp: Setting[Boolean] = BooleanSetting(RootSetting, "usejavacp", "Utilize the java.class.path in classpath resolution.", aliases = List("--use-java-class-path")) + val scalajs: Setting[Boolean] = BooleanSetting(RootSetting, "scalajs", "Compile in Scala.js mode (requires scalajs-library.jar on the classpath).", aliases = List("--scalajs")) end CommonScalaSettings /** -P "plugin" settings. Various tools might support plugins. */ private sealed trait PluginSettings: self: SettingGroup => - val plugin: Setting[List[String]] = MultiStringSetting ("-Xplugin", "paths", "Load a plugin from each classpath.") - val disable: Setting[List[String]] = MultiStringSetting ("-Xplugin-disable", "plugin", "Disable plugins by name.") - val require: Setting[List[String]] = MultiStringSetting ("-Xplugin-require", "plugin", "Abort if a named plugin is not loaded.") - val showPlugins: Setting[Boolean] = BooleanSetting ("-Xplugin-list", "Print a synopsis of loaded plugins.") - val pluginsDir: Setting[String] = StringSetting ("-Xpluginsdir", "path", "Path to search for plugin archives.", Defaults.scalaPluginPath) - val pluginOptions: Setting[List[String]] = MultiStringSetting ("-P", "plugin:opt", "Pass an option to a plugin, e.g. -P::") + val plugin: Setting[List[String]] = MultiStringSetting (AdvancedSetting, "Xplugin", "paths", "Load a plugin from each classpath.") + val disable: Setting[List[String]] = MultiStringSetting (AdvancedSetting, "Xplugin-disable", "plugin", "Disable plugins by name.") + val require: Setting[List[String]] = MultiStringSetting (AdvancedSetting, "Xplugin-require", "plugin", "Abort if a named plugin is not loaded.") + val showPlugins: Setting[Boolean] = BooleanSetting (AdvancedSetting, "Xplugin-list", "Print a synopsis of loaded plugins.") + val pluginsDir: Setting[String] = StringSetting (AdvancedSetting, "Xpluginsdir", "path", "Path to search for plugin archives.", Defaults.scalaPluginPath) + val pluginOptions: Setting[List[String]] = MultiStringSetting (RootSetting, "P", "plugin:opt", "Pass an option to a plugin, e.g. -P::") /** -V "Verbose" settings */ private sealed trait VerboseSettings: self: SettingGroup => - val Vhelp: Setting[Boolean] = BooleanSetting("-V", "Print a synopsis of verbose options.") - val Xprint: Setting[List[String]] = PhasesSetting("-Vprint", "Print out program after", aliases = List("-Xprint")) - val XshowPhases: Setting[Boolean] = BooleanSetting("-Vphases", "List compiler phases.", aliases = List("-Xshow-phases")) + val Vhelp: Setting[Boolean] = BooleanSetting(VerboseSetting, "V", "Print a synopsis of verbose options.") + val Xprint: Setting[List[String]] = PhasesSetting(VerboseSetting, "Vprint", "Print out program after", aliases = List("-Xprint")) + val XshowPhases: Setting[Boolean] = BooleanSetting(VerboseSetting, "Vphases", "List compiler phases.", aliases = List("-Xshow-phases")) - val Vprofile: Setting[Boolean] = BooleanSetting("-Vprofile", "Show metrics about sources and internal representations to estimate compile-time complexity.") - val VprofileSortedBy = ChoiceSetting("-Vprofile-sorted-by", "key", "Show metrics about sources and internal representations sorted by given column name", List("name", "path", "lines", "tokens", "tasty", "complexity"), "") - val VprofileDetails = IntSetting("-Vprofile-details", "Show metrics about sources and internal representations of the most complex methods", 0) - val VreplMaxPrintElements: Setting[Int] = IntSetting("-Vrepl-max-print-elements", "Number of elements to be printed before output is truncated.", 1000) - val VreplMaxPrintCharacters: Setting[Int] = IntSetting("-Vrepl-max-print-characters", "Number of characters to be printed before output is truncated.", 50000) + val Vprofile: Setting[Boolean] = BooleanSetting(VerboseSetting, "Vprofile", "Show metrics about sources and internal representations to estimate compile-time complexity.") + val VprofileSortedBy = ChoiceSetting(VerboseSetting, "Vprofile-sorted-by", "key", "Show metrics about sources and internal representations sorted by given column name", List("name", "path", "lines", "tokens", "tasty", "complexity"), "") + val VprofileDetails = IntSetting(VerboseSetting, "Vprofile-details", "Show metrics about sources and internal representations of the most complex methods", 0) + val VreplMaxPrintElements: Setting[Int] = IntSetting(VerboseSetting, "Vrepl-max-print-elements", "Number of elements to be printed before output is truncated.", 1000) + val VreplMaxPrintCharacters: Setting[Int] = IntSetting(VerboseSetting, "Vrepl-max-print-characters", "Number of characters to be printed before output is truncated.", 50000) /** -W "Warnings" settings */ private sealed trait WarningSettings: self: SettingGroup => - val Whelp: Setting[Boolean] = BooleanSetting("-W", "Print a synopsis of warning options.") - val XfatalWarnings: Setting[Boolean] = BooleanSetting("-Werror", "Fail the compilation if there are any warnings.", aliases = List("-Xfatal-warnings")) - val WvalueDiscard: Setting[Boolean] = BooleanSetting("-Wvalue-discard", "Warn when non-Unit expression results are unused.") - val WNonUnitStatement = BooleanSetting("-Wnonunit-statement", "Warn when block statements are non-Unit expressions.") - val WenumCommentDiscard = BooleanSetting("-Wenum-comment-discard", "Warn when a comment ambiguously assigned to multiple enum cases is discarded.") - val WimplausiblePatterns = BooleanSetting("-Wimplausible-patterns", "Warn if comparison with a pattern value looks like it might always fail.") - val WunstableInlineAccessors = BooleanSetting("-WunstableInlineAccessors", "Warn an inline methods has references to non-stable binary APIs.") + val Whelp: Setting[Boolean] = BooleanSetting(WarningSetting, "-W", "Print a synopsis of warning options.") + val XfatalWarnings: Setting[Boolean] = BooleanSetting(WarningSetting, "-Werror", "Fail the compilation if there are any warnings.", aliases = List("-Xfatal-warnings")) + val WvalueDiscard: Setting[Boolean] = BooleanSetting(WarningSetting, "-Wvalue-discard", "Warn when non-Unit expression results are unused.") + val WNonUnitStatement = BooleanSetting(WarningSetting, "-Wnonunit-statement", "Warn when block statements are non-Unit expressions.") + val WenumCommentDiscard = BooleanSetting(WarningSetting, "-Wenum-comment-discard", "Warn when a comment ambiguously assigned to multiple enum cases is discarded.") + val WimplausiblePatterns = BooleanSetting(WarningSetting, "-Wimplausible-patterns", "Warn if comparison with a pattern value looks like it might always fail.") + val WunstableInlineAccessors = BooleanSetting(WarningSetting, "-WunstableInlineAccessors", "Warn an inline methods has references to non-stable binary APIs.") val Wunused: Setting[List[ChoiceWithHelp[String]]] = MultiChoiceHelpSetting( - name = "-Wunused", + WarningSetting, + name = "Wunused", helpArg = "warning", descr = "Enable or disable specific `unused` warnings", choices = List( @@ -231,7 +250,8 @@ private sealed trait WarningSettings: isChoiceSet("strict-no-implicit-warn") val Wconf: Setting[List[String]] = MultiStringSetting( - "-Wconf", + WarningSetting, + "Wconf", "patterns", default = List(), descr = @@ -277,47 +297,9 @@ private sealed trait WarningSettings: |to prevent the shell from expanding patterns.""".stripMargin, ) -/** -X "Extended" or "Advanced" settings */ -private sealed trait XSettings: - self: SettingGroup => - - val Xhelp: Setting[Boolean] = BooleanSetting("-X", "Print a synopsis of advanced options.") - val XnoForwarders: Setting[Boolean] = BooleanSetting("-Xno-forwarders", "Do not generate static forwarders in mirror classes.") - val XmaxInlines: Setting[Int] = IntSetting("-Xmax-inlines", "Maximal number of successive inlines.", 32) - val XmaxInlinedTrees: Setting[Int] = IntSetting("-Xmax-inlined-trees", "Maximal number of inlined trees.", 2_000_000) - val Xmigration: Setting[ScalaVersion] = VersionSetting("-Xmigration", "Warn about constructs whose behavior may have changed since version.") - val XprintTypes: Setting[Boolean] = BooleanSetting("-Xprint-types", "Print tree types (debugging option).") - val XprintDiff: Setting[Boolean] = BooleanSetting("-Xprint-diff", "Print changed parts of the tree since last print.") - val XprintDiffDel: Setting[Boolean] = BooleanSetting("-Xprint-diff-del", "Print changed parts of the tree since last print including deleted parts.") - val XprintInline: Setting[Boolean] = BooleanSetting("-Xprint-inline", "Show where inlined code comes from.") - val XprintSuspension: Setting[Boolean] = BooleanSetting("-Xprint-suspension", "Show when code is suspended until macros are compiled.") - val Xprompt: Setting[Boolean] = BooleanSetting("-Xprompt", "Display a prompt after each error (debugging option).") - val XreplDisableDisplay: Setting[Boolean] = BooleanSetting("-Xrepl-disable-display", "Do not display definitions in REPL.") - val XverifySignatures: Setting[Boolean] = BooleanSetting("-Xverify-signatures", "Verify generic signatures in generated bytecode.") - val XignoreScala2Macros: Setting[Boolean] = BooleanSetting("-Xignore-scala2-macros", "Ignore errors when compiling code that calls Scala2 macros, these will fail at runtime.") - val XimportSuggestionTimeout: Setting[Int] = IntSetting("-Ximport-suggestion-timeout", "Timeout (in ms) for searching for import suggestions when errors are reported.", 8000) - val Xsemanticdb: Setting[Boolean] = BooleanSetting("-Xsemanticdb", "Store information in SemanticDB.", aliases = List("-Ysemanticdb")) - val XuncheckedJavaOutputVersion: Setting[String] = ChoiceSetting("-Xunchecked-java-output-version", "target", "Emit bytecode for the specified version of the Java platform. This might produce bytecode that will break at runtime. Corresponds to -target flag in javac. When on JDK 9+, consider -java-output-version as a safer alternative.", ScalaSettings.supportedTargetVersions, "", aliases = List("-Xtarget", "--Xtarget")) - val XcheckMacros: Setting[Boolean] = BooleanSetting("-Xcheck-macros", "Check some invariants of macro generated code while expanding macros", aliases = List("--Xcheck-macros")) - val XmainClass: Setting[String] = StringSetting("-Xmain-class", "path", "Class for manifest's Main-Class entry (only useful with -d )", "") - val XimplicitSearchLimit: Setting[Int] = IntSetting("-Ximplicit-search-limit", "Maximal number of expressions to be generated in an implicit search", 50000) - - val XmixinForceForwarders = ChoiceSetting( - name = "-Xmixin-force-forwarders", - helpArg = "mode", - descr = "Generate forwarder methods in classes inhering concrete methods from traits.", - choices = List("true", "junit", "false"), - default = "true") - - object mixinForwarderChoices { - def isTruthy(using Context) = XmixinForceForwarders.value == "true" - def isAtLeastJunit(using Context) = isTruthy || XmixinForceForwarders.value == "junit" - } - - val XmacroSettings: Setting[List[String]] = MultiStringSetting("-Xmacro-settings", "setting1,setting2,..settingN", "List of settings which exposed to the macros") - val Xlint: Setting[List[ChoiceWithHelp[String]]] = UncompleteMultiChoiceHelpSetting( - name = "-Xlint", + AdvancedSetting, + name = "Xlint", helpArg = "advanced warning", descr = "Enable or disable specific `lint` warnings", choices = List( @@ -336,111 +318,150 @@ private sealed trait XSettings: def typeParameterShadow(using Context) = allOr("type-parameter-shadow") + +/** -X "Extended" or "Advanced" settings */ +private sealed trait XSettings: + self: SettingGroup => + + val Xhelp: Setting[Boolean] = BooleanSetting(AdvancedSetting, "X", "Print a synopsis of advanced options.") + val XnoForwarders: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xno-forwarders", "Do not generate static forwarders in mirror classes.") + val XmaxInlines: Setting[Int] = IntSetting(AdvancedSetting, "Xmax-inlines", "Maximal number of successive inlines.", 32) + val XmaxInlinedTrees: Setting[Int] = IntSetting(AdvancedSetting, "Xmax-inlined-trees", "Maximal number of inlined trees.", 2_000_000) + val Xmigration: Setting[ScalaVersion] = VersionSetting(AdvancedSetting, "Xmigration", "Warn about constructs whose behavior may have changed since version.") + val XprintTypes: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xprint-types", "Print tree types (debugging option).") + val XprintDiff: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xprint-diff", "Print changed parts of the tree since last print.") + val XprintDiffDel: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xprint-diff-del", "Print changed parts of the tree since last print including deleted parts.") + val XprintInline: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xprint-inline", "Show where inlined code comes from.") + val XprintSuspension: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xprint-suspension", "Show when code is suspended until macros are compiled.") + val Xprompt: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xprompt", "Display a prompt after each error (debugging option).") + val XreplDisableDisplay: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xrepl-disable-display", "Do not display definitions in REPL.") + val XverifySignatures: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xverify-signatures", "Verify generic signatures in generated bytecode.") + val XignoreScala2Macros: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xignore-scala2-macros", "Ignore errors when compiling code that calls Scala2 macros, these will fail at runtime.") + val XimportSuggestionTimeout: Setting[Int] = IntSetting(AdvancedSetting, "Ximport-suggestion-timeout", "Timeout (in ms) for searching for import suggestions when errors are reported.", 8000) + val Xsemanticdb: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xsemanticdb", "Store information in SemanticDB.", aliases = List("-Ysemanticdb")) + val XuncheckedJavaOutputVersion: Setting[String] = ChoiceSetting(AdvancedSetting, "Xunchecked-java-output-version", "target", "Emit bytecode for the specified version of the Java platform. This might produce bytecode that will break at runtime. Corresponds to -target flag in javac. When on JDK 9+, consider -java-output-version as a safer alternative.", ScalaSettings.supportedTargetVersions, "", aliases = List("-Xtarget", "--Xtarget")) + val XcheckMacros: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xcheck-macros", "Check some invariants of macro generated code while expanding macros", aliases = List("--Xcheck-macros")) + val XmainClass: Setting[String] = StringSetting(AdvancedSetting, "Xmain-class", "path", "Class for manifest's Main-Class entry (only useful with -d )", "") + val XimplicitSearchLimit: Setting[Int] = IntSetting(AdvancedSetting, "Ximplicit-search-limit", "Maximal number of expressions to be generated in an implicit search", 50000) + + val XmixinForceForwarders = ChoiceSetting( + AdvancedSetting, + name = "Xmixin-force-forwarders", + helpArg = "mode", + descr = "Generate forwarder methods in classes inhering concrete methods from traits.", + choices = List("true", "junit", "false"), + default = "true") + + object mixinForwarderChoices { + def isTruthy(using Context) = XmixinForceForwarders.value == "true" + def isAtLeastJunit(using Context) = isTruthy || XmixinForceForwarders.value == "junit" + } + + val XmacroSettings: Setting[List[String]] = MultiStringSetting(AdvancedSetting, "Xmacro-settings", "setting1,setting2,..settingN", "List of settings which exposed to the macros") end XSettings /** -Y "Forking" as in forked tongue or "Private" settings */ private sealed trait YSettings: self: SettingGroup => - val Yhelp: Setting[Boolean] = BooleanSetting("-Y", "Print a synopsis of private options.") - val Ycheck: Setting[List[String]] = PhasesSetting("-Ycheck", "Check the tree at the end of") - val YcheckMods: Setting[Boolean] = BooleanSetting("-Ycheck-mods", "Check that symbols and their defining trees have modifiers in sync.") - val Ydebug: Setting[Boolean] = BooleanSetting("-Ydebug", "Increase the quantity of debugging output.") - val YdebugTrace: Setting[Boolean] = BooleanSetting("-Ydebug-trace", "Trace core operations.") - val YdebugFlags: Setting[Boolean] = BooleanSetting("-Ydebug-flags", "Print all flags of definitions.") - val YdebugMissingRefs: Setting[Boolean] = BooleanSetting("-Ydebug-missing-refs", "Print a stacktrace when a required symbol is missing.") - val YdebugNames: Setting[Boolean] = BooleanSetting("-Ydebug-names", "Show internal representation of names.") - val YdebugPos: Setting[Boolean] = BooleanSetting("-Ydebug-pos", "Show full source positions including spans.") - val YdebugTreeWithId: Setting[Int] = IntSetting("-Ydebug-tree-with-id", "Print the stack trace when the tree with the given id is created.", Int.MinValue) - 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.") - val YdisableFlatCpCaching: Setting[Boolean] = BooleanSetting("-YdisableFlatCpCaching", "Do not cache flat classpath representation of classpath elements from jars across compiler instances.") - - val Yscala2Unpickler: Setting[String] = StringSetting("-Yscala2-unpickler", "", "Control where we may get Scala 2 symbols from. This is either \"always\", \"never\", or a classpath.", "always") - - val YnoImports: Setting[Boolean] = BooleanSetting("-Yno-imports", "Compile without importing scala.*, java.lang.*, or Predef.") - val Yimports: Setting[List[String]] = MultiStringSetting("-Yimports", helpArg="", "Custom root imports. If set, none of scala.*, java.lang.*, or Predef.* will be imported unless explicitly included.") - val YnoGenericSig: Setting[Boolean] = BooleanSetting("-Yno-generic-signatures", "Suppress generation of generic signatures for Java.") - val YnoPredef: Setting[Boolean] = BooleanSetting("-Yno-predef", "Compile without importing Predef.") - val Yskip: Setting[List[String]] = PhasesSetting("-Yskip", "Skip") - val Ydumpclasses: Setting[String] = StringSetting("-Ydump-classes", "dir", "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders).", "") - val YjarCompressionLevel: Setting[Int] = IntChoiceSetting("-Yjar-compression-level", "compression level to use when writing jar files", Deflater.DEFAULT_COMPRESSION to Deflater.BEST_COMPRESSION, Deflater.DEFAULT_COMPRESSION) - val YbackendParallelism: Setting[Int] = IntChoiceSetting("-Ybackend-parallelism", "maximum worker threads for backend", 1 to 16, 1) - val YbackendWorkerQueue: Setting[Int] = IntChoiceSetting("-Ybackend-worker-queue", "backend threads worker queue size", 0 to 1000, 0) - val YstopAfter: Setting[List[String]] = PhasesSetting("-Ystop-after", "Stop after", aliases = List("-stop")) // backward compat - val YstopBefore: Setting[List[String]] = PhasesSetting("-Ystop-before", "Stop before") // stop before erasure as long as we have not debugged it fully - val YshowSuppressedErrors: Setting[Boolean] = BooleanSetting("-Yshow-suppressed-errors", "Also show follow-on errors and warnings that are normally suppressed.") - val YdetailedStats: Setting[Boolean] = BooleanSetting("-Ydetailed-stats", "Show detailed internal compiler stats (needs Stats.enabled to be set to true).") - val YkindProjector: Setting[String] = ChoiceSetting("-Ykind-projector", "[underscores, disable]", "Allow `*` as type lambda placeholder to be compatible with kind projector. When invoked as -Ykind-projector:underscores will repurpose `_` to be a type parameter placeholder, this will disable usage of underscore as a wildcard.", List("disable", "", "underscores"), "disable") - val YprintPos: Setting[Boolean] = BooleanSetting("-Yprint-pos", "Show tree positions.") - val YprintPosSyms: Setting[Boolean] = BooleanSetting("-Yprint-pos-syms", "Show symbol definitions positions.") - val YnoDeepSubtypes: Setting[Boolean] = BooleanSetting("-Yno-deep-subtypes", "Throw an exception on deep subtyping call stacks.") - val YnoPatmatOpt: Setting[Boolean] = BooleanSetting("-Yno-patmat-opt", "Disable all pattern matching optimizations.") - val YplainPrinter: Setting[Boolean] = BooleanSetting("-Yplain-printer", "Pretty-print using a plain printer.") - val YprintSyms: Setting[Boolean] = BooleanSetting("-Yprint-syms", "When printing trees print info in symbols instead of corresponding info in trees.") - val YprintDebug: Setting[Boolean] = BooleanSetting("-Yprint-debug", "When printing trees, print some extra information useful for debugging.") - val YprintDebugOwners: Setting[Boolean] = BooleanSetting("-Yprint-debug-owners", "When printing trees, print owners of definitions.") - val YprintLevel: Setting[Boolean] = BooleanSetting("-Yprint-level", "print nesting levels of symbols and type variables.") - val YshowPrintErrors: Setting[Boolean] = BooleanSetting("-Yshow-print-errors", "Don't suppress exceptions thrown during tree printing.") - val YprintTasty: Setting[Boolean] = BooleanSetting("-Yprint-tasty", "Prints the generated TASTY to stdout.") - val YtestPickler: Setting[Boolean] = BooleanSetting("-Ytest-pickler", "Self-test for pickling functionality; should be used with -Ystop-after:pickler.") - val YtestPicklerCheck: Setting[Boolean] = BooleanSetting("-Ytest-pickler-check", "Self-test for pickling -print-tasty output; should be used with -Ytest-pickler.") - val YcheckReentrant: Setting[Boolean] = BooleanSetting("-Ycheck-reentrant", "Check that compiled program does not contain vars that can be accessed from a global root.") - val YdropComments: Setting[Boolean] = BooleanSetting("-Ydrop-docs", "Drop documentation when scanning source files.", aliases = List("-Ydrop-comments")) - val YcookComments: Setting[Boolean] = BooleanSetting("-Ycook-docs", "Cook the documentation (type check `@usecase`, etc.)", aliases = List("-Ycook-comments")) - val YreadComments: Setting[Boolean] = BooleanSetting("-Yread-docs", "Read documentation from tasty.") - val YforceSbtPhases: Setting[Boolean] = BooleanSetting("-Yforce-sbt-phases", "Run the phases used by sbt for incremental compilation (ExtractDependencies and ExtractAPI) even if the compiler is ran outside of sbt, for debugging.") - val YdumpSbtInc: Setting[Boolean] = BooleanSetting("-Ydump-sbt-inc", "For every compiled foo.scala, output the API representation and dependencies used for sbt incremental compilation in foo.inc, implies -Yforce-sbt-phases.") - val YcheckAllPatmat: Setting[Boolean] = BooleanSetting("-Ycheck-all-patmat", "Check exhaustivity and redundancy of all pattern matching (used for testing the algorithm).") - val YcheckConstraintDeps: Setting[Boolean] = BooleanSetting("-Ycheck-constraint-deps", "Check dependency tracking in constraints (used for testing the algorithm).") - val YretainTrees: Setting[Boolean] = BooleanSetting("-Yretain-trees", "Retain trees for top-level classes, accessible from ClassSymbol#tree") - val YshowTreeIds: Setting[Boolean] = BooleanSetting("-Yshow-tree-ids", "Uniquely tag all tree nodes in debugging output.") - val YfromTastyIgnoreList: Setting[List[String]] = MultiStringSetting("-Yfrom-tasty-ignore-list", "file", "List of `tasty` files in jar files that will not be loaded when using -from-tasty.") - val YnoExperimental: Setting[Boolean] = BooleanSetting("-Yno-experimental", "Disable experimental language features by default in NIGHTLY/SNAPSHOT versions of the compiler.") - val YlegacyLazyVals: Setting[Boolean] = BooleanSetting("-Ylegacy-lazy-vals", "Use legacy (pre 3.3.0) implementation of lazy vals.") - val YcompileScala2Library: Setting[Boolean] = BooleanSetting("-Ycompile-scala2-library", "Used when compiling the Scala 2 standard library.") - val YoutputOnlyTasty: Setting[Boolean] = BooleanSetting("-Youtput-only-tasty", "Used to only generate the TASTy file without the classfiles") - - val YprofileEnabled: Setting[Boolean] = BooleanSetting("-Yprofile-enabled", "Enable profiling.") - val YprofileDestination: Setting[String] = StringSetting("-Yprofile-destination", "file", "Where to send profiling output - specify a file, default is to the console.", "") + val Yhelp: Setting[Boolean] = BooleanSetting(ForkSetting, "Y", "Print a synopsis of private options.") + val Ycheck: Setting[List[String]] = PhasesSetting(ForkSetting, "Ycheck", "Check the tree at the end of") + val YcheckMods: Setting[Boolean] = BooleanSetting(ForkSetting, "Ycheck-mods", "Check that symbols and their defining trees have modifiers in sync.") + val Ydebug: Setting[Boolean] = BooleanSetting(ForkSetting, "Ydebug", "Increase the quantity of debugging output.") + val YdebugTrace: Setting[Boolean] = BooleanSetting(ForkSetting, "Ydebug-trace", "Trace core operations.") + val YdebugFlags: Setting[Boolean] = BooleanSetting(ForkSetting, "Ydebug-flags", "Print all flags of definitions.") + val YdebugMissingRefs: Setting[Boolean] = BooleanSetting(ForkSetting, "Ydebug-missing-refs", "Print a stacktrace when a required symbol is missing.") + val YdebugNames: Setting[Boolean] = BooleanSetting(ForkSetting, "Ydebug-names", "Show internal representation of names.") + val YdebugPos: Setting[Boolean] = BooleanSetting(ForkSetting, "Ydebug-pos", "Show full source positions including spans.") + val YdebugTreeWithId: Setting[Int] = IntSetting(ForkSetting, "Ydebug-tree-with-id", "Print the stack trace when the tree with the given id is created.", Int.MinValue) + val YdebugTypeError: Setting[Boolean] = BooleanSetting(ForkSetting, "Ydebug-type-error", "Print the stack trace when a TypeError is caught", false) + val YdebugError: Setting[Boolean] = BooleanSetting(ForkSetting, "Ydebug-error", "Print the stack trace when any error is caught.", false) + val YdebugUnpickling: Setting[Boolean] = BooleanSetting(ForkSetting, "Ydebug-unpickling", "Print the stack trace when an error occurs when reading Tasty.", false) + val YdebugCyclic: Setting[Boolean] = BooleanSetting(ForkSetting, "Ydebug-cyclic", "Print the stack trace when a cyclic reference error occurs.", false) + val YtermConflict: Setting[String] = ChoiceSetting(ForkSetting, "Yresolve-term-conflict", "strategy", "Resolve term conflicts", List("package", "object", "error"), "error") + val Ylog: Setting[List[String]] = PhasesSetting(ForkSetting, "Ylog", "Log operations during") + val YlogClasspath: Setting[Boolean] = BooleanSetting(ForkSetting, "Ylog-classpath", "Output information about what classpath is being applied.") + val YdisableFlatCpCaching: Setting[Boolean] = BooleanSetting(ForkSetting, "YdisableFlatCpCaching", "Do not cache flat classpath representation of classpath elements from jars across compiler instances.") + + val Yscala2Unpickler: Setting[String] = StringSetting(ForkSetting, "Yscala2-unpickler", "", "Control where we may get Scala 2 symbols from. This is either \"always\", \"never\", or a classpath.", "always") + + val YnoImports: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-imports", "Compile without importing scala.*, java.lang.*, or Predef.") + val Yimports: Setting[List[String]] = MultiStringSetting(ForkSetting, "Yimports", helpArg="", "Custom root imports. If set, none of scala.*, java.lang.*, or Predef.* will be imported unless explicitly included.") + val YnoGenericSig: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-generic-signatures", "Suppress generation of generic signatures for Java.") + val YnoPredef: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-predef", "Compile without importing Predef.") + val Yskip: Setting[List[String]] = PhasesSetting(ForkSetting, "Yskip", "Skip") + val Ydumpclasses: Setting[String] = StringSetting(ForkSetting, "Ydump-classes", "dir", "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders).", "") + val YjarCompressionLevel: Setting[Int] = IntChoiceSetting(ForkSetting, "Yjar-compression-level", "compression level to use when writing jar files", Deflater.DEFAULT_COMPRESSION to Deflater.BEST_COMPRESSION, Deflater.DEFAULT_COMPRESSION) + val YbackendParallelism: Setting[Int] = IntChoiceSetting(ForkSetting, "Ybackend-parallelism", "maximum worker threads for backend", 1 to 16, 1) + val YbackendWorkerQueue: Setting[Int] = IntChoiceSetting(ForkSetting, "Ybackend-worker-queue", "backend threads worker queue size", 0 to 1000, 0) + val YstopAfter: Setting[List[String]] = PhasesSetting(ForkSetting, "Ystop-after", "Stop after", aliases = List("-stop")) // backward compat + val YstopBefore: Setting[List[String]] = PhasesSetting(ForkSetting, "Ystop-before", "Stop before") // stop before erasure as long as we have not debugged it fully + val YshowSuppressedErrors: Setting[Boolean] = BooleanSetting(ForkSetting, "Yshow-suppressed-errors", "Also show follow-on errors and warnings that are normally suppressed.") + val YdetailedStats: Setting[Boolean] = BooleanSetting(ForkSetting, "Ydetailed-stats", "Show detailed internal compiler stats (needs Stats.enabled to be set to true).") + val YkindProjector: Setting[String] = ChoiceSetting(ForkSetting, "Ykind-projector", "[underscores, disable]", "Allow `*` as type lambda placeholder to be compatible with kind projector. When invoked as -Ykind-projector:underscores will repurpose `_` to be a type parameter placeholder, this will disable usage of underscore as a wildcard.", List("disable", "", "underscores"), "disable") + val YprintPos: Setting[Boolean] = BooleanSetting(ForkSetting, "Yprint-pos", "Show tree positions.") + val YprintPosSyms: Setting[Boolean] = BooleanSetting(ForkSetting, "Yprint-pos-syms", "Show symbol definitions positions.") + val YnoDeepSubtypes: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-deep-subtypes", "Throw an exception on deep subtyping call stacks.") + val YnoPatmatOpt: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-patmat-opt", "Disable all pattern matching optimizations.") + val YplainPrinter: Setting[Boolean] = BooleanSetting(ForkSetting, "Yplain-printer", "Pretty-print using a plain printer.") + val YprintSyms: Setting[Boolean] = BooleanSetting(ForkSetting, "Yprint-syms", "When printing trees print info in symbols instead of corresponding info in trees.") + val YprintDebug: Setting[Boolean] = BooleanSetting(ForkSetting, "Yprint-debug", "When printing trees, print some extra information useful for debugging.") + val YprintDebugOwners: Setting[Boolean] = BooleanSetting(ForkSetting, "Yprint-debug-owners", "When printing trees, print owners of definitions.") + val YprintLevel: Setting[Boolean] = BooleanSetting(ForkSetting, "Yprint-level", "print nesting levels of symbols and type variables.") + val YshowPrintErrors: Setting[Boolean] = BooleanSetting(ForkSetting, "Yshow-print-errors", "Don't suppress exceptions thrown during tree printing.") + val YprintTasty: Setting[Boolean] = BooleanSetting(ForkSetting, "Yprint-tasty", "Prints the generated TASTY to stdout.") + val YtestPickler: Setting[Boolean] = BooleanSetting(ForkSetting, "Ytest-pickler", "Self-test for pickling functionality; should be used with -Ystop-after:pickler.") + val YtestPicklerCheck: Setting[Boolean] = BooleanSetting(ForkSetting, "Ytest-pickler-check", "Self-test for pickling -print-tasty output; should be used with -Ytest-pickler.") + val YcheckReentrant: Setting[Boolean] = BooleanSetting(ForkSetting, "Ycheck-reentrant", "Check that compiled program does not contain vars that can be accessed from a global root.") + val YdropComments: Setting[Boolean] = BooleanSetting(ForkSetting, "Ydrop-docs", "Drop documentation when scanning source files.", aliases = List("-Ydrop-comments")) + val YcookComments: Setting[Boolean] = BooleanSetting(ForkSetting, "Ycook-docs", "Cook the documentation (type check `@usecase`, etc.)", aliases = List("-Ycook-comments")) + val YreadComments: Setting[Boolean] = BooleanSetting(ForkSetting, "Yread-docs", "Read documentation from tasty.") + val YforceSbtPhases: Setting[Boolean] = BooleanSetting(ForkSetting, "Yforce-sbt-phases", "Run the phases used by sbt for incremental compilation (ExtractDependencies and ExtractAPI) even if the compiler is ran outside of sbt, for debugging.") + val YdumpSbtInc: Setting[Boolean] = BooleanSetting(ForkSetting, "Ydump-sbt-inc", "For every compiled foo.scala, output the API representation and dependencies used for sbt incremental compilation in foo.inc, implies -Yforce-sbt-phases.") + val YcheckAllPatmat: Setting[Boolean] = BooleanSetting(ForkSetting, "Ycheck-all-patmat", "Check exhaustivity and redundancy of all pattern matching (used for testing the algorithm).") + val YcheckConstraintDeps: Setting[Boolean] = BooleanSetting(ForkSetting, "Ycheck-constraint-deps", "Check dependency tracking in constraints (used for testing the algorithm).") + val YretainTrees: Setting[Boolean] = BooleanSetting(ForkSetting, "Yretain-trees", "Retain trees for top-level classes, accessible from ClassSymbol#tree") + val YshowTreeIds: Setting[Boolean] = BooleanSetting(ForkSetting, "Yshow-tree-ids", "Uniquely tag all tree nodes in debugging output.") + val YfromTastyIgnoreList: Setting[List[String]] = MultiStringSetting(ForkSetting, "Yfrom-tasty-ignore-list", "file", "List of `tasty` files in jar files that will not be loaded when using -from-tasty.") + val YnoExperimental: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-experimental", "Disable experimental language features by default in NIGHTLY/SNAPSHOT versions of the compiler.") + val YlegacyLazyVals: Setting[Boolean] = BooleanSetting(ForkSetting, "Ylegacy-lazy-vals", "Use legacy (pre 3.3.0) implementation of lazy vals.") + val YcompileScala2Library: Setting[Boolean] = BooleanSetting(ForkSetting, "Ycompile-scala2-library", "Used when compiling the Scala 2 standard library.") + val YoutputOnlyTasty: Setting[Boolean] = BooleanSetting(ForkSetting, "Youtput-only-tasty", "Used to only generate the TASTy file without the classfiles") + val YprofileEnabled: Setting[Boolean] = BooleanSetting(ForkSetting, "Yprofile-enabled", "Enable profiling.") + val YprofileDestination: Setting[String] = StringSetting(ForkSetting, "Yprofile-destination", "file", "Where to send profiling output - specify a file, default is to the console.", "") //.withPostSetHook( _ => YprofileEnabled.value = true ) - val YprofileExternalTool: Setting[List[String]] = PhasesSetting("-Yprofile-external-tool", "Enable profiling for a phase using an external tool hook. Generally only useful for a single phase.", "typer") + val YprofileExternalTool: Setting[List[String]] = PhasesSetting(ForkSetting, "Yprofile-external-tool", "Enable profiling for a phase using an external tool hook. Generally only useful for a single phase.", "typer") //.withPostSetHook( _ => YprofileEnabled.value = true ) - val YprofileRunGcBetweenPhases: Setting[List[String]] = PhasesSetting("-Yprofile-run-gc", "Run a GC between phases - this allows heap size to be accurate at the expense of more time. Specify a list of phases, or *", "_") + val YprofileRunGcBetweenPhases: Setting[List[String]] = PhasesSetting(ForkSetting, "Yprofile-run-gc", "Run a GC between phases - this allows heap size to be accurate at the expense of more time. Specify a list of phases, or *", "_") //.withPostSetHook( _ => YprofileEnabled.value = true ) // Experimental language features - val YnoKindPolymorphism: Setting[Boolean] = BooleanSetting("-Yno-kind-polymorphism", "Disable kind polymorphism.") - val YexplicitNulls: Setting[Boolean] = BooleanSetting("-Yexplicit-nulls", "Make reference types non-nullable. Nullable types can be expressed with unions: e.g. String|Null.") - val YcheckInit: Setting[Boolean] = BooleanSetting("-Ysafe-init", "Ensure safe initialization of objects.") - val YcheckInitGlobal: Setting[Boolean] = BooleanSetting("-Ysafe-init-global", "Check safe initialization of global objects.") - val YrequireTargetName: Setting[Boolean] = BooleanSetting("-Yrequire-targetName", "Warn if an operator is defined without a @targetName annotation.") - val YrecheckTest: Setting[Boolean] = BooleanSetting("-Yrecheck-test", "Run basic rechecking (internal test only).") - val YccDebug: Setting[Boolean] = BooleanSetting("-Ycc-debug", "Used in conjunction with captureChecking language import, debug info for captured references.") - val YccNew: Setting[Boolean] = BooleanSetting("-Ycc-new", "Used in conjunction with captureChecking language import, try out new variants (debug option)") - val YccLog: Setting[Boolean] = BooleanSetting("-Ycc-log", "Used in conjunction with captureChecking language import, print tracing and debug info") - val YccPrintSetup: Setting[Boolean] = BooleanSetting("-Ycc-print-setup", "Used in conjunction with captureChecking language import, print trees after cc.Setup phase") + val YnoKindPolymorphism: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-kind-polymorphism", "Disable kind polymorphism.") + val YexplicitNulls: Setting[Boolean] = BooleanSetting(ForkSetting, "Yexplicit-nulls", "Make reference types non-nullable. Nullable types can be expressed with unions: e.g. String|Null.") + val YcheckInit: Setting[Boolean] = BooleanSetting(ForkSetting, "Ysafe-init", "Ensure safe initialization of objects.") + val YcheckInitGlobal: Setting[Boolean] = BooleanSetting(ForkSetting, "Ysafe-init-global", "Check safe initialization of global objects.") + val YrequireTargetName: Setting[Boolean] = BooleanSetting(ForkSetting, "Yrequire-targetName", "Warn if an operator is defined without a @targetName annotation.") + val YrecheckTest: Setting[Boolean] = BooleanSetting(ForkSetting, "Yrecheck-test", "Run basic rechecking (internal test only).") + val YccDebug: Setting[Boolean] = BooleanSetting(ForkSetting, "Ycc-debug", "Used in conjunction with captureChecking language import, debug info for captured references.") + val YccNew: Setting[Boolean] = BooleanSetting(ForkSetting, "Ycc-new", "Used in conjunction with captureChecking language import, try out new variants (debug option)") + val YccLog: Setting[Boolean] = BooleanSetting(ForkSetting, "Ycc-log", "Used in conjunction with captureChecking language import, print tracing and debug info") + val YccPrintSetup: Setting[Boolean] = BooleanSetting(ForkSetting, "Ycc-print-setup", "Used in conjunction with captureChecking language import, print trees after cc.Setup phase") /** Area-specific debug output */ - val YexplainLowlevel: Setting[Boolean] = BooleanSetting("-Yexplain-lowlevel", "When explaining type errors, show types at a lower level.") - val YnoDoubleBindings: Setting[Boolean] = BooleanSetting("-Yno-double-bindings", "Assert no namedtype is bound twice (should be enabled only if program is error-free).") - val YshowVarBounds: Setting[Boolean] = BooleanSetting("-Yshow-var-bounds", "Print type variables with their bounds.") + val YexplainLowlevel: Setting[Boolean] = BooleanSetting(ForkSetting, "Yexplain-lowlevel", "When explaining type errors, show types at a lower level.") + val YnoDoubleBindings: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-double-bindings", "Assert no namedtype is bound twice (should be enabled only if program is error-free).") + val YshowVarBounds: Setting[Boolean] = BooleanSetting(ForkSetting, "Yshow-var-bounds", "Print type variables with their bounds.") - val YnoDecodeStacktraces: Setting[Boolean] = BooleanSetting("-Yno-decode-stacktraces", "Show raw StackOverflow stacktraces, instead of decoding them into triggering operations.") - val YnoEnrichErrorMessages: Setting[Boolean] = BooleanSetting("-Yno-enrich-error-messages", "Show raw error messages, instead of enriching them with contextual information.") + val YnoDecodeStacktraces: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-decode-stacktraces", "Show raw StackOverflow stacktraces, instead of decoding them into triggering operations.") + val YnoEnrichErrorMessages: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-enrich-error-messages", "Show raw error messages, instead of enriching them with contextual information.") - val Yinstrument: Setting[Boolean] = BooleanSetting("-Yinstrument", "Add instrumentation code that counts allocations and closure creations.") - val YinstrumentDefs: Setting[Boolean] = BooleanSetting("-Yinstrument-defs", "Add instrumentation code that counts method calls; needs -Yinstrument to be set, too.") + val Yinstrument: Setting[Boolean] = BooleanSetting(ForkSetting, "Yinstrument", "Add instrumentation code that counts allocations and closure creations.") + val YinstrumentDefs: Setting[Boolean] = BooleanSetting(ForkSetting, "Yinstrument-defs", "Add instrumentation code that counts method calls; needs -Yinstrument to be set, too.") - val YdebugMacros: Setting[Boolean] = BooleanSetting("-Ydebug-macros", "Show debug info when quote pattern match fails") + val YdebugMacros: Setting[Boolean] = BooleanSetting(ForkSetting, "Ydebug-macros", "Show debug info when quote pattern match fails") // Pipeline compilation options - val YjavaTasty: Setting[Boolean] = BooleanSetting("-Yjava-tasty", "Pickler phase should compute pickles for .java defined symbols for use by build tools") - val YjavaTastyOutput: Setting[AbstractFile] = OutputSetting("-Yjava-tasty-output", "directory|jar", "(Internal use only!) destination for generated .tasty files containing Java type signatures.", NoAbstractFile) - val YallowOutlineFromTasty: Setting[Boolean] = BooleanSetting("-Yallow-outline-from-tasty", "Allow outline TASTy to be loaded with the -from-tasty option.") + val YjavaTasty: Setting[Boolean] = BooleanSetting(ForkSetting, "Yjava-tasty", "Pickler phase should compute pickles for .java defined symbols for use by build tools") + val YjavaTastyOutput: Setting[AbstractFile] = OutputSetting(ForkSetting, "Yjava-tasty-output", "directory|jar", "(Internal use only!) destination for generated .tasty files containing Java type signatures.", NoAbstractFile) + val YallowOutlineFromTasty: Setting[Boolean] = BooleanSetting(ForkSetting, "Yallow-outline-from-tasty", "Allow outline TASTy to be loaded with the -from-tasty option.") end YSettings diff --git a/compiler/src/dotty/tools/dotc/config/Settings.scala b/compiler/src/dotty/tools/dotc/config/Settings.scala index 79eb2b882f8f..961bca4da121 100644 --- a/compiler/src/dotty/tools/dotc/config/Settings.scala +++ b/compiler/src/dotty/tools/dotc/config/Settings.scala @@ -9,6 +9,7 @@ import dotty.tools.io.{AbstractFile, Directory, JarArchive, PlainDirectory} import annotation.tailrec import collection.mutable.ArrayBuffer +import collection.mutable import reflect.ClassTag import scala.util.{Success, Failure} import dotty.tools.dotc.config.Settings.Setting.ChoiceWithHelp @@ -23,8 +24,9 @@ object Settings: val OptionTag: ClassTag[Option[?]] = ClassTag(classOf[Option[?]]) val OutputTag: ClassTag[AbstractFile] = ClassTag(classOf[AbstractFile]) - class SettingsState(initialValues: Seq[Any]): + class SettingsState(initialValues: Seq[Any], initialChanged: Set[Int] = Set.empty): private val values = ArrayBuffer(initialValues*) + private val changed: mutable.Set[Int] = initialChanged.to(mutable.Set) private var _wasRead: Boolean = false override def toString: String = s"SettingsState(values: ${values.toList})" @@ -33,10 +35,13 @@ object Settings: _wasRead = true values(idx) + def wasChanged(idx: Int): Boolean = changed.contains(idx) + def update(idx: Int, x: Any): SettingsState = - if (_wasRead) then SettingsState(values.toSeq).update(idx, x) + if (_wasRead) then SettingsState(values.toSeq, changed.toSet).update(idx, x) else values(idx) = x + changed.add(idx) this end SettingsState @@ -54,18 +59,21 @@ object Settings: } case class Setting[T: ClassTag] private[Settings] ( + category: String, name: String, description: String, default: T, helpArg: String = "", choices: Option[Seq[?]] = None, - prefix: String = "", + prefix: Option[String] = None, aliases: List[String] = Nil, depends: List[(Setting[?], Any)] = Nil, ignoreInvalidArgs: Boolean = false, propertyClass: Option[Class[?]] = None)(private[Settings] val idx: Int) { - private var changed: Boolean = false + assert(name.startsWith(s"-$category"), s"Setting $name does not start with category -$category") + + val allFullNames: List[String] = s"$name" :: s"-$name" :: aliases def valueIn(state: SettingsState): T = state.value(idx).asInstanceOf[T] @@ -77,6 +85,8 @@ object Settings: def isMultivalue: Boolean = summon[ClassTag[T]] == ListTag + def acceptsNoArg: Boolean = summon[ClassTag[T]] == BooleanTag || summon[ClassTag[T]] == OptionTag || choices.exists(_.contains("")) + def legalChoices: String = choices match { case Some(xs) if xs.isEmpty => "" @@ -89,17 +99,16 @@ object Settings: val ArgsSummary(sstate, arg :: args, errors, warnings) = state: @unchecked def update(value: Any, args: List[String]): ArgsSummary = var dangers = warnings - val value1 = - if changed && isMultivalue then - val value0 = value.asInstanceOf[List[String]] + val valueNew = + if sstate.wasChanged(idx) && isMultivalue then + val valueList = value.asInstanceOf[List[String]] val current = valueIn(sstate).asInstanceOf[List[String]] - value0.filter(current.contains).foreach(s => dangers :+= s"Setting $name set to $s redundantly") - current ++ value0 + valueList.filter(current.contains).foreach(s => dangers :+= s"Setting $name set to $s redundantly") + current ++ valueList else - if changed then dangers :+= s"Flag $name set repeatedly" + if sstate.wasChanged(idx) then dangers :+= s"Flag $name set repeatedly" value - changed = true - ArgsSummary(updateIn(sstate, value1), args, errors, dangers) + ArgsSummary(updateIn(sstate, valueNew), args, errors, dangers) end update def fail(msg: String, args: List[String]) = @@ -141,53 +150,56 @@ object Settings: catch case _: NumberFormatException => fail(s"$argValue is not an integer argument for $name", args) - def doSet(argRest: String) = ((summon[ClassTag[T]], args): @unchecked) match { - case (BooleanTag, _) => - setBoolean(argRest, args) - case (OptionTag, _) => - update(Some(propertyClass.get.getConstructor().newInstance()), args) - case (ListTag, _) => - if (argRest.isEmpty) missingArg - else - val strings = argRest.split(",").toList - choices match - case Some(valid) => strings.filterNot(valid.contains) match - case Nil => update(strings, args) - case invalid => invalidChoices(invalid) - case _ => update(strings, args) - case (StringTag, _) if argRest.nonEmpty || choices.exists(_.contains("")) => - setString(argRest, args) - case (StringTag, arg2 :: args2) => - if (arg2 startsWith "-") missingArg - else setString(arg2, args2) - case (OutputTag, arg :: args) => - val path = Directory(arg) - val isJar = path.extension == "jar" - if (!isJar && !path.isDirectory) - fail(s"'$arg' does not exist or is not a directory or .jar file", args) - else { - val output = if (isJar) JarArchive.create(path) else new PlainDirectory(path) - update(output, args) - } - case (IntTag, args) if argRest.nonEmpty => - setInt(argRest, args) - case (IntTag, arg2 :: args2) => - setInt(arg2, args2) - case (VersionTag, _) => - ScalaVersion.parse(argRest) match { - case Success(v) => update(v, args) - case Failure(ex) => fail(ex.getMessage, args) - } - case (_, Nil) => - missingArg - } - - def matches(argName: String) = (name :: aliases).exists(_ == argName) - - if (prefix != "" && arg.startsWith(prefix)) - doSet(arg drop prefix.length) - else if (prefix == "" && matches(arg.takeWhile(_ != ':'))) - doSet(arg.dropWhile(_ != ':').drop(1)) + def doSet(argRest: String) = + ((summon[ClassTag[T]], args): @unchecked) match { + case (BooleanTag, _) => + setBoolean(argRest, args) + case (OptionTag, _) => + update(Some(propertyClass.get.getConstructor().newInstance()), args) + case (ListTag, _) => + if (argRest.isEmpty) missingArg + else + val strings = argRest.split(",").toList + choices match + case Some(valid) => strings.filterNot(valid.contains) match + case Nil => update(strings, args) + case invalid => invalidChoices(invalid) + case _ => update(strings, args) + case (StringTag, _) if argRest.nonEmpty || choices.exists(_.contains("")) => + setString(argRest, args) + case (StringTag, arg2 :: args2) => + if (arg2 startsWith "-") missingArg + else setString(arg2, args2) + case (OutputTag, arg :: args) => + val path = Directory(arg) + val isJar = path.extension == "jar" + if (!isJar && !path.isDirectory) + fail(s"'$arg' does not exist or is not a directory or .jar file", args) + else { + val output = if (isJar) JarArchive.create(path) else new PlainDirectory(path) + update(output, args) + } + case (IntTag, args) if argRest.nonEmpty => + setInt(argRest, args) + case (IntTag, arg2 :: args2) => + setInt(arg2, args2) + case (VersionTag, _) => + ScalaVersion.parse(argRest) match { + case Success(v) => update(v, args) + case Failure(ex) => fail(ex.getMessage, args) + } + case (_, Nil) => + missingArg + } + + def matches(argName: String): Boolean = + (allFullNames).exists(_ == argName.takeWhile(_ != ':')) || prefix.exists(arg.startsWith) + + def argValRest: String = + if(prefix.isEmpty) arg.dropWhile(_ != ':').drop(1) else arg.drop(prefix.get.length) + + if matches(arg) then + doSet(argValRest) else state } @@ -281,49 +293,59 @@ object Settings: setting } - def BooleanSetting(name: String, descr: String, initialValue: Boolean = false, aliases: List[String] = Nil): Setting[Boolean] = - publish(Setting(name, descr, initialValue, aliases = aliases)) + val settingCharacters = "[a-zA-Z0-9_\\-]*".r + def validateSetting(setting: String): String = + assert(settingCharacters.matches(setting), s"Setting $setting contains invalid characters") + setting + + def validateAndPrependName(name: String): String = + assert(!name.startsWith("-"), s"Setting $name cannot start with -") + "-" + validateSetting(name) + + def BooleanSetting(category: String, name: String, descr: String, initialValue: Boolean = false, aliases: List[String] = Nil): Setting[Boolean] = + publish(Setting(category, validateAndPrependName(name), descr, initialValue, aliases = aliases.map(validateSetting))) - def StringSetting(name: String, helpArg: String, descr: String, default: String, aliases: List[String] = Nil): Setting[String] = - publish(Setting(name, descr, default, helpArg, aliases = aliases)) + def StringSetting(category: String, name: String, helpArg: String, descr: String, default: String, aliases: List[String] = Nil): Setting[String] = + publish(Setting(category, validateAndPrependName(name), descr, default, helpArg, aliases = aliases.map(validateSetting))) - def ChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String], default: String, aliases: List[String] = Nil): Setting[String] = - publish(Setting(name, descr, default, helpArg, Some(choices), aliases = aliases)) + def ChoiceSetting(category: String, name: String, helpArg: String, descr: String, choices: List[String], default: String, aliases: List[String] = Nil): Setting[String] = + publish(Setting(category, validateAndPrependName(name), descr, default, helpArg, Some(choices), aliases = aliases.map(validateSetting))) - def MultiChoiceSetting(name: String, helpArg: String, descr: String, choices: List[String], default: List[String], aliases: List[String] = Nil): Setting[List[String]] = - publish(Setting(name, descr, default, helpArg, Some(choices), aliases = aliases)) + def MultiChoiceSetting(category: String, name: String, helpArg: String, descr: String, choices: List[String], default: List[String], aliases: List[String] = Nil): Setting[List[String]] = + publish(Setting(category, validateAndPrependName(name), descr, default, helpArg, Some(choices), aliases = aliases.map(validateSetting))) - def MultiChoiceHelpSetting(name: String, helpArg: String, descr: String, choices: List[ChoiceWithHelp[String]], default: List[ChoiceWithHelp[String]], aliases: List[String] = Nil): Setting[List[ChoiceWithHelp[String]]] = - publish(Setting(name, descr, default, helpArg, Some(choices), aliases = aliases)) + def MultiChoiceHelpSetting(category: String, name: String, helpArg: String, descr: String, choices: List[ChoiceWithHelp[String]], default: List[ChoiceWithHelp[String]], aliases: List[String] = Nil): Setting[List[ChoiceWithHelp[String]]] = + publish(Setting(category, validateAndPrependName(name), descr, default, helpArg, Some(choices), aliases = aliases.map(validateSetting))) - def UncompleteMultiChoiceHelpSetting(name: String, helpArg: String, descr: String, choices: List[ChoiceWithHelp[String]], default: List[ChoiceWithHelp[String]], aliases: List[String] = Nil): Setting[List[ChoiceWithHelp[String]]] = - publish(Setting(name, descr, default, helpArg, Some(choices), aliases = aliases, ignoreInvalidArgs = true)) + def UncompleteMultiChoiceHelpSetting(category: String, name: String, helpArg: String, descr: String, choices: List[ChoiceWithHelp[String]], default: List[ChoiceWithHelp[String]], aliases: List[String] = Nil): Setting[List[ChoiceWithHelp[String]]] = + publish(Setting(category, validateAndPrependName(name), descr, default, helpArg, Some(choices), aliases = aliases.map(validateSetting), ignoreInvalidArgs = true)) - def IntSetting(name: String, descr: String, default: Int, aliases: List[String] = Nil): Setting[Int] = - publish(Setting(name, descr, default, aliases = aliases)) + def IntSetting(category: String, name: String, descr: String, default: Int, aliases: List[String] = Nil): Setting[Int] = + publish(Setting(category, validateAndPrependName(name), descr, default, aliases = aliases.map(validateSetting))) - def IntChoiceSetting(name: String, descr: String, choices: Seq[Int], default: Int): Setting[Int] = - publish(Setting(name, descr, default, choices = Some(choices))) + def IntChoiceSetting(category: String, name: String, descr: String, choices: Seq[Int], default: Int): Setting[Int] = + publish(Setting(category, validateAndPrependName(name), descr, default, choices = Some(choices))) - def MultiStringSetting(name: String, helpArg: String, descr: String, default: List[String] = Nil, aliases: List[String] = Nil): Setting[List[String]] = - publish(Setting(name, descr, default, helpArg, aliases = aliases)) + def MultiStringSetting(category: String, name: String, helpArg: String, descr: String, default: List[String] = Nil, aliases: List[String] = Nil): Setting[List[String]] = + publish(Setting(category, validateAndPrependName(name), descr, default, helpArg, aliases = aliases.map(validateSetting))) - def OutputSetting(name: String, helpArg: String, descr: String, default: AbstractFile): Setting[AbstractFile] = - publish(Setting(name, descr, default, helpArg)) + def OutputSetting(category: String, name: String, helpArg: String, descr: String, default: AbstractFile): Setting[AbstractFile] = + publish(Setting(category, validateAndPrependName(name), descr, default, helpArg)) - def PathSetting(name: String, descr: String, default: String, aliases: List[String] = Nil): Setting[String] = - publish(Setting(name, descr, default, aliases = aliases)) + def PathSetting(category: String, name: String, descr: String, default: String, aliases: List[String] = Nil): Setting[String] = + publish(Setting(category, validateAndPrependName(name), descr, default, aliases = aliases.map(validateSetting))) - def PhasesSetting(name: String, descr: String, default: String = "", aliases: List[String] = Nil): Setting[List[String]] = - publish(Setting(name, descr, if (default.isEmpty) Nil else List(default), aliases = aliases)) + def PhasesSetting(category: String, name: String, descr: String, default: String = "", aliases: List[String] = Nil): Setting[List[String]] = + publish(Setting(category, validateAndPrependName(name), descr, if (default.isEmpty) Nil else List(default), aliases = aliases.map(validateSetting))) - def PrefixSetting(name: String, pre: String, descr: String): Setting[List[String]] = - publish(Setting(name, descr, Nil, prefix = pre)) + def PrefixSetting(category: String, name: String, descr: String): Setting[List[String]] = + val prefix = name.takeWhile(_ != '<') + publish(Setting(category, "-" + name, descr, Nil, prefix = Some(validateSetting(prefix)))) - def VersionSetting(name: String, descr: String, default: ScalaVersion = NoScalaVersion): Setting[ScalaVersion] = - publish(Setting(name, descr, default)) + def VersionSetting(category: String, name: String, descr: String, default: ScalaVersion = NoScalaVersion): Setting[ScalaVersion] = + publish(Setting(category, validateAndPrependName(name), descr, default)) - def OptionSetting[T: ClassTag](name: String, descr: String, aliases: List[String] = Nil): Setting[Option[T]] = - publish(Setting(name, descr, None, propertyClass = Some(summon[ClassTag[T]].runtimeClass), aliases = aliases)) + def OptionSetting[T: ClassTag](category: String, name: String, descr: String, aliases: List[String] = Nil): Setting[Option[T]] = + publish(Setting(category, validateAndPrependName(name), descr, None, propertyClass = Some(summon[ClassTag[T]].runtimeClass), aliases = aliases.map(validateSetting))) } end Settings diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index c5f04d18b7fb..b94824ac3a2b 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -513,7 +513,7 @@ object Contexts { s"""Context( |${outersIterator.map(ctx => cinfo(using ctx)).mkString("\n\n")})""".stripMargin - def settings: ScalaSettings = base.settings + def settings: ScalaSettings.type = base.settings def definitions: Definitions = base.definitions def platform: Platform = base.platform def pendingUnderlying: util.HashSet[Type] = base.pendingUnderlying @@ -861,8 +861,7 @@ object Contexts { with Phases.PhasesBase with Plugins { - /** The applicable settings */ - val settings: ScalaSettings = new ScalaSettings + val settings: ScalaSettings.type = ScalaSettings /** The initial context */ val initialCtx: Context = FreshContext.initial(this: @unchecked, settings) diff --git a/compiler/test/dotty/tools/dotc/ScalaCommandTest.scala b/compiler/test/dotty/tools/dotc/ScalaCommandTest.scala index 53f063a9e767..852a232e4c6a 100644 --- a/compiler/test/dotty/tools/dotc/ScalaCommandTest.scala +++ b/compiler/test/dotty/tools/dotc/ScalaCommandTest.scala @@ -17,7 +17,7 @@ class ScalaCommandTest: def temporaryFolder = _temporaryFolder @Test def `Simple one parameter`: Unit = inContext { - val settings = config.ScalaSettings() + val settings = config.ScalaSettings val args = "-cp path/to/classes1:other/path/to/classes2 files".split(" ") val summary = ScalacCommand.distill(args, settings)() given SettingsState = summary.sstate @@ -26,7 +26,7 @@ class ScalaCommandTest: } @Test def `Unfold @file`: Unit = inContext { - val settings = config.ScalaSettings() + val settings = config.ScalaSettings val file = temporaryFolder.newFile("config") val writer = java.io.FileWriter(file); writer.write("-sourceroot myNewRoot someMoreFiles"); diff --git a/compiler/test/dotty/tools/dotc/SettingsTests.scala b/compiler/test/dotty/tools/dotc/SettingsTests.scala index 8c571a321548..416b3fcc8b91 100644 --- a/compiler/test/dotty/tools/dotc/SettingsTests.scala +++ b/compiler/test/dotty/tools/dotc/SettingsTests.scala @@ -43,8 +43,8 @@ class SettingsTests { @Test def acceptUnconstrained: Unit = object Settings extends SettingGroup: - val foo = StringSetting("-foo", "foo", "Foo", "a") - val bar = IntSetting("-bar", "Bar", 0) + val foo = StringSetting("", "foo", "foo", "Foo", "a") + val bar = IntSetting("", "bar", "Bar", 0) val args = List("-foo", "b", "-bar", "1") val summary = Settings.processArguments(args, true) @@ -72,7 +72,7 @@ class SettingsTests { @Test def `dont crash on many options`: Unit = object Settings extends SettingGroup: - val option = BooleanSetting("-option", "Some option") + val option = BooleanSetting("", "-option", "Some option") val limit = 6000 val args = List.fill(limit)("-option") @@ -87,7 +87,7 @@ class SettingsTests { @Test def `bad option warning consumes an arg`: Unit = object Settings extends SettingGroup: - val option = BooleanSetting("-option", "Some option") + val option = BooleanSetting("", "-option", "Some option") val args = List("-adoption", "dogs", "cats") val summary = Settings.processArguments(args, processAll = true) @@ -97,7 +97,7 @@ class SettingsTests { @Test def `bad option settings throws`: Unit = object Settings extends SettingGroup: - val option = BooleanSetting("-option", "Some option") + val option = BooleanSetting("", "-option", "Some option") def checkMessage(s: String): (Throwable => Boolean) = t => if t.getMessage == s then true @@ -112,12 +112,12 @@ class SettingsTests { @Test def validateChoices: Unit = object Settings extends SettingGroup: - val foo = ChoiceSetting("-foo", "foo", "Foo", List("a", "b"), "a") - val bar = IntChoiceSetting("-bar", "Bar", List(0, 1, 2), 0) - val baz = IntChoiceSetting("-baz", "Baz", 0 to 10, 10) + val foo = ChoiceSetting("", "-foo", "foo", "Foo", List("a", "b"), "a") + val bar = IntChoiceSetting("", "-bar", "Bar", List(0, 1, 2), 0) + val baz = IntChoiceSetting("", "-baz", "Baz", 0 to 10, 10) - val quux = ChoiceSetting("-quux", "quux", "Quux", List(), "") - val quuz = IntChoiceSetting("-quuz", "Quuz", List(), 0) + val quux = ChoiceSetting("", "-quux", "quux", "Quux", List(), "") + val quuz = IntChoiceSetting("", "-quuz", "Quuz", List(), 0) locally { val args = List("-foo", "b", "-bar", "1", "-baz", "5") @@ -169,7 +169,7 @@ class SettingsTests { @Test def `Allow IntSetting's to be set with a colon`: Unit = object Settings extends SettingGroup: - val foo = IntSetting("-foo", "foo", 80) + val foo = IntSetting("", "-foo", "foo", 80) import Settings._ val args = List("-foo:100") @@ -181,10 +181,10 @@ class SettingsTests { @Test def `Set BooleanSettings correctly`: Unit = object Settings extends SettingGroup: - val foo = BooleanSetting("-foo", "foo", false) - val bar = BooleanSetting("-bar", "bar", true) - val baz = BooleanSetting("-baz", "baz", false) - val qux = BooleanSetting("-qux", "qux", false) + val foo = BooleanSetting("", "-foo", "foo", false) + val bar = BooleanSetting("", "-bar", "bar", true) + val baz = BooleanSetting("", "-baz", "baz", false) + val qux = BooleanSetting("", "-qux", "qux", false) import Settings._ val args = List("-foo:true", "-bar:false", "-baz", "-qux:true", "-qux:false") diff --git a/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala b/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala index a1014043724e..77691e1008e0 100644 --- a/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala +++ b/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala @@ -12,7 +12,7 @@ class ScalaSettingsTests: @Test def `A setting with aliases is accepted`: Unit = class MySettings extends SettingGroup: - val classpath: Setting[String] = PathSetting("-classpath", "Specify where to find user class files.", ".", aliases = List("--class-path", "-cp")) + val classpath: Setting[String] = PathSetting("", "classpath", "Specify where to find user class files.", ".", aliases = List("--class-path", "-cp")) val settings = MySettings() val args = tokenize("-cp path/to/classes1:other/path/to/classes2") val summary = ArgsSummary(settings.defaultState, args, errors = Nil, warnings = Nil) @@ -25,7 +25,7 @@ class ScalaSettingsTests: @Test def `A multistring setting is multivalued`: Unit = class SUT extends SettingGroup: - val language: Setting[List[String]] = MultiStringSetting("-language", "feature", "Enable one or more language features.") + val language: Setting[List[String]] = MultiStringSetting("", "language", "feature", "Enable one or more language features.") val sut = SUT() val args = tokenize("-language:implicitConversions,dynamics") val sumy = ArgsSummary(sut.defaultState, args, errors = Nil, warnings = Nil) @@ -39,7 +39,7 @@ class ScalaSettingsTests: @Test def `t9719 Apply -language more than once`: Unit = class SUT extends SettingGroup: - val language: Setting[List[String]] = MultiStringSetting("-language", "feature", "Enable one or more language features.") + val language: Setting[List[String]] = MultiStringSetting("", "language", "feature", "Enable one or more language features.") val sut = SUT() val args = tokenize("-language:implicitConversions -language:dynamics") val sumy = ArgsSummary(sut.defaultState, args, errors = Nil, warnings = Nil) @@ -53,7 +53,7 @@ class ScalaSettingsTests: @Test def `Warn if multistring element is supplied multiply`: Unit = class SUT extends SettingGroup: - val language: Setting[List[String]] = MultiStringSetting("-language", "feature", "Enable one or more language features.") + val language: Setting[List[String]] = MultiStringSetting("", "language", "feature", "Enable one or more language features.") val sut = SUT() val args = tokenize("-language:dynamics -language:implicitConversions -language:dynamics") val sumy = ArgsSummary(sut.defaultState, args, errors = Nil, warnings = Nil) @@ -67,7 +67,7 @@ class ScalaSettingsTests: @Test def `WConf setting is parsed`: Unit = import reporting.{Action, Diagnostic, NoExplanation} - val sets = new ScalaSettings + val sets = ScalaSettings val args = List("-Wconf:cat=deprecation:s,cat=feature:e", "-Wconf:msg=a problem\\.:s") val sumy = ArgsSummary(sets.defaultState, args, errors = Nil, warnings = Nil) val proc = sets.processArguments(sumy, processAll = true, skipped = Nil) @@ -85,7 +85,7 @@ class ScalaSettingsTests: @Test def `i18367 rightmost WConf flags take precedence over flags to the left`: Unit = import reporting.{Action, Diagnostic} - val sets = new ScalaSettings + val sets = ScalaSettings val args = List("-Wconf:cat=deprecation:e", "-Wconf:cat=deprecation:s") val sumy = ArgsSummary(sets.defaultState, args, errors = Nil, warnings = Nil) val proc = sets.processArguments(sumy, processAll = true, skipped = Nil) From 85d4a876d4908f50e412e7f9d4875fb6e34036f3 Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Thu, 22 Feb 2024 18:15:56 +0100 Subject: [PATCH 214/277] Fix scaladoc --- .../tools/scaladoc/ScaladocSettings.scala | 70 +++++++++++-------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/scaladoc/src/dotty/tools/scaladoc/ScaladocSettings.scala b/scaladoc/src/dotty/tools/scaladoc/ScaladocSettings.scala index 4802f5d24ecc..5acfac03d52c 100644 --- a/scaladoc/src/dotty/tools/scaladoc/ScaladocSettings.scala +++ b/scaladoc/src/dotty/tools/scaladoc/ScaladocSettings.scala @@ -2,6 +2,7 @@ package dotty.tools.scaladoc import dotty.tools.dotc.config.Settings._ import dotty.tools.dotc.config.AllScalaSettings +import dotty.tools.dotc.config.ScalaSettingCategories.RootSetting class ScaladocSettings extends SettingGroup with AllScalaSettings: val unsupportedSettings = Seq( @@ -11,90 +12,95 @@ class ScaladocSettings extends SettingGroup with AllScalaSettings: val projectName: Setting[String] = - StringSetting("-project", "project title", "The name of the project.", "", aliases = List("-doc-title")) + StringSetting(RootSetting, "project", "project title", "The name of the project.", "", aliases = List("-doc-title")) val projectVersion: Setting[String] = - StringSetting("-project-version", "project version", "The current version of your project.", "", aliases = List("-doc-version")) + StringSetting(RootSetting, "project-version", "project version", "The current version of your project.", "", aliases = List("-doc-version")) val projectLogo: Setting[String] = - StringSetting("-project-logo", "project logo filename", "Path to the file that contains the project's logo. Provided path can be absolute or relative to the project root directory.", "", aliases = List("-doc-logo")) + StringSetting(RootSetting, "project-logo", "project logo filename", "Path to the file that contains the project's logo. Provided path can be absolute or relative to the project root directory.", "", aliases = List("-doc-logo")) - val projectFooter: Setting[String] = StringSetting("-project-footer", "project footer", "A footer on every Scaladoc page.", "", aliases = List("-doc-footer")) + val projectFooter: Setting[String] = StringSetting(RootSetting, "project-footer", "project footer", "A footer on every Scaladoc page.", "", aliases = List("-doc-footer")) val sourceLinks: Setting[List[String]] = - MultiStringSetting("-source-links", "sources", SourceLinks.usage) + MultiStringSetting(RootSetting, "source-links", "sources", SourceLinks.usage) val legacySourceLink: Setting[String] = - StringSetting("-doc-source-url", "sources", "Legacy option from Scala 2. Use -source-links instead.", "") + StringSetting(RootSetting, "doc-source-url", "sources", "Legacy option from Scala 2. Use -source-links instead.", "") val syntax: Setting[List[String]] = - MultiStringSetting("-comment-syntax", "syntax", tasty.comments.CommentSyntaxArgs.usage) + MultiStringSetting(RootSetting, "comment-syntax", "syntax", tasty.comments.CommentSyntaxArgs.usage) val revision: Setting[String] = - StringSetting("-revision", "revision", "Revision (branch or ref) used to build project project", "") + StringSetting(RootSetting, "revision", "revision", "Revision (branch or ref) used to build project project", "") val externalDocumentationMappings: Setting[List[String]] = - MultiStringSetting("-external-mappings", "external-mappings", + MultiStringSetting(RootSetting, "external-mappings", "external-mappings", "Mapping between regexes matching classpath entries and external documentation. " + "'regex::[scaladoc|scaladoc|javadoc]::path' syntax is used") val legacyExternalDocumentationMappings: Setting[List[String]] = - MultiStringSetting("-doc-external-doc", "legacy-external-mappings", "Legacy option from Scala 2. Mapping betweeen path and external documentation. Use -external-mappings instead.") + MultiStringSetting(RootSetting, "doc-external-doc", "legacy-external-mappings", "Legacy option from Scala 2. Mapping betweeen path and external documentation. Use -external-mappings instead.") val socialLinks: Setting[List[String]] = - MultiStringSetting("-social-links", "social-links", + MultiStringSetting(RootSetting, "social-links", "social-links", "Links to social sites. '[github|twitter|gitter|discord]::link' or 'custom::link::light_icon_file_name[::dark_icon_file_name]' syntax is used. For custom links, the icons must be present in '_assets/images/'") val deprecatedSkipPackages: Setting[List[String]] = - MultiStringSetting("-skip-packages", "packages", "Deprecated, please use `-skip-by-id` or `-skip-by-regex`") + MultiStringSetting(RootSetting, "skip-packages", "packages", "Deprecated, please use `-skip-by-id` or `-skip-by-regex`") val skipById: Setting[List[String]] = - MultiStringSetting("-skip-by-id", "package or class identifier", "Identifiers of packages or top-level classes to skip when generating documentation") + MultiStringSetting(RootSetting, "skip-by-id", "package or class identifier", "Identifiers of packages or top-level classes to skip when generating documentation") val skipByRegex: Setting[List[String]] = - MultiStringSetting("-skip-by-regex", "regex", "Regexes that match fully qualified names of packages or top-level classes to skip when generating documentation") + MultiStringSetting(RootSetting, "skip-by-regex", "regex", "Regexes that match fully qualified names of packages or top-level classes to skip when generating documentation") val docRootContent: Setting[String] = - StringSetting("-doc-root-content", "path", "The file from which the root package documentation should be imported.", "") + StringSetting(RootSetting, "doc-root-content", "path", "The file from which the root package documentation should be imported.", "") val author: Setting[Boolean] = - BooleanSetting("-author", "Include authors.", false) + BooleanSetting(RootSetting, "author", "Include authors.", false) val groups: Setting[Boolean] = - BooleanSetting("-groups", "Group similar functions together (based on the @group annotation)", false) + BooleanSetting(RootSetting, "groups", "Group similar functions together (based on the @group annotation)", false) val visibilityPrivate: Setting[Boolean] = - BooleanSetting("-private", "Show all types and members. Unless specified, show only public and protected types and members.", false) + BooleanSetting(RootSetting, "private", "Show all types and members. Unless specified, show only public and protected types and members.", false) val docCanonicalBaseUrl: Setting[String] = StringSetting( - "-doc-canonical-base-url", + RootSetting, + "doc-canonical-base-url", "url", s"A base URL to use as prefix and add `canonical` URLs to all pages. The canonical URL may be used by search engines to choose the URL that you want people to see in search results. If unset no canonical URLs are generated.", "" ) val siteRoot: Setting[String] = StringSetting( - "-siteroot", + RootSetting, + "siteroot", "site root", "A directory containing static files from which to generate documentation.", "./docs" ) val noLinkWarnings: Setting[Boolean] = BooleanSetting( - "-no-link-warnings", + RootSetting, + "no-link-warnings", "Avoid warnings for ambiguous and incorrect links in members look up. Doesn't affect warnings for incorrect links of assets etc.", false ) val noLinkAssetWarnings: Setting[Boolean] = BooleanSetting( - "-no-link-asset-warnings", + RootSetting, + "no-link-asset-warnings", "Avoid warnings for incorrect links of assets like images, static pages, etc.", false ) val versionsDictionaryUrl: Setting[String] = StringSetting( - "-versions-dictionary-url", + RootSetting, + "versions-dictionary-url", "versions dictionary url", "A URL pointing to a JSON document containing a dictionary `version label -> documentation location`. " + "The JSON file has single property \"versions\" that holds dictionary of labels of specific docs and URL pointing to their index.html top-level file. " + @@ -103,23 +109,24 @@ class ScaladocSettings extends SettingGroup with AllScalaSettings: ) val YdocumentSyntheticTypes: Setting[Boolean] = - BooleanSetting("-Ydocument-synthetic-types", "Attach pages with documentation of the intrinsic types e. g. Any, Nothing to the docs. Setting is useful only for stdlib.", false) + BooleanSetting(RootSetting, "Ydocument-synthetic-types", "Attach pages with documentation of the intrinsic types e. g. Any, Nothing to the docs. Setting is useful only for stdlib.", false) val snippetCompiler: Setting[List[String]] = - MultiStringSetting("-snippet-compiler", "snippet-compiler", snippets.SnippetCompilerArgs.usage) + MultiStringSetting(RootSetting, "snippet-compiler", "snippet-compiler", snippets.SnippetCompilerArgs.usage) val generateInkuire: Setting[Boolean] = - BooleanSetting("-Ygenerate-inkuire", "Generates InkuireDB and enables Hoogle-like searches", false) + BooleanSetting(RootSetting, "Ygenerate-inkuire", "Generates InkuireDB and enables Hoogle-like searches", false) val apiSubdirectory: Setting[Boolean] = - BooleanSetting("-Yapi-subdirectory", "Put the API documentation pages inside a directory `api/`", false) + BooleanSetting(RootSetting, "Yapi-subdirectory", "Put the API documentation pages inside a directory `api/`", false) val scastieConfiguration: Setting[String] = - StringSetting("-scastie-configuration", "Scastie configuration", "Additional configuration passed to Scastie in code snippets", "") + StringSetting(RootSetting, "scastie-configuration", "Scastie configuration", "Additional configuration passed to Scastie in code snippets", "") val defaultTemplate: Setting[String] = StringSetting( - "-default-template", + RootSetting, + "default-template", "default template used by static site", "The static site is generating empty files for indexes that haven't been provided explicitly in a sidebar/missing index.html in directory. " + "User can specify what default template should be used for such indexes. It can be useful for providing generic templates that interpolate some common settings, like title, or can have some custom html embedded.", @@ -128,13 +135,14 @@ class ScaladocSettings extends SettingGroup with AllScalaSettings: val quickLinks: Setting[List[String]] = MultiStringSetting( - "-quick-links", + RootSetting, + "quick-links", "quick-links", "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) + BooleanSetting(RootSetting, "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, dynamicSideMenu) From 03c695d1c7099de6f9a2204faa77b7303fc61b66 Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Fri, 23 Feb 2024 13:27:26 +0100 Subject: [PATCH 215/277] More unification, fixed test --- .../dotty/tools/dotc/config/Settings.scala | 16 +++++++++++++- .../test/dotty/tools/dotc/SettingsTests.scala | 22 +++++++++---------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/Settings.scala b/compiler/src/dotty/tools/dotc/config/Settings.scala index 961bca4da121..af160a8bf1fe 100644 --- a/compiler/src/dotty/tools/dotc/config/Settings.scala +++ b/compiler/src/dotty/tools/dotc/config/Settings.scala @@ -170,6 +170,15 @@ object Settings: case (StringTag, arg2 :: args2) => if (arg2 startsWith "-") missingArg else setString(arg2, args2) + case (OutputTag, _) if argRest.nonEmpty => + val path = Directory(argRest) + val isJar = path.extension == "jar" + if (!isJar && !path.isDirectory) + fail(s"'$argRest' does not exist or is not a directory or .jar file", args) + else { + val output = if (isJar) JarArchive.create(path) else new PlainDirectory(path) + update(output, args) + } case (OutputTag, arg :: args) => val path = Directory(arg) val isJar = path.extension == "jar" @@ -183,11 +192,16 @@ object Settings: setInt(argRest, args) case (IntTag, arg2 :: args2) => setInt(arg2, args2) - case (VersionTag, _) => + case (VersionTag, _) if argRest.nonEmpty => ScalaVersion.parse(argRest) match { case Success(v) => update(v, args) case Failure(ex) => fail(ex.getMessage, args) } + case (VersionTag, arg2 :: args2) => + ScalaVersion.parse(arg2) match { + case Success(v) => update(v, args2) + case Failure(ex) => fail(ex.getMessage, args2) + } case (_, Nil) => missingArg } diff --git a/compiler/test/dotty/tools/dotc/SettingsTests.scala b/compiler/test/dotty/tools/dotc/SettingsTests.scala index 416b3fcc8b91..ab9ac00099c3 100644 --- a/compiler/test/dotty/tools/dotc/SettingsTests.scala +++ b/compiler/test/dotty/tools/dotc/SettingsTests.scala @@ -87,7 +87,7 @@ class SettingsTests { @Test def `bad option warning consumes an arg`: Unit = object Settings extends SettingGroup: - val option = BooleanSetting("", "-option", "Some option") + val option = BooleanSetting("", "option", "Some option") val args = List("-adoption", "dogs", "cats") val summary = Settings.processArguments(args, processAll = true) @@ -97,7 +97,7 @@ class SettingsTests { @Test def `bad option settings throws`: Unit = object Settings extends SettingGroup: - val option = BooleanSetting("", "-option", "Some option") + val option = BooleanSetting("", "option", "Some option") def checkMessage(s: String): (Throwable => Boolean) = t => if t.getMessage == s then true @@ -112,12 +112,12 @@ class SettingsTests { @Test def validateChoices: Unit = object Settings extends SettingGroup: - val foo = ChoiceSetting("", "-foo", "foo", "Foo", List("a", "b"), "a") - val bar = IntChoiceSetting("", "-bar", "Bar", List(0, 1, 2), 0) - val baz = IntChoiceSetting("", "-baz", "Baz", 0 to 10, 10) + val foo = ChoiceSetting("", "foo", "foo", "Foo", List("a", "b"), "a") + val bar = IntChoiceSetting("", "bar", "Bar", List(0, 1, 2), 0) + val baz = IntChoiceSetting("", "baz", "Baz", 0 to 10, 10) - val quux = ChoiceSetting("", "-quux", "quux", "Quux", List(), "") - val quuz = IntChoiceSetting("", "-quuz", "Quuz", List(), 0) + val quux = ChoiceSetting("", "quux", "quux", "Quux", List(), "") + val quuz = IntChoiceSetting("", "quuz", "Quuz", List(), 0) locally { val args = List("-foo", "b", "-bar", "1", "-baz", "5") @@ -181,10 +181,10 @@ class SettingsTests { @Test def `Set BooleanSettings correctly`: Unit = object Settings extends SettingGroup: - val foo = BooleanSetting("", "-foo", "foo", false) - val bar = BooleanSetting("", "-bar", "bar", true) - val baz = BooleanSetting("", "-baz", "baz", false) - val qux = BooleanSetting("", "-qux", "qux", false) + val foo = BooleanSetting("", "foo", "foo", false) + val bar = BooleanSetting("", "bar", "bar", true) + val baz = BooleanSetting("", "baz", "baz", false) + val qux = BooleanSetting("", "qux", "qux", false) import Settings._ val args = List("-foo:true", "-bar:false", "-baz", "-qux:true", "-qux:false") From 748073bac7b55ebcc8a052a585657da8ab5562e2 Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Thu, 29 Feb 2024 15:34:25 +0100 Subject: [PATCH 216/277] Keep ScalaSettings as a class --- compiler/src/dotty/tools/dotc/Driver.scala | 1 - .../tools/dotc/config/CompilerCommand.scala | 2 +- .../tools/dotc/config/ScalaSettings.scala | 27 ++++++++++--------- .../src/dotty/tools/dotc/core/Contexts.scala | 4 +-- .../dotty/tools/dotc/ScalaCommandTest.scala | 4 +-- .../tools/dotc/TastyBootstrapTests.scala | 2 +- .../dotc/config/ScalaSettingsTests.scala | 4 +-- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/Driver.scala b/compiler/src/dotty/tools/dotc/Driver.scala index 82a9f5850bb6..6b461cc8e81b 100644 --- a/compiler/src/dotty/tools/dotc/Driver.scala +++ b/compiler/src/dotty/tools/dotc/Driver.scala @@ -200,7 +200,6 @@ class Driver { } def main(args: Array[String]): Unit = { - println("settings: " + ScalaSettings.allSettings) // Preload scala.util.control.NonFatal. Otherwise, when trying to catch a StackOverflowError, // we may try to load it but fail with another StackOverflowError and lose the original exception, // see . diff --git a/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala b/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala index 2e82c6a3cd67..587f94dad7b3 100644 --- a/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala +++ b/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala @@ -5,7 +5,7 @@ import Settings.* import core.Contexts.* abstract class CompilerCommand extends CliCommand: - type ConcreteSettings = ScalaSettings.type + type ConcreteSettings = ScalaSettings final def helpMsg(using settings: ConcreteSettings)(using SettingsState, Context): String = settings.allSettings.find(isHelping) match diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 92150ae6e426..f5b2fd6e1f6a 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -23,19 +23,7 @@ object ScalaSettingCategories: val AdvancedSetting = "X" val VerboseSetting = "V" -object ScalaSettings extends SettingGroup with AllScalaSettings: - - val settingsByCategory: Map[String, List[Setting[_]]] = - allSettings.groupBy(_.category) - .view.mapValues(_.toList).toMap - .withDefaultValue(Nil) - def categories: List[String] = settingsByCategory.keys.toList - val rootSettings: List[Setting[_]] = settingsByCategory(RootSetting) - val warningSettings: List[Setting[_]] = settingsByCategory(WarningSetting) - val forkSettings: List[Setting[_]] = settingsByCategory(ForkSetting) - val advancedSettings: List[Setting[_]] = settingsByCategory(AdvancedSetting) - val verboseSettings: List[Setting[_]] = settingsByCategory(VerboseSetting) - val settingsByAliases: Map[String, Setting[_]] = allSettings.flatMap(s => s.aliases.map(_ -> s)).toMap +object ScalaSettings: private lazy val minTargetVersion = classfileVersionMap.keysIterator.map(_.toInt).min private lazy val maxTargetVersion = classfileVersionMap.keysIterator.map(_.toInt).max @@ -69,6 +57,19 @@ object ScalaSettings extends SettingGroup with AllScalaSettings: else defaultWidth else defaultWidth } + +class ScalaSettings extends SettingGroup, AllScalaSettings: + val settingsByCategory: Map[String, List[Setting[_]]] = + allSettings.groupBy(_.category) + .view.mapValues(_.toList).toMap + .withDefaultValue(Nil) + def categories: List[String] = settingsByCategory.keys.toList + val rootSettings: List[Setting[_]] = settingsByCategory(RootSetting) + val warningSettings: List[Setting[_]] = settingsByCategory(WarningSetting) + val forkSettings: List[Setting[_]] = settingsByCategory(ForkSetting) + val advancedSettings: List[Setting[_]] = settingsByCategory(AdvancedSetting) + val verboseSettings: List[Setting[_]] = settingsByCategory(VerboseSetting) + val settingsByAliases: Map[String, Setting[_]] = allSettings.flatMap(s => s.aliases.map(_ -> s)).toMap trait AllScalaSettings extends CommonScalaSettings, PluginSettings, VerboseSettings, WarningSettings, XSettings, YSettings: self: SettingGroup => diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index b94824ac3a2b..708852076279 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -513,7 +513,7 @@ object Contexts { s"""Context( |${outersIterator.map(ctx => cinfo(using ctx)).mkString("\n\n")})""".stripMargin - def settings: ScalaSettings.type = base.settings + def settings: ScalaSettings = base.settings def definitions: Definitions = base.definitions def platform: Platform = base.platform def pendingUnderlying: util.HashSet[Type] = base.pendingUnderlying @@ -861,7 +861,7 @@ object Contexts { with Phases.PhasesBase with Plugins { - val settings: ScalaSettings.type = ScalaSettings + val settings: ScalaSettings = new ScalaSettings() /** The initial context */ val initialCtx: Context = FreshContext.initial(this: @unchecked, settings) diff --git a/compiler/test/dotty/tools/dotc/ScalaCommandTest.scala b/compiler/test/dotty/tools/dotc/ScalaCommandTest.scala index 852a232e4c6a..9f51a3b27baa 100644 --- a/compiler/test/dotty/tools/dotc/ScalaCommandTest.scala +++ b/compiler/test/dotty/tools/dotc/ScalaCommandTest.scala @@ -17,7 +17,7 @@ class ScalaCommandTest: def temporaryFolder = _temporaryFolder @Test def `Simple one parameter`: Unit = inContext { - val settings = config.ScalaSettings + val settings = new config.ScalaSettings() val args = "-cp path/to/classes1:other/path/to/classes2 files".split(" ") val summary = ScalacCommand.distill(args, settings)() given SettingsState = summary.sstate @@ -26,7 +26,7 @@ class ScalaCommandTest: } @Test def `Unfold @file`: Unit = inContext { - val settings = config.ScalaSettings + val settings = new config.ScalaSettings() val file = temporaryFolder.newFile("config") val writer = java.io.FileWriter(file); writer.write("-sourceroot myNewRoot someMoreFiles"); diff --git a/compiler/test/dotty/tools/dotc/TastyBootstrapTests.scala b/compiler/test/dotty/tools/dotc/TastyBootstrapTests.scala index 27311497de9c..9929e1e87214 100644 --- a/compiler/test/dotty/tools/dotc/TastyBootstrapTests.scala +++ b/compiler/test/dotty/tools/dotc/TastyBootstrapTests.scala @@ -51,7 +51,7 @@ class TastyBootstrapTests { Properties.compilerInterface, Properties.scalaLibrary, Properties.scalaAsm, Properties.dottyInterfaces, Properties.jlineTerminal, Properties.jlineReader, ).mkString(File.pathSeparator), - Array("-Ycheck-reentrant", "-language:postfixOps", "-Xsemanticdb") + Array("-Ycheck-reentrant", "-Ylog:checkReentrant+", "-language:postfixOps", "-Xsemanticdb") ) val libraryDirs = List(Paths.get("library/src"), Paths.get("library/src-bootstrapped")) diff --git a/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala b/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala index 77691e1008e0..fe566e1a4de3 100644 --- a/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala +++ b/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala @@ -67,7 +67,7 @@ class ScalaSettingsTests: @Test def `WConf setting is parsed`: Unit = import reporting.{Action, Diagnostic, NoExplanation} - val sets = ScalaSettings + val sets = new ScalaSettings() val args = List("-Wconf:cat=deprecation:s,cat=feature:e", "-Wconf:msg=a problem\\.:s") val sumy = ArgsSummary(sets.defaultState, args, errors = Nil, warnings = Nil) val proc = sets.processArguments(sumy, processAll = true, skipped = Nil) @@ -85,7 +85,7 @@ class ScalaSettingsTests: @Test def `i18367 rightmost WConf flags take precedence over flags to the left`: Unit = import reporting.{Action, Diagnostic} - val sets = ScalaSettings + val sets = new ScalaSettings() val args = List("-Wconf:cat=deprecation:e", "-Wconf:cat=deprecation:s") val sumy = ArgsSummary(sets.defaultState, args, errors = Nil, warnings = Nil) val proc = sets.processArguments(sumy, processAll = true, skipped = Nil) From 22fe3534c4b7abe47c236cb7b86b59347a952939 Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Fri, 1 Mar 2024 14:19:40 +0100 Subject: [PATCH 217/277] Fix SettingsTests --- compiler/test/dotty/tools/dotc/SettingsTests.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/test/dotty/tools/dotc/SettingsTests.scala b/compiler/test/dotty/tools/dotc/SettingsTests.scala index ab9ac00099c3..595c4875bb12 100644 --- a/compiler/test/dotty/tools/dotc/SettingsTests.scala +++ b/compiler/test/dotty/tools/dotc/SettingsTests.scala @@ -72,7 +72,7 @@ class SettingsTests { @Test def `dont crash on many options`: Unit = object Settings extends SettingGroup: - val option = BooleanSetting("", "-option", "Some option") + val option = BooleanSetting("", "option", "Some option") val limit = 6000 val args = List.fill(limit)("-option") @@ -169,7 +169,7 @@ class SettingsTests { @Test def `Allow IntSetting's to be set with a colon`: Unit = object Settings extends SettingGroup: - val foo = IntSetting("", "-foo", "foo", 80) + val foo = IntSetting("", "foo", "foo", 80) import Settings._ val args = List("-foo:100") From 97f0c1d308b4070690f5a7d0b3999d7d884aec6d Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Mon, 4 Mar 2024 13:58:40 +0100 Subject: [PATCH 218/277] Revert object state & mark as unshared --- .../tools/dotc/config/ScalaSettings.scala | 28 +++++++++---------- .../dotty/tools/dotc/config/Settings.scala | 3 ++ .../src/dotty/tools/dotc/core/Contexts.scala | 2 +- .../dotty/tools/dotc/ScalaCommandTest.scala | 4 +-- .../dotc/config/ScalaSettingsTests.scala | 4 +-- 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index f5b2fd6e1f6a..33311aa23291 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -23,7 +23,20 @@ object ScalaSettingCategories: val AdvancedSetting = "X" val VerboseSetting = "V" -object ScalaSettings: +type ScalaSettings = ScalaSettings.type + +object ScalaSettings extends SettingGroup, AllScalaSettings: + val settingsByCategory: Map[String, List[Setting[_]]] = + allSettings.groupBy(_.category) + .view.mapValues(_.toList).toMap + .withDefaultValue(Nil) + def categories: List[String] = settingsByCategory.keys.toList + val rootSettings: List[Setting[_]] = settingsByCategory(RootSetting) + val warningSettings: List[Setting[_]] = settingsByCategory(WarningSetting) + val forkSettings: List[Setting[_]] = settingsByCategory(ForkSetting) + val advancedSettings: List[Setting[_]] = settingsByCategory(AdvancedSetting) + val verboseSettings: List[Setting[_]] = settingsByCategory(VerboseSetting) + val settingsByAliases: Map[String, Setting[_]] = allSettings.flatMap(s => s.aliases.map(_ -> s)).toMap private lazy val minTargetVersion = classfileVersionMap.keysIterator.map(_.toInt).min private lazy val maxTargetVersion = classfileVersionMap.keysIterator.map(_.toInt).max @@ -58,19 +71,6 @@ object ScalaSettings: else defaultWidth } -class ScalaSettings extends SettingGroup, AllScalaSettings: - val settingsByCategory: Map[String, List[Setting[_]]] = - allSettings.groupBy(_.category) - .view.mapValues(_.toList).toMap - .withDefaultValue(Nil) - def categories: List[String] = settingsByCategory.keys.toList - val rootSettings: List[Setting[_]] = settingsByCategory(RootSetting) - val warningSettings: List[Setting[_]] = settingsByCategory(WarningSetting) - val forkSettings: List[Setting[_]] = settingsByCategory(ForkSetting) - val advancedSettings: List[Setting[_]] = settingsByCategory(AdvancedSetting) - val verboseSettings: List[Setting[_]] = settingsByCategory(VerboseSetting) - val settingsByAliases: Map[String, Setting[_]] = allSettings.flatMap(s => s.aliases.map(_ -> s)).toMap - trait AllScalaSettings extends CommonScalaSettings, PluginSettings, VerboseSettings, WarningSettings, XSettings, YSettings: self: SettingGroup => diff --git a/compiler/src/dotty/tools/dotc/config/Settings.scala b/compiler/src/dotty/tools/dotc/config/Settings.scala index af160a8bf1fe..16af5468ccf0 100644 --- a/compiler/src/dotty/tools/dotc/config/Settings.scala +++ b/compiler/src/dotty/tools/dotc/config/Settings.scala @@ -8,6 +8,7 @@ import core.Contexts.* import dotty.tools.io.{AbstractFile, Directory, JarArchive, PlainDirectory} import annotation.tailrec +import annotation.internal.unshared import collection.mutable.ArrayBuffer import collection.mutable import reflect.ClassTag @@ -240,6 +241,7 @@ object Settings: class SettingGroup { + @unshared private val _allSettings = new ArrayBuffer[Setting[?]] def allSettings: Seq[Setting[?]] = _allSettings.toSeq @@ -307,6 +309,7 @@ object Settings: setting } + @unshared val settingCharacters = "[a-zA-Z0-9_\\-]*".r def validateSetting(setting: String): String = assert(settingCharacters.matches(setting), s"Setting $setting contains invalid characters") diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 708852076279..ae21c6fb8763 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -861,7 +861,7 @@ object Contexts { with Phases.PhasesBase with Plugins { - val settings: ScalaSettings = new ScalaSettings() + val settings: ScalaSettings = ScalaSettings /** The initial context */ val initialCtx: Context = FreshContext.initial(this: @unchecked, settings) diff --git a/compiler/test/dotty/tools/dotc/ScalaCommandTest.scala b/compiler/test/dotty/tools/dotc/ScalaCommandTest.scala index 9f51a3b27baa..852a232e4c6a 100644 --- a/compiler/test/dotty/tools/dotc/ScalaCommandTest.scala +++ b/compiler/test/dotty/tools/dotc/ScalaCommandTest.scala @@ -17,7 +17,7 @@ class ScalaCommandTest: def temporaryFolder = _temporaryFolder @Test def `Simple one parameter`: Unit = inContext { - val settings = new config.ScalaSettings() + val settings = config.ScalaSettings val args = "-cp path/to/classes1:other/path/to/classes2 files".split(" ") val summary = ScalacCommand.distill(args, settings)() given SettingsState = summary.sstate @@ -26,7 +26,7 @@ class ScalaCommandTest: } @Test def `Unfold @file`: Unit = inContext { - val settings = new config.ScalaSettings() + val settings = config.ScalaSettings val file = temporaryFolder.newFile("config") val writer = java.io.FileWriter(file); writer.write("-sourceroot myNewRoot someMoreFiles"); diff --git a/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala b/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala index fe566e1a4de3..77691e1008e0 100644 --- a/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala +++ b/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala @@ -67,7 +67,7 @@ class ScalaSettingsTests: @Test def `WConf setting is parsed`: Unit = import reporting.{Action, Diagnostic, NoExplanation} - val sets = new ScalaSettings() + val sets = ScalaSettings val args = List("-Wconf:cat=deprecation:s,cat=feature:e", "-Wconf:msg=a problem\\.:s") val sumy = ArgsSummary(sets.defaultState, args, errors = Nil, warnings = Nil) val proc = sets.processArguments(sumy, processAll = true, skipped = Nil) @@ -85,7 +85,7 @@ class ScalaSettingsTests: @Test def `i18367 rightmost WConf flags take precedence over flags to the left`: Unit = import reporting.{Action, Diagnostic} - val sets = new ScalaSettings() + val sets = ScalaSettings val args = List("-Wconf:cat=deprecation:e", "-Wconf:cat=deprecation:s") val sumy = ArgsSummary(sets.defaultState, args, errors = Nil, warnings = Nil) val proc = sets.processArguments(sumy, processAll = true, skipped = Nil) From f885c41c5f32568ed6dcb7d51b0269255a011482 Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Mon, 4 Mar 2024 15:23:16 +0100 Subject: [PATCH 219/277] Remove ScalaSettings type: --- compiler/src/dotty/tools/dotc/config/CompilerCommand.scala | 2 +- compiler/src/dotty/tools/dotc/config/ScalaSettings.scala | 2 -- compiler/src/dotty/tools/dotc/core/Contexts.scala | 4 ++-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala b/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala index 587f94dad7b3..2e82c6a3cd67 100644 --- a/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala +++ b/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala @@ -5,7 +5,7 @@ import Settings.* import core.Contexts.* abstract class CompilerCommand extends CliCommand: - type ConcreteSettings = ScalaSettings + type ConcreteSettings = ScalaSettings.type final def helpMsg(using settings: ConcreteSettings)(using SettingsState, Context): String = settings.allSettings.find(isHelping) match diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 33311aa23291..de3fa70d89e4 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -23,8 +23,6 @@ object ScalaSettingCategories: val AdvancedSetting = "X" val VerboseSetting = "V" -type ScalaSettings = ScalaSettings.type - object ScalaSettings extends SettingGroup, AllScalaSettings: val settingsByCategory: Map[String, List[Setting[_]]] = allSettings.groupBy(_.category) diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index ae21c6fb8763..b94824ac3a2b 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -513,7 +513,7 @@ object Contexts { s"""Context( |${outersIterator.map(ctx => cinfo(using ctx)).mkString("\n\n")})""".stripMargin - def settings: ScalaSettings = base.settings + def settings: ScalaSettings.type = base.settings def definitions: Definitions = base.definitions def platform: Platform = base.platform def pendingUnderlying: util.HashSet[Type] = base.pendingUnderlying @@ -861,7 +861,7 @@ object Contexts { with Phases.PhasesBase with Plugins { - val settings: ScalaSettings = ScalaSettings + val settings: ScalaSettings.type = ScalaSettings /** The initial context */ val initialCtx: Context = FreshContext.initial(this: @unchecked, settings) From 7a2a24aaf78165089d46cf043f1a343a14bed7b4 Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Mon, 4 Mar 2024 17:49:49 +0100 Subject: [PATCH 220/277] Changes in parameter parsing & deprecation of -Xlint --- .../dotty/tools/dotc/config/CliCommand.scala | 2 +- .../tools/dotc/config/ScalaSettings.scala | 14 ++-- .../dotty/tools/dotc/config/Settings.scala | 72 ++++++++++--------- .../tools/dotc/transform/CheckShadowing.scala | 6 +- .../dotty/tools/dotc/CompilationTests.scala | 2 +- tests/neg/i17612b/i17612b.scala | 2 +- tests/neg/i17613b/i17613b.scala | 2 +- tests/warn/i17612a.scala | 2 +- tests/warn/i17613a.scala | 2 +- 9 files changed, 58 insertions(+), 46 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/CliCommand.scala b/compiler/src/dotty/tools/dotc/config/CliCommand.scala index 5c24dd57eeba..be97297218fa 100644 --- a/compiler/src/dotty/tools/dotc/config/CliCommand.scala +++ b/compiler/src/dotty/tools/dotc/config/CliCommand.scala @@ -86,7 +86,7 @@ trait CliCommand: protected def isVerbose(s: Setting[?])(using settings: ConcreteSettings)(using SettingsState): Boolean = s.name.startsWith("-V") && s.name != "-V" protected def isWarning(s: Setting[?])(using settings: ConcreteSettings)(using SettingsState): Boolean = - s.name.startsWith("-W") && s.name != "-W" || s.name == "-Xlint" + s.name.startsWith("-W") && s.name != "-W" protected def isAdvanced(s: Setting[?])(using settings: ConcreteSettings)(using SettingsState): Boolean = s.name.startsWith("-X") && s.name != "-X" protected def isPrivate(s: Setting[?])(using settings: ConcreteSettings)(using SettingsState): Boolean = diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index de3fa70d89e4..1c7554dcd74e 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -296,9 +296,9 @@ private sealed trait WarningSettings: |to prevent the shell from expanding patterns.""".stripMargin, ) - val Xlint: Setting[List[ChoiceWithHelp[String]]] = UncompleteMultiChoiceHelpSetting( - AdvancedSetting, - name = "Xlint", + val Wshadow: Setting[List[ChoiceWithHelp[String]]] = MultiChoiceHelpSetting( + WarningSetting, + name = "Wshadow", helpArg = "advanced warning", descr = "Enable or disable specific `lint` warnings", choices = List( @@ -309,9 +309,9 @@ private sealed trait WarningSettings: default = Nil ) - object XlintHas: + object WshadowHas: def allOr(s: String)(using Context) = - Xlint.value.pipe(us => us.contains("all") || us.contains(s)) + Wshadow.value.pipe(us => us.contains("all") || us.contains(s)) def privateShadow(using Context) = allOr("private-shadow") def typeParameterShadow(using Context) = @@ -357,6 +357,10 @@ private sealed trait XSettings: } val XmacroSettings: Setting[List[String]] = MultiStringSetting(AdvancedSetting, "Xmacro-settings", "setting1,setting2,..settingN", "List of settings which exposed to the macros") + + // Deprecated + val Xlint: Setting[_] = DeprecatedSetting(AdvancedSetting, "Xlint", "Enable or disable specific warnings", "Use -Wshadow to enable shadowing lints or -W: to enable specific sets of warnings.") + end XSettings /** -Y "Forking" as in forked tongue or "Private" settings */ diff --git a/compiler/src/dotty/tools/dotc/config/Settings.scala b/compiler/src/dotty/tools/dotc/config/Settings.scala index 16af5468ccf0..c352d2cb9cbb 100644 --- a/compiler/src/dotty/tools/dotc/config/Settings.scala +++ b/compiler/src/dotty/tools/dotc/config/Settings.scala @@ -70,10 +70,15 @@ object Settings: aliases: List[String] = Nil, depends: List[(Setting[?], Any)] = Nil, ignoreInvalidArgs: Boolean = false, - propertyClass: Option[Class[?]] = None)(private[Settings] val idx: Int) { + propertyClass: Option[Class[?]] = None, + deprecationMsg: Option[String] = None)(private[Settings] val idx: Int) { assert(name.startsWith(s"-$category"), s"Setting $name does not start with category -$category") + // Without the following assertion, it would be easy to mistakenly try to pass a file to a setting that ignores invalid args. + // Example: -opt Main.scala would be interpreted as -opt:Main.scala, and the source file would be ignored. + assert(!(summon[ClassTag[T]] == ListTag && ignoreInvalidArgs), s"Ignoring invalid args is not supported for multivalue settings: $name") + val allFullNames: List[String] = s"$name" :: s"-$name" :: aliases def valueIn(state: SettingsState): T = state.value(idx).asInstanceOf[T] @@ -150,6 +155,24 @@ object Settings: update(x, args) catch case _: NumberFormatException => fail(s"$argValue is not an integer argument for $name", args) + + def setOutput(argValue: String, args: List[String]) = + val path = Directory(argValue) + val isJar = path.extension == "jar" + if (!isJar && !path.isDirectory) + fail(s"'$argValue' does not exist or is not a directory or .jar file", args) + else { + val output = if (isJar) JarArchive.create(path) else new PlainDirectory(path) + update(output, args) + } + + def appendList(strings: List[String], args: List[String]) = + choices match + case Some(valid) => strings.filterNot(valid.contains) match + case Nil => update(strings, args) + case invalid => invalidChoices(invalid) + case _ => update(strings, args) + def doSet(argRest: String) = ((summon[ClassTag[T]], args): @unchecked) match { @@ -157,38 +180,20 @@ object Settings: setBoolean(argRest, args) case (OptionTag, _) => update(Some(propertyClass.get.getConstructor().newInstance()), args) - case (ListTag, _) => - if (argRest.isEmpty) missingArg - else - val strings = argRest.split(",").toList - choices match - case Some(valid) => strings.filterNot(valid.contains) match - case Nil => update(strings, args) - case invalid => invalidChoices(invalid) - case _ => update(strings, args) + case (ListTag, args) if argRest.nonEmpty => + val strings = argRest.split(",").toList + appendList(strings, args) + case (ListTag, arg2 :: args2) if !(arg2 startsWith "-")=> + appendList(arg2 :: Nil, args2) case (StringTag, _) if argRest.nonEmpty || choices.exists(_.contains("")) => setString(argRest, args) case (StringTag, arg2 :: args2) => if (arg2 startsWith "-") missingArg else setString(arg2, args2) - case (OutputTag, _) if argRest.nonEmpty => - val path = Directory(argRest) - val isJar = path.extension == "jar" - if (!isJar && !path.isDirectory) - fail(s"'$argRest' does not exist or is not a directory or .jar file", args) - else { - val output = if (isJar) JarArchive.create(path) else new PlainDirectory(path) - update(output, args) - } - case (OutputTag, arg :: args) => - val path = Directory(arg) - val isJar = path.extension == "jar" - if (!isJar && !path.isDirectory) - fail(s"'$arg' does not exist or is not a directory or .jar file", args) - else { - val output = if (isJar) JarArchive.create(path) else new PlainDirectory(path) - update(output, args) - } + case (OutputTag, args) if argRest.nonEmpty => + setOutput(argRest, args) + case (OutputTag, arg2 :: args2) => + setOutput(arg2, args2) case (IntTag, args) if argRest.nonEmpty => setInt(argRest, args) case (IntTag, arg2 :: args2) => @@ -214,7 +219,10 @@ object Settings: if(prefix.isEmpty) arg.dropWhile(_ != ':').drop(1) else arg.drop(prefix.get.length) if matches(arg) then - doSet(argValRest) + if deprecationMsg.isDefined then + warn(s"Option $name is deprecated: ${deprecationMsg.get}", args) + else + doSet(argValRest) else state } @@ -334,9 +342,6 @@ object Settings: def MultiChoiceHelpSetting(category: String, name: String, helpArg: String, descr: String, choices: List[ChoiceWithHelp[String]], default: List[ChoiceWithHelp[String]], aliases: List[String] = Nil): Setting[List[ChoiceWithHelp[String]]] = publish(Setting(category, validateAndPrependName(name), descr, default, helpArg, Some(choices), aliases = aliases.map(validateSetting))) - def UncompleteMultiChoiceHelpSetting(category: String, name: String, helpArg: String, descr: String, choices: List[ChoiceWithHelp[String]], default: List[ChoiceWithHelp[String]], aliases: List[String] = Nil): Setting[List[ChoiceWithHelp[String]]] = - publish(Setting(category, validateAndPrependName(name), descr, default, helpArg, Some(choices), aliases = aliases.map(validateSetting), ignoreInvalidArgs = true)) - def IntSetting(category: String, name: String, descr: String, default: Int, aliases: List[String] = Nil): Setting[Int] = publish(Setting(category, validateAndPrependName(name), descr, default, aliases = aliases.map(validateSetting))) @@ -364,5 +369,8 @@ object Settings: def OptionSetting[T: ClassTag](category: String, name: String, descr: String, aliases: List[String] = Nil): Setting[Option[T]] = publish(Setting(category, validateAndPrependName(name), descr, None, propertyClass = Some(summon[ClassTag[T]].runtimeClass), aliases = aliases.map(validateSetting))) + + def DeprecatedSetting(category: String, name: String, descr: String, deprecationMsg: String): Setting[Boolean] = + publish(Setting(category, validateAndPrependName(name), descr, false, deprecationMsg = Some(deprecationMsg))) } end Settings diff --git a/compiler/src/dotty/tools/dotc/transform/CheckShadowing.scala b/compiler/src/dotty/tools/dotc/transform/CheckShadowing.scala index a85cabdd5460..87d652bd9133 100644 --- a/compiler/src/dotty/tools/dotc/transform/CheckShadowing.scala +++ b/compiler/src/dotty/tools/dotc/transform/CheckShadowing.scala @@ -51,7 +51,7 @@ class CheckShadowing extends MiniPhase: override def isRunnable(using Context): Boolean = super.isRunnable && - ctx.settings.Xlint.value.nonEmpty && + ctx.settings.Wshadow.value.nonEmpty && !ctx.isJava // Setup before the traversal @@ -266,12 +266,12 @@ object CheckShadowing: /** Get the shadowing analysis's result */ def getShadowingResult(using Context): ShadowResult = val privateWarnings: List[ShadowWarning] = - if ctx.settings.XlintHas.privateShadow then + if ctx.settings.WshadowHas.privateShadow then privateShadowWarnings.toList else Nil val typeParamWarnings: List[ShadowWarning] = - if ctx.settings.XlintHas.typeParameterShadow then + if ctx.settings.WshadowHas.typeParameterShadow then typeParamShadowWarnings.toList else Nil diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 64c2bd3b8807..a96a4ea09102 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -31,7 +31,7 @@ class CompilationTests { @Test def pos: Unit = { implicit val testGroup: TestGroup = TestGroup("compilePos") var tests = List( - compileFilesInDir("tests/pos", defaultOptions.and("-Ysafe-init", "-Wunused:all", "-Xlint:private-shadow", "-Xlint:type-parameter-shadow"), FileFilter.include(TestSources.posLintingAllowlist)), + compileFilesInDir("tests/pos", defaultOptions.and("-Ysafe-init", "-Wunused:all", "-Wshadow:private-shadow", "-Wshadow:type-parameter-shadow"), FileFilter.include(TestSources.posLintingAllowlist)), compileFilesInDir("tests/pos", defaultOptions.and("-Ysafe-init"), FileFilter.exclude(TestSources.posLintingAllowlist)), compileFilesInDir("tests/pos-deep-subtype", allowDeepSubtypes), compileFilesInDir("tests/pos-special/sourcepath/outer", defaultOptions.and("-sourcepath", "tests/pos-special/sourcepath")), diff --git a/tests/neg/i17612b/i17612b.scala b/tests/neg/i17612b/i17612b.scala index 62d6ad17ff3d..a7afbf019d07 100644 --- a/tests/neg/i17612b/i17612b.scala +++ b/tests/neg/i17612b/i17612b.scala @@ -1,4 +1,4 @@ -//> using options -Xfatal-warnings -Xlint:private-shadow -source:3.3 +//> using options -Xfatal-warnings -Wshadow:private-shadow -source:3.3 object i17612b: diff --git a/tests/neg/i17613b/i17613b.scala b/tests/neg/i17613b/i17613b.scala index 42506a274a65..0969a9a869ea 100644 --- a/tests/neg/i17613b/i17613b.scala +++ b/tests/neg/i17613b/i17613b.scala @@ -1,4 +1,4 @@ -//> using options -Xlint:type-parameter-shadow -Xfatal-warnings +//> using options -Wshadow:type-parameter-shadow -Xfatal-warnings object i17613b: import importTry._ diff --git a/tests/warn/i17612a.scala b/tests/warn/i17612a.scala index 7473d8fd9ec9..87fddf9c180f 100644 --- a/tests/warn/i17612a.scala +++ b/tests/warn/i17612a.scala @@ -1,4 +1,4 @@ -//> using options -Xlint:private-shadow -source:3.3 +//> using options -Wshadow:private-shadow -source:3.3 object i17612a: class Base(var x: Int, val y: Int, var z: Int): diff --git a/tests/warn/i17613a.scala b/tests/warn/i17613a.scala index 6ee55a5cf973..5e841a79d105 100644 --- a/tests/warn/i17613a.scala +++ b/tests/warn/i17613a.scala @@ -1,4 +1,4 @@ -//> using options -Xlint:type-parameter-shadow +//> using options -Wshadow:type-parameter-shadow object i17613a: class B: From 55e4477350d2fe80db12139584515f634ed33dc2 Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Tue, 5 Mar 2024 12:50:24 +0100 Subject: [PATCH 221/277] Unify settings parsing --- .../tools/dotc/config/ScalaSettings.scala | 2 +- .../dotty/tools/dotc/config/Settings.scala | 64 +++++++++---------- tests/neg/kind-projector.scala | 2 +- .../dotc/config/ScalaSettings.scala | 2 +- tests/pos/kind-projector.scala | 2 +- 5 files changed, 36 insertions(+), 36 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 1c7554dcd74e..835f5d5a6668 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -401,7 +401,7 @@ private sealed trait YSettings: val YstopBefore: Setting[List[String]] = PhasesSetting(ForkSetting, "Ystop-before", "Stop before") // stop before erasure as long as we have not debugged it fully val YshowSuppressedErrors: Setting[Boolean] = BooleanSetting(ForkSetting, "Yshow-suppressed-errors", "Also show follow-on errors and warnings that are normally suppressed.") val YdetailedStats: Setting[Boolean] = BooleanSetting(ForkSetting, "Ydetailed-stats", "Show detailed internal compiler stats (needs Stats.enabled to be set to true).") - val YkindProjector: Setting[String] = ChoiceSetting(ForkSetting, "Ykind-projector", "[underscores, disable]", "Allow `*` as type lambda placeholder to be compatible with kind projector. When invoked as -Ykind-projector:underscores will repurpose `_` to be a type parameter placeholder, this will disable usage of underscore as a wildcard.", List("disable", "", "underscores"), "disable") + val YkindProjector: Setting[String] = ChoiceSetting(ForkSetting, "Ykind-projector", "[underscores, enable, disable]", "Allow `*` as type lambda placeholder to be compatible with kind projector. When invoked as -Ykind-projector:underscores will repurpose `_` to be a type parameter placeholder, this will disable usage of underscore as a wildcard.", List("disable", "enable", "underscores"), "disable") val YprintPos: Setting[Boolean] = BooleanSetting(ForkSetting, "Yprint-pos", "Show tree positions.") val YprintPosSyms: Setting[Boolean] = BooleanSetting(ForkSetting, "Yprint-pos-syms", "Show symbol definitions positions.") val YnoDeepSubtypes: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-deep-subtypes", "Throw an exception on deep subtyping call stacks.") diff --git a/compiler/src/dotty/tools/dotc/config/Settings.scala b/compiler/src/dotty/tools/dotc/config/Settings.scala index c352d2cb9cbb..7c687eb5988b 100644 --- a/compiler/src/dotty/tools/dotc/config/Settings.scala +++ b/compiler/src/dotty/tools/dotc/config/Settings.scala @@ -72,9 +72,10 @@ object Settings: ignoreInvalidArgs: Boolean = false, propertyClass: Option[Class[?]] = None, deprecationMsg: Option[String] = None)(private[Settings] val idx: Int) { - + + assert(name.startsWith(s"-$category"), s"Setting $name does not start with category -$category") - + assert(!choices.contains(""), s"Empty string is not supported as a choice for setting $name") // Without the following assertion, it would be easy to mistakenly try to pass a file to a setting that ignores invalid args. // Example: -opt Main.scala would be interpreted as -opt:Main.scala, and the source file would be ignored. assert(!(summon[ClassTag[T]] == ListTag && ignoreInvalidArgs), s"Ignoring invalid args is not supported for multivalue settings: $name") @@ -165,6 +166,12 @@ object Settings: val output = if (isJar) JarArchive.create(path) else new PlainDirectory(path) update(output, args) } + + def setVersion(argValue: String, args: List[String]) = + ScalaVersion.parse(argValue) match { + case Success(v) => update(v, args) + case Failure(ex) => fail(ex.getMessage, args) + } def appendList(strings: List[String], args: List[String]) = choices match @@ -180,38 +187,31 @@ object Settings: setBoolean(argRest, args) case (OptionTag, _) => update(Some(propertyClass.get.getConstructor().newInstance()), args) - case (ListTag, args) if argRest.nonEmpty => - val strings = argRest.split(",").toList - appendList(strings, args) - case (ListTag, arg2 :: args2) if !(arg2 startsWith "-")=> - appendList(arg2 :: Nil, args2) - case (StringTag, _) if argRest.nonEmpty || choices.exists(_.contains("")) => - setString(argRest, args) - case (StringTag, arg2 :: args2) => - if (arg2 startsWith "-") missingArg - else setString(arg2, args2) - case (OutputTag, args) if argRest.nonEmpty => - setOutput(argRest, args) - case (OutputTag, arg2 :: args2) => - setOutput(arg2, args2) - case (IntTag, args) if argRest.nonEmpty => - setInt(argRest, args) - case (IntTag, arg2 :: args2) => - setInt(arg2, args2) - case (VersionTag, _) if argRest.nonEmpty => - ScalaVersion.parse(argRest) match { - case Success(v) => update(v, args) - case Failure(ex) => fail(ex.getMessage, args) - } - case (VersionTag, arg2 :: args2) => - ScalaVersion.parse(arg2) match { - case Success(v) => update(v, args2) - case Failure(ex) => fail(ex.getMessage, args2) - } - case (_, Nil) => - missingArg + case (_, args) => + val argInArgRest = !argRest.isEmpty + val argAfterParam = !argInArgRest && args.nonEmpty && !args.head.startsWith("-") + if argInArgRest then + doSetArg(argRest, args) + else if argAfterParam then + doSetArg(args.head, args.tail) + else missingArg } + def doSetArg(arg: String, argsLeft: List[String]) = summon[ClassTag[T]] match + case ListTag => + val strings = arg.split(",").toList + appendList(strings, argsLeft) + case StringTag => + setString(arg, argsLeft) + case OutputTag => + setOutput(arg, argsLeft) + case IntTag => + setInt(arg, argsLeft) + case VersionTag => + setVersion(arg, argsLeft) + case _ => + missingArg + def matches(argName: String): Boolean = (allFullNames).exists(_ == argName.takeWhile(_ != ':')) || prefix.exists(arg.startsWith) diff --git a/tests/neg/kind-projector.scala b/tests/neg/kind-projector.scala index a7fc24c70b93..fa2bd20d60ce 100644 --- a/tests/neg/kind-projector.scala +++ b/tests/neg/kind-projector.scala @@ -1,4 +1,4 @@ -//> using options -Ykind-projector +//> using options -Ykind-projector:enable package kind_projector_neg diff --git a/tests/pos-with-compiler-cc/dotc/config/ScalaSettings.scala b/tests/pos-with-compiler-cc/dotc/config/ScalaSettings.scala index b3250eb7b536..558eb3e0a12b 100644 --- a/tests/pos-with-compiler-cc/dotc/config/ScalaSettings.scala +++ b/tests/pos-with-compiler-cc/dotc/config/ScalaSettings.scala @@ -289,7 +289,7 @@ private sealed trait YSettings: val YstopBefore: Setting[List[String]] = PhasesSetting("-Ystop-before", "Stop before") // stop before erasure as long as we have not debugged it fully val YshowSuppressedErrors: Setting[Boolean] = BooleanSetting("-Yshow-suppressed-errors", "Also show follow-on errors and warnings that are normally suppressed.") val YdetailedStats: Setting[Boolean] = BooleanSetting("-Ydetailed-stats", "Show detailed internal compiler stats (needs Stats.enabled to be set to true).") - val YkindProjector: Setting[String] = ChoiceSetting("-Ykind-projector", "[underscores, disable]", "Allow `*` as type lambda placeholder to be compatible with kind projector. When invoked as -Ykind-projector:underscores will repurpose `_` to be a type parameter placeholder, this will disable usage of underscore as a wildcard.", List("disable", "", "underscores"), "disable") + val YkindProjector: Setting[String] = ChoiceSetting("-Ykind-projector", "[underscores, enable, disable]", "Allow `*` as type lambda placeholder to be compatible with kind projector. When invoked as -Ykind-projector:underscores will repurpose `_` to be a type parameter placeholder, this will disable usage of underscore as a wildcard.", List("disable", "enable", "underscores"), "disable") val YprintPos: Setting[Boolean] = BooleanSetting("-Yprint-pos", "Show tree positions.") val YprintPosSyms: Setting[Boolean] = BooleanSetting("-Yprint-pos-syms", "Show symbol definitions positions.") val YnoDeepSubtypes: Setting[Boolean] = BooleanSetting("-Yno-deep-subtypes", "Throw an exception on deep subtyping call stacks.") diff --git a/tests/pos/kind-projector.scala b/tests/pos/kind-projector.scala index 4d6ec8c932a9..07e6272efd90 100644 --- a/tests/pos/kind-projector.scala +++ b/tests/pos/kind-projector.scala @@ -1,4 +1,4 @@ -//> using options -Ykind-projector +//> using options -Ykind-projector:enable package kind_projector From bf0da9c7ee9c2d5888743878fef85aa1c19baa44 Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Tue, 5 Mar 2024 18:12:22 +0100 Subject: [PATCH 222/277] Fix negative numeric args --- compiler/src/dotty/tools/dotc/config/Settings.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/Settings.scala b/compiler/src/dotty/tools/dotc/config/Settings.scala index 7c687eb5988b..e998270a6052 100644 --- a/compiler/src/dotty/tools/dotc/config/Settings.scala +++ b/compiler/src/dotty/tools/dotc/config/Settings.scala @@ -187,9 +187,9 @@ object Settings: setBoolean(argRest, args) case (OptionTag, _) => update(Some(propertyClass.get.getConstructor().newInstance()), args) - case (_, args) => + case (ct, args) => val argInArgRest = !argRest.isEmpty - val argAfterParam = !argInArgRest && args.nonEmpty && !args.head.startsWith("-") + val argAfterParam = !argInArgRest && args.nonEmpty && (ct == IntTag || !args.head.startsWith("-")) if argInArgRest then doSetArg(argRest, args) else if argAfterParam then From d6d796dc84fc09fccaebe7f7dc7de29c0a0f76f0 Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Wed, 6 Mar 2024 16:42:45 +0100 Subject: [PATCH 223/277] Handle -Ykind-projector as legacy option --- .../src/dotty/tools/dotc/config/ScalaSettings.scala | 2 +- compiler/src/dotty/tools/dotc/config/Settings.scala | 10 ++++++++-- .../test/dotty/tools/dotc/TastyBootstrapTests.scala | 2 +- tests/neg/kind-projector.scala | 2 +- tests/pos/kind-projector.scala | 2 +- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 835f5d5a6668..7eda918638b9 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -401,7 +401,7 @@ private sealed trait YSettings: val YstopBefore: Setting[List[String]] = PhasesSetting(ForkSetting, "Ystop-before", "Stop before") // stop before erasure as long as we have not debugged it fully val YshowSuppressedErrors: Setting[Boolean] = BooleanSetting(ForkSetting, "Yshow-suppressed-errors", "Also show follow-on errors and warnings that are normally suppressed.") val YdetailedStats: Setting[Boolean] = BooleanSetting(ForkSetting, "Ydetailed-stats", "Show detailed internal compiler stats (needs Stats.enabled to be set to true).") - val YkindProjector: Setting[String] = ChoiceSetting(ForkSetting, "Ykind-projector", "[underscores, enable, disable]", "Allow `*` as type lambda placeholder to be compatible with kind projector. When invoked as -Ykind-projector:underscores will repurpose `_` to be a type parameter placeholder, this will disable usage of underscore as a wildcard.", List("disable", "enable", "underscores"), "disable") + val YkindProjector: Setting[String] = LegacyChoiceSetting(ForkSetting, "Ykind-projector", "[underscores, enable, disable]", "Allow `*` as type lambda placeholder to be compatible with kind projector. When invoked as -Ykind-projector:underscores will repurpose `_` to be a type parameter placeholder, this will disable usage of underscore as a wildcard.", List("disable", "", "underscores"), "disable") val YprintPos: Setting[Boolean] = BooleanSetting(ForkSetting, "Yprint-pos", "Show tree positions.") val YprintPosSyms: Setting[Boolean] = BooleanSetting(ForkSetting, "Yprint-pos-syms", "Show symbol definitions positions.") val YnoDeepSubtypes: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-deep-subtypes", "Throw an exception on deep subtyping call stacks.") diff --git a/compiler/src/dotty/tools/dotc/config/Settings.scala b/compiler/src/dotty/tools/dotc/config/Settings.scala index e998270a6052..c64abb3dddb8 100644 --- a/compiler/src/dotty/tools/dotc/config/Settings.scala +++ b/compiler/src/dotty/tools/dotc/config/Settings.scala @@ -71,7 +71,9 @@ object Settings: depends: List[(Setting[?], Any)] = Nil, ignoreInvalidArgs: Boolean = false, propertyClass: Option[Class[?]] = None, - deprecationMsg: Option[String] = None)(private[Settings] val idx: Int) { + deprecationMsg: Option[String] = None, + // kept only for -Ykind-projector option compatibility + legacyArgs: Boolean = false)(private[Settings] val idx: Int) { assert(name.startsWith(s"-$category"), s"Setting $name does not start with category -$category") @@ -188,7 +190,7 @@ object Settings: case (OptionTag, _) => update(Some(propertyClass.get.getConstructor().newInstance()), args) case (ct, args) => - val argInArgRest = !argRest.isEmpty + val argInArgRest = !argRest.isEmpty || (legacyArgs && choices.exists(_.contains(""))) val argAfterParam = !argInArgRest && args.nonEmpty && (ct == IntTag || !args.head.startsWith("-")) if argInArgRest then doSetArg(argRest, args) @@ -336,6 +338,10 @@ object Settings: def ChoiceSetting(category: String, name: String, helpArg: String, descr: String, choices: List[String], default: String, aliases: List[String] = Nil): Setting[String] = publish(Setting(category, validateAndPrependName(name), descr, default, helpArg, Some(choices), aliases = aliases.map(validateSetting))) + // Allows only args after :, but supports empty string as a choice. Used for -Ykind-projector + def LegacyChoiceSetting(category: String, name: String, helpArg: String, descr: String, choices: List[String], default: String, aliases: List[String] = Nil): Setting[String] = + publish(Setting(category, validateAndPrependName(name), descr, default, helpArg, Some(choices), aliases = aliases.map(validateSetting), legacyArgs = true)) + def MultiChoiceSetting(category: String, name: String, helpArg: String, descr: String, choices: List[String], default: List[String], aliases: List[String] = Nil): Setting[List[String]] = publish(Setting(category, validateAndPrependName(name), descr, default, helpArg, Some(choices), aliases = aliases.map(validateSetting))) diff --git a/compiler/test/dotty/tools/dotc/TastyBootstrapTests.scala b/compiler/test/dotty/tools/dotc/TastyBootstrapTests.scala index 9929e1e87214..27311497de9c 100644 --- a/compiler/test/dotty/tools/dotc/TastyBootstrapTests.scala +++ b/compiler/test/dotty/tools/dotc/TastyBootstrapTests.scala @@ -51,7 +51,7 @@ class TastyBootstrapTests { Properties.compilerInterface, Properties.scalaLibrary, Properties.scalaAsm, Properties.dottyInterfaces, Properties.jlineTerminal, Properties.jlineReader, ).mkString(File.pathSeparator), - Array("-Ycheck-reentrant", "-Ylog:checkReentrant+", "-language:postfixOps", "-Xsemanticdb") + Array("-Ycheck-reentrant", "-language:postfixOps", "-Xsemanticdb") ) val libraryDirs = List(Paths.get("library/src"), Paths.get("library/src-bootstrapped")) diff --git a/tests/neg/kind-projector.scala b/tests/neg/kind-projector.scala index fa2bd20d60ce..a7fc24c70b93 100644 --- a/tests/neg/kind-projector.scala +++ b/tests/neg/kind-projector.scala @@ -1,4 +1,4 @@ -//> using options -Ykind-projector:enable +//> using options -Ykind-projector package kind_projector_neg diff --git a/tests/pos/kind-projector.scala b/tests/pos/kind-projector.scala index 07e6272efd90..4d6ec8c932a9 100644 --- a/tests/pos/kind-projector.scala +++ b/tests/pos/kind-projector.scala @@ -1,4 +1,4 @@ -//> using options -Ykind-projector:enable +//> using options -Ykind-projector package kind_projector From 2f7ff98a65a702a371d36901942636f3b9e5d4a8 Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Thu, 7 Mar 2024 14:06:40 +0100 Subject: [PATCH 224/277] Clean up the PR --- compiler/src/dotty/tools/backend/jvm/BackendUtils.scala | 2 +- compiler/src/dotty/tools/dotc/Driver.scala | 1 - compiler/src/dotty/tools/dotc/config/ScalaSettings.scala | 6 +++--- compiler/src/dotty/tools/dotc/config/Settings.scala | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/backend/jvm/BackendUtils.scala b/compiler/src/dotty/tools/backend/jvm/BackendUtils.scala index 459f1b2b2613..c953358d7940 100644 --- a/compiler/src/dotty/tools/backend/jvm/BackendUtils.scala +++ b/compiler/src/dotty/tools/backend/jvm/BackendUtils.scala @@ -186,4 +186,4 @@ object BackendUtils { "21" -> asm.Opcodes.V21, "22" -> asm.Opcodes.V22, ) -} \ No newline at end of file +} diff --git a/compiler/src/dotty/tools/dotc/Driver.scala b/compiler/src/dotty/tools/dotc/Driver.scala index 6b461cc8e81b..196752aceb29 100644 --- a/compiler/src/dotty/tools/dotc/Driver.scala +++ b/compiler/src/dotty/tools/dotc/Driver.scala @@ -10,7 +10,6 @@ import dotty.tools.io.AbstractFile import reporting.* import core.Decorators.* import config.Feature -import dotty.tools.dotc.config.ScalaSettings import scala.util.control.NonFatal import fromtasty.{TASTYCompiler, TastyFileUtil} diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 7eda918638b9..07529be36c52 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -299,8 +299,8 @@ private sealed trait WarningSettings: val Wshadow: Setting[List[ChoiceWithHelp[String]]] = MultiChoiceHelpSetting( WarningSetting, name = "Wshadow", - helpArg = "advanced warning", - descr = "Enable or disable specific `lint` warnings", + helpArg = "warning", + descr = "Enable or disable specific `shadow` warnings", choices = List( ChoiceWithHelp("all", ""), ChoiceWithHelp("private-shadow", "Warn if a private field or class parameter shadows a superclass field"), @@ -359,7 +359,7 @@ private sealed trait XSettings: val XmacroSettings: Setting[List[String]] = MultiStringSetting(AdvancedSetting, "Xmacro-settings", "setting1,setting2,..settingN", "List of settings which exposed to the macros") // Deprecated - val Xlint: Setting[_] = DeprecatedSetting(AdvancedSetting, "Xlint", "Enable or disable specific warnings", "Use -Wshadow to enable shadowing lints or -W: to enable specific sets of warnings.") + val Xlint: Setting[_] = DeprecatedSetting(AdvancedSetting, "Xlint", "Enable or disable specific warnings", "Use -Wshadow to enable shadowing lints.") end XSettings diff --git a/compiler/src/dotty/tools/dotc/config/Settings.scala b/compiler/src/dotty/tools/dotc/config/Settings.scala index c64abb3dddb8..2fa484ba2882 100644 --- a/compiler/src/dotty/tools/dotc/config/Settings.scala +++ b/compiler/src/dotty/tools/dotc/config/Settings.scala @@ -77,7 +77,7 @@ object Settings: assert(name.startsWith(s"-$category"), s"Setting $name does not start with category -$category") - assert(!choices.contains(""), s"Empty string is not supported as a choice for setting $name") + assert(legacyArgs || !choices.exists(_.contains("")), s"Empty string is not supported as a choice for setting $name") // Without the following assertion, it would be easy to mistakenly try to pass a file to a setting that ignores invalid args. // Example: -opt Main.scala would be interpreted as -opt:Main.scala, and the source file would be ignored. assert(!(summon[ClassTag[T]] == ListTag && ignoreInvalidArgs), s"Ignoring invalid args is not supported for multivalue settings: $name") From 2ee562e0681c5361f1f2b9c5f7803cf4f20fefba Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Tue, 12 Mar 2024 12:30:32 +0100 Subject: [PATCH 225/277] Keep ScalaSettings class for back compat --- .../tools/dotc/config/CompilerCommand.scala | 2 +- .../tools/dotc/config/ScalaSettings.scala | 54 ++++++++++--------- .../src/dotty/tools/dotc/core/Contexts.scala | 4 +- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala b/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala index 2e82c6a3cd67..587f94dad7b3 100644 --- a/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala +++ b/compiler/src/dotty/tools/dotc/config/CompilerCommand.scala @@ -5,7 +5,7 @@ import Settings.* import core.Contexts.* abstract class CompilerCommand extends CliCommand: - type ConcreteSettings = ScalaSettings.type + type ConcreteSettings = ScalaSettings final def helpMsg(using settings: ConcreteSettings)(using SettingsState, Context): String = settings.allSettings.find(isHelping) match diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 07529be36c52..c27ba0863ebe 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -23,18 +23,7 @@ object ScalaSettingCategories: val AdvancedSetting = "X" val VerboseSetting = "V" -object ScalaSettings extends SettingGroup, AllScalaSettings: - val settingsByCategory: Map[String, List[Setting[_]]] = - allSettings.groupBy(_.category) - .view.mapValues(_.toList).toMap - .withDefaultValue(Nil) - def categories: List[String] = settingsByCategory.keys.toList - val rootSettings: List[Setting[_]] = settingsByCategory(RootSetting) - val warningSettings: List[Setting[_]] = settingsByCategory(WarningSetting) - val forkSettings: List[Setting[_]] = settingsByCategory(ForkSetting) - val advancedSettings: List[Setting[_]] = settingsByCategory(AdvancedSetting) - val verboseSettings: List[Setting[_]] = settingsByCategory(VerboseSetting) - val settingsByAliases: Map[String, Setting[_]] = allSettings.flatMap(s => s.aliases.map(_ -> s)).toMap +object ScalaSettingsProperties: private lazy val minTargetVersion = classfileVersionMap.keysIterator.map(_.toInt).min private lazy val maxTargetVersion = classfileVersionMap.keysIterator.map(_.toInt).max @@ -68,6 +57,23 @@ object ScalaSettings extends SettingGroup, AllScalaSettings: else defaultWidth else defaultWidth } + +object ScalaSettings extends ScalaSettings + +// Kept as seperate type to avoid breaking backward compatibility +abstract class ScalaSettings extends SettingGroup, AllScalaSettings: + val settingsByCategory: Map[String, List[Setting[_]]] = + allSettings.groupBy(_.category) + .view.mapValues(_.toList).toMap + .withDefaultValue(Nil) + def categories: List[String] = settingsByCategory.keys.toList + val rootSettings: List[Setting[_]] = settingsByCategory(RootSetting) + val warningSettings: List[Setting[_]] = settingsByCategory(WarningSetting) + val forkSettings: List[Setting[_]] = settingsByCategory(ForkSetting) + val advancedSettings: List[Setting[_]] = settingsByCategory(AdvancedSetting) + val verboseSettings: List[Setting[_]] = settingsByCategory(VerboseSetting) + val settingsByAliases: Map[String, Setting[_]] = allSettings.flatMap(s => s.aliases.map(_ -> s)).toMap + trait AllScalaSettings extends CommonScalaSettings, PluginSettings, VerboseSettings, WarningSettings, XSettings, YSettings: self: SettingGroup => @@ -76,7 +82,7 @@ trait AllScalaSettings extends CommonScalaSettings, PluginSettings, VerboseSetti val semanticdbTarget: Setting[String] = PathSetting(RootSetting, "semanticdb-target", "Specify an alternative output directory for SemanticDB files.", "") val semanticdbText: Setting[Boolean] = BooleanSetting(RootSetting, "semanticdb-text", "Specifies whether to include source code in SemanticDB files or not.") - val source: Setting[String] = ChoiceSetting(RootSetting, "source", "source version", "source version", ScalaSettings.supportedSourceVersions, SourceVersion.defaultSourceVersion.toString, aliases = List("--source")) + val source: Setting[String] = ChoiceSetting(RootSetting, "source", "source version", "source version", ScalaSettingsProperties.supportedSourceVersions, SourceVersion.defaultSourceVersion.toString, aliases = List("--source")) val uniqid: Setting[Boolean] = BooleanSetting(RootSetting, "uniqid", "Uniquely tag all identifiers in debugging output.", aliases = List("--unique-id")) val rewrite: Setting[Option[Rewrites]] = OptionSetting[Rewrites](RootSetting, "rewrite", "When used in conjunction with a `...-migration` source version, rewrites sources to migrate to new version.", aliases = List("--rewrite")) val fromTasty: Setting[Boolean] = BooleanSetting(RootSetting, "from-tasty", "Compile classes from tasty files. The arguments are .tasty or .jar files.", aliases = List("--from-tasty")) @@ -119,17 +125,17 @@ trait CommonScalaSettings: val sourcepath: Setting[String] = PathSetting(RootSetting, "sourcepath", "Specify location(s) of source files.", Defaults.scalaSourcePath, aliases = List("--source-path")) val sourceroot: Setting[String] = PathSetting(RootSetting, "sourceroot", "Specify workspace root directory.", ".") - val classpath: Setting[String] = PathSetting(RootSetting, "classpath", "Specify where to find user class files.", ScalaSettings.defaultClasspath, aliases = List("-cp", "--class-path")) + val classpath: Setting[String] = PathSetting(RootSetting, "classpath", "Specify where to find user class files.", ScalaSettingsProperties.defaultClasspath, aliases = List("-cp", "--class-path")) val outputDir: Setting[AbstractFile] = OutputSetting(RootSetting, "d", "directory|jar", "Destination for generated classfiles.", new PlainDirectory(Directory("."))) val color: Setting[String] = ChoiceSetting(RootSetting, "color", "mode", "Colored output", List("always", "never"/*, "auto"*/), "always"/* "auto"*/, aliases = List("--color")) val verbose: Setting[Boolean] = BooleanSetting(RootSetting, "verbose", "Output messages about what the compiler is doing.", aliases = List("--verbose")) val version: Setting[Boolean] = BooleanSetting(RootSetting, "version", "Print product version and exit.", aliases = List("--version")) val help: Setting[Boolean] = BooleanSetting(RootSetting, "help", "Print a synopsis of standard options.", aliases = List("--help", "-h")) - val pageWidth: Setting[Int] = IntSetting(RootSetting, "pagewidth", "Set page width", ScalaSettings.defaultPageWidth, aliases = List("--page-width")) + val pageWidth: Setting[Int] = IntSetting(RootSetting, "pagewidth", "Set page width", ScalaSettingsProperties.defaultPageWidth, aliases = List("--page-width")) val silentWarnings: Setting[Boolean] = BooleanSetting(RootSetting, "nowarn", "Silence all warnings.", aliases = List("--no-warnings")) - val javaOutputVersion: Setting[String] = ChoiceSetting(RootSetting, "java-output-version", "version", "Compile code with classes specific to the given version of the Java platform available on the classpath and emit bytecode for this version. Corresponds to -release flag in javac.", ScalaSettings.supportedReleaseVersions, "", aliases = List("-release", "--release")) + val javaOutputVersion: Setting[String] = ChoiceSetting(RootSetting, "java-output-version", "version", "Compile code with classes specific to the given version of the Java platform available on the classpath and emit bytecode for this version. Corresponds to -release flag in javac.", ScalaSettingsProperties.supportedReleaseVersions, "", aliases = List("-release", "--release")) val deprecation: Setting[Boolean] = BooleanSetting(RootSetting, "deprecation", "Emit warning and location for usages of deprecated APIs.", aliases = List("--deprecation")) val feature: Setting[Boolean] = BooleanSetting(RootSetting, "feature", "Emit warning and location for usages of features that should be imported explicitly.", aliases = List("--feature")) @@ -181,13 +187,13 @@ private sealed trait VerboseSettings: private sealed trait WarningSettings: self: SettingGroup => - val Whelp: Setting[Boolean] = BooleanSetting(WarningSetting, "-W", "Print a synopsis of warning options.") - val XfatalWarnings: Setting[Boolean] = BooleanSetting(WarningSetting, "-Werror", "Fail the compilation if there are any warnings.", aliases = List("-Xfatal-warnings")) - val WvalueDiscard: Setting[Boolean] = BooleanSetting(WarningSetting, "-Wvalue-discard", "Warn when non-Unit expression results are unused.") - val WNonUnitStatement = BooleanSetting(WarningSetting, "-Wnonunit-statement", "Warn when block statements are non-Unit expressions.") - val WenumCommentDiscard = BooleanSetting(WarningSetting, "-Wenum-comment-discard", "Warn when a comment ambiguously assigned to multiple enum cases is discarded.") - val WimplausiblePatterns = BooleanSetting(WarningSetting, "-Wimplausible-patterns", "Warn if comparison with a pattern value looks like it might always fail.") - val WunstableInlineAccessors = BooleanSetting(WarningSetting, "-WunstableInlineAccessors", "Warn an inline methods has references to non-stable binary APIs.") + val Whelp: Setting[Boolean] = BooleanSetting(WarningSetting, "W", "Print a synopsis of warning options.") + val XfatalWarnings: Setting[Boolean] = BooleanSetting(WarningSetting, "Werror", "Fail the compilation if there are any warnings.", aliases = List("-Xfatal-warnings")) + val WvalueDiscard: Setting[Boolean] = BooleanSetting(WarningSetting, "Wvalue-discard", "Warn when non-Unit expression results are unused.") + val WNonUnitStatement = BooleanSetting(WarningSetting, "Wnonunit-statement", "Warn when block statements are non-Unit expressions.") + val WenumCommentDiscard = BooleanSetting(WarningSetting, "Wenum-comment-discard", "Warn when a comment ambiguously assigned to multiple enum cases is discarded.") + val WimplausiblePatterns = BooleanSetting(WarningSetting, "Wimplausible-patterns", "Warn if comparison with a pattern value looks like it might always fail.") + val WunstableInlineAccessors = BooleanSetting(WarningSetting, "WunstableInlineAccessors", "Warn an inline methods has references to non-stable binary APIs.") val Wunused: Setting[List[ChoiceWithHelp[String]]] = MultiChoiceHelpSetting( WarningSetting, name = "Wunused", @@ -338,7 +344,7 @@ private sealed trait XSettings: val XignoreScala2Macros: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xignore-scala2-macros", "Ignore errors when compiling code that calls Scala2 macros, these will fail at runtime.") val XimportSuggestionTimeout: Setting[Int] = IntSetting(AdvancedSetting, "Ximport-suggestion-timeout", "Timeout (in ms) for searching for import suggestions when errors are reported.", 8000) val Xsemanticdb: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xsemanticdb", "Store information in SemanticDB.", aliases = List("-Ysemanticdb")) - val XuncheckedJavaOutputVersion: Setting[String] = ChoiceSetting(AdvancedSetting, "Xunchecked-java-output-version", "target", "Emit bytecode for the specified version of the Java platform. This might produce bytecode that will break at runtime. Corresponds to -target flag in javac. When on JDK 9+, consider -java-output-version as a safer alternative.", ScalaSettings.supportedTargetVersions, "", aliases = List("-Xtarget", "--Xtarget")) + val XuncheckedJavaOutputVersion: Setting[String] = ChoiceSetting(AdvancedSetting, "Xunchecked-java-output-version", "target", "Emit bytecode for the specified version of the Java platform. This might produce bytecode that will break at runtime. Corresponds to -target flag in javac. When on JDK 9+, consider -java-output-version as a safer alternative.", ScalaSettingsProperties.supportedTargetVersions, "", aliases = List("-Xtarget", "--Xtarget")) val XcheckMacros: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xcheck-macros", "Check some invariants of macro generated code while expanding macros", aliases = List("--Xcheck-macros")) val XmainClass: Setting[String] = StringSetting(AdvancedSetting, "Xmain-class", "path", "Class for manifest's Main-Class entry (only useful with -d )", "") val XimplicitSearchLimit: Setting[Int] = IntSetting(AdvancedSetting, "Ximplicit-search-limit", "Maximal number of expressions to be generated in an implicit search", 50000) diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index b94824ac3a2b..ae21c6fb8763 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -513,7 +513,7 @@ object Contexts { s"""Context( |${outersIterator.map(ctx => cinfo(using ctx)).mkString("\n\n")})""".stripMargin - def settings: ScalaSettings.type = base.settings + def settings: ScalaSettings = base.settings def definitions: Definitions = base.definitions def platform: Platform = base.platform def pendingUnderlying: util.HashSet[Type] = base.pendingUnderlying @@ -861,7 +861,7 @@ object Contexts { with Phases.PhasesBase with Plugins { - val settings: ScalaSettings.type = ScalaSettings + val settings: ScalaSettings = ScalaSettings /** The initial context */ val initialCtx: Context = FreshContext.initial(this: @unchecked, settings) From 2b3c05aa0e35127e237bad6f7b156f08c447d933 Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Wed, 13 Mar 2024 17:13:44 +0100 Subject: [PATCH 226/277] Applied review suggestions --- .../tools/backend/jvm/BackendUtils.scala | 34 +++---- .../tools/dotc/config/ScalaSettings.scala | 69 ++++---------- .../dotc/config/ScalaSettingsProperties.scala | 41 +++++++++ .../dotty/tools/dotc/config/Settings.scala | 90 ++++++++++--------- .../test/dotty/tools/dotc/SettingsTests.scala | 31 +++---- .../dotc/config/ScalaSettingsTests.scala | 10 +-- 6 files changed, 145 insertions(+), 130 deletions(-) create mode 100644 compiler/src/dotty/tools/dotc/config/ScalaSettingsProperties.scala diff --git a/compiler/src/dotty/tools/backend/jvm/BackendUtils.scala b/compiler/src/dotty/tools/backend/jvm/BackendUtils.scala index c953358d7940..865ee9bf4af9 100644 --- a/compiler/src/dotty/tools/backend/jvm/BackendUtils.scala +++ b/compiler/src/dotty/tools/backend/jvm/BackendUtils.scala @@ -20,7 +20,7 @@ class BackendUtils(val postProcessor: PostProcessor) { import bTypes.* import coreBTypes.jliLambdaMetaFactoryAltMetafactoryHandle - lazy val classfileVersion: Int = BackendUtils.classfileVersionMap(compilerSettings.target) + lazy val classfileVersion: Int = BackendUtils.classfileVersionMap(compilerSettings.target.toInt) lazy val extraProc: Int = { import GenBCodeOps.addFlagIf @@ -169,21 +169,21 @@ class BackendUtils(val postProcessor: PostProcessor) { } object BackendUtils { - lazy val classfileVersionMap = Map( - "8" -> asm.Opcodes.V1_8, - "9" -> asm.Opcodes.V9, - "10" -> asm.Opcodes.V10, - "11" -> asm.Opcodes.V11, - "12" -> asm.Opcodes.V12, - "13" -> asm.Opcodes.V13, - "14" -> asm.Opcodes.V14, - "15" -> asm.Opcodes.V15, - "16" -> asm.Opcodes.V16, - "17" -> asm.Opcodes.V17, - "18" -> asm.Opcodes.V18, - "19" -> asm.Opcodes.V19, - "20" -> asm.Opcodes.V20, - "21" -> asm.Opcodes.V21, - "22" -> asm.Opcodes.V22, + lazy val classfileVersionMap: Map[Int, Int] = Map( + 8 -> asm.Opcodes.V1_8, + 9 -> asm.Opcodes.V9, + 10 -> asm.Opcodes.V10, + 11 -> asm.Opcodes.V11, + 12 -> asm.Opcodes.V12, + 13 -> asm.Opcodes.V13, + 14 -> asm.Opcodes.V14, + 15 -> asm.Opcodes.V15, + 16 -> asm.Opcodes.V16, + 17 -> asm.Opcodes.V17, + 18 -> asm.Opcodes.V18, + 19 -> asm.Opcodes.V19, + 20 -> asm.Opcodes.V20, + 21 -> asm.Opcodes.V21, + 22 -> asm.Opcodes.V22, ) } diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index c27ba0863ebe..12fe7df8d4d1 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -2,9 +2,8 @@ package dotty.tools.dotc package config import scala.language.unsafeNulls -import dotty.tools.backend.jvm.BackendUtils.classfileVersionMap import dotty.tools.dotc.config.PathResolver.Defaults -import dotty.tools.dotc.config.Settings.{Setting, SettingGroup} +import dotty.tools.dotc.config.Settings.{Setting, SettingGroup, SettingCategory} import dotty.tools.dotc.config.SourceVersion import dotty.tools.dotc.core.Contexts.* import dotty.tools.dotc.rewrites.Rewrites @@ -16,62 +15,32 @@ import scala.util.chaining.* import java.util.zip.Deflater -object ScalaSettingCategories: - val RootSetting = "" - val WarningSetting = "W" - val ForkSetting = "Y" - val AdvancedSetting = "X" - val VerboseSetting = "V" - -object ScalaSettingsProperties: - - private lazy val minTargetVersion = classfileVersionMap.keysIterator.map(_.toInt).min - private lazy val maxTargetVersion = classfileVersionMap.keysIterator.map(_.toInt).max - - def supportedTargetVersions: List[String] = - (minTargetVersion to maxTargetVersion).toList.map(_.toString) - - def supportedReleaseVersions: List[String] = - if scala.util.Properties.isJavaAtLeast("9") then - val jdkVersion = JDK9Reflectors.runtimeVersionMajor(JDK9Reflectors.runtimeVersion()).intValue() - val maxVersion = Math.min(jdkVersion, maxTargetVersion) - (minTargetVersion to maxVersion).toList.map(_.toString) - else List(minTargetVersion).map(_.toString) - - def supportedScalaReleaseVersions: List[String] = - ScalaRelease.values.toList.map(_.show) - - def supportedSourceVersions: List[String] = - SourceVersion.values.toList.map(_.toString) - - def defaultClasspath: String = sys.env.getOrElse("CLASSPATH", ".") - - def defaultPageWidth: Int = { - val defaultWidth = 80 - val columnsVar = System.getenv("COLUMNS") - if columnsVar != null then columnsVar.toInt - else if Properties.isWin then - val ansiconVar = System.getenv("ANSICON") // eg. "142x32766 (142x26)" - if ansiconVar != null && ansiconVar.matches("[0-9]+x.*") then - ansiconVar.substring(0, ansiconVar.indexOf("x")).toInt - else defaultWidth - else defaultWidth - } +enum ScalaSettingCategories(val prefixLetter: String) extends SettingCategory: + // Root settings, a category for setting that are used to configure the core compilation process + case RootSetting extends ScalaSettingCategories("") + // Warning settings, a category for settings that are used to enable and configure warnings + case WarningSetting extends ScalaSettingCategories("W") + // Fork / private settings, a category for settings that enable private or advanced features, mainly used for debugging the compiler + case ForkSetting extends ScalaSettingCategories("Y") + // Advanced settings, a category for settings that enable advanced, often unstable, features + case AdvancedSetting extends ScalaSettingCategories("X") + // Verbose settings, a category to configure the verbosity of the compiler + case VerboseSetting extends ScalaSettingCategories("V") object ScalaSettings extends ScalaSettings // Kept as seperate type to avoid breaking backward compatibility abstract class ScalaSettings extends SettingGroup, AllScalaSettings: - val settingsByCategory: Map[String, List[Setting[_]]] = + val settingsByCategory: Map[SettingCategory, List[Setting[_]]] = allSettings.groupBy(_.category) .view.mapValues(_.toList).toMap .withDefaultValue(Nil) - def categories: List[String] = settingsByCategory.keys.toList - val rootSettings: List[Setting[_]] = settingsByCategory(RootSetting) - val warningSettings: List[Setting[_]] = settingsByCategory(WarningSetting) - val forkSettings: List[Setting[_]] = settingsByCategory(ForkSetting) - val advancedSettings: List[Setting[_]] = settingsByCategory(AdvancedSetting) - val verboseSettings: List[Setting[_]] = settingsByCategory(VerboseSetting) + def categories: List[SettingCategory] = settingsByCategory.keys.toList.sortBy(_.prefixLetter) + val rootSettings: List[Setting[_]] = settingsByCategory(RootSetting).sortBy(_.name) + val warningSettings: List[Setting[_]] = settingsByCategory(WarningSetting).sortBy(_.name) + val forkSettings: List[Setting[_]] = settingsByCategory(ForkSetting).sortBy(_.name) + val advancedSettings: List[Setting[_]] = settingsByCategory(AdvancedSetting).sortBy(_.name) + val verboseSettings: List[Setting[_]] = settingsByCategory(VerboseSetting).sortBy(_.name) val settingsByAliases: Map[String, Setting[_]] = allSettings.flatMap(s => s.aliases.map(_ -> s)).toMap diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettingsProperties.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettingsProperties.scala new file mode 100644 index 000000000000..e8a55dc6e737 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettingsProperties.scala @@ -0,0 +1,41 @@ +package dotty.tools.dotc +package config + +import dotty.tools.backend.jvm.BackendUtils.classfileVersionMap +import dotty.tools.io.{AbstractFile, Directory, JDK9Reflectors, PlainDirectory, NoAbstractFile} +import scala.language.unsafeNulls + +object ScalaSettingsProperties: + + private lazy val minTargetVersion = classfileVersionMap.keysIterator.min + private lazy val maxTargetVersion = classfileVersionMap.keysIterator.max + + def supportedTargetVersions: List[String] = + (minTargetVersion to maxTargetVersion).toList.map(_.toString) + + def supportedReleaseVersions: List[String] = + if scala.util.Properties.isJavaAtLeast("9") then + val jdkVersion = JDK9Reflectors.runtimeVersionMajor(JDK9Reflectors.runtimeVersion()).intValue() + val maxVersion = Math.min(jdkVersion, maxTargetVersion) + (minTargetVersion to maxVersion).toList.map(_.toString) + else List(minTargetVersion).map(_.toString) + + def supportedScalaReleaseVersions: List[String] = + ScalaRelease.values.toList.map(_.show) + + def supportedSourceVersions: List[String] = + SourceVersion.values.toList.map(_.toString) + + def defaultClasspath: String = sys.env.getOrElse("CLASSPATH", ".") + + def defaultPageWidth: Int = { + val defaultWidth = 80 + val columnsVar = System.getenv("COLUMNS") + if columnsVar != null then columnsVar.toInt + else if Properties.isWin then + val ansiconVar = System.getenv("ANSICON") // eg. "142x32766 (142x26)" + if ansiconVar != null && ansiconVar.matches("[0-9]+x.*") then + ansiconVar.substring(0, ansiconVar.indexOf("x")).toInt + else defaultWidth + else defaultWidth + } diff --git a/compiler/src/dotty/tools/dotc/config/Settings.scala b/compiler/src/dotty/tools/dotc/config/Settings.scala index 2fa484ba2882..649fd600bdc2 100644 --- a/compiler/src/dotty/tools/dotc/config/Settings.scala +++ b/compiler/src/dotty/tools/dotc/config/Settings.scala @@ -25,6 +25,9 @@ object Settings: val OptionTag: ClassTag[Option[?]] = ClassTag(classOf[Option[?]]) val OutputTag: ClassTag[AbstractFile] = ClassTag(classOf[AbstractFile]) + trait SettingCategory: + def prefixLetter: String + class SettingsState(initialValues: Seq[Any], initialChanged: Set[Int] = Set.empty): private val values = ArrayBuffer(initialValues*) private val changed: mutable.Set[Int] = initialChanged.to(mutable.Set) @@ -59,8 +62,14 @@ object Settings: ArgsSummary(sstate, arguments.tail, errors, warnings :+ msg) } + @unshared + val settingCharacters = "[a-zA-Z0-9_\\-]*".r + def validateSettingString(name: String): Unit = + assert(settingCharacters.matches(name), s"Setting string $name contains invalid characters") + + case class Setting[T: ClassTag] private[Settings] ( - category: String, + category: SettingCategory, name: String, description: String, default: T, @@ -75,8 +84,9 @@ object Settings: // kept only for -Ykind-projector option compatibility legacyArgs: Boolean = false)(private[Settings] val idx: Int) { - - assert(name.startsWith(s"-$category"), s"Setting $name does not start with category -$category") + validateSettingString(prefix.getOrElse(name)) + aliases.foreach(validateSettingString) + assert(name.startsWith(s"-${category.prefixLetter}"), s"Setting $name does not start with category -$category") assert(legacyArgs || !choices.exists(_.contains("")), s"Empty string is not supported as a choice for setting $name") // Without the following assertion, it would be easy to mistakenly try to pass a file to a setting that ignores invalid args. // Example: -opt Main.scala would be interpreted as -opt:Main.scala, and the source file would be ignored. @@ -319,64 +329,58 @@ object Settings: setting } - @unshared - val settingCharacters = "[a-zA-Z0-9_\\-]*".r - def validateSetting(setting: String): String = - assert(settingCharacters.matches(setting), s"Setting $setting contains invalid characters") - setting - - def validateAndPrependName(name: String): String = + def prependName(name: String): String = assert(!name.startsWith("-"), s"Setting $name cannot start with -") - "-" + validateSetting(name) + "-" + name - def BooleanSetting(category: String, name: String, descr: String, initialValue: Boolean = false, aliases: List[String] = Nil): Setting[Boolean] = - publish(Setting(category, validateAndPrependName(name), descr, initialValue, aliases = aliases.map(validateSetting))) + def BooleanSetting(category: SettingCategory, name: String, descr: String, initialValue: Boolean = false, aliases: List[String] = Nil): Setting[Boolean] = + publish(Setting(category, prependName(name), descr, initialValue, aliases = aliases)) - def StringSetting(category: String, name: String, helpArg: String, descr: String, default: String, aliases: List[String] = Nil): Setting[String] = - publish(Setting(category, validateAndPrependName(name), descr, default, helpArg, aliases = aliases.map(validateSetting))) + def StringSetting(category: SettingCategory, name: String, helpArg: String, descr: String, default: String, aliases: List[String] = Nil): Setting[String] = + publish(Setting(category, prependName(name), descr, default, helpArg, aliases = aliases)) - def ChoiceSetting(category: String, name: String, helpArg: String, descr: String, choices: List[String], default: String, aliases: List[String] = Nil): Setting[String] = - publish(Setting(category, validateAndPrependName(name), descr, default, helpArg, Some(choices), aliases = aliases.map(validateSetting))) + def ChoiceSetting(category: SettingCategory, name: String, helpArg: String, descr: String, choices: List[String], default: String, aliases: List[String] = Nil): Setting[String] = + publish(Setting(category, prependName(name), descr, default, helpArg, Some(choices), aliases = aliases)) // Allows only args after :, but supports empty string as a choice. Used for -Ykind-projector - def LegacyChoiceSetting(category: String, name: String, helpArg: String, descr: String, choices: List[String], default: String, aliases: List[String] = Nil): Setting[String] = - publish(Setting(category, validateAndPrependName(name), descr, default, helpArg, Some(choices), aliases = aliases.map(validateSetting), legacyArgs = true)) + def LegacyChoiceSetting(category: SettingCategory, name: String, helpArg: String, descr: String, choices: List[String], default: String, aliases: List[String] = Nil): Setting[String] = + publish(Setting(category, prependName(name), descr, default, helpArg, Some(choices), aliases = aliases, legacyArgs = true)) - def MultiChoiceSetting(category: String, name: String, helpArg: String, descr: String, choices: List[String], default: List[String], aliases: List[String] = Nil): Setting[List[String]] = - publish(Setting(category, validateAndPrependName(name), descr, default, helpArg, Some(choices), aliases = aliases.map(validateSetting))) + def MultiChoiceSetting(category: SettingCategory, name: String, helpArg: String, descr: String, choices: List[String], default: List[String], aliases: List[String] = Nil): Setting[List[String]] = + publish(Setting(category, prependName(name), descr, default, helpArg, Some(choices), aliases = aliases)) - def MultiChoiceHelpSetting(category: String, name: String, helpArg: String, descr: String, choices: List[ChoiceWithHelp[String]], default: List[ChoiceWithHelp[String]], aliases: List[String] = Nil): Setting[List[ChoiceWithHelp[String]]] = - publish(Setting(category, validateAndPrependName(name), descr, default, helpArg, Some(choices), aliases = aliases.map(validateSetting))) + def MultiChoiceHelpSetting(category: SettingCategory, name: String, helpArg: String, descr: String, choices: List[ChoiceWithHelp[String]], default: List[ChoiceWithHelp[String]], aliases: List[String] = Nil): Setting[List[ChoiceWithHelp[String]]] = + publish(Setting(category, prependName(name), descr, default, helpArg, Some(choices), aliases = aliases)) - def IntSetting(category: String, name: String, descr: String, default: Int, aliases: List[String] = Nil): Setting[Int] = - publish(Setting(category, validateAndPrependName(name), descr, default, aliases = aliases.map(validateSetting))) + def IntSetting(category: SettingCategory, name: String, descr: String, default: Int, aliases: List[String] = Nil): Setting[Int] = + publish(Setting(category, prependName(name), descr, default, aliases = aliases)) - def IntChoiceSetting(category: String, name: String, descr: String, choices: Seq[Int], default: Int): Setting[Int] = - publish(Setting(category, validateAndPrependName(name), descr, default, choices = Some(choices))) + def IntChoiceSetting(category: SettingCategory, name: String, descr: String, choices: Seq[Int], default: Int): Setting[Int] = + publish(Setting(category, prependName(name), descr, default, choices = Some(choices))) - def MultiStringSetting(category: String, name: String, helpArg: String, descr: String, default: List[String] = Nil, aliases: List[String] = Nil): Setting[List[String]] = - publish(Setting(category, validateAndPrependName(name), descr, default, helpArg, aliases = aliases.map(validateSetting))) + def MultiStringSetting(category: SettingCategory, name: String, helpArg: String, descr: String, default: List[String] = Nil, aliases: List[String] = Nil): Setting[List[String]] = + publish(Setting(category, prependName(name), descr, default, helpArg, aliases = aliases)) - def OutputSetting(category: String, name: String, helpArg: String, descr: String, default: AbstractFile): Setting[AbstractFile] = - publish(Setting(category, validateAndPrependName(name), descr, default, helpArg)) + def OutputSetting(category: SettingCategory, name: String, helpArg: String, descr: String, default: AbstractFile): Setting[AbstractFile] = + publish(Setting(category, prependName(name), descr, default, helpArg)) - def PathSetting(category: String, name: String, descr: String, default: String, aliases: List[String] = Nil): Setting[String] = - publish(Setting(category, validateAndPrependName(name), descr, default, aliases = aliases.map(validateSetting))) + def PathSetting(category: SettingCategory, name: String, descr: String, default: String, aliases: List[String] = Nil): Setting[String] = + publish(Setting(category, prependName(name), descr, default, aliases = aliases)) - def PhasesSetting(category: String, name: String, descr: String, default: String = "", aliases: List[String] = Nil): Setting[List[String]] = - publish(Setting(category, validateAndPrependName(name), descr, if (default.isEmpty) Nil else List(default), aliases = aliases.map(validateSetting))) + def PhasesSetting(category: SettingCategory, name: String, descr: String, default: String = "", aliases: List[String] = Nil): Setting[List[String]] = + publish(Setting(category, prependName(name), descr, if (default.isEmpty) Nil else List(default), aliases = aliases)) - def PrefixSetting(category: String, name: String, descr: String): Setting[List[String]] = + def PrefixSetting(category: SettingCategory, name: String, descr: String): Setting[List[String]] = val prefix = name.takeWhile(_ != '<') - publish(Setting(category, "-" + name, descr, Nil, prefix = Some(validateSetting(prefix)))) + publish(Setting(category, "-" + name, descr, Nil, prefix = Some(prefix))) - def VersionSetting(category: String, name: String, descr: String, default: ScalaVersion = NoScalaVersion): Setting[ScalaVersion] = - publish(Setting(category, validateAndPrependName(name), descr, default)) + def VersionSetting(category: SettingCategory, name: String, descr: String, default: ScalaVersion = NoScalaVersion): Setting[ScalaVersion] = + publish(Setting(category, prependName(name), descr, default)) - def OptionSetting[T: ClassTag](category: String, name: String, descr: String, aliases: List[String] = Nil): Setting[Option[T]] = - publish(Setting(category, validateAndPrependName(name), descr, None, propertyClass = Some(summon[ClassTag[T]].runtimeClass), aliases = aliases.map(validateSetting))) + def OptionSetting[T: ClassTag](category: SettingCategory, name: String, descr: String, aliases: List[String] = Nil): Setting[Option[T]] = + publish(Setting(category, prependName(name), descr, None, propertyClass = Some(summon[ClassTag[T]].runtimeClass), aliases = aliases)) - def DeprecatedSetting(category: String, name: String, descr: String, deprecationMsg: String): Setting[Boolean] = - publish(Setting(category, validateAndPrependName(name), descr, false, deprecationMsg = Some(deprecationMsg))) + def DeprecatedSetting(category: SettingCategory, name: String, descr: String, deprecationMsg: String): Setting[Boolean] = + publish(Setting(category, prependName(name), descr, false, deprecationMsg = Some(deprecationMsg))) } end Settings diff --git a/compiler/test/dotty/tools/dotc/SettingsTests.scala b/compiler/test/dotty/tools/dotc/SettingsTests.scala index 595c4875bb12..8125a80f29f8 100644 --- a/compiler/test/dotty/tools/dotc/SettingsTests.scala +++ b/compiler/test/dotty/tools/dotc/SettingsTests.scala @@ -8,6 +8,7 @@ import vulpix.TestConfiguration import core.Contexts.{Context, ContextBase} import dotty.tools.dotc.config.Settings._ +import dotty.tools.dotc.config.ScalaSettingCategories._ import dotty.tools.vulpix.TestConfiguration.mkClasspath import java.nio.file._ @@ -43,8 +44,8 @@ class SettingsTests { @Test def acceptUnconstrained: Unit = object Settings extends SettingGroup: - val foo = StringSetting("", "foo", "foo", "Foo", "a") - val bar = IntSetting("", "bar", "Bar", 0) + val foo = StringSetting(RootSetting, "foo", "foo", "Foo", "a") + val bar = IntSetting(RootSetting, "bar", "Bar", 0) val args = List("-foo", "b", "-bar", "1") val summary = Settings.processArguments(args, true) @@ -72,7 +73,7 @@ class SettingsTests { @Test def `dont crash on many options`: Unit = object Settings extends SettingGroup: - val option = BooleanSetting("", "option", "Some option") + val option = BooleanSetting(RootSetting, "option", "Some option") val limit = 6000 val args = List.fill(limit)("-option") @@ -87,7 +88,7 @@ class SettingsTests { @Test def `bad option warning consumes an arg`: Unit = object Settings extends SettingGroup: - val option = BooleanSetting("", "option", "Some option") + val option = BooleanSetting(RootSetting, "option", "Some option") val args = List("-adoption", "dogs", "cats") val summary = Settings.processArguments(args, processAll = true) @@ -97,7 +98,7 @@ class SettingsTests { @Test def `bad option settings throws`: Unit = object Settings extends SettingGroup: - val option = BooleanSetting("", "option", "Some option") + val option = BooleanSetting(RootSetting, "option", "Some option") def checkMessage(s: String): (Throwable => Boolean) = t => if t.getMessage == s then true @@ -112,12 +113,12 @@ class SettingsTests { @Test def validateChoices: Unit = object Settings extends SettingGroup: - val foo = ChoiceSetting("", "foo", "foo", "Foo", List("a", "b"), "a") - val bar = IntChoiceSetting("", "bar", "Bar", List(0, 1, 2), 0) - val baz = IntChoiceSetting("", "baz", "Baz", 0 to 10, 10) + val foo = ChoiceSetting(RootSetting, "foo", "foo", "Foo", List("a", "b"), "a") + val bar = IntChoiceSetting(RootSetting, "bar", "Bar", List(0, 1, 2), 0) + val baz = IntChoiceSetting(RootSetting, "baz", "Baz", 0 to 10, 10) - val quux = ChoiceSetting("", "quux", "quux", "Quux", List(), "") - val quuz = IntChoiceSetting("", "quuz", "Quuz", List(), 0) + val quux = ChoiceSetting(RootSetting, "quux", "quux", "Quux", List(), "") + val quuz = IntChoiceSetting(RootSetting, "quuz", "Quuz", List(), 0) locally { val args = List("-foo", "b", "-bar", "1", "-baz", "5") @@ -169,7 +170,7 @@ class SettingsTests { @Test def `Allow IntSetting's to be set with a colon`: Unit = object Settings extends SettingGroup: - val foo = IntSetting("", "foo", "foo", 80) + val foo = IntSetting(RootSetting, "foo", "foo", 80) import Settings._ val args = List("-foo:100") @@ -181,10 +182,10 @@ class SettingsTests { @Test def `Set BooleanSettings correctly`: Unit = object Settings extends SettingGroup: - val foo = BooleanSetting("", "foo", "foo", false) - val bar = BooleanSetting("", "bar", "bar", true) - val baz = BooleanSetting("", "baz", "baz", false) - val qux = BooleanSetting("", "qux", "qux", false) + val foo = BooleanSetting(RootSetting, "foo", "foo", false) + val bar = BooleanSetting(RootSetting, "bar", "bar", true) + val baz = BooleanSetting(RootSetting, "baz", "baz", false) + val qux = BooleanSetting(RootSetting, "qux", "qux", false) import Settings._ val args = List("-foo:true", "-bar:false", "-baz", "-qux:true", "-qux:false") diff --git a/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala b/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala index 77691e1008e0..e958a5925fce 100644 --- a/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala +++ b/compiler/test/dotty/tools/dotc/config/ScalaSettingsTests.scala @@ -3,7 +3,7 @@ package config import CommandLineParser.tokenize import Settings._ - +import dotty.tools.dotc.config.ScalaSettingCategories._ import org.junit.Test import org.junit.Assert._ import core.Decorators.toMessage @@ -12,7 +12,7 @@ class ScalaSettingsTests: @Test def `A setting with aliases is accepted`: Unit = class MySettings extends SettingGroup: - val classpath: Setting[String] = PathSetting("", "classpath", "Specify where to find user class files.", ".", aliases = List("--class-path", "-cp")) + val classpath: Setting[String] = PathSetting(RootSetting, "classpath", "Specify where to find user class files.", ".", aliases = List("--class-path", "-cp")) val settings = MySettings() val args = tokenize("-cp path/to/classes1:other/path/to/classes2") val summary = ArgsSummary(settings.defaultState, args, errors = Nil, warnings = Nil) @@ -25,7 +25,7 @@ class ScalaSettingsTests: @Test def `A multistring setting is multivalued`: Unit = class SUT extends SettingGroup: - val language: Setting[List[String]] = MultiStringSetting("", "language", "feature", "Enable one or more language features.") + val language: Setting[List[String]] = MultiStringSetting(RootSetting, "language", "feature", "Enable one or more language features.") val sut = SUT() val args = tokenize("-language:implicitConversions,dynamics") val sumy = ArgsSummary(sut.defaultState, args, errors = Nil, warnings = Nil) @@ -39,7 +39,7 @@ class ScalaSettingsTests: @Test def `t9719 Apply -language more than once`: Unit = class SUT extends SettingGroup: - val language: Setting[List[String]] = MultiStringSetting("", "language", "feature", "Enable one or more language features.") + val language: Setting[List[String]] = MultiStringSetting(RootSetting, "language", "feature", "Enable one or more language features.") val sut = SUT() val args = tokenize("-language:implicitConversions -language:dynamics") val sumy = ArgsSummary(sut.defaultState, args, errors = Nil, warnings = Nil) @@ -53,7 +53,7 @@ class ScalaSettingsTests: @Test def `Warn if multistring element is supplied multiply`: Unit = class SUT extends SettingGroup: - val language: Setting[List[String]] = MultiStringSetting("", "language", "feature", "Enable one or more language features.") + val language: Setting[List[String]] = MultiStringSetting(RootSetting, "language", "feature", "Enable one or more language features.") val sut = SUT() val args = tokenize("-language:dynamics -language:implicitConversions -language:dynamics") val sumy = ArgsSummary(sut.defaultState, args, errors = Nil, warnings = Nil) From b5cff5717bd6830f3cef6112308c705ff762b5b4 Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 13 Mar 2024 19:05:25 +0100 Subject: [PATCH 227/277] Put all code in import suggestions under a try-catch There was a val that escaped before, which caused cyclic references raised during importSuggestions to be reported instead of being ignored. --- .../tools/dotc/typer/ImportSuggestions.scala | 2 +- tests/neg/i11994.check | 18 +++++++----------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala b/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala index 7615fbda9f0a..33643a0fae2f 100644 --- a/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala +++ b/compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala @@ -158,7 +158,7 @@ trait ImportSuggestions: // Candidates that are already available without explicit import because they // are already provided by the context (imported or inherited) or because they // are in the implicit scope of `pt`. - val alreadyAvailableCandidates: Set[Symbol] = { + lazy val alreadyAvailableCandidates: Set[Symbol] = { val wildProto = wildApprox(pt) val contextualCandidates = ctx.implicits.eligible(wildProto) val implicitScopeCandidates = ctx.run.nn.implicitScope(wildProto).eligible diff --git a/tests/neg/i11994.check b/tests/neg/i11994.check index 8895515898c2..fcb49fe3411d 100644 --- a/tests/neg/i11994.check +++ b/tests/neg/i11994.check @@ -1,12 +1,8 @@ --- [E046] Cyclic Error: tests/neg/i11994.scala:3:18 -------------------------------------------------------------------- +-- [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 +-- [E008] Not Found Error: tests/neg/i11994.scala:3:18 ----------------------------------------------------------------- 3 |given [T <: Tuple.meow]: Unit = ??? // error - | ^ - | Cyclic reference involving method given_Unit - | - | The error occurred while trying to compute the signature of given instance given_Unit - | which required to compute the signature of type T - | which required to compute the signature of given instance given_Unit - | - | Run with both -explain-cyclic and -Ydebug-cyclic to see full stack trace. - | - | longer explanation available when compiling with `-explain` + | ^^^^^^^^^^ + | type meow is not a member of object Tuple From e91006ae7b895df82d02fa0cc587682880d512c4 Mon Sep 17 00:00:00 2001 From: Dan13llljws Date: Wed, 13 Mar 2024 21:18:50 -0400 Subject: [PATCH 228/277] added Vector.emptyIterator to white list --- compiler/src/dotty/tools/dotc/transform/init/Objects.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala index 4b56a7c81ca4..061f7f902bbf 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala @@ -1683,10 +1683,12 @@ class Objects: end if // class body + val whiteList = Set("scala.collection.immutable.Vector.emptyIterator") tpl.body.foreach { case vdef : ValDef if !vdef.symbol.is(Flags.Lazy) && !vdef.rhs.isEmpty => - val res = eval(vdef.rhs, thisV, klass) + var res = eval(vdef.rhs, thisV, klass) val sym = vdef.symbol + if (whiteList.contains(sym.showFullName)) res = Bottom if sym.is(Flags.Mutable) then val addr = Heap.fieldVarAddr(summon[Regions.Data], sym, State.currentObject) thisV.initVar(sym, addr) From 676b25048499e26be98a7878a1c1f69cc3da32c7 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 14 Mar 2024 09:02:56 +0100 Subject: [PATCH 229/277] Detect non `Exp[..]` splice patterns We compute the pattern using `Expr[pt]` of the prototype `pt` of the splice, but this is not enough to reject non-matching patterns. The quoted splices are encoded away before we get to the pattern matching phase where we could potentially detect that they will not match. Instead we check that all quote patterns are `Expr[..]` when typing the pattern. Fixes #19941 --- compiler/src/dotty/tools/dotc/quoted/QuotePatterns.scala | 4 +++- tests/neg-macros/i19941.check | 4 ++++ tests/neg-macros/i19941.scala | 7 +++++++ tests/{pos-macros => neg-macros}/quotedPatterns-4.scala | 2 +- 4 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 tests/neg-macros/i19941.check create mode 100644 tests/neg-macros/i19941.scala rename tests/{pos-macros => neg-macros}/quotedPatterns-4.scala (64%) diff --git a/compiler/src/dotty/tools/dotc/quoted/QuotePatterns.scala b/compiler/src/dotty/tools/dotc/quoted/QuotePatterns.scala index 76961f691617..3eba9e3e12b2 100644 --- a/compiler/src/dotty/tools/dotc/quoted/QuotePatterns.scala +++ b/compiler/src/dotty/tools/dotc/quoted/QuotePatterns.scala @@ -28,7 +28,9 @@ object QuotePatterns: /** Check for restricted patterns */ def checkPattern(quotePattern: QuotePattern)(using Context): Unit = new tpd.TreeTraverser { def traverse(tree: Tree)(using Context): Unit = tree match { - case _: SplicePattern => + case tree: SplicePattern => + if !tree.body.typeOpt.derivesFrom(defn.QuotedExprClass) then + report.error(i"Spice pattern must match an Expr[...]", tree.body.srcPos) case tdef: TypeDef if tdef.symbol.isClass => val kind = if tdef.symbol.is(Module) then "objects" else "classes" report.error(em"Implementation restriction: cannot match $kind", tree.srcPos) diff --git a/tests/neg-macros/i19941.check b/tests/neg-macros/i19941.check new file mode 100644 index 000000000000..3f0da80f08fe --- /dev/null +++ b/tests/neg-macros/i19941.check @@ -0,0 +1,4 @@ +-- Error: tests/neg-macros/i19941.scala:7:14 --------------------------------------------------------------------------- +7 | case '{ ${hd *: tl} : *:[Int, EmptyTuple] } => '{ ??? } // error + | ^^^^^^^^ + | Spice pattern must match an Expr[...] diff --git a/tests/neg-macros/i19941.scala b/tests/neg-macros/i19941.scala new file mode 100644 index 000000000000..58a2275d055b --- /dev/null +++ b/tests/neg-macros/i19941.scala @@ -0,0 +1,7 @@ +import scala.quoted.* + +inline def expandMacro(inline from: Tuple): Any = ${ expandMacroImpl } + +def expandMacroImpl(using Quotes): Expr[?] = + '{ 1 *: EmptyTuple } match + case '{ ${hd *: tl} : *:[Int, EmptyTuple] } => '{ ??? } // error diff --git a/tests/pos-macros/quotedPatterns-4.scala b/tests/neg-macros/quotedPatterns-4.scala similarity index 64% rename from tests/pos-macros/quotedPatterns-4.scala rename to tests/neg-macros/quotedPatterns-4.scala index 309b026e3d54..811196bc3a3b 100644 --- a/tests/pos-macros/quotedPatterns-4.scala +++ b/tests/neg-macros/quotedPatterns-4.scala @@ -3,7 +3,7 @@ object Test { def impl(receiver: Expr[StringContext])(using qctx: scala.quoted.Quotes) = { import quotes.reflect.Repeated receiver match { - case '{ StringContext(${Repeated(parts, tpt)}*) } => // now OK + case '{ StringContext(${Repeated(parts, tpt)}*) } => // error: Repeated is not an Expr pattern } } } From 96afd7a4dfd177f8db99d5216d95278759cc37a3 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 14 Mar 2024 17:20:51 +0100 Subject: [PATCH 230/277] Avoid spurious val binding in quote pattern Fixes #19947 --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 6 +++--- tests/pos-macros/i19947/Macro_1.scala | 9 +++++++++ tests/pos-macros/i19947/Test_2.scala | 1 + 3 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 tests/pos-macros/i19947/Macro_1.scala create mode 100644 tests/pos-macros/i19947/Test_2.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 1903b3d6f019..e9b645640801 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -3003,8 +3003,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer /** Translate infix operation expression `l op r` to * * l.op(r) if `op` is left-associative - * { val x = l; r.op(x) } if `op` is right-associative call-by-value and `l` is impure - * r.op(l) if `op` is right-associative call-by-name or `l` is pure + * { val x = l; r.op(x) } if `op` is right-associative call-by-value and `l` is impure, and not in a quote pattern + * r.op(l) if `op` is right-associative call-by-name, or `l` is pure, or in a quote pattern * * Translate infix type `l op r` to `op[l, r]` * Translate infix pattern `l op r` to `op(l, r)` @@ -3021,7 +3021,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer typedUnApply(cpy.Apply(tree)(op, l :: r :: Nil), pt) else { val app = typedApply(desugar.binop(l, op, r), pt) - if op.name.isRightAssocOperatorName then + if op.name.isRightAssocOperatorName && !ctx.mode.is(Mode.QuotedExprPattern) then val defs = new mutable.ListBuffer[Tree] def lift(app: Tree): Tree = (app: @unchecked) match case Apply(fn, args) => diff --git a/tests/pos-macros/i19947/Macro_1.scala b/tests/pos-macros/i19947/Macro_1.scala new file mode 100644 index 000000000000..dc9ae46eb55f --- /dev/null +++ b/tests/pos-macros/i19947/Macro_1.scala @@ -0,0 +1,9 @@ +import scala.quoted.* + +inline def expandMacro(inline from: Tuple): Any = + ${ expandMacroImpl } + +def expandMacroImpl(using Quotes): Expr[?] = + '{ 1 *: EmptyTuple } match + case '{ ($hd: Int) *: ($tl: Tuple) } => '{ ??? } + case x => throw new MatchError(x.show) diff --git a/tests/pos-macros/i19947/Test_2.scala b/tests/pos-macros/i19947/Test_2.scala new file mode 100644 index 000000000000..85c0dc845dc4 --- /dev/null +++ b/tests/pos-macros/i19947/Test_2.scala @@ -0,0 +1 @@ +def test: Any = expandMacro From f8a5583c023ef6d51850a5b713bf17522041bec0 Mon Sep 17 00:00:00 2001 From: Matt Bovel Date: Sat, 16 Mar 2024 01:34:06 +0100 Subject: [PATCH 231/277] Symbol with top-level access boundary is not local to compilation unit Co-Authored-By: Dale Wijnand --- compiler/src/dotty/tools/dotc/core/SymDenotations.scala | 2 +- tests/generic-java-signatures/outer-ref-elimination.check | 3 ++- tests/generic-java-signatures/outer-ref-elimination.scala | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 77849e1f0624..14ba05568735 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1209,7 +1209,7 @@ object SymDenotations { final def isLocalToCompilationUnit(using Context): Boolean = is(Private) || owner.ownersIterator.takeWhile(!_.isStaticOwner).exists(_.isTerm) - || accessBoundary(defn.RootClass).isContainedIn(symbol.topLevelClass) + || accessBoundary(defn.RootClass).isProperlyContainedIn(symbol.topLevelClass) final def isTransparentClass(using Context): Boolean = is(TransparentType) diff --git a/tests/generic-java-signatures/outer-ref-elimination.check b/tests/generic-java-signatures/outer-ref-elimination.check index 7dd664e5d766..60fb5e63b11a 100644 --- a/tests/generic-java-signatures/outer-ref-elimination.check +++ b/tests/generic-java-signatures/outer-ref-elimination.check @@ -7,4 +7,5 @@ List(public T6$$anon$3$C6()) List(public T7$C7$1()) List(public T8$$anon$4$C8()) List(public T9$C9$1(T9)) -List(public T10$C10()) +List(public T10$C10(T10)) +List(public T11$D11$C11()) diff --git a/tests/generic-java-signatures/outer-ref-elimination.scala b/tests/generic-java-signatures/outer-ref-elimination.scala index 6e4e8218c535..6a10544cdb08 100644 --- a/tests/generic-java-signatures/outer-ref-elimination.scala +++ b/tests/generic-java-signatures/outer-ref-elimination.scala @@ -28,6 +28,8 @@ class T9 { var x = 451; def t9(): Unit = { class C9 {def getX = x}; test(classOf class T10 { private[T10] class C10; test(classOf[C10]) } +class T11 { class D11 { private[D11] class C11; test(classOf[C11]) } } + object Test { def main(args: Array[String]): Unit = { T1 @@ -40,5 +42,6 @@ object Test { new T8().t8() new T9().t9() new T10() + val t11 = new T11(); new t11.D11() } } From 0f7de67245a8519842f2ef25b985fe967a24d561 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Wed, 13 Mar 2024 16:17:04 +0100 Subject: [PATCH 232/277] Partial revert of previous commit. Instead of avoiding fully qualified names, use a different separator in zincMangledName. --- .../src/dotty/tools/dotc/sbt/package.scala | 20 ++++++++++++------- .../xsbt/ExtractUsedNamesSpecification.scala | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/sbt/package.scala b/compiler/src/dotty/tools/dotc/sbt/package.scala index 7c24319005ed..dc0df381f08f 100644 --- a/compiler/src/dotty/tools/dotc/sbt/package.scala +++ b/compiler/src/dotty/tools/dotc/sbt/package.scala @@ -4,6 +4,7 @@ import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Symbols.Symbol import dotty.tools.dotc.core.NameOps.stripModuleClassSuffix import dotty.tools.dotc.core.Names.Name +import dotty.tools.dotc.core.Names.termName inline val TermNameHash = 1987 // 300th prime inline val TypeNameHash = 1993 // 301st prime @@ -11,10 +12,15 @@ inline val InlineParamHash = 1997 // 302nd prime extension (sym: Symbol) - def constructorName(using Context) = - sym.owner.name ++ ";init;" - - /** Mangle a JVM symbol name in a format better suited for internal uses by sbt. */ - def zincMangledName(using Context): Name = - if (sym.isConstructor) constructorName - else sym.name.stripModuleClassSuffix + /** Mangle a JVM symbol name in a format better suited for internal uses by sbt. + * WARNING: output must not be written to TASTy, as it is not a valid TASTy name. + */ + private[sbt] def zincMangledName(using Context): Name = + if sym.isConstructor then + // TODO: ideally we should avoid unnecessarily caching these Zinc specific + // names in the global chars array. But we would need to restructure + // ExtractDependencies caches to avoid expensive `toString` on + // each member reference. + termName(sym.owner.fullName.mangledString.replace(".", ";").nn ++ ";init;") + else + sym.name.stripModuleClassSuffix diff --git a/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala b/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala index d6cc3ac6339d..e47371175de6 100644 --- a/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala +++ b/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala @@ -306,7 +306,7 @@ class ExtractUsedNamesSpecification { // All classes extend Object "Object", // All classes have a default constructor called - "Object;init;", + "java;lang;Object;init;", // the return type of the default constructor is Unit "Unit" ) From b0ba045090b9abbd742859b62b37b43d765c00a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Fornal?= <24961583+Florian3k@users.noreply.github.com> Date: Sun, 17 Mar 2024 21:15:34 +0100 Subject: [PATCH 233/277] Repl - method signatures in autocomplete (#19917) Closes #17367 This PR brings method signatures to repl completions, as in Scala 2 repl (but with syntax highlighting). After typing `List(1).max`: ![image](https://github.com/scala/scala3/assets/24961583/0846e7b1-ff44-4e95-aaff-398069821b2f) --- .../src/dotty/tools/repl/ReplDriver.scala | 52 ++++++++++++------- compiler/test/dotty/tools/repl/ReplTest.scala | 2 +- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/compiler/src/dotty/tools/repl/ReplDriver.scala b/compiler/src/dotty/tools/repl/ReplDriver.scala index 5226ef0b4546..f8bba2f59fe1 100644 --- a/compiler/src/dotty/tools/repl/ReplDriver.scala +++ b/compiler/src/dotty/tools/repl/ReplDriver.scala @@ -31,6 +31,7 @@ import dotty.tools.dotc.util.{SourceFile, SourcePosition} import dotty.tools.dotc.{CompilationUnit, Driver} import dotty.tools.dotc.config.CompilerCommand import dotty.tools.io.* +import dotty.tools.repl.Rendering.showUser import dotty.tools.runner.ScalaClassLoader.* import org.jline.reader.* @@ -149,11 +150,36 @@ class ReplDriver(settings: Array[String], /** Blockingly read a line, getting back a parse result */ def readLine()(using state: State): ParseResult = { - val completer: Completer = { (_, line, candidates) => + given Context = state.context + val completer: Completer = { (lineReader, line, candidates) => + def makeCandidate(label: String) = { + new Candidate( + /* value = */ label, + /* displ = */ stripBackTicks(label), // displayed value + /* group = */ null, // can be used to group completions together + /* descr = */ null, // TODO use for documentation? + /* suffix = */ null, + /* key = */ null, + /* complete = */ false // if true adds space when completing + ) + } val comps = completions(line.cursor, line.line, state) - candidates.addAll(comps.asJava) + candidates.addAll(comps.map(_.label).distinct.map(makeCandidate).asJava) + val lineWord = line.word() + comps.filter(c => c.label == lineWord && c.symbols.nonEmpty) match + case Nil => + case exachMatches => + val terminal = lineReader.nn.getTerminal + lineReader.callWidget(LineReader.CLEAR) + terminal.writer.println() + exachMatches.foreach: exact => + exact.symbols.foreach: sym => + terminal.writer.println(SyntaxHighlighting.highlight(sym.showUser)) + lineReader.callWidget(LineReader.REDRAW_LINE) + lineReader.callWidget(LineReader.REDISPLAY) + terminal.flush() } - given Context = state.context + try { val line = terminal.readLine(completer) ParseResult(line) @@ -230,23 +256,10 @@ class ReplDriver(settings: Array[String], label /** Extract possible completions at the index of `cursor` in `expr` */ - protected final def completions(cursor: Int, expr: String, state0: State): List[Candidate] = - def makeCandidate(label: String) = { - - new Candidate( - /* value = */ label, - /* displ = */ stripBackTicks(label), // displayed value - /* group = */ null, // can be used to group completions together - /* descr = */ null, // TODO use for documentation? - /* suffix = */ null, - /* key = */ null, - /* complete = */ false // if true adds space when completing - ) - } - + protected final def completions(cursor: Int, expr: String, state0: State): List[Completion] = if expr.startsWith(":") then ParseResult.commands.collect { - case command if command._1.startsWith(expr) => makeCandidate(command._1) + case command if command._1.startsWith(expr) => Completion(command._1, "", List()) } else given state: State = newRun(state0) @@ -259,8 +272,7 @@ class ReplDriver(settings: Array[String], unit.tpdTree = tpdTree given Context = state.context.fresh.setCompilationUnit(unit) val srcPos = SourcePosition(file, Span(cursor)) - val completions = try Completion.completions(srcPos)._2 catch case NonFatal(_) => Nil - completions.map(_.label).distinct.map(makeCandidate) + try Completion.completions(srcPos)._2 catch case NonFatal(_) => Nil } .getOrElse(Nil) end completions diff --git a/compiler/test/dotty/tools/repl/ReplTest.scala b/compiler/test/dotty/tools/repl/ReplTest.scala index bc70f68e45fe..3e827a0f1e36 100644 --- a/compiler/test/dotty/tools/repl/ReplTest.scala +++ b/compiler/test/dotty/tools/repl/ReplTest.scala @@ -42,7 +42,7 @@ extends ReplDriver(options, new PrintStream(out, true, StandardCharsets.UTF_8.na /** Returns the `(, )`*/ def tabComplete(src: String)(implicit state: State): List[String] = - completions(src.length, src, state).map(_.value).sorted + completions(src.length, src, state).map(_.label).sorted.distinct extension [A](state: State) infix def andThen(op: State ?=> A): A = op(using state) From e59335f8d1f6382998d2d74730a33eefce2d7e53 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 18 Mar 2024 08:32:40 +0100 Subject: [PATCH 234/277] Avoid eta-reduction of `(..., f: T => R, ...) => f.apply(..)` into `f` Fixes #19962 --- compiler/src/dotty/tools/dotc/transform/EtaReduce.scala | 1 + tests/pos/i19962.scala | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 tests/pos/i19962.scala diff --git a/compiler/src/dotty/tools/dotc/transform/EtaReduce.scala b/compiler/src/dotty/tools/dotc/transform/EtaReduce.scala index a8565d008f46..2b0c49644b09 100644 --- a/compiler/src/dotty/tools/dotc/transform/EtaReduce.scala +++ b/compiler/src/dotty/tools/dotc/transform/EtaReduce.scala @@ -43,6 +43,7 @@ class EtaReduce extends MiniPhase: arg.isInstanceOf[Ident] && arg.symbol == param.symbol) && isPurePath(fn) && fn.tpe <:< tree.tpe + && !(fn.symbol.is(Flags.Param) && fn.symbol.owner == mdef.symbol) // Do not eta-educe `(..., f: T => R, ...) => f.apply(..)` into `f` && defn.isFunctionClass(fn.tpe.widen.typeSymbol) => report.log(i"eta reducing $tree --> $fn") fn diff --git a/tests/pos/i19962.scala b/tests/pos/i19962.scala new file mode 100644 index 000000000000..66e538a04d5f --- /dev/null +++ b/tests/pos/i19962.scala @@ -0,0 +1,4 @@ +def selfie0: (AnyRef => AnyRef) => AnyRef = (f:AnyRef => AnyRef) => f(f) +def selfie1: Any = (f: Any => Any) => f(f) +def selfie2: Any = (f: (Any, Any) => Any, g: (Any, Any) => Any) => f(f, g) +def selfie3: Any = (f: (Any, Any) => Any, g: (Any, Any) => Any) => g(f, g) From bd9ca7d1c0231b233b07f6f662d2ce45eb4d11e7 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 18 Mar 2024 11:44:19 +0100 Subject: [PATCH 235/277] Make sure that the Scala 2 library CC compiles on the stable branch --- project/Build.scala | 1 + .../src/scala/collection/generic/IsSeq.scala | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index ea56039fa401..19bb9a7c0419 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1066,6 +1066,7 @@ object Build { Compile / doc / scalacOptions += "-Ydocument-synthetic-types", scalacOptions += "-Ycompile-scala2-library", scalacOptions += "-Yscala2Unpickler:never", + scalacOptions += "-Yno-experimental", scalacOptions -= "-Xfatal-warnings", Compile / compile / logLevel := Level.Error, ivyConfigurations += SourceDeps.hide, diff --git a/scala2-library-cc/src/scala/collection/generic/IsSeq.scala b/scala2-library-cc/src/scala/collection/generic/IsSeq.scala index 420a81d94ab4..0be512c4bec1 100644 --- a/scala2-library-cc/src/scala/collection/generic/IsSeq.scala +++ b/scala2-library-cc/src/scala/collection/generic/IsSeq.scala @@ -58,8 +58,8 @@ object IsSeq { * The helper method [[seqViewIsSeq_]] is added to make the binary compatible. */ @annotation.targetName("seqViewIsSeq") - @annotation.publicInBinary - private[IsSeq] def seqViewIsSeq_[CC0[X] <: SeqView[X], A0]: IsSeq[CC0[A0]] { type A = A0; type C = View[A0] } = ??? + // @annotation.publicInBinary private[IsSeq] // FIXME: enable when publicInBinary becomes stable + def seqViewIsSeq_[CC0[X] <: SeqView[X], A0]: IsSeq[CC0[A0]] { type A = A0; type C = View[A0] } = ??? implicit inline def seqViewIsSeq[CC0[X] <: SeqView[X], A0]: IsIterable[CC0[A0]] { type A = A0; type C = View[A0] } = seqViewIsSeq_[CC0, A0].asInstanceOf /** !!! Under cc, views are not Seqs and can't use SeqOps. @@ -67,8 +67,8 @@ object IsSeq { * The helper method [[stringViewIsSeq__]] is added to make the binary compatible. */ @annotation.targetName("stringViewIsSeq") - @annotation.publicInBinary - private[IsSeq] val stringViewIsSeq_ : IsSeq[StringView] { type A = Char; type C = View[Char] } = ??? + // @annotation.publicInBinary private[IsSeq] // FIXME: enable when publicInBinary becomes stable + val stringViewIsSeq_ : IsSeq[StringView] { type A = Char; type C = View[Char] } = ??? inline implicit def stringViewIsSeq: IsIterable[StringView] { type A = Char; type C = View[Char] } = stringViewIsSeq_.asInstanceOf implicit val stringIsSeq: IsSeq[String] { type A = Char; type C = String } = From cf520a05d36145b1617e099167c5129cc22a527f Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sat, 16 Mar 2024 16:40:23 +0000 Subject: [PATCH 236/277] Fix eta-expanding guards in adaptType --- .../src/dotty/tools/dotc/typer/Typer.scala | 11 ++++++++- tests/pos/i19942.scala | 23 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i19942.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 47bd25e5d45e..bc7fa3438374 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -4281,7 +4281,16 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer def adaptType(tp: Type): Tree = { val tree1 = - if ((pt eq AnyTypeConstructorProto) || tp.typeParamSymbols.isEmpty) tree + if pt eq AnyTypeConstructorProto then tree + else if tp.typeParamSymbols.isEmpty || tp.typeParamSymbols.isEmpty then + // call typeParamSymbols twice, to get the stable results + // (see also note inside typeParamSymbols) + // given `type LifecycleF = [_] =>> Any` in pos/i19942.scala + // with an Ident of LifecycleF, calling typeParams will return: + // 1. [type _] a list of the symbol _ in the type def tree, on the first call + // 2. [+_] a list of a lambda param, afterwards + // we only want to eta-expand if there are real type param symbols, so we check twice + tree else { if (ctx.isJava) // Cook raw type diff --git a/tests/pos/i19942.scala b/tests/pos/i19942.scala new file mode 100644 index 000000000000..9be97f635df4 --- /dev/null +++ b/tests/pos/i19942.scala @@ -0,0 +1,23 @@ +type LifecycleF = [_] =>> Any +trait Lifecycle[+F[_], +A] + +trait LifecycleTag[R] +object LifecycleTag: + implicit def resourceTag[R <: Lifecycle[F0, A0], F0[_], A0]: LifecycleTag[R] = ??? + +trait MakeDSL[T]: + final def fromResource[R <: Lifecycle[LifecycleF, T]](implicit tag: LifecycleTag[R]): Any = ??? + +object distage: + // Cannot be defined in the same scope as rest of code + final type Identity[+A] = A +import distage.* + +trait Resource +trait DependentResource() extends Lifecycle[Identity, Resource] + +@main def Test = { + val dsl: MakeDSL[Resource] = ??? + val fails = dsl.fromResource[DependentResource] + val works = dsl.fromResource[DependentResource](using LifecycleTag.resourceTag[DependentResource, Identity, Resource]) +} From 2ef48d9cff10372e42914d6f7ad530119954da58 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sat, 16 Mar 2024 16:46:46 +0000 Subject: [PATCH 237/277] Add second test case from comment 1 --- tests/pos/i19942.1.scala | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 tests/pos/i19942.1.scala diff --git a/tests/pos/i19942.1.scala b/tests/pos/i19942.1.scala new file mode 100644 index 000000000000..20f923886089 --- /dev/null +++ b/tests/pos/i19942.1.scala @@ -0,0 +1,29 @@ +trait Alternative[F[_]] + +opaque type Derived[A] = A +object Derived: + extension [A](derived: Derived[A]) def instance: A = derived + infix type <<<[F[_], G[_]] = [x] =>> F[G[x]] + +import Derived.* +import scala.compiletime.summonInline + +type DerivedAlternative[F[_]] = Derived[Alternative[F]] +object DerivedAlternative: + inline def apply[F[_]]: Alternative[F] = + import DerivedAlternative.given + summonInline[DerivedAlternative[F]].instance + given nested[F[_], G[_]]: DerivedAlternative[F <<< G] = ??? + +object auto: + object alternative: + transparent inline given [F[_]]: Alternative[F] = DerivedAlternative[F] + +trait Test: + import Test.* + import auto.alternative.given + val fails = summon[Alternative[OptList]] + +// Fails if companion object defined AFTER trait +object Test: + type OptList[A] = Option[List[A]] From c65bdb30eb10074c06c4823d0414b50fb84e36d2 Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 18 Mar 2024 12:56:21 +0100 Subject: [PATCH 238/277] Move retry logic to one special case in typeParams --- .../src/dotty/tools/dotc/core/TypeApplications.scala | 12 +++++++++++- compiler/src/dotty/tools/dotc/typer/Typer.scala | 11 +---------- .../quote-type-variable-no-inference-3.check | 4 ++-- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index 223d3bb11515..eeb18eaa9cc7 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -182,7 +182,17 @@ class TypeApplications(val self: Type) extends AnyVal { val tsym = self.symbol if (tsym.isClass) tsym.typeParams else tsym.infoOrCompleter match { - case info: LazyType if isTrivial(self.prefix, tsym) => info.completerTypeParams(tsym) + case info: LazyType if isTrivial(self.prefix, tsym) => + val tparams = info.completerTypeParams(tsym) + if tsym.isCompleted then tsym.info.typeParams + // Completers sometimes represent parameters as symbols where + // the completed type represents them as paramrefs. Make sure we get + // a stable result by calling `typeParams` recursively. Test case + // is pos/i19942.scala, where parameter F0 has initially a Namer#TypeDefCompleter. + // After calling its completerTypeParams, we get a list of parameter symbols + // and as a side effect F0 is completed. Calling typeParams on the completed + // type gives a list of paramrefs. + else tparams case _ => self.info.typeParams } case self: AppliedType => diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index bc7fa3438374..e6fd7c5abcbb 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -4281,16 +4281,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer def adaptType(tp: Type): Tree = { val tree1 = - if pt eq AnyTypeConstructorProto then tree - else if tp.typeParamSymbols.isEmpty || tp.typeParamSymbols.isEmpty then - // call typeParamSymbols twice, to get the stable results - // (see also note inside typeParamSymbols) - // given `type LifecycleF = [_] =>> Any` in pos/i19942.scala - // with an Ident of LifecycleF, calling typeParams will return: - // 1. [type _] a list of the symbol _ in the type def tree, on the first call - // 2. [+_] a list of a lambda param, afterwards - // we only want to eta-expand if there are real type param symbols, so we check twice - tree + if (pt eq AnyTypeConstructorProto) || tp.typeParamSymbols.isEmpty then tree else { if (ctx.isJava) // Cook raw type diff --git a/tests/neg-macros/quote-type-variable-no-inference-3.check b/tests/neg-macros/quote-type-variable-no-inference-3.check index 91476728654d..e98900069740 100644 --- a/tests/neg-macros/quote-type-variable-no-inference-3.check +++ b/tests/neg-macros/quote-type-variable-no-inference-3.check @@ -1,10 +1,10 @@ -- Warning: tests/neg-macros/quote-type-variable-no-inference-3.scala:5:22 --------------------------------------------- 5 | case '{ $_ : F[t, t]; () } => // warn // error | ^ - | Ignored bound <: Comparable[U] + | Ignored bound <: Comparable[Any] | | Consider defining bounds explicitly: - | '{ type t <: Comparable[U]; ... } + | '{ type t <: Comparable[Any]; ... } -- Warning: tests/neg-macros/quote-type-variable-no-inference-3.scala:6:49 --------------------------------------------- 6 | case '{ type u <: Comparable[`u`]; $_ : F[u, u] } => | ^ From 9a166171b00d0f81c879524fc185a31667c60022 Mon Sep 17 00:00:00 2001 From: Szymon Rodziewicz Date: Mon, 18 Mar 2024 13:31:33 +0100 Subject: [PATCH 239/277] Fix -Xmigration legacy behavior --- .../dotty/tools/dotc/config/ScalaSettings.scala | 4 ++-- .../src/dotty/tools/dotc/config/Settings.scala | 14 +++++--------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 12fe7df8d4d1..687adfe05ca7 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -301,7 +301,7 @@ private sealed trait XSettings: val XnoForwarders: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xno-forwarders", "Do not generate static forwarders in mirror classes.") val XmaxInlines: Setting[Int] = IntSetting(AdvancedSetting, "Xmax-inlines", "Maximal number of successive inlines.", 32) val XmaxInlinedTrees: Setting[Int] = IntSetting(AdvancedSetting, "Xmax-inlined-trees", "Maximal number of inlined trees.", 2_000_000) - val Xmigration: Setting[ScalaVersion] = VersionSetting(AdvancedSetting, "Xmigration", "Warn about constructs whose behavior may have changed since version.") + val Xmigration: Setting[ScalaVersion] = VersionSetting(AdvancedSetting, "Xmigration", "Warn about constructs whose behavior may have changed since version.", legacyArgs = true) val XprintTypes: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xprint-types", "Print tree types (debugging option).") val XprintDiff: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xprint-diff", "Print changed parts of the tree since last print.") val XprintDiffDel: Setting[Boolean] = BooleanSetting(AdvancedSetting, "Xprint-diff-del", "Print changed parts of the tree since last print including deleted parts.") @@ -376,7 +376,7 @@ private sealed trait YSettings: val YstopBefore: Setting[List[String]] = PhasesSetting(ForkSetting, "Ystop-before", "Stop before") // stop before erasure as long as we have not debugged it fully val YshowSuppressedErrors: Setting[Boolean] = BooleanSetting(ForkSetting, "Yshow-suppressed-errors", "Also show follow-on errors and warnings that are normally suppressed.") val YdetailedStats: Setting[Boolean] = BooleanSetting(ForkSetting, "Ydetailed-stats", "Show detailed internal compiler stats (needs Stats.enabled to be set to true).") - val YkindProjector: Setting[String] = LegacyChoiceSetting(ForkSetting, "Ykind-projector", "[underscores, enable, disable]", "Allow `*` as type lambda placeholder to be compatible with kind projector. When invoked as -Ykind-projector:underscores will repurpose `_` to be a type parameter placeholder, this will disable usage of underscore as a wildcard.", List("disable", "", "underscores"), "disable") + val YkindProjector: Setting[String] = ChoiceSetting(ForkSetting, "Ykind-projector", "[underscores, enable, disable]", "Allow `*` as type lambda placeholder to be compatible with kind projector. When invoked as -Ykind-projector:underscores will repurpose `_` to be a type parameter placeholder, this will disable usage of underscore as a wildcard.", List("disable", "", "underscores"), "disable", legacyArgs = true) val YprintPos: Setting[Boolean] = BooleanSetting(ForkSetting, "Yprint-pos", "Show tree positions.") val YprintPosSyms: Setting[Boolean] = BooleanSetting(ForkSetting, "Yprint-pos-syms", "Show symbol definitions positions.") val YnoDeepSubtypes: Setting[Boolean] = BooleanSetting(ForkSetting, "Yno-deep-subtypes", "Throw an exception on deep subtyping call stacks.") diff --git a/compiler/src/dotty/tools/dotc/config/Settings.scala b/compiler/src/dotty/tools/dotc/config/Settings.scala index 649fd600bdc2..a65072427ba7 100644 --- a/compiler/src/dotty/tools/dotc/config/Settings.scala +++ b/compiler/src/dotty/tools/dotc/config/Settings.scala @@ -200,7 +200,7 @@ object Settings: case (OptionTag, _) => update(Some(propertyClass.get.getConstructor().newInstance()), args) case (ct, args) => - val argInArgRest = !argRest.isEmpty || (legacyArgs && choices.exists(_.contains(""))) + val argInArgRest = !argRest.isEmpty || legacyArgs val argAfterParam = !argInArgRest && args.nonEmpty && (ct == IntTag || !args.head.startsWith("-")) if argInArgRest then doSetArg(argRest, args) @@ -339,12 +339,8 @@ object Settings: def StringSetting(category: SettingCategory, name: String, helpArg: String, descr: String, default: String, aliases: List[String] = Nil): Setting[String] = publish(Setting(category, prependName(name), descr, default, helpArg, aliases = aliases)) - def ChoiceSetting(category: SettingCategory, name: String, helpArg: String, descr: String, choices: List[String], default: String, aliases: List[String] = Nil): Setting[String] = - publish(Setting(category, prependName(name), descr, default, helpArg, Some(choices), aliases = aliases)) - - // Allows only args after :, but supports empty string as a choice. Used for -Ykind-projector - def LegacyChoiceSetting(category: SettingCategory, name: String, helpArg: String, descr: String, choices: List[String], default: String, aliases: List[String] = Nil): Setting[String] = - publish(Setting(category, prependName(name), descr, default, helpArg, Some(choices), aliases = aliases, legacyArgs = true)) + def ChoiceSetting(category: SettingCategory, name: String, helpArg: String, descr: String, choices: List[String], default: String, aliases: List[String] = Nil, legacyArgs: Boolean = false): Setting[String] = + publish(Setting(category, prependName(name), descr, default, helpArg, Some(choices), aliases = aliases, legacyArgs = legacyArgs)) def MultiChoiceSetting(category: SettingCategory, name: String, helpArg: String, descr: String, choices: List[String], default: List[String], aliases: List[String] = Nil): Setting[List[String]] = publish(Setting(category, prependName(name), descr, default, helpArg, Some(choices), aliases = aliases)) @@ -374,8 +370,8 @@ object Settings: val prefix = name.takeWhile(_ != '<') publish(Setting(category, "-" + name, descr, Nil, prefix = Some(prefix))) - def VersionSetting(category: SettingCategory, name: String, descr: String, default: ScalaVersion = NoScalaVersion): Setting[ScalaVersion] = - publish(Setting(category, prependName(name), descr, default)) + def VersionSetting(category: SettingCategory, name: String, descr: String, default: ScalaVersion = NoScalaVersion, legacyArgs: Boolean = false): Setting[ScalaVersion] = + publish(Setting(category, prependName(name), descr, default, legacyArgs = legacyArgs)) def OptionSetting[T: ClassTag](category: SettingCategory, name: String, descr: String, aliases: List[String] = Nil): Setting[Option[T]] = publish(Setting(category, prependName(name), descr, None, propertyClass = Some(summon[ClassTag[T]].runtimeClass), aliases = aliases)) From 572d6b13f2e00142a6c3ddb23e3d92152cd404b5 Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 18 Mar 2024 14:22:00 +0100 Subject: [PATCH 240/277] Avoid repetitions in name hints Fixes #19958 --- .../src/dotty/tools/dotc/reporting/DidYouMean.scala | 2 +- tests/neg/i19958.check | 8 ++++++++ tests/neg/i19958.scala | 11 +++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 tests/neg/i19958.check create mode 100644 tests/neg/i19958.scala diff --git a/compiler/src/dotty/tools/dotc/reporting/DidYouMean.scala b/compiler/src/dotty/tools/dotc/reporting/DidYouMean.scala index 04b9b518fd5e..14e5e7798e05 100644 --- a/compiler/src/dotty/tools/dotc/reporting/DidYouMean.scala +++ b/compiler/src/dotty/tools/dotc/reporting/DidYouMean.scala @@ -149,7 +149,7 @@ object DidYouMean: if d != 0 || b.sym.is(ModuleClass) => // Avoid repeating the same name in "did you mean" if qualifies(b) then def hint(b: Binding) = prefix ++ showName(b.name, b.sym) - val alts = alternatives(d, rest).map(hint).take(3) + val alts = alternatives(d, rest).filter(_.name != b.name).map(hint).take(3).distinct val suffix = if alts.isEmpty then "" else alts.mkString(" or perhaps ", " or ", "?") s" - did you mean ${hint(b)}?$suffix" else diff --git a/tests/neg/i19958.check b/tests/neg/i19958.check new file mode 100644 index 000000000000..dbe1ddf682fd --- /dev/null +++ b/tests/neg/i19958.check @@ -0,0 +1,8 @@ +-- [E008] Not Found Error: tests/neg/i19958.scala:1:21 ----------------------------------------------------------------- +1 |val b = new Object().unit // error + | ^^^^^^^^^^^^^^^^^ + | value unit is not a member of Object - did you mean Object.wait? +-- [E008] Not Found Error: tests/neg/i19958.scala:10:10 ---------------------------------------------------------------- +10 |val d = c.unit // error + | ^^^^^^ + | value unit is not a member of C - did you mean c.blit? or perhaps c.wait? diff --git a/tests/neg/i19958.scala b/tests/neg/i19958.scala new file mode 100644 index 000000000000..eba89d969b63 --- /dev/null +++ b/tests/neg/i19958.scala @@ -0,0 +1,11 @@ +val b = new Object().unit // error + +abstract class C: + def wait: Unit + def wait(x: Int): Unit + def blit: Unit + def blit(x: Int): Unit + +val c: C = ??? +val d = c.unit // error + From 8a5cf8b441b3d1fe09ad8e6a11e6c71dd0added3 Mon Sep 17 00:00:00 2001 From: Dan13llljws Date: Mon, 18 Mar 2024 10:01:37 -0400 Subject: [PATCH 241/277] changed plain string to Definitions --- .../src/dotty/tools/dotc/transform/init/Objects.scala | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala index 061f7f902bbf..90df85b98ecf 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala @@ -66,7 +66,9 @@ import dotty.tools.dotc.core.Flags.AbstractOrTrait * whole-program analysis. However, the check is not modular in terms of project boundaries. * */ -class Objects: +class Objects(using Context @constructorOnly): + val immutableHashSetBuider: Symbol = requiredClass("scala.collection.immutable.HashSetBuilder") + val HashSetBuilder_rootNode: Symbol = immutableHashSetBuider.requiredValue("rootNode") // ----------------------------- abstract domain ----------------------------- @@ -1683,12 +1685,11 @@ class Objects: end if // class body - val whiteList = Set("scala.collection.immutable.Vector.emptyIterator") + val whiteList = Set(HashSetBuilder_rootNode) tpl.body.foreach { case vdef : ValDef if !vdef.symbol.is(Flags.Lazy) && !vdef.rhs.isEmpty => - var res = eval(vdef.rhs, thisV, klass) val sym = vdef.symbol - if (whiteList.contains(sym.showFullName)) res = Bottom + var res = if (whiteList.contains(sym)) Bottom else eval(vdef.rhs, thisV, klass) if sym.is(Flags.Mutable) then val addr = Heap.fieldVarAddr(summon[Regions.Data], sym, State.currentObject) thisV.initVar(sym, addr) From 8315f78f746ad7b7a9d73e9c40f3dc63602a3b94 Mon Sep 17 00:00:00 2001 From: Dan13llljws Date: Mon, 18 Mar 2024 14:39:17 -0400 Subject: [PATCH 242/277] changed to --- compiler/src/dotty/tools/dotc/transform/init/Objects.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala index 90df85b98ecf..28f4121d25e6 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala @@ -1689,7 +1689,7 @@ class Objects(using Context @constructorOnly): tpl.body.foreach { case vdef : ValDef if !vdef.symbol.is(Flags.Lazy) && !vdef.rhs.isEmpty => val sym = vdef.symbol - var res = if (whiteList.contains(sym)) Bottom else eval(vdef.rhs, thisV, klass) + val res = if (whiteList.contains(sym)) Bottom else eval(vdef.rhs, thisV, klass) if sym.is(Flags.Mutable) then val addr = Heap.fieldVarAddr(summon[Regions.Data], sym, State.currentObject) thisV.initVar(sym, addr) From 11eff96ba77830f44fd196dd4d5e40ce7aeb921c Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 18 Mar 2024 22:13:16 -0700 Subject: [PATCH 243/277] Preliminary ported edits --- docs/_spec/11-annotations.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/_spec/11-annotations.md b/docs/_spec/11-annotations.md index 3381856d78fb..e8b23be0e007 100644 --- a/docs/_spec/11-annotations.md +++ b/docs/_spec/11-annotations.md @@ -20,7 +20,7 @@ Here, ´c´ is a constructor of a class ´C´, which must conform to the class ` Annotations may apply to definitions, types, or expressions. An annotation of a definition appears in front of that definition. An annotation of a type appears after that type. -An annotation of an expression ´e´ appears after the expression ´e´, separated by a colon. +An annotation of an expression appears after that expression, separated by a colon. More than one annotation clause may apply to an entity. The order in which these annotations are given does not matter. @@ -86,7 +86,7 @@ def f(x: Option[Int]) = (x: @unchecked) match { ``` Without the `@unchecked` annotation, a Scala compiler could infer that the pattern match is non-exhaustive, and could produce a warning because `Option` is a `sealed` class. -* `@uncheckedStable` When applied a value definition, it allows the defined value to appear in a path, even if its type is [volatile](03-types.html#volatile-types). +* `@uncheckedStable` When applied to a value definition, it allows the defined value to appear in a path, even if its type is [volatile](03-types.html#volatile-types). For instance, the following member definitions are legal: ```scala type A { type T } @@ -97,7 +97,7 @@ val y: x.T // OK since `x' is still a path Without the `@uncheckedStable` annotation, the designator `x` would not be a path since its type `A with B` is volatile. Hence, the reference `x.T` would be malformed. -When applied to value definitions that have non-volatile types, the annotation has no effect. +When applied to value definitions that have no volatile types, the annotation has no effect. * `@specialized` When applied to the definition of a type parameter, this annotation causes the compiler to generate specialized definitions for primitive types. An optional list of primitive types may be given, in which case specialization takes into account only those types. From f7d5a8daaf9ce71ff182fd7a36c4823b04949e0c Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 18 Mar 2024 23:43:07 -0700 Subject: [PATCH 244/277] Port tailrec spec --- docs/_spec/04-basic-definitions.md | 16 +++++ docs/_spec/11-annotations.md | 93 ++++++++++++++++-------------- 2 files changed, 67 insertions(+), 42 deletions(-) diff --git a/docs/_spec/04-basic-definitions.md b/docs/_spec/04-basic-definitions.md index 369709b52bff..28eb2d43a627 100644 --- a/docs/_spec/04-basic-definitions.md +++ b/docs/_spec/04-basic-definitions.md @@ -710,6 +710,22 @@ class C extends I { Here, it is OK to leave out the result type of `factorial` in `C`, even though the method is recursive. +### Tail-Recursive Call Elimination + +Method definitions which contain self-recursive invocations in tail position are optimized for stack safety. +Self-invocations which are the last operation before returning from the method are replaced with jumps to the beginning of the method, much as in a while loop. +Sibling-invocations, in which a method calls itself but with a different instance as receiver, are also optimized. + +This transform is performed automatically by the compiler whenever possible. +A method definition bearing the annotation, `scala.annotation.tailrec`, will fail to compile if the transform is not possible. +(The annotation is intended for cases where deoptimization would likely result in a stack overflow.) + +```scala +@annotation.tailrec +def sum(xs: List[Int], acc: Int): Int = + xs match { case h :: t => sum(t, acc + h) case _ => acc } +``` + isIncomplete --- compiler/src/dotty/tools/dotc/core/TypeComparer.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index ab783ad82ddc..b8732d8edd34 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -1707,13 +1707,13 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling val tparam = tparams2.head val v = tparam.paramVarianceSign - /** An argument test is hard if it implies a comparison A <: B where + /** An argument test is incomplete if it implies a comparison A <: B where * A is an AndType or B is an OrType. In these cases we need to run an * either, which can lose solutions if there are type variables involved. * So we defer such tests to run last, on the chance that some other argument * comparison will instantiate or constrain type variables first. */ - def isHard(arg1: Type, arg2: Type): Boolean = + def isIncomplete(arg1: Type, arg2: Type): Boolean = val arg1d = arg1.stripped val arg2d = arg2.stripped (v >= 0) && (arg1d.isInstanceOf[AndType] || arg2d.isInstanceOf[OrType]) @@ -1811,7 +1811,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling if !canDefer || rest1.isEmpty && deferred1.isEmpty // skip the hardness test if this is the last argument and no previous arguments were hard - || !isHard(arg1, arg2) + || !isIncomplete(arg1, arg2) then isSubArg(arg1, arg2) && recurArgs( From 0f30c9800725f889bb91f05aae692495f1387bf6 Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 25 Mar 2024 18:17:36 +0100 Subject: [PATCH 269/277] Apply suggestions from code review Co-authored-by: Guillaume Martres --- compiler/src/dotty/tools/dotc/core/TypeComparer.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index b8732d8edd34..9fe3a1daf9e1 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -1691,7 +1691,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling def paramBounds(tparam: Symbol): TypeBounds = tparam.info.substApprox(tparams2.asInstanceOf[List[Symbol]], args2).bounds - /** Test all arguments. Hard argument tests (according to isHard) are deferred in + /** Test all arguments. Incomplete argument tests (according to isIncomplete) are deferred in * the first run and picked up in the second. */ def recurArgs(args1: List[Type], args2: List[Type], tparams2: List[ParamInfo], @@ -1714,8 +1714,8 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling * comparison will instantiate or constrain type variables first. */ def isIncomplete(arg1: Type, arg2: Type): Boolean = - val arg1d = arg1.stripped - val arg2d = arg2.stripped + val arg1d = arg1.strippedDealias + val arg2d = arg2.strippedDealias (v >= 0) && (arg1d.isInstanceOf[AndType] || arg2d.isInstanceOf[OrType]) || (v <= 0) && (arg1d.isInstanceOf[OrType] || arg2d.isInstanceOf[AndType]) @@ -1810,7 +1810,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling val rest1 = args1.tail if !canDefer || rest1.isEmpty && deferred1.isEmpty - // skip the hardness test if this is the last argument and no previous arguments were hard + // skip the incompleteness test if this is the last argument and no previous argument tests were incomplete || !isIncomplete(arg1, arg2) then isSubArg(arg1, arg2) From 181bc79480310d0ebde65868a24ff40af8bab22d Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Tue, 26 Mar 2024 13:39:01 +0100 Subject: [PATCH 270/277] Add warning about Java version in CI --- .github/workflows/ci.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 71a2c4ed6eb0..1ecd641841fd 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -353,6 +353,9 @@ jobs: )" steps: + ###################################################################################### + ## WARNING: DO NOT CHANGE THE JAVA VERSION HERE. SCALA IS DISTRIBUTED USING JAVA 8. ## + ###################################################################################### - name: Set JDK 8 as default run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo @@ -407,6 +410,9 @@ jobs: )" steps: + ###################################################################################### + ## WARNING: DO NOT CHANGE THE JAVA VERSION HERE. SCALA IS DISTRIBUTED USING JAVA 8. ## + ###################################################################################### - name: Set JDK 8 as default run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo @@ -461,6 +467,9 @@ jobs: )" steps: + ###################################################################################### + ## WARNING: DO NOT CHANGE THE JAVA VERSION HERE. SCALA IS DISTRIBUTED USING JAVA 8. ## + ###################################################################################### - name: Set JDK 8 as default run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo @@ -562,6 +571,9 @@ jobs: )" steps: + #################################################################################### + ## WARNING: DO NOT CHANGE THE JAVA VERSION HERE. THIS TEST IS SPECIFIC FOR JAVA 8 ## + #################################################################################### - name: Set JDK 8 as default run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH @@ -611,6 +623,9 @@ jobs: SONATYPE_USER: ${{ secrets.SONATYPE_USER_ORGSCALALANG }} steps: + ###################################################################################### + ## WARNING: DO NOT CHANGE THE JAVA VERSION HERE. SCALA IS DISTRIBUTED USING JAVA 8. ## + ###################################################################################### - name: Set JDK 8 as default run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo @@ -722,6 +737,9 @@ jobs: SONATYPE_USER: ${{ secrets.SONATYPE_USER_ORGSCALALANG }} steps: + ###################################################################################### + ## WARNING: DO NOT CHANGE THE JAVA VERSION HERE. SCALA IS DISTRIBUTED USING JAVA 8. ## + ###################################################################################### - name: Set JDK 8 as default run: echo "/usr/lib/jvm/java-8-openjdk-amd64/bin" >> $GITHUB_PATH - name: Reset existing repo From 7a3dc444ac5f0c87d0f7733b925b0057a4386ec4 Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Tue, 26 Mar 2024 14:07:33 +0100 Subject: [PATCH 271/277] Avoid duplications of properties in pom.xml --- project/Build.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/project/Build.scala b/project/Build.scala index a7107d1f139d..e3b4ed789a1f 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1999,6 +1999,10 @@ object Build { publishTo := sonatypePublishToBundle.value, publishConfiguration ~= (_.withOverwrite(true)), publishLocalConfiguration ~= (_.withOverwrite(true)), + projectID ~= {id => + val line = "scala.versionLine" -> versionLine + id.withExtraAttributes(id.extraAttributes + line) + }, Test / publishArtifact := false, homepage := Some(url(dottyGithubUrl)), licenses += (("Apache-2.0", @@ -2009,10 +2013,6 @@ object Build { "scm:git:git@github.com:scala/scala3.git" ) ), - pomExtra := - - {versionLine} - , developers := List( Developer( id = "odersky", From ff6ef73f2bcf2c997bef5937e0522ae0e44a27f3 Mon Sep 17 00:00:00 2001 From: Valentin Schneeberger Date: Tue, 26 Mar 2024 15:55:45 +0100 Subject: [PATCH 272/277] Catch stackoverflow errors in the highlighter (#19836) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matt Bovel Co-authored-by: Sébastien Doeraene --- .../dotc/printing/SyntaxHighlighting.scala | 38 +++++++++++-------- .../dotty/tools/repl/ReplCompilerTests.scala | 13 +++++++ 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala b/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala index 6f65320d2c8e..ce925e336b53 100644 --- a/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala +++ b/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala @@ -124,24 +124,30 @@ object SyntaxHighlighting { } } - val parser = new Parser(source) - val trees = parser.blockStatSeq() - TreeHighlighter.highlight(trees) - - val highlighted = new StringBuilder() - - for (idx <- colorAt.indices) { - val prev = if (idx == 0) NoColor else colorAt(idx - 1) - val curr = colorAt(idx) - if (curr != prev) - highlighted.append(curr) - highlighted.append(in(idx)) - } + try + val parser = new Parser(source) + val trees = parser.blockStatSeq() + TreeHighlighter.highlight(trees) + + + val highlighted = new StringBuilder() - if (colorAt.last != NoColor) - highlighted.append(NoColor) + for (idx <- colorAt.indices) { + val prev = if (idx == 0) NoColor else colorAt(idx - 1) + val curr = colorAt(idx) + if (curr != prev) + highlighted.append(curr) + highlighted.append(in(idx)) + } + + if (colorAt.last != NoColor) + highlighted.append(NoColor) - highlighted.toString + highlighted.toString + catch + case e: StackOverflowError => + in } } + } diff --git a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala index a5bdddc51118..ecae111604cf 100644 --- a/compiler/test/dotty/tools/repl/ReplCompilerTests.scala +++ b/compiler/test/dotty/tools/repl/ReplCompilerTests.scala @@ -497,3 +497,16 @@ class ReplVerboseTests extends ReplTest(ReplTest.defaultOptions :+ "-verbose"): } end ReplVerboseTests + +class ReplHighlightTests extends ReplTest(ReplTest.defaultOptions.filterNot(_.startsWith("-color")) :+ "-color:always"): + @Test def i18596: Unit = initially: + run("""(1 to 500).foldRight("x") { case (_, n) => s"$n" }""") + + @Test def i16904: Unit = initially: + run(""""works not fine"* 10000""") + + run(""" + case class Tree(left: Tree, right: Tree) + def deepTree(depth: Int): Tree + deepTree(300)""") + From ab06ff6a87b99c5500eea4d7895d12bd06e2eff7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Marks?= Date: Thu, 28 Mar 2024 11:31:14 +0100 Subject: [PATCH 273/277] Bring back old completions as a deprecated method --- .../src/dotty/tools/repl/ReplDriver.scala | 20 ++++++++++++++++--- compiler/test/dotty/tools/repl/ReplTest.scala | 2 +- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/repl/ReplDriver.scala b/compiler/src/dotty/tools/repl/ReplDriver.scala index f8bba2f59fe1..0d64c88d9228 100644 --- a/compiler/src/dotty/tools/repl/ReplDriver.scala +++ b/compiler/src/dotty/tools/repl/ReplDriver.scala @@ -163,7 +163,7 @@ class ReplDriver(settings: Array[String], /* complete = */ false // if true adds space when completing ) } - val comps = completions(line.cursor, line.line, state) + val comps = completionsWithSignatures(line.cursor, line.line, state) candidates.addAll(comps.map(_.label).distinct.map(makeCandidate).asJava) val lineWord = line.word() comps.filter(c => c.label == lineWord && c.symbols.nonEmpty) match @@ -255,8 +255,22 @@ class ReplDriver(settings: Array[String], else label + @deprecated("Use completionsWithSignatures instead", "3.4.2") + protected final def completions(cursor: Int, expr: String, state0: State): List[Candidate] = + completionsWithSignatures(cursor, expr, state0).map: c => + new Candidate( + /* value = */ c.label, + /* displ = */ stripBackTicks(c.label), // displayed value + /* group = */ null, // can be used to group completions together + /* descr = */ null, // TODO use for documentation? + /* suffix = */ null, + /* key = */ null, + /* complete = */ false // if true adds space when completing + ) + end completions + /** Extract possible completions at the index of `cursor` in `expr` */ - protected final def completions(cursor: Int, expr: String, state0: State): List[Completion] = + protected final def completionsWithSignatures(cursor: Int, expr: String, state0: State): List[Completion] = if expr.startsWith(":") then ParseResult.commands.collect { case command if command._1.startsWith(expr) => Completion(command._1, "", List()) @@ -275,7 +289,7 @@ class ReplDriver(settings: Array[String], try Completion.completions(srcPos)._2 catch case NonFatal(_) => Nil } .getOrElse(Nil) - end completions + end completionsWithSignatures protected def interpret(res: ParseResult, quiet: Boolean = false)(using state: State): State = { res match { diff --git a/compiler/test/dotty/tools/repl/ReplTest.scala b/compiler/test/dotty/tools/repl/ReplTest.scala index 3e827a0f1e36..3925b61d7de0 100644 --- a/compiler/test/dotty/tools/repl/ReplTest.scala +++ b/compiler/test/dotty/tools/repl/ReplTest.scala @@ -42,7 +42,7 @@ extends ReplDriver(options, new PrintStream(out, true, StandardCharsets.UTF_8.na /** Returns the `(, )`*/ def tabComplete(src: String)(implicit state: State): List[String] = - completions(src.length, src, state).map(_.label).sorted.distinct + completionsWithSignatures(src.length, src, state).map(_.label).sorted.distinct extension [A](state: State) infix def andThen(op: State ?=> A): A = op(using state) From 76cd2dc26bd0b720b30425b5062b445e3bf4c810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Marks?= Date: Thu, 28 Mar 2024 12:09:35 +0100 Subject: [PATCH 274/277] Add changelog for 3.4.2-RC1 --- changelogs/3.4.2-RC1.md | 209 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 changelogs/3.4.2-RC1.md diff --git a/changelogs/3.4.2-RC1.md b/changelogs/3.4.2-RC1.md new file mode 100644 index 000000000000..464a5f6b086a --- /dev/null +++ b/changelogs/3.4.2-RC1.md @@ -0,0 +1,209 @@ +# Highlights of the release + +- Bump JLine 3.19.0 -> 3.24.1 & sbt 1.9.7 -> 1.9.9 [#19744](https://github.com/lampepfl/dotty/pull/19744) +- Refactor settings & improve dx [#19766](https://github.com/lampepfl/dotty/pull/19766) +- Publish `scala2-library-tasty-experimental` [#19588](https://github.com/lampepfl/dotty/pull/19588) +- Repl - method signatures in autocomplete [#19917](https://github.com/lampepfl/dotty/pull/19917) + +# Other changes and fixes + +## Annotations + +- Attempt implicit search for old style `implicit` parameters in Application matchArgs [#19737](https://github.com/lampepfl/dotty/pull/19737) + +## Backend + +- Fix(#17255): cannot find Scala companion module from Java [#19773](https://github.com/lampepfl/dotty/pull/19773) +- Change isStatic to isStaticOwner in hasLocalInstantiation [#19803](https://github.com/lampepfl/dotty/pull/19803) + +## Coverage + +- Port coverage filter options for packages and files [#19727](https://github.com/lampepfl/dotty/pull/19727) + +## Default parameters + +- Lift all non trivial prefixes for default parameters [#19739](https://github.com/lampepfl/dotty/pull/19739) + +## Doctool + +- Prevent HTML/XSS Injection in Scala Search [#19980](https://github.com/lampepfl/dotty/pull/19980) +- Parse search query param in Scaladoc [#19669](https://github.com/lampepfl/dotty/pull/19669) + +## Experimental: Capture Checking + +- Disallow covariant `cap`s in the lower bound of type members [#19624](https://github.com/lampepfl/dotty/pull/19624) +- Ignore orphan parameters inside a retains annotation during Ycheck [#19684](https://github.com/lampepfl/dotty/pull/19684) +- Fix the pickling of `This` inside capture sets [#19797](https://github.com/lampepfl/dotty/pull/19797) +- Add updated to SeqViewOps [#19798](https://github.com/lampepfl/dotty/pull/19798) +- Fix Function tree copier [#19822](https://github.com/lampepfl/dotty/pull/19822) +- Drop FreeSeqFactory from stdlib-cc [#19849](https://github.com/lampepfl/dotty/pull/19849) +- Fix i19859 [#19860](https://github.com/lampepfl/dotty/pull/19860) +- Various fixes to stdlib-cc [#19873](https://github.com/lampepfl/dotty/pull/19873) +- Add more methods in `SeqViewOps` [#19993](https://github.com/lampepfl/dotty/pull/19993) +- Check `This` references in `refersToParamOf` [#20005](https://github.com/lampepfl/dotty/pull/20005) + +## Exports + +- Fix the tparam bounds of exported inherited classes [#18647](https://github.com/lampepfl/dotty/pull/18647) + +## Implicits + +- Prefer extensions over conversions for member selection [#19717](https://github.com/lampepfl/dotty/pull/19717) +- Don't allow implicit conversions on prefixes of type selections [#19934](https://github.com/lampepfl/dotty/pull/19934) +- Make sure typeParams returns a stable result even in the presence of completions [#19974](https://github.com/lampepfl/dotty/pull/19974) + +## Incremental Compilation + +- Fix undercompilation upon ctor change [#19911](https://github.com/lampepfl/dotty/pull/19911) +- Load but not enter case accessors fields in Scala2Unpickler [#19926](https://github.com/lampepfl/dotty/pull/19926) + +## Initialization + +- Add supports for type cast and filtering type for field and method owner in global initialization checker [#19612](https://github.com/lampepfl/dotty/pull/19612) +- Added a second trace for global init checker showing creation of mutable fields [#19996](https://github.com/lampepfl/dotty/pull/19996) +- Suppressing repetitive warnings in the global initialization checker [#19898](https://github.com/lampepfl/dotty/pull/19898) + +## Inline + +- Specialized retained inline FunctionN apply methods [#19801](https://github.com/lampepfl/dotty/pull/19801) +- Avoid crash after StopMacroExpansion [#19883](https://github.com/lampepfl/dotty/pull/19883) +- Check deprecation of inline methods [#19914](https://github.com/lampepfl/dotty/pull/19914) +- Inline transparent implicit parameters when typing Unapply trees [#19646](https://github.com/lampepfl/dotty/pull/19646) +- Restore pre-3.3.2 behavior of `inline implicit def` [#19877](https://github.com/lampepfl/dotty/pull/19877) + +## Match Types + +- Cover patterns using `reflect.TypeTest` in isMatchTypeShaped [#19923](https://github.com/lampepfl/dotty/pull/19923) +- Rework MatchType recursion in collectParts [#19867](https://github.com/lampepfl/dotty/pull/19867) + +## Nullability + +- Fix #19808: Don't force to compute the owner of a symbol when there is no denotation [#19813](https://github.com/lampepfl/dotty/pull/19813) + +## Parser + +- Add support for JEP-409 (sealed classes) + Add javacOpt directive [#19080](https://github.com/lampepfl/dotty/pull/19080) +- Fix(#16458): regression in xml syntax parsing [#19522](https://github.com/lampepfl/dotty/pull/19522) +- Fix parsing of conditional expressions in parentheses [#19985](https://github.com/lampepfl/dotty/pull/19985) + +## Presentation Compiler + +- Allow range selection on function parameter to select a parameter list [#19777](https://github.com/lampepfl/dotty/pull/19777) + +## Quotes + +- Disallow ill-staged references to local classes [#19869](https://github.com/lampepfl/dotty/pull/19869) +- Add regression test for #19909 [#19915](https://github.com/lampepfl/dotty/pull/19915) +- Detect non `Expr[..]` splice patterns [#19944](https://github.com/lampepfl/dotty/pull/19944) +- Avoid spurious `val` binding in quote pattern [#19948](https://github.com/lampepfl/dotty/pull/19948) +- Add regression test and imporve -Xprint-suspension message [#19688](https://github.com/lampepfl/dotty/pull/19688) + +## REPL + +- Repl truncation copes with null [#17336](https://github.com/lampepfl/dotty/pull/17336) +- Catch stackoverflow errors in the highlighter [#19836](https://github.com/lampepfl/dotty/pull/19836) +- Fix a REPL bad symbolic reference [#19786](https://github.com/lampepfl/dotty/pull/19786) + +## Reflection + +- Fix `TypeTreeTypeTest` to not match `TypeBoundsTree`s [#19485](https://github.com/lampepfl/dotty/pull/19485) +- Improve message when tree cannot be shown as source [#19906](https://github.com/lampepfl/dotty/pull/19906) +- Fix #19732: quotes.reflect.Ref incorrectly casting `This` to `RefTree` [#19930](https://github.com/lampepfl/dotty/pull/19930) +- Add check for parents in Quotes (#19842) [#19870](https://github.com/lampepfl/dotty/pull/19870) + +## Reporting + +- Improve error reporting for missing members [#19800](https://github.com/lampepfl/dotty/pull/19800) +- Avoid repetitions in name hints [#19975](https://github.com/lampepfl/dotty/pull/19975) +- Improve error message when using experimental definitions [#19782](https://github.com/lampepfl/dotty/pull/19782) +- Make -Xprompt work as desired under -Werror [#19765](https://github.com/lampepfl/dotty/pull/19765) +- Fix #19402: emit proper error in absence of using in given definitions [#19714](https://github.com/lampepfl/dotty/pull/19714) +- Bugfix: Choose correct signature is signatureHelp for overloaded methods [#19707](https://github.com/lampepfl/dotty/pull/19707) +- Unify completion pos usage, fix presentation compiler crash in interpolation [#19614](https://github.com/lampepfl/dotty/pull/19614) + +## Scaladoc + +- Fix(#16610): warn ignored Scaladoc on multiple enum cases [#19555](https://github.com/lampepfl/dotty/pull/19555) + +## TASTy format + +- Add patch for undefined behavior with `object $` [#19705](https://github.com/lampepfl/dotty/pull/19705) +- Fix(#19806): wrong tasty of scala module class reference [#19827](https://github.com/lampepfl/dotty/pull/19827) +- Used derived types to type arguments of dependent function type [#19838](https://github.com/lampepfl/dotty/pull/19838) + +## Tooling + +- Java TASTy: use new threadsafe writer implementation [#19690](https://github.com/lampepfl/dotty/pull/19690) +- Remove `-Yforce-inline-while-typing` [#19889](https://github.com/lampepfl/dotty/pull/19889) +- Cleanup unnecessary language flag [#19865](https://github.com/lampepfl/dotty/pull/19865) +- Bugfix: Auto imports in worksheets in Scala 3 [#19793](https://github.com/lampepfl/dotty/pull/19793) +- Refine behavior of `-Yno-experimental` [#19741](https://github.com/lampepfl/dotty/pull/19741) + +## Transform + +- Short-circuit isCheckable with classSymbol [#19634](https://github.com/lampepfl/dotty/pull/19634) +- Avoid eta-reduction of `(..., f: T => R, ...) => f.apply(..)` into `f` [#19966](https://github.com/lampepfl/dotty/pull/19966) +- Tweak parameter accessor scheme [#19719](https://github.com/lampepfl/dotty/pull/19719) + +## Typer + +- Update phrasing for NotClassType explain error message [#19635](https://github.com/lampepfl/dotty/pull/19635) +- Fix java typer problems with inner class references and raw types [#19747](https://github.com/lampepfl/dotty/pull/19747) +- Approximate MatchTypes with lub of case bodies, if non-recursive [#19761](https://github.com/lampepfl/dotty/pull/19761) +- Revert broken changes with transparent inline [#19922](https://github.com/lampepfl/dotty/pull/19922) +- Delay hard argument comparisons [#20007](https://github.com/lampepfl/dotty/pull/20007) +- Fix #19607: Allow to instantiate *wildcard* type captures to TypeBounds. [#19627](https://github.com/lampepfl/dotty/pull/19627) +- Fix #19907: Skip soft unions in widenSingle of widenInferred [#19995](https://github.com/lampepfl/dotty/pull/19995) +- Fix untupling of functions in for comprehensions [#19620](https://github.com/lampepfl/dotty/pull/19620) + +# Contributors + +Thank you to all the contributors who made this release possible 🎉 + +According to `git shortlog -sn --no-merges 3.4.1..3.42-RC1` these are: + +``` + 46 Nicolas Stucki + 33 Martin Odersky + 25 Dale Wijnand + 22 Hamza REMMAL + 18 Yichen Xu + 17 Jamie Thompson + 15 Szymon Rodziewicz + 11 EnzeXing + 11 i10416 + 7 Paweł Marks + 6 Kacper Korban + 4 Dan13llljws + 4 Katarzyna Marek + 4 Matt Bovel + 4 Som Snytt + 4 noti0na1 + 3 110416 + 3 Eugene Flesselle + 3 Sébastien Doeraene + 3 dependabot[bot] + 2 Bersier + 2 Hamza Remmal + 2 Jakub Ciesluk + 2 João Costa + 2 Jędrzej Rochala + 2 Natsu Kagami + 2 Stephane Bersier + 2 Taro L. Saito + 2 aherlihy + 1 Aleksander Boruch-Gruszecki + 1 Aviv Keller + 1 Eugene Yokota + 1 Guillaume Martres + 1 Jan Chyb + 1 Lukas Rytz + 1 Mikołaj Fornal + 1 Olga Mazhara + 1 Ondřej Lhoták + 1 Robert Stoll + 1 Seth Tisue + 1 Valentin Schneeberger + 1 Yilin Wei + 1 willerf +``` From 4029577068587ddc523e84fa39849446f83c0ea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Marks?= Date: Thu, 28 Mar 2024 12:10:26 +0100 Subject: [PATCH 275/277] Release 3.4.2-RC1 --- 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 e3b4ed789a1f..a5569c0d8888 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -83,7 +83,7 @@ object DottyJSPlugin extends AutoPlugin { object Build { import ScaladocConfigs._ - val referenceVersion = "3.4.0" + val referenceVersion = "3.4.1" val baseVersion = "3.4.2-RC1" @@ -104,7 +104,7 @@ object Build { * set to 3.1.3. If it is going to be 3.1.0, it must be set to the latest * 3.0.x release. */ - val previousDottyVersion = "3.4.0" + val previousDottyVersion = "3.4.1" /** Version against which we check binary compatibility. */ val ltsDottyVersion = "3.3.0" 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. * From 638d15a24b4e88ac892ae22a4ae81a73dfa5fa3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Marks?= Date: Mon, 13 May 2024 14:42:59 +0200 Subject: [PATCH 276/277] Add changelog for 3.4.2 --- changelogs/3.4.2.md | 209 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 changelogs/3.4.2.md diff --git a/changelogs/3.4.2.md b/changelogs/3.4.2.md new file mode 100644 index 000000000000..bb6fcc40c952 --- /dev/null +++ b/changelogs/3.4.2.md @@ -0,0 +1,209 @@ +# Highlights of the release + +- Bump JLine 3.19.0 -> 3.24.1 & sbt 1.9.7 -> 1.9.9 [#19744](https://github.com/lampepfl/dotty/pull/19744) +- Refactor settings & improve dx [#19766](https://github.com/lampepfl/dotty/pull/19766) +- Publish `scala2-library-tasty-experimental` [#19588](https://github.com/lampepfl/dotty/pull/19588) +- Repl - method signatures in autocomplete [#19917](https://github.com/lampepfl/dotty/pull/19917) + +# Other changes and fixes + +## Annotations + +- Attempt implicit search for old style `implicit` parameters in Application matchArgs [#19737](https://github.com/lampepfl/dotty/pull/19737) + +## Backend + +- Fix(#17255): cannot find Scala companion module from Java [#19773](https://github.com/lampepfl/dotty/pull/19773) +- Change isStatic to isStaticOwner in hasLocalInstantiation [#19803](https://github.com/lampepfl/dotty/pull/19803) + +## Coverage + +- Port coverage filter options for packages and files [#19727](https://github.com/lampepfl/dotty/pull/19727) + +## Default parameters + +- Lift all non trivial prefixes for default parameters [#19739](https://github.com/lampepfl/dotty/pull/19739) + +## Doctool + +- Prevent HTML/XSS Injection in Scala Search [#19980](https://github.com/lampepfl/dotty/pull/19980) +- Parse search query param in Scaladoc [#19669](https://github.com/lampepfl/dotty/pull/19669) + +## Experimental: Capture Checking + +- Disallow covariant `cap`s in the lower bound of type members [#19624](https://github.com/lampepfl/dotty/pull/19624) +- Ignore orphan parameters inside a retains annotation during Ycheck [#19684](https://github.com/lampepfl/dotty/pull/19684) +- Fix the pickling of `This` inside capture sets [#19797](https://github.com/lampepfl/dotty/pull/19797) +- Add updated to SeqViewOps [#19798](https://github.com/lampepfl/dotty/pull/19798) +- Fix Function tree copier [#19822](https://github.com/lampepfl/dotty/pull/19822) +- Drop FreeSeqFactory from stdlib-cc [#19849](https://github.com/lampepfl/dotty/pull/19849) +- Fix i19859 [#19860](https://github.com/lampepfl/dotty/pull/19860) +- Various fixes to stdlib-cc [#19873](https://github.com/lampepfl/dotty/pull/19873) +- Add more methods in `SeqViewOps` [#19993](https://github.com/lampepfl/dotty/pull/19993) +- Check `This` references in `refersToParamOf` [#20005](https://github.com/lampepfl/dotty/pull/20005) + +## Exports + +- Fix the tparam bounds of exported inherited classes [#18647](https://github.com/lampepfl/dotty/pull/18647) + +## Implicits + +- Prefer extensions over conversions for member selection [#19717](https://github.com/lampepfl/dotty/pull/19717) +- Don't allow implicit conversions on prefixes of type selections [#19934](https://github.com/lampepfl/dotty/pull/19934) +- Make sure typeParams returns a stable result even in the presence of completions [#19974](https://github.com/lampepfl/dotty/pull/19974) + +## Incremental Compilation + +- Fix undercompilation upon ctor change [#19911](https://github.com/lampepfl/dotty/pull/19911) +- Load but not enter case accessors fields in Scala2Unpickler [#19926](https://github.com/lampepfl/dotty/pull/19926) + +## Initialization + +- Add supports for type cast and filtering type for field and method owner in global initialization checker [#19612](https://github.com/lampepfl/dotty/pull/19612) +- Added a second trace for global init checker showing creation of mutable fields [#19996](https://github.com/lampepfl/dotty/pull/19996) +- Suppressing repetitive warnings in the global initialization checker [#19898](https://github.com/lampepfl/dotty/pull/19898) + +## Inline + +- Specialized retained inline FunctionN apply methods [#19801](https://github.com/lampepfl/dotty/pull/19801) +- Avoid crash after StopMacroExpansion [#19883](https://github.com/lampepfl/dotty/pull/19883) +- Check deprecation of inline methods [#19914](https://github.com/lampepfl/dotty/pull/19914) +- Inline transparent implicit parameters when typing Unapply trees [#19646](https://github.com/lampepfl/dotty/pull/19646) +- Restore pre-3.3.2 behavior of `inline implicit def` [#19877](https://github.com/lampepfl/dotty/pull/19877) + +## Match Types + +- Cover patterns using `reflect.TypeTest` in isMatchTypeShaped [#19923](https://github.com/lampepfl/dotty/pull/19923) +- Rework MatchType recursion in collectParts [#19867](https://github.com/lampepfl/dotty/pull/19867) + +## Nullability + +- Fix #19808: Don't force to compute the owner of a symbol when there is no denotation [#19813](https://github.com/lampepfl/dotty/pull/19813) + +## Parser + +- Add support for JEP-409 (sealed classes) + Add javacOpt directive [#19080](https://github.com/lampepfl/dotty/pull/19080) +- Fix(#16458): regression in xml syntax parsing [#19522](https://github.com/lampepfl/dotty/pull/19522) +- Fix parsing of conditional expressions in parentheses [#19985](https://github.com/lampepfl/dotty/pull/19985) + +## Presentation Compiler + +- Allow range selection on function parameter to select a parameter list [#19777](https://github.com/lampepfl/dotty/pull/19777) + +## Quotes + +- Disallow ill-staged references to local classes [#19869](https://github.com/lampepfl/dotty/pull/19869) +- Add regression test for #19909 [#19915](https://github.com/lampepfl/dotty/pull/19915) +- Detect non `Expr[..]` splice patterns [#19944](https://github.com/lampepfl/dotty/pull/19944) +- Avoid spurious `val` binding in quote pattern [#19948](https://github.com/lampepfl/dotty/pull/19948) +- Add regression test and imporve -Xprint-suspension message [#19688](https://github.com/lampepfl/dotty/pull/19688) + +## REPL + +- Repl truncation copes with null [#17336](https://github.com/lampepfl/dotty/pull/17336) +- Catch stackoverflow errors in the highlighter [#19836](https://github.com/lampepfl/dotty/pull/19836) +- Fix a REPL bad symbolic reference [#19786](https://github.com/lampepfl/dotty/pull/19786) + +## Reflection + +- Fix `TypeTreeTypeTest` to not match `TypeBoundsTree`s [#19485](https://github.com/lampepfl/dotty/pull/19485) +- Improve message when tree cannot be shown as source [#19906](https://github.com/lampepfl/dotty/pull/19906) +- Fix #19732: quotes.reflect.Ref incorrectly casting `This` to `RefTree` [#19930](https://github.com/lampepfl/dotty/pull/19930) +- Add check for parents in Quotes (#19842) [#19870](https://github.com/lampepfl/dotty/pull/19870) + +## Reporting + +- Improve error reporting for missing members [#19800](https://github.com/lampepfl/dotty/pull/19800) +- Avoid repetitions in name hints [#19975](https://github.com/lampepfl/dotty/pull/19975) +- Improve error message when using experimental definitions [#19782](https://github.com/lampepfl/dotty/pull/19782) +- Make -Xprompt work as desired under -Werror [#19765](https://github.com/lampepfl/dotty/pull/19765) +- Fix #19402: emit proper error in absence of using in given definitions [#19714](https://github.com/lampepfl/dotty/pull/19714) +- Bugfix: Choose correct signature is signatureHelp for overloaded methods [#19707](https://github.com/lampepfl/dotty/pull/19707) +- Unify completion pos usage, fix presentation compiler crash in interpolation [#19614](https://github.com/lampepfl/dotty/pull/19614) + +## Scaladoc + +- Fix(#16610): warn ignored Scaladoc on multiple enum cases [#19555](https://github.com/lampepfl/dotty/pull/19555) + +## TASTy format + +- Add patch for undefined behavior with `object $` [#19705](https://github.com/lampepfl/dotty/pull/19705) +- Fix(#19806): wrong tasty of scala module class reference [#19827](https://github.com/lampepfl/dotty/pull/19827) +- Used derived types to type arguments of dependent function type [#19838](https://github.com/lampepfl/dotty/pull/19838) + +## Tooling + +- Java TASTy: use new threadsafe writer implementation [#19690](https://github.com/lampepfl/dotty/pull/19690) +- Remove `-Yforce-inline-while-typing` [#19889](https://github.com/lampepfl/dotty/pull/19889) +- Cleanup unnecessary language flag [#19865](https://github.com/lampepfl/dotty/pull/19865) +- Bugfix: Auto imports in worksheets in Scala 3 [#19793](https://github.com/lampepfl/dotty/pull/19793) +- Refine behavior of `-Yno-experimental` [#19741](https://github.com/lampepfl/dotty/pull/19741) + +## Transform + +- Short-circuit isCheckable with classSymbol [#19634](https://github.com/lampepfl/dotty/pull/19634) +- Avoid eta-reduction of `(..., f: T => R, ...) => f.apply(..)` into `f` [#19966](https://github.com/lampepfl/dotty/pull/19966) +- Tweak parameter accessor scheme [#19719](https://github.com/lampepfl/dotty/pull/19719) + +## Typer + +- Update phrasing for NotClassType explain error message [#19635](https://github.com/lampepfl/dotty/pull/19635) +- Fix java typer problems with inner class references and raw types [#19747](https://github.com/lampepfl/dotty/pull/19747) +- Approximate MatchTypes with lub of case bodies, if non-recursive [#19761](https://github.com/lampepfl/dotty/pull/19761) +- Revert broken changes with transparent inline [#19922](https://github.com/lampepfl/dotty/pull/19922) +- Delay hard argument comparisons [#20007](https://github.com/lampepfl/dotty/pull/20007) +- Fix #19607: Allow to instantiate *wildcard* type captures to TypeBounds. [#19627](https://github.com/lampepfl/dotty/pull/19627) +- Fix #19907: Skip soft unions in widenSingle of widenInferred [#19995](https://github.com/lampepfl/dotty/pull/19995) +- Fix untupling of functions in for comprehensions [#19620](https://github.com/lampepfl/dotty/pull/19620) + +# Contributors + +Thank you to all the contributors who made this release possible 🎉 + +According to `git shortlog -sn --no-merges 3.4.1..3.4.2` these are: + +``` + 46 Nicolas Stucki + 33 Martin Odersky + 25 Dale Wijnand + 22 Hamza REMMAL + 18 Yichen Xu + 17 Jamie Thompson + 15 Szymon Rodziewicz + 11 EnzeXing + 11 i10416 + 9 Paweł Marks + 6 Kacper Korban + 4 Dan13llljws + 4 Katarzyna Marek + 4 Matt Bovel + 4 Som Snytt + 4 noti0na1 + 3 110416 + 3 Eugene Flesselle + 3 Sébastien Doeraene + 3 dependabot[bot] + 2 Bersier + 2 Hamza Remmal + 2 Jakub Ciesluk + 2 João Costa + 2 Jędrzej Rochala + 2 Natsu Kagami + 2 Stephane Bersier + 2 Taro L. Saito + 2 aherlihy + 1 Aleksander Boruch-Gruszecki + 1 Aviv Keller + 1 Eugene Yokota + 1 Guillaume Martres + 1 Jan Chyb + 1 Lukas Rytz + 1 Mikołaj Fornal + 1 Olga Mazhara + 1 Ondřej Lhoták + 1 Robert Stoll + 1 Seth Tisue + 1 Valentin Schneeberger + 1 Yilin Wei + 1 willerf +``` From 0f7f990b3bc20ad87b163b73ea4c858bff30a77e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Marks?= Date: Mon, 13 May 2024 14:43:17 +0200 Subject: [PATCH 277/277] Release 3.4.2 --- project/Build.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Build.scala b/project/Build.scala index a5569c0d8888..b75bf1778b3f 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -85,7 +85,7 @@ object Build { val referenceVersion = "3.4.1" - val baseVersion = "3.4.2-RC1" + val baseVersion = "3.4.2" // LTS or Next val versionLine = "Next"