Skip to content

Commit

Permalink
Move CrossVersionChecks before FirstTransform (scala#17301)
Browse files Browse the repository at this point in the history
  • Loading branch information
smarter authored Apr 25, 2023
2 parents 824295e + 57c4479 commit bdadfd3
Show file tree
Hide file tree
Showing 12 changed files with 57 additions and 44 deletions.
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/config/PathResolver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/printing/Printer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/printing/Texts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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("")
Expand Down
41 changes: 13 additions & 28 deletions compiler/src/dotty/tools/dotc/typer/CrossVersionChecks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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 = {
Expand Down Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions tests/neg-custom-args/deprecation/14034b.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 2 additions & 2 deletions tests/neg-custom-args/no-experimental/14034.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 7 additions & 0 deletions tests/neg-custom-args/no-experimental/i17292.scala
Original file line number Diff line number Diff line change
@@ -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
21 changes: 21 additions & 0 deletions tests/neg-custom-args/no-experimental/i17292b.scala
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit bdadfd3

Please sign in to comment.