Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move CrossVersionChecks before FirstTransform #17301

Merged
merged 2 commits into from
Apr 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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