From 3133d8541d3767c833024fcbb35b0126708db066 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 18 Apr 2023 17:22:50 +0200 Subject: [PATCH 1/2] Remove references to deprecated classes `scala.{Traversable,TraversableOnce,BufferedIterator}` are deprecated since 2.13.0. It seems these deprecated references where not found when the check was performed after `FirstTransform` as the types might have been dealiased in the `TypeTree`. --- compiler/src/dotty/tools/dotc/config/PathResolver.scala | 2 +- compiler/src/dotty/tools/dotc/core/SymDenotations.scala | 2 +- .../dotty/tools/dotc/parsing/xml/MarkupParserCommon.scala | 3 +-- .../src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala | 1 + compiler/src/dotty/tools/dotc/printing/Printer.scala | 6 +++--- compiler/src/dotty/tools/dotc/printing/Texts.scala | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/PathResolver.scala b/compiler/src/dotty/tools/dotc/config/PathResolver.scala index afa30e38dc2a..8b4eedb0e9d2 100644 --- a/compiler/src/dotty/tools/dotc/config/PathResolver.scala +++ b/compiler/src/dotty/tools/dotc/config/PathResolver.scala @@ -211,7 +211,7 @@ class PathResolver(using c: Context) { import classPathFactory._ // Assemble the elements! - def basis: List[Traversable[ClassPath]] = + def basis: List[Iterable[ClassPath]] = val release = Option(ctx.settings.javaOutputVersion.value).filter(_.nonEmpty) List( diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index beeaa2ee922e..aac1760fb1f7 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -299,7 +299,7 @@ object SymDenotations { } /** Add all given annotations to this symbol */ - final def addAnnotations(annots: TraversableOnce[Annotation])(using Context): Unit = + final def addAnnotations(annots: IterableOnce[Annotation])(using Context): Unit = annots.iterator.foreach(addAnnotation) @tailrec diff --git a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParserCommon.scala b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParserCommon.scala index 2c6c5361e51c..0f7d426fbd28 100644 --- a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParserCommon.scala +++ b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParserCommon.scala @@ -11,8 +11,7 @@ package xml import Utility._ import util.Chars.SU - - +import scala.collection.BufferedIterator /** This is not a public trait - it contains common code shared * between the library level XML parser and the compiler's. diff --git a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala index 77c5a1bf376b..b3f41fab9eaa 100644 --- a/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/xml/MarkupParsers.scala @@ -6,6 +6,7 @@ package xml import scala.language.unsafeNulls import scala.collection.mutable +import scala.collection.BufferedIterator import core.Contexts.Context import mutable.{ Buffer, ArrayBuffer, ListBuffer } import scala.util.control.ControlThrowable diff --git a/compiler/src/dotty/tools/dotc/printing/Printer.scala b/compiler/src/dotty/tools/dotc/printing/Printer.scala index 326630844dde..697ab063a646 100644 --- a/compiler/src/dotty/tools/dotc/printing/Printer.scala +++ b/compiler/src/dotty/tools/dotc/printing/Printer.scala @@ -174,15 +174,15 @@ abstract class Printer { atPrec(GlobalPrec) { elem.toText(this) } /** Render elements alternating with `sep` string */ - def toText(elems: Traversable[Showable], sep: String): Text = + def toText(elems: Iterable[Showable], sep: String): Text = Text(elems map (_ toText this), sep) /** Render elements within highest precedence */ - def toTextLocal(elems: Traversable[Showable], sep: String): Text = + def toTextLocal(elems: Iterable[Showable], sep: String): Text = atPrec(DotPrec) { toText(elems, sep) } /** Render elements within lowest precedence */ - def toTextGlobal(elems: Traversable[Showable], sep: String): Text = + def toTextGlobal(elems: Iterable[Showable], sep: String): Text = atPrec(GlobalPrec) { toText(elems, sep) } /** A plain printer without any embellishments */ diff --git a/compiler/src/dotty/tools/dotc/printing/Texts.scala b/compiler/src/dotty/tools/dotc/printing/Texts.scala index 7c040a78de5e..475e2c6900d5 100644 --- a/compiler/src/dotty/tools/dotc/printing/Texts.scala +++ b/compiler/src/dotty/tools/dotc/printing/Texts.scala @@ -173,7 +173,7 @@ object Texts { /** A concatenation of elements in `xs` and interspersed with * separator strings `sep`. */ - def apply(xs: Traversable[Text], sep: String = " "): Text = + def apply(xs: Iterable[Text], sep: String = " "): Text = if (sep == "\n") lines(xs) else { val ys = xs.filterNot(_.isEmpty) @@ -182,7 +182,7 @@ object Texts { } /** The given texts `xs`, each on a separate line */ - def lines(xs: Traversable[Text]): Vertical = Vertical(xs.toList.reverse) + def lines(xs: Iterable[Text]): Vertical = Vertical(xs.toList.reverse) extension (text: => Text) def provided(cond: Boolean): Text = if (cond) text else Str("") From 57c44794449ed53b4bd287960eec69f07d6be6b6 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 18 Apr 2023 16:17:36 +0200 Subject: [PATCH 2/2] Move CrossVersionChecks before FirstTransform Fixes #17292 --- compiler/src/dotty/tools/dotc/Compiler.scala | 6 +-- .../tools/dotc/typer/CrossVersionChecks.scala | 41 ++++++------------- .../neg-custom-args/deprecation/14034b.scala | 4 +- .../no-experimental/14034.scala | 4 +- .../no-experimental/i17292.scala | 7 ++++ .../no-experimental/i17292b.scala | 21 ++++++++++ 6 files changed, 48 insertions(+), 35 deletions(-) create mode 100644 tests/neg-custom-args/no-experimental/i17292.scala create mode 100644 tests/neg-custom-args/no-experimental/i17292b.scala diff --git a/compiler/src/dotty/tools/dotc/Compiler.scala b/compiler/src/dotty/tools/dotc/Compiler.scala index b0f7b0a533d7..a6118732d4ae 100644 --- a/compiler/src/dotty/tools/dotc/Compiler.scala +++ b/compiler/src/dotty/tools/dotc/Compiler.scala @@ -59,7 +59,8 @@ class Compiler { /** Phases dealing with the transformation from pickled trees to backend trees */ protected def transformPhases: List[List[Phase]] = List(new InstrumentCoverage) :: // Perform instrumentation for code coverage (if -coverage-out is set) - List(new FirstTransform, // Some transformations to put trees into a canonical form + List(new CrossVersionChecks, // Check issues related to deprecated and experimental + new FirstTransform, // Some transformations to put trees into a canonical form new CheckReentrant, // Internal use only: Check that compiled program has no data races involving global vars new ElimPackagePrefixes, // Eliminate references to package prefixes in Select nodes new CookComments, // Cook the comments: expand variables, doc, etc. @@ -71,8 +72,7 @@ class Compiler { new ElimRepeated, // Rewrite vararg parameters and arguments new RefChecks) :: // Various checks mostly related to abstract members and overriding List(new init.Checker) :: // Check initialization of objects - List(new CrossVersionChecks, // Check issues related to deprecated and experimental - new ProtectedAccessors, // Add accessors for protected members + List(new ProtectedAccessors, // Add accessors for protected members new ExtensionMethods, // Expand methods of value classes with extension methods new UncacheGivenAliases, // Avoid caching RHS of simple parameterless given aliases new ElimByName, // Map by-name parameters to functions diff --git a/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala b/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala index ef9599be551c..0d68b0b1f766 100644 --- a/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala @@ -18,9 +18,6 @@ class CrossVersionChecks extends MiniPhase: override def description: String = CrossVersionChecks.description - override def runsAfterGroupsOf: Set[String] = Set(FirstTransform.name) - // We assume all type trees except TypeTree have been eliminated - // Note: if a symbol has both @deprecated and @migration annotations and both // warnings are enabled, only the first one checked here will be emitted. // I assume that's a consequence of some code trying to avoid noise by suppressing @@ -69,18 +66,8 @@ class CrossVersionChecks extends MiniPhase: val since = annot.argumentConstant(1).map(" since " + _.stringValue).getOrElse("") report.deprecationWarning(em"${sym.showLocated} is deprecated${since}${msg}", pos) - private def checkExperimentalSignature(sym: Symbol, pos: SrcPos)(using Context): Unit = - class Checker extends TypeTraverser: - def traverse(tp: Type): Unit = - if tp.typeSymbol.isExperimental then - Feature.checkExperimentalDef(tp.typeSymbol, pos) - else - traverseChildren(tp) - if !sym.isInExperimentalScope then - new Checker().traverse(sym.info) - private def checkExperimentalAnnots(sym: Symbol)(using Context): Unit = - if !sym.isInExperimentalScope then + if sym.exists && !sym.isInExperimentalScope then for annot <- sym.annotations if annot.symbol.isExperimental do Feature.checkExperimentalDef(annot.symbol, annot.tree) @@ -119,13 +106,16 @@ class CrossVersionChecks extends MiniPhase: override def transformValDef(tree: ValDef)(using Context): ValDef = checkDeprecatedOvers(tree) checkExperimentalAnnots(tree.symbol) - checkExperimentalSignature(tree.symbol, tree) tree override def transformDefDef(tree: DefDef)(using Context): DefDef = checkDeprecatedOvers(tree) checkExperimentalAnnots(tree.symbol) - checkExperimentalSignature(tree.symbol, tree) + tree + + override def transformTypeDef(tree: TypeDef)(using Context): TypeDef = + // TODO do we need to check checkDeprecatedOvers(tree)? + checkExperimentalAnnots(tree.symbol) tree override def transformIdent(tree: Ident)(using Context): Ident = { @@ -157,19 +147,14 @@ class CrossVersionChecks extends MiniPhase: tree } - override def transformTypeDef(tree: TypeDef)(using Context): TypeDef = { - checkExperimentalAnnots(tree.symbol) + override def transformOther(tree: Tree)(using Context): Tree = + tree.foreachSubTree { // Find references in type trees and imports + case tree: Ident => transformIdent(tree) + case tree: Select => transformSelect(tree) + case tree: TypeTree => transformTypeTree(tree) + case _ => + } tree - } - - override def transformOther(tree: Tree)(using Context): Tree = tree match - case tree: Import => - tree.foreachSubTree { - case t: RefTree => checkUndesiredProperties(t.symbol, t.srcPos) - case _ => - } - tree - case _ => tree end CrossVersionChecks diff --git a/tests/neg-custom-args/deprecation/14034b.scala b/tests/neg-custom-args/deprecation/14034b.scala index d22a945fe10d..07960bba9574 100644 --- a/tests/neg-custom-args/deprecation/14034b.scala +++ b/tests/neg-custom-args/deprecation/14034b.scala @@ -9,6 +9,6 @@ type Foo0 = Exp // error type Foo = Option[Exp] // error type Bar = Option[exp.type] // error type Baz = Exp | Int // error -type Quux = [X] =>> X match // error - case Exp => Int +type Quux = [X] =>> X match + case Exp => Int // error type Quuz[A <: Exp] = Int // error diff --git a/tests/neg-custom-args/no-experimental/14034.scala b/tests/neg-custom-args/no-experimental/14034.scala index c0b4cc6899db..ab824c43395e 100644 --- a/tests/neg-custom-args/no-experimental/14034.scala +++ b/tests/neg-custom-args/no-experimental/14034.scala @@ -7,6 +7,6 @@ type Foo0 = Exp // error type Foo = Option[Exp] // error type Bar = Option[exp.type] // error type Baz = Exp | Int // error -type Quux = [X] =>> X match // error - case Exp => Int +type Quux = [X] =>> X match + case Exp => Int // error type Quuz[A <: Exp] = Int // error diff --git a/tests/neg-custom-args/no-experimental/i17292.scala b/tests/neg-custom-args/no-experimental/i17292.scala new file mode 100644 index 000000000000..381d252dbea8 --- /dev/null +++ b/tests/neg-custom-args/no-experimental/i17292.scala @@ -0,0 +1,7 @@ +import annotation.experimental + +class Foo { @experimental type Bar = (Int, String) } + +val f: Foo = Foo() + +def g: Tuple.Elem[f.Bar, 0] = ??? // error diff --git a/tests/neg-custom-args/no-experimental/i17292b.scala b/tests/neg-custom-args/no-experimental/i17292b.scala new file mode 100644 index 000000000000..f644dd60ecd5 --- /dev/null +++ b/tests/neg-custom-args/no-experimental/i17292b.scala @@ -0,0 +1,21 @@ +import annotation.experimental +type A[T] = Int +class Foo { + @experimental type Bar = (Int, String) +} + +type Elem1[X <: Tuple, N <: Int] = X match { case x *: xs => N match { case 0 => x } } +type Elem2[X <: Tuple, N <: Int] + +val f: Foo = Foo() + +def bar1: f.Bar = ??? // error +def bar2 = // error + ??? : f.Bar // error + +def g0: Elem1[f.Bar, 0] = ??? // error +def g1(a: Elem1[f.Bar, 0]) = ??? // error +def g2 = + ??? : Elem1[f.Bar, 0] // error + +def h: Elem2[f.Bar, 0] = ??? // error