Skip to content

Add language.deprecated.symbolLiterals import #11588

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

Merged
merged 3 commits into from
Mar 5, 2021
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: 4 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -251,14 +251,16 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
case TypeDefs(_) => true
case _ => isUsingClause(params)

private val languageSubCategories = Set(nme.experimental, nme.deprecated)

/** If `path` looks like a language import, `Some(name)` where name
* is `experimental` if that sub-module is imported, and the empty
* term name otherwise.
*/
def languageImport(path: Tree): Option[TermName] = path match
case Select(p1, nme.experimental) =>
case Select(p1, name: TermName) if languageSubCategories.contains(name) =>
languageImport(p1) match
case Some(EmptyTermName) => Some(nme.experimental)
case Some(EmptyTermName) => Some(name)
case _ => None
case p1: RefTree if p1.name == nme.language =>
p1.qualifier match
Expand Down
6 changes: 6 additions & 0 deletions compiler/src/dotty/tools/dotc/config/Feature.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@ object Feature:
private def experimental(str: String): TermName =
QualifiedName(nme.experimental, str.toTermName)

private def deprecated(str: String): TermName =
QualifiedName(nme.deprecated, str.toTermName)

private val Xdependent = experimental("dependent")
private val XnamedTypeArguments = experimental("namedTypeArguments")
private val XgenericNumberLiterals = experimental("genericNumberLiterals")
private val Xmacros = experimental("macros")
private val symbolLiterals: TermName = deprecated("symbolLiterals")

/** Is `feature` enabled by by a command-line setting? The enabling setting is
*
Expand Down Expand Up @@ -64,6 +68,8 @@ object Feature:

def genericNumberLiteralsEnabled(using Context) = enabled(XgenericNumberLiterals)

def symbolLiteralsEnabled(using Context) = enabled(symbolLiterals)

def scala2ExperimentalMacroEnabled(using Context) = enabled(Xmacros)

def sourceVersionSetting(using Context): SourceVersion =
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,7 @@ class Definitions {
@tu lazy val LanguageModule: Symbol = requiredModule("scala.language")
@tu lazy val LanguageModuleClass: Symbol = LanguageModule.moduleClass.asClass
@tu lazy val LanguageExperimentalModule: Symbol = requiredModule("scala.language.experimental")
@tu lazy val LanguageDeprecatedModule: Symbol = requiredModule("scala.language.deprecated")
@tu lazy val NonLocalReturnControlClass: ClassSymbol = requiredClass("scala.runtime.NonLocalReturnControl")
@tu lazy val SelectableClass: ClassSymbol = requiredClass("scala.Selectable")

Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/core/StdNames.scala
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ object StdNames {
val definitions: N = "definitions"
val delayedInit: N = "delayedInit"
val delayedInitArg: N = "delayedInit$body"
val deprecated: N = "deprecated"
val derived: N = "derived"
val derives: N = "derives"
val doubleHash: N = "doubleHash"
Expand Down
46 changes: 25 additions & 21 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,18 @@ import NameKinds.WildcardParamName
import NameOps._
import ast.{Positioned, Trees}
import ast.Trees._
import typer.ImportInfo
import StdNames._
import util.Spans._
import Constants._
import Symbols.defn
import Symbols.{defn, NoSymbol}
import ScriptParsers._
import Decorators._
import util.Chars
import scala.annotation.{tailrec, switch}
import rewrites.Rewrites.{patch, overlapsPatch}
import reporting._
import config.Feature.{sourceVersion, migrateTo3, dependentEnabled}
import config.Feature.{sourceVersion, migrateTo3, dependentEnabled, symbolLiteralsEnabled}
import config.SourceVersion._
import config.SourceVersion

Expand Down Expand Up @@ -492,20 +493,19 @@ object Parsers {
* Parameters appear in reverse order.
*/
var placeholderParams: List[ValDef] = Nil
var languageImportContext: Context = ctx

def checkNoEscapingPlaceholders[T](op: => T): T = {
def checkNoEscapingPlaceholders[T](op: => T): T =
val savedPlaceholderParams = placeholderParams
val savedLanguageImportContext = languageImportContext
placeholderParams = Nil

try op
finally {
placeholderParams match {
finally
placeholderParams match
case vd :: _ => syntaxError(UnboundPlaceholderParameter(), vd.span)
case _ =>
}
placeholderParams = savedPlaceholderParams
}
}
languageImportContext = savedLanguageImportContext

def isWildcard(t: Tree): Boolean = t match {
case Ident(name1) => placeholderParams.nonEmpty && name1 == placeholderParams.head.name
Expand Down Expand Up @@ -1193,17 +1193,19 @@ object Parsers {
in.nextToken()
Quote(t)
}
else {
report.errorOrMigrationWarning(
em"""symbol literal '${in.name} is no longer supported,
|use a string literal "${in.name}" or an application Symbol("${in.name}") instead,
|or enclose in braces '{${in.name}} if you want a quoted expression.""",
in.sourcePos())
if migrateTo3 then
patch(source, Span(in.offset, in.offset + 1), "Symbol(\"")
patch(source, Span(in.charOffset - 1), "\")")
else
if !symbolLiteralsEnabled(using languageImportContext) then
report.errorOrMigrationWarning(
em"""symbol literal '${in.name} is no longer supported,
|use a string literal "${in.name}" or an application Symbol("${in.name}") instead,
|or enclose in braces '{${in.name}} if you want a quoted expression.
|For now, you can also `import language.deprecated.symbolLiterals` to accept
|the idiom, but this possibility might no longer be available in the future.""",
in.sourcePos())
if migrateTo3 then
patch(source, Span(in.offset, in.offset + 1), "Symbol(\"")
patch(source, Span(in.charOffset - 1), "\")")
atSpan(in.skipToken()) { SymbolLit(in.strVal) }
}
else if (in.token == INTERPOLATIONID) interpolatedString(inPattern)
else {
val t = literalOf(in.token)
Expand Down Expand Up @@ -1625,7 +1627,7 @@ object Parsers {
typeIdent()
else
def singletonArgs(t: Tree): Tree =
if in.token == LPAREN && dependentEnabled
if in.token == LPAREN && dependentEnabled(using languageImportContext)
then singletonArgs(AppliedTypeTree(t, inParens(commaSeparated(singleton))))
else t
singletonArgs(simpleType1())
Expand Down Expand Up @@ -3090,7 +3092,9 @@ object Parsers {

/** Create an import node and handle source version imports */
def mkImport(outermost: Boolean = false): ImportConstr = (tree, selectors) =>
val imp = Import(tree, selectors)
if isLanguageImport(tree) then
languageImportContext = languageImportContext.importContext(imp, NoSymbol)
for
case ImportSelector(id @ Ident(imported), EmptyTree, _) <- selectors
if allSourceVersionNames.contains(imported)
Expand All @@ -3101,7 +3105,7 @@ object Parsers {
syntaxError(i"duplicate source version import", id.span)
else
ctx.compilationUnit.sourceVersion = Some(SourceVersion.valueOf(imported.toString))
Import(tree, selectors)
imp

/** ImportExpr ::= SimpleRef {‘.’ id} ‘.’ ImportSpec
* | SimpleRef ‘as’ id
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/typer/Checking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,7 @@ trait Checking {
case Some(prefix) =>
val required =
if prefix == nme.experimental then defn.LanguageExperimentalModule
else if prefix == nme.deprecated then defn.LanguageDeprecatedModule
else defn.LanguageModule
if path.symbol != required then
report.error(em"import looks like a language import, but refers to something else: ${path.symbol.showLocated}", path.srcPos)
Expand Down
16 changes: 16 additions & 0 deletions library/src/scala/runtime/stdLibPatches/language.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,22 @@ object language:
object genericNumberLiterals
end experimental

/** The deprecated object contains features that are no longer officially suypported in Scala.
* Features in this object are slated for removal. New code should not use them and
* old code should migrate away from them.
*/
object deprecated:

/** Symbol literals have been deprecated since 2.13. Since Scala 3.0 they
* are no longer an official part of Scala. For compatibility with legacy software,
* symbol literals are still supported with a language import, but new software
* should not use them.
*/
object symbolLiterals
end deprecated

object symbolLiterals

/** Where imported, auto-tupling is disabled.
*
* '''Why control the feature?''' Auto-tupling can lead to confusing and
Expand Down
5 changes: 5 additions & 0 deletions tests/neg/symlits.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
def f =
import language.deprecated.symbolLiterals
val x = 'Hello

val y = 'no // error