diff options
author | Martin Odersky <odersky@gmail.com> | 2012-04-12 18:56:20 -0700 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2012-04-12 18:56:20 -0700 |
commit | a7a1e3a1959f26c9b44b40b328ef217b4ebdbaba (patch) | |
tree | 62e2b8b9149e9b62621591c1bfc1b6ffb0170c53 /src/compiler/scala | |
parent | 6061a22fcd3480e18e60254ad06c8a46b2f1ce53 (diff) | |
download | scala-a7a1e3a1959f26c9b44b40b328ef217b4ebdbaba.tar.gz scala-a7a1e3a1959f26c9b44b40b328ef217b4ebdbaba.tar.bz2 scala-a7a1e3a1959f26c9b44b40b328ef217b4ebdbaba.zip |
Various improvements to SIP 18 diagnostics. Made scala library and compiler feature clean.
Diffstat (limited to 'src/compiler/scala')
50 files changed, 142 insertions, 85 deletions
diff --git a/src/compiler/scala/reflect/internal/Names.scala b/src/compiler/scala/reflect/internal/Names.scala index 5f38374f20..d2b55d9d39 100644 --- a/src/compiler/scala/reflect/internal/Names.scala +++ b/src/compiler/scala/reflect/internal/Names.scala @@ -8,6 +8,7 @@ package internal import scala.io.Codec import java.security.MessageDigest +import language.implicitConversions /** The class Names ... * diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala index 1666887133..3679daa9a2 100644 --- a/src/compiler/scala/reflect/internal/StdNames.scala +++ b/src/compiler/scala/reflect/internal/StdNames.scala @@ -9,12 +9,13 @@ package internal import scala.collection.immutable import NameTransformer.MODULE_SUFFIX_STRING import annotation.switch +import language.implicitConversions trait StdNames extends NameManglers { self: SymbolTable => def encode(str: String): TermName = newTermNameCached(NameTransformer.encode(str)) - implicit def lowerTermNames(n: TermName): String = "" + n + implicit def lowerTermNames(n: TermName): String = n.toString // implicit def stringToTermName(s: String): TermName = newTermName(s) @@ -56,6 +57,7 @@ trait StdNames extends NameManglers { self: SymbolTable => final val RETURNkw: TermName = kw("return") final val SEALEDkw: TermName = kw("sealed") final val SUPERkw: TermName = kw("super") + final val THENkw: TermName = kw("then") final val THISkw: TermName = kw("this") final val THROWkw: TermName = kw("throw") final val TRAITkw: TermName = kw("trait") diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala index ffc8178528..9f67c5aa01 100644 --- a/src/compiler/scala/reflect/internal/SymbolTable.scala +++ b/src/compiler/scala/reflect/internal/SymbolTable.scala @@ -260,6 +260,8 @@ abstract class SymbolTable extends api.Universe import java.lang.ref.WeakReference import scala.runtime.ScalaRunTime.stringOf + import language.reflectiveCalls + // We can allow ourselves a structural type, these methods // amount to a few calls per run at most. This does suggest // a "Clearable" trait may be useful. diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index fc94e96acd..78d0ebbc67 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -850,6 +850,16 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isStructuralRefinement: Boolean = (isClass || isType || isModule) && info.normalize/*.underlying*/.isStructuralRefinement + /** Is this a term symbol only defined in a refinement (so that it needs + * to be accessed by reflection)? + */ + def isOnlyRefinementMember: Boolean = + isTerm && // type members are not affected + owner.isRefinementClass && // owner must be a refinement class + (owner.info decl name) == this && // symbol must be explicitly declared in the refinement (not synthesized from glb) + allOverriddenSymbols.isEmpty && // symbol must not override a symbol in a base class + !isConstant // symbol must not be a constant. Question: Can we exclude @inline methods as well? + final def isStructuralRefinementMember = owner.isStructuralRefinement && isPossibleInRefinement && isPublic final def isPossibleInRefinement = !isConstructor && !isOverridingSymbol @@ -1751,7 +1761,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => } else owner.enclosingTopLevelClass /** Is this symbol defined in the same scope and compilation unit as `that` symbol? */ - def isCoDefinedWith(that: Symbol) = ( + def isCoDefinedWith(that: Symbol) = { + import language.reflectiveCalls (this.rawInfo ne NoType) && (this.effectiveOwner == that.effectiveOwner) && { !this.effectiveOwner.isPackageClass || @@ -1770,7 +1781,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => false } } - ) + } /** The internal representation of classes and objects: * @@ -3093,10 +3104,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => if (settings.debug.value) printStackTrace() } - case class InvalidCompanions(sym1: Symbol, sym2: Symbol) extends Throwable( + case class InvalidCompanions(sym1: Symbol, sym2: Symbol) extends Throwable({ + import language.reflectiveCalls "Companions '" + sym1 + "' and '" + sym2 + "' must be defined in same file:\n" + " Found in " + sym1.sourceFile.canonicalPath + " and " + sym2.sourceFile.canonicalPath - ) { + }) { override def toString = getMessage } diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala index 0d7e68aee3..0413fd9896 100644 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ b/src/compiler/scala/reflect/internal/Trees.scala @@ -103,9 +103,7 @@ trait Trees extends api.Trees { self: SymbolTable => // --- extension methods -------------------------------------------------------- - implicit def treeOps(tree: Tree): TreeOps = new TreeOps(tree) - - class TreeOps(tree: Tree) { + implicit class TreeOps(tree: Tree) { def isErroneous = (tree.tpe ne null) && tree.tpe.isErroneous def isTyped = (tree.tpe ne null) && !tree.tpe.isErroneous diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index 797b5db127..c13a33a6fc 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -712,7 +712,9 @@ trait Types extends api.Types { self: SymbolTable => /** Returns all parts of this type which satisfy predicate `p` */ def filter(p: Type => Boolean): List[Type] = new FilterTypeCollector(p) collect this - def withFilter(p: Type => Boolean) = new FilterTypeCollector(p) { + def withFilter(p: Type => Boolean) = new FilterMapForeach(p) + + class FilterMapForeach(p: Type => Boolean) extends FilterTypeCollector(p){ def foreach[U](f: Type => U): Unit = collect(Type.this) foreach f def map[T](f: Type => T): List[T] = collect(Type.this) map f } @@ -2538,12 +2540,11 @@ trait Types extends api.Types { self: SymbolTable => val qset = quantified.toSet underlying match { case TypeRef(_, sym, args) => - sameLength(args, quantified) && { - args forall { arg => - qset(arg.typeSymbol) && - (!checkBounds || !qset.exists(arg.typeSymbol.info.bounds contains _)) - } - } + def isQuantified(tpe: Type) = tpe exists (t => quantified contains t.typeSymbol) + val (wildcardArgs, otherArgs) = args partition (arg => qset contains arg.typeSymbol) + wildcardArgs.distinct == wildcardArgs && + !(otherArgs exists (arg => isQuantified(arg))) && + !(wildcardArgs exists (arg => isQuantified(arg.typeSymbol.info.bounds))) case _ => false } } diff --git a/src/compiler/scala/reflect/reify/phases/Calculate.scala b/src/compiler/scala/reflect/reify/phases/Calculate.scala index 59a36f0ba4..e4f3fce407 100644 --- a/src/compiler/scala/reflect/reify/phases/Calculate.scala +++ b/src/compiler/scala/reflect/reify/phases/Calculate.scala @@ -8,14 +8,12 @@ trait Calculate { import definitions._ import treeInfo._ - implicit def sym2richSym(sym: Symbol): RichSymbol = new RichSymbol(sym) - class RichSymbol(sym: Symbol) { + implicit class RichSymbol(sym: Symbol) { def metalevel: Int = { assert(sym != NoSymbol); localSymbols.getOrElse(sym, 0) } def isLocalToReifee = (localSymbols contains sym) // [Eugene] how do I account for local skolems? } - implicit def tpe2richTpe(tpe: Type): RichType = new RichType(tpe) - class RichType(tpe: Type) { + implicit class RichType(tpe: Type) { def isLocalToReifee = tpe != null && (tpe exists (tp => (localSymbols contains tp.typeSymbol) || (localSymbols contains tp.termSymbol))) } @@ -58,4 +56,4 @@ trait Calculate { super.traverse(tree) } } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala index 27722a99c9..92a0efff1e 100644 --- a/src/compiler/scala/tools/nsc/CompilationUnits.scala +++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala @@ -88,12 +88,10 @@ trait CompilationUnits { self: Global => reporter.warning(pos, msg) def deprecationWarning(pos: Position, msg: String) = - if (opt.deprecation) warning(pos, msg) - else currentRun.deprecationWarnings ::= ((pos, msg)) + currentRun.deprecationWarnings.warn(pos, msg) def uncheckedWarning(pos: Position, msg: String) = - if (opt.unchecked) warning(pos, msg) - else currentRun.uncheckedWarnings ::= ((pos, msg)) + currentRun.uncheckedWarnings.warn(pos, msg) def incompleteInputError(pos: Position, msg:String) = reporter.incompleteInputError(pos, msg) diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index b7d7f5d16f..228496515b 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -938,6 +938,17 @@ class Global(var currentSettings: Settings, var reporter: NscReporter) extends S inform("[running phase " + ph.name + " on " + currentRun.size + " compilation units]") } + /** Collects for certain classes of warnings during this run. */ + class ConditionalWarning(what: String, option: Settings#BooleanSetting) { + val warnings = new mutable.ListBuffer[(Position, String)] + def warn(pos: Position, msg: String) = + if (option.value) reporter.warning(pos, msg) + else warnings += ((pos, msg)) + def summarize() = + if (option.isDefault && warnings.nonEmpty) + reporter.warning(NoPosition, "there were %d %s warnings; re-run with %s for details".format(warnings.size, what, option.name)) + } + /** A Run is a single execution of the compiler on a sets of units */ class Run { @@ -949,9 +960,12 @@ class Global(var currentSettings: Settings, var reporter: NscReporter) extends S /** The currently compiled unit; set from GlobalPhase */ var currentUnit: CompilationUnit = NoCompilationUnit - /** Counts for certain classes of warnings during this run. */ - var deprecationWarnings: List[(Position, String)] = Nil - var uncheckedWarnings: List[(Position, String)] = Nil + val deprecationWarnings = new ConditionalWarning("deprecation", settings.deprecation) + val uncheckedWarnings = new ConditionalWarning("unchecked", settings.unchecked) + val featureWarnings = new ConditionalWarning("feature", settings.feature) + val allConditionalWarnings = List(deprecationWarnings, uncheckedWarnings, featureWarnings) + + var reportedFeature = Set[Symbol]() /** A flag whether macro expansions failed */ var macroExpansionFailed = false @@ -1241,12 +1255,8 @@ class Global(var currentSettings: Settings, var reporter: NscReporter) extends S } } else { - def warn(count: Int, what: String, option: Settings#BooleanSetting) = ( - if (option.isDefault && count > 0) - warning("there were %d %s warnings; re-run with %s for details".format(count, what, option.name)) - ) - warn(deprecationWarnings.size, "deprecation", settings.deprecation) - warn(uncheckedWarnings.size, "unchecked", settings.unchecked) + allConditionalWarnings foreach (_.summarize) + if (macroExpansionFailed) warning("some macros could not be expanded and code fell back to overridden methods;"+ "\nrecompiling with generated classfiles on the classpath might help.") diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala index 3302c11127..b4beb231ab 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala @@ -18,6 +18,7 @@ import scala.concurrent.Lock import scala.text._ import symtab.Flags._ import symtab.SymbolTable +import language.implicitConversions /** * Tree browsers can show the AST in a graphical and interactive diff --git a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala index 2b75925d9a..283bdecf26 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala @@ -9,6 +9,7 @@ package ast import PartialFunction._ import symtab.Flags +import language.implicitConversions /** A DSL for generating scala code. The goal is that the * code generating code should look a lot like the code it diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 978640b4a5..431f0593b9 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -2490,7 +2490,8 @@ self => blockExpr() } else { accept(EQUALS) - if (settings.Xmacros.value && in.token == MACRO) { + if (settings.Xmacros.value && in.token == MACRO || // [Martin] Xmacros can be retired now + in.token == IDENTIFIER && in.name == nme.MACROkw) { in.nextToken() newmods |= Flags.MACRO } diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index 81d81a4fb7..fa63ea33d0 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -119,6 +119,16 @@ trait Scanners extends ScannersCommon { cbuf.clear() } + /** Convert name to token */ + private def name2token(name: Name) = { + val idx = name.start - kwOffset + if (idx >= 0 && idx < kwArray.length) { + val token = kwArray(idx) + if (token == IDENTIFIER) deprecationWarning(name+" is now a reserved word; usage as an identifier is deprecated") + token + } else IDENTIFIER + } + /** Clear buffer and set string */ private def setStrVal() { strVal = cbuf.toString @@ -1124,9 +1134,9 @@ trait Scanners extends ScannersCommon { nme.VIEWBOUNDkw -> VIEWBOUND, nme.SUPERTYPEkw -> SUPERTYPE, nme.HASHkw -> HASH, - nme.ATkw -> AT - ) ++ - (if (settings.Xmacros.value) List(nme.MACROkw -> MACRO) else List()) + nme.ATkw -> AT, + nme.MACROkw -> IDENTIFIER, + nme.THENkw -> IDENTIFIER) private var kwOffset: Int = -1 private val kwArray: Array[Int] = { @@ -1137,13 +1147,6 @@ trait Scanners extends ScannersCommon { final val token2name = allKeywords map (_.swap) toMap - /** Convert name to token */ - final def name2token(name: Name) = { - val idx = name.start - kwOffset - if (idx >= 0 && idx < kwArray.length) kwArray(idx) - else IDENTIFIER - } - // Token representation ---------------------------------------------------- /** Returns the string representation of given token. */ diff --git a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala index 849437e4ff..0f2a3e0395 100755 --- a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala @@ -11,6 +11,7 @@ import xml.{ EntityRef, Text } import xml.XML.{ xmlns } import symtab.Flags.MUTABLE import scala.tools.util.StringOps.splitWhere +import language.implicitConversions /** This class builds instance of `Tree` that represent XML. * diff --git a/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala b/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala index e17bbf5e46..a4a062609b 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala @@ -110,7 +110,8 @@ object Tokens extends Tokens { final val MATCH = 58 final val FORSOME = 59 final val LAZY = 61 - final val MACRO = 62 + final val MACRO = 62 // not yet used in 2.10 + final val THEN = 63 // not yet used in 2.10 def isKeyword(code: Int) = code >= IF && code <= LAZY diff --git a/src/compiler/scala/tools/nsc/doc/Uncompilable.scala b/src/compiler/scala/tools/nsc/doc/Uncompilable.scala index 9b29ebd745..e9e243171e 100644 --- a/src/compiler/scala/tools/nsc/doc/Uncompilable.scala +++ b/src/compiler/scala/tools/nsc/doc/Uncompilable.scala @@ -5,6 +5,7 @@ package scala.tools.nsc package doc +import language.implicitConversions /** Some glue between DocParser (which reads source files which can't be compiled) * and the scaladoc model. diff --git a/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala index ef3c2beffb..6392de22ff 100755 --- a/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala @@ -8,6 +8,7 @@ package doc package model import scala.collection._ +import language.reflectiveCalls object IndexModelFactory { @@ -15,7 +16,7 @@ object IndexModelFactory { lazy val firstLetterIndex: Map[Char, SymbolMap] = { - val result = new mutable.HashMap[Char,SymbolMap] { + object result extends mutable.HashMap[Char,SymbolMap] { /* Owner template ordering */ implicit def orderingSet = math.Ordering.String.on { x: MemberEntity => x.name.toLowerCase } diff --git a/src/compiler/scala/tools/nsc/interactive/BuildManager.scala b/src/compiler/scala/tools/nsc/interactive/BuildManager.scala index 2ef34cdd96..0f89236861 100644 --- a/src/compiler/scala/tools/nsc/interactive/BuildManager.scala +++ b/src/compiler/scala/tools/nsc/interactive/BuildManager.scala @@ -13,6 +13,7 @@ import util.FakePos import dependencies._ import io.AbstractFile +import language.implicitConversions trait BuildManager { diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala index 7233b11701..ec73af4dca 100644 --- a/src/compiler/scala/tools/nsc/interactive/Global.scala +++ b/src/compiler/scala/tools/nsc/interactive/Global.scala @@ -19,6 +19,7 @@ import scala.tools.nsc.io.Pickler._ import scala.tools.nsc.typechecker.DivergentImplicit import scala.annotation.tailrec import symtab.Flags.{ACCESSOR, PARAMACCESSOR} +import language.implicitConversions /** The main class of the presentation compiler in an interactive environment such as an IDE */ diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala index 108d4377a8..bf386d8a12 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala @@ -23,6 +23,7 @@ import scala.reflect.NameTransformer._ import util.ScalaClassLoader import ScalaClassLoader._ import scala.tools.util._ +import language.{implicitConversions, existentials} /** The Scala interactive shell. It provides a read-eval-print loop * around the Interpreter class. diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala index c0f7d8412a..43e01bebfd 100644 --- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala +++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala @@ -24,6 +24,7 @@ import scala.collection.{ mutable, immutable } import scala.util.control.Exception.{ ultimately } import IMain._ import java.util.concurrent.Future +import language.implicitConversions /** directory to save .class files to */ private class ReplVirtualDirectory(out: JPrintWriter) extends VirtualDirectory("(memory)", None) { @@ -203,8 +204,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends }).toList } - implicit def installReplTypeOps(tp: Type): ReplTypeOps = new ReplTypeOps(tp) - class ReplTypeOps(tp: Type) { + implicit class ReplTypeOps(tp: Type) { def orElse(other: => Type): Type = if (tp ne NoType) tp else other def andAlso(fn: Type => Type): Type = if (tp eq NoType) tp else fn(tp) } @@ -825,7 +825,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends } def lastWarnings: List[(Position, String)] = ( if (lastRun == null) Nil - else removeDupWarnings(lastRun.deprecationWarnings.reverse) ++ lastRun.uncheckedWarnings.reverse + else removeDupWarnings(lastRun.allConditionalWarnings flatMap (_.warnings)) ) private var lastRun: Run = _ private def evalMethod(name: String) = evalClass.getMethods filter (_.getName == name) match { diff --git a/src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala b/src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala index 9469baa4e2..3520a60ee5 100644 --- a/src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala +++ b/src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala @@ -8,6 +8,7 @@ package interpreter import collection.{ mutable, immutable } import mutable.ListBuffer +import language.implicitConversions class ProcessResult(val line: String) { import sys.process._ diff --git a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala index 68bfeafbc6..d617215452 100644 --- a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala +++ b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala @@ -9,6 +9,7 @@ package interpreter import scala.collection.{ mutable, immutable } import scala.PartialFunction.cond import scala.reflect.internal.Chars +import language.implicitConversions trait MemberHandlers { val intp: IMain diff --git a/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala b/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala index e92888d89b..e2b1bf34d6 100644 --- a/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala +++ b/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala @@ -7,6 +7,7 @@ package scala.tools.nsc package interpreter import NamedParam._ +import language.implicitConversions trait NamedParamCreator { protected def freshName: () => String @@ -43,4 +44,4 @@ trait NamedParam { def tpe: String def value: Any override def toString = name + ": " + tpe -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/interpreter/Phased.scala b/src/compiler/scala/tools/nsc/interpreter/Phased.scala index d164d1cbb0..f39c025a86 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Phased.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Phased.scala @@ -7,6 +7,7 @@ package scala.tools.nsc package interpreter import scala.collection.{ mutable, immutable } +import language.implicitConversions /** Mix this into an object and use it as a phasing * swiss army knife. diff --git a/src/compiler/scala/tools/nsc/interpreter/Power.scala b/src/compiler/scala/tools/nsc/interpreter/Power.scala index cc06100f5f..ecf9dd219b 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Power.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Power.scala @@ -13,6 +13,7 @@ import session.{ History } import scala.io.Codec import java.net.{ URL, MalformedURLException } import io.{ Path } +import language.implicitConversions /** Collecting some power mode examples. diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplTokens.scala b/src/compiler/scala/tools/nsc/interpreter/ReplTokens.scala index 1c7b256c33..e63fabf151 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ReplTokens.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ReplTokens.scala @@ -9,6 +9,7 @@ package interpreter import util.{ BatchSourceFile, Indenter } import scala.tools.nsc.ast.parser.Tokens._ import java.lang.Integer.toOctalString +import language.{implicitConversions, existentials} /** This began as an attempt at a completely minimal * pretty printer for a token stream, but as it turns out diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala b/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala index e293c0fed9..8b891e0010 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala @@ -6,6 +6,8 @@ package scala.tools.nsc package interpreter +import language.implicitConversions + /** A class which the repl utilizes to expose predefined objects. * The base implementation is empty; the standard repl implementation * is StdReplVals. diff --git a/src/compiler/scala/tools/nsc/interpreter/package.scala b/src/compiler/scala/tools/nsc/interpreter/package.scala index e78e92c8f8..e35b4e3103 100644 --- a/src/compiler/scala/tools/nsc/interpreter/package.scala +++ b/src/compiler/scala/tools/nsc/interpreter/package.scala @@ -5,6 +5,8 @@ package scala.tools.nsc +import language.implicitConversions + /** The main REPL related classes and values are as follows. * In addition to standard compiler classes Global and Settings, there are: * diff --git a/src/compiler/scala/tools/nsc/interpreter/session/package.scala b/src/compiler/scala/tools/nsc/interpreter/session/package.scala index 8fbba2f05e..4e5b08c8cb 100644 --- a/src/compiler/scala/tools/nsc/interpreter/session/package.scala +++ b/src/compiler/scala/tools/nsc/interpreter/session/package.scala @@ -5,6 +5,7 @@ package scala.tools.nsc package interpreter +import language.implicitConversions /** Files having to do with the state of a repl session: * lines of text entered, types and terms defined, etc. diff --git a/src/compiler/scala/tools/nsc/io/File.scala b/src/compiler/scala/tools/nsc/io/File.scala index cc512493d9..06cb20e4ac 100644 --- a/src/compiler/scala/tools/nsc/io/File.scala +++ b/src/compiler/scala/tools/nsc/io/File.scala @@ -15,6 +15,7 @@ import java.io.{ BufferedInputStream, BufferedOutputStream, IOException, PrintStream, PrintWriter, Closeable => JCloseable } import java.nio.channels.{ Channel, FileChannel } import scala.io.Codec +import language.{reflectiveCalls, implicitConversions} object File { def pathSeparator = java.io.File.pathSeparator diff --git a/src/compiler/scala/tools/nsc/io/Jar.scala b/src/compiler/scala/tools/nsc/io/Jar.scala index bbed5a9e20..b322df986c 100644 --- a/src/compiler/scala/tools/nsc/io/Jar.scala +++ b/src/compiler/scala/tools/nsc/io/Jar.scala @@ -11,6 +11,7 @@ import java.util.jar._ import collection.JavaConverters._ import Attributes.Name import util.ClassPath +import language.implicitConversions // Attributes.Name instances: // diff --git a/src/compiler/scala/tools/nsc/io/Path.scala b/src/compiler/scala/tools/nsc/io/Path.scala index a1b8e5e4d5..b8cf15bfcf 100644 --- a/src/compiler/scala/tools/nsc/io/Path.scala +++ b/src/compiler/scala/tools/nsc/io/Path.scala @@ -11,6 +11,7 @@ import java.io.{ BufferedInputStream, BufferedOutputStream, RandomAccessFile } import java.net.{ URI, URL } import scala.util.Random.alphanumeric +import language.implicitConversions /** An abstraction for filesystem paths. The differences between * Path, File, and Directory are primarily to communicate intent. diff --git a/src/compiler/scala/tools/nsc/io/Pickler.scala b/src/compiler/scala/tools/nsc/io/Pickler.scala index 80b6e086da..86c7ca7b9a 100644 --- a/src/compiler/scala/tools/nsc/io/Pickler.scala +++ b/src/compiler/scala/tools/nsc/io/Pickler.scala @@ -3,6 +3,7 @@ package scala.tools.nsc.io import annotation.unchecked import Lexer._ import java.io.Writer +import language.implicitConversions /** An abstract class for writing and reading Scala objects to and * from a legible representation. The presesentation follows the following grammar: @@ -168,14 +169,11 @@ object Pickler { case class ~[+S, +T](fst: S, snd: T) /** A wrapper class to be able to use `~` s an infix method */ - class TildeDecorator[S](x: S) { + implicit class TildeDecorator[S](x: S) { /** Infix method that forms a `~`-pair. */ def ~ [T](y: T): S ~ T = new ~ (x, y) } - /** An implicit wrapper that adds `~` as a method to any value. */ - implicit def tildeDecorator[S](x: S): TildeDecorator[S] = new TildeDecorator(x) - /** A converter from binary functions to functions over `~`-pairs */ implicit def fromTilde[T1, T2, R](f: (T1, T2) => R): T1 ~ T2 => R = { case x1 ~ x2 => f(x1, x2) } diff --git a/src/compiler/scala/tools/nsc/io/package.scala b/src/compiler/scala/tools/nsc/io/package.scala index 88679e6dce..8ea14e7f8b 100644 --- a/src/compiler/scala/tools/nsc/io/package.scala +++ b/src/compiler/scala/tools/nsc/io/package.scala @@ -8,6 +8,7 @@ package scala.tools.nsc import java.util.concurrent.{ Future, Callable } import java.util.{ Timer, TimerTask } import java.util.jar.{ Attributes } +import language.implicitConversions package object io { type JManifest = java.util.jar.Manifest @@ -41,4 +42,4 @@ package object io { alarm.schedule(tt, seconds * 1000) alarm } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index 06b06c50a6..ca3f3ff635 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -12,6 +12,7 @@ import scala.tools.nsc.util.OffsetPosition import scala.collection.mutable.ListBuffer import symtab.Flags import JavaTokens._ +import language.implicitConversions trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { val global : Global diff --git a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala index 45b63b0ca0..d47756e757 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala @@ -10,6 +10,7 @@ import scala.tools.nsc.util._ import scala.reflect.internal.Chars._ import JavaTokens._ import scala.annotation.switch +import language.implicitConversions // Todo merge these better with Scanners trait JavaScanners extends ast.parser.ScannersCommon { diff --git a/src/compiler/scala/tools/nsc/matching/MatchSupport.scala b/src/compiler/scala/tools/nsc/matching/MatchSupport.scala index 371f4bc4d8..05bd4966df 100644 --- a/src/compiler/scala/tools/nsc/matching/MatchSupport.scala +++ b/src/compiler/scala/tools/nsc/matching/MatchSupport.scala @@ -29,11 +29,10 @@ trait MatchSupport extends ast.TreeDSL { self: ParallelMatching => object Types { import definitions._ - implicit def enrichType(x: Type): RichType = new RichType(x) val subrangeTypes = Set(ByteClass, ShortClass, CharClass, IntClass) - class RichType(undecodedTpe: Type) { + implicit class RichType(undecodedTpe: Type) { def tpe = decodedEqualsType(undecodedTpe) def isAnyRef = tpe <:< AnyRefClass.tpe diff --git a/src/compiler/scala/tools/nsc/matching/Matrix.scala b/src/compiler/scala/tools/nsc/matching/Matrix.scala index e1ff88557e..b29fac225a 100644 --- a/src/compiler/scala/tools/nsc/matching/Matrix.scala +++ b/src/compiler/scala/tools/nsc/matching/Matrix.scala @@ -9,6 +9,7 @@ package matching import transform.ExplicitOuter import symtab.Flags import scala.collection.mutable +import language.implicitConversions trait Matrix extends MatrixAdditions { self: ExplicitOuter with ParallelMatching => @@ -255,4 +256,4 @@ trait Matrix extends MatrixAdditions { recordSyntheticSym(owner.newVariable(n, pos, flagsLong) setInfo tpe) } } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala b/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala index c010c6a3ea..2fdc3004d6 100644 --- a/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala @@ -23,6 +23,7 @@ trait AestheticSettings { def deprecation = settings.deprecation.value def experimental = settings.Xexperimental.value def fatalWarnings = settings.fatalWarnings.value + def feature = settings.feature.value def future = settings.future.value def logClasspath = settings.Ylogcp.value def printStats = settings.Ystatistics.value diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index a89aa88585..f7878cae71 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -11,6 +11,7 @@ package settings import annotation.elidable import scala.tools.util.PathResolver.Defaults import scala.collection.mutable +import language.{implicitConversions, existentials} trait ScalaSettings extends AbsScalaSettings with StandardScalaSettings @@ -62,7 +63,7 @@ trait ScalaSettings extends AbsScalaSettings val classpath = PathSetting ("-classpath", "Specify where to find user class files.", defaultClasspath) withAbbreviation "-cp" val d = OutputSetting (outputDirs, ".") val nospecialization = BooleanSetting ("-no-specialization", "Ignore @specialize annotations.") - val feature = MultiStringSetting("-language", "feature", "Enable one or more language features.") + val language = MultiStringSetting("-language", "feature", "Enable one or more language features.") /** * -X "Advanced" settings @@ -204,7 +205,7 @@ trait ScalaSettings extends AbsScalaSettings val Xexperimental = BooleanSetting("-Xexperimental", "Enable experimental extensions.") enabling experimentalSettings // Feature extensions - val Xmacros = BooleanSetting("-Xmacros", "Enable macros.") + val Xmacros = BooleanSetting("-Xmacros", "Enable macros.") // [Martin] Can be retired now. val XmacroSettings = MultiStringSetting("-Xmacro-settings", "option", "Custom settings for macros.") val XmacroPrimaryClasspath = PathSetting("-Xmacro-primary-classpath", "Classpath to load macros implementations from, defaults to compilation classpath (aka \"library classpath\".", "") val XmacroFallbackClasspath = PathSetting("-Xmacro-fallback-classpath", "Classpath to load macros implementations from if they cannot be loaded from library classpath.", "") diff --git a/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala index c5b477c7bd..a69b88a5df 100644 --- a/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala @@ -32,6 +32,7 @@ trait StandardScalaSettings { val deprecation = BooleanSetting ("-deprecation", "Emit warning and location for usages of deprecated APIs.") val encoding = StringSetting ("-encoding", "encoding", "Specify character encoding used by source files.", Properties.sourceEncoding) val explaintypes = BooleanSetting ("-explaintypes", "Explain type errors in more detail.") + val feature = BooleanSetting ("-feature", "Emit warning and location for usages of features that should be imported explicitly.") val g = ChoiceSetting ("-g", "level", "Set level of generated debugging info.", List("none", "source", "line", "vars", "notailcalls"), "vars") val help = BooleanSetting ("-help", "Print a synopsis of standard options") val make = ChoiceSetting ("-make", "policy", "Recompilation detection policy", List("all", "changed", "immediate", "transitive", "transitivenocp"), "all") diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala index e62070a239..310753871f 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala @@ -7,6 +7,7 @@ package scala.tools.nsc package symtab import scala.collection.{ mutable, immutable } +import language.implicitConversions /** Printing the symbol graph (for those symbols attached to an AST node) * after each phase. diff --git a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala index 4b847fa94a..028d6f2484 100644 --- a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala @@ -12,6 +12,7 @@ import ch.epfl.lamp.compiler.msil.{Type => MSILType, Attribute => MSILAttribute, import scala.collection.{ mutable, immutable } import scala.reflect.internal.pickling.UnPickler import ch.epfl.lamp.compiler.msil.Type.TMVarUsage +import language.implicitConversions /** * @author Nikolay Mihaylov diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index 9608108a0d..18636ecb05 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -183,9 +183,9 @@ trait Macros { self: Analyzer => def typedMacroBody(typer: Typer, ddef: DefDef): Tree = { import typer.context if (macroDebug) println("typechecking macro def %s at %s".format(ddef.symbol, ddef.pos)) + typer.checkFeature(ddef.pos, MacrosFeature) - implicit def augmentString(s: String) = new AugmentedString(s) - class AugmentedString(s: String) { + implicit class AugmentedString(s: String) { def abbreviateCoreAliases: String = { // hack! var result = s result = result.replace("c.mirror.TypeTag", "c.TypeTag") diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala index e1c12adbcc..9e06cbe0d3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala +++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala @@ -8,6 +8,7 @@ package typechecker import symtab.Flags._ import scala.collection.{ mutable, immutable } import scala.tools.util.StringOps.{ ojoin } +import language.higherKinds /** Logic related to method synthesis which involves cooperation between * Namer and Typer. @@ -377,7 +378,7 @@ trait MethodSynthesis { } def derivedTree: DefDef = factoryMeth(mods & flagsMask | flagsExtra, name, tree, symbolic = false) - def flagsExtra: Long = METHOD | IMPLICIT + def flagsExtra: Long = METHOD | IMPLICIT | SYNTHETIC def flagsMask: Long = AccessFlags def name: TermName = tree.name.toTermName } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 3a5abb4cea..0233974f6f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -737,24 +737,25 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if (!isPastTyper) { val nestedOwners = featureTrait.owner.ownerChain.takeWhile(_ != languageFeatureModule.moduleClass).reverse - val featureName = (nestedOwners map (_ + ".")).mkString + featureTrait.name + val featureName = (nestedOwners map (_.name + ".")).mkString + featureTrait.name unit.toCheck += { () => - if (!(unit.checkedFeatures contains featureTrait)) { - def hasImport = inferImplicit(EmptyTree: Tree, featureTrait.tpe, true, false, context) != SearchFailure - def hasOption = settings.feature.value contains featureName - if (!hasImport && !hasOption) { - val Some(AnnotationInfo(_, List(Literal(Constant(featureDesc: String)), Literal(Constant(required: Boolean))), _)) = - featureTrait getAnnotation LanguageFeatureClass - val req = if (required) "needs to" else "should" - val raw = featureDesc + " " + req + " be enabled by making\n" + - "the implicit value language." + featureName + " visible. This can be achieved by adding the import\n" + - "import language." + featureName + " or by setting the compiler option -language:" + featureName + ".\n" + + def hasImport = inferImplicit(EmptyTree: Tree, featureTrait.tpe, true, false, context) != SearchFailure + def hasOption = settings.language.value contains featureName + if (!hasImport && !hasOption) { + val Some(AnnotationInfo(_, List(Literal(Constant(featureDesc: String)), Literal(Constant(required: Boolean))), _)) = + featureTrait getAnnotation LanguageFeatureClass + val req = if (required) "needs to" else "should" + var raw = featureDesc + " " + req + " be enabled\n" + + "by making the implicit value language." + featureName + " visible." + if (!(currentRun.reportedFeature contains featureTrait)) + raw += "\nThis can be achieved by adding the import clause 'import language." + featureName + "'\n" + + "or by setting the compiler option -language:" + featureName + ".\n" + "See the Scala docs for value scala.language." + featureName + "for a discussion\n" + "why the feature " + req + " be explicitly enabled." - val msg = raw replace ("#", construct) - if (required) unit.error(pos, msg) else unit.warning(pos, msg) - unit.checkedFeatures += featureTrait - } + currentRun.reportedFeature += featureTrait + val msg = raw replace ("#", construct) + if (required) unit.error(pos, msg) + else currentRun.featureWarnings.warn(pos, msg) } } } @@ -1972,9 +1973,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if (meth.isStructuralRefinementMember) checkMethodStructuralCompatible(meth) - if (meth.isImplicit) meth.info.paramss match { + if (meth.isImplicit && !meth.isSynthetic) meth.info.paramss match { case List(param) :: _ if !param.isImplicit => - println("check implicit +"+meth+" "+isPastTyper) checkFeature(ddef.pos, ImplicitConversionsFeature, meth.toString) case _ => } @@ -4751,9 +4751,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { else typedSelect(qual1, name) - val sym = tree1.symbol - if (sym != null && sym.isTerm && sym.owner.isRefinementClass && !sym.isConstant) - checkFeature(tree1.pos, ReflectiveCallsFeature, sym.toString) + if (tree1.symbol != null && tree1.symbol.isOnlyRefinementMember) + checkFeature(tree1.pos, ReflectiveCallsFeature, tree1.symbol.toString) if (qual1.symbol == RootPackage) treeCopy.Ident(tree1, name) else tree1 diff --git a/src/compiler/scala/tools/nsc/util/CommandLineParser.scala b/src/compiler/scala/tools/nsc/util/CommandLineParser.scala index 00fe49d36a..78bfd5e908 100644 --- a/src/compiler/scala/tools/nsc/util/CommandLineParser.scala +++ b/src/compiler/scala/tools/nsc/util/CommandLineParser.scala @@ -20,11 +20,10 @@ import scala.collection.mutable.ListBuffer */ trait ParserUtil extends Parsers { - class ParserPlus[+T](underlying: Parser[T]) { + protected implicit class ParserPlus[+T](underlying: Parser[T]) { def !~>[U](p: => Parser[U]): Parser[U] = (underlying ~! p) ^^ { case a~b => b } def <~![U](p: => Parser[U]): Parser[T] = (underlying ~! p) ^^ { case a~b => a } } - protected implicit def parser2parserPlus[T](p: Parser[T]): ParserPlus[T] = new ParserPlus(p) } case class CommandLine( diff --git a/src/compiler/scala/tools/nsc/util/Exceptional.scala b/src/compiler/scala/tools/nsc/util/Exceptional.scala index 667b7d15a6..7452aa1b67 100644 --- a/src/compiler/scala/tools/nsc/util/Exceptional.scala +++ b/src/compiler/scala/tools/nsc/util/Exceptional.scala @@ -5,6 +5,7 @@ import java.util.concurrent.ExecutionException import java.lang.reflect.{ InvocationTargetException, UndeclaredThrowableException } import io.{ Sources, Fileish } import scala.tools.util.StringOps._ +import language.implicitConversions /** A simple throwable wrapper so it looks more like a parade of * glittering frame-shaped beauties than the other thing. diff --git a/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala b/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala index fda713c5c6..700fe0c1a6 100644 --- a/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala +++ b/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala @@ -14,6 +14,8 @@ import java.net.URL import scala.reflect.ReflectionUtils.unwrapHandler import ScalaClassLoader._ import scala.util.control.Exception.{ catching } +import language.implicitConversions + // import Exceptional.unwrap trait HasClassPath { |