diff options
Diffstat (limited to 'src')
194 files changed, 1711 insertions, 1638 deletions
diff --git a/src/actors-migration/scala/actors/Pattern.scala b/src/actors-migration/scala/actors/Pattern.scala index 97dbd2cccd..26e9d1bb64 100644 --- a/src/actors-migration/scala/actors/Pattern.scala +++ b/src/actors-migration/scala/actors/Pattern.scala @@ -1,6 +1,7 @@ package scala.actors import scala.concurrent.util.Duration +import language.implicitConversions object pattern { diff --git a/src/actors-migration/scala/actors/StashingActor.scala b/src/actors-migration/scala/actors/StashingActor.scala index 37300f9d63..8f96e1b002 100644 --- a/src/actors-migration/scala/actors/StashingActor.scala +++ b/src/actors-migration/scala/actors/StashingActor.scala @@ -3,6 +3,7 @@ package scala.actors import scala.collection._ import scala.concurrent.util.Duration import java.util.concurrent.TimeUnit +import language.implicitConversions object StashingActor extends Combinators { implicit def mkBody[A](body: => A) = new InternalActor.Body[A] { diff --git a/src/actors-migration/scala/actors/Timeout.scala b/src/actors-migration/scala/actors/Timeout.scala index 0d9532a14b..7e400ab140 100644 --- a/src/actors-migration/scala/actors/Timeout.scala +++ b/src/actors-migration/scala/actors/Timeout.scala @@ -10,6 +10,7 @@ package scala.actors import scala.concurrent.util.Duration import java.util.concurrent.TimeUnit +import language.implicitConversions case class Timeout(duration: Duration) { def this(timeout: Long) = this(Duration(timeout, TimeUnit.MILLISECONDS)) diff --git a/src/actors/scala/actors/AbstractActor.scala b/src/actors/scala/actors/AbstractActor.scala index 3817f9cda3..dec91859bb 100644 --- a/src/actors/scala/actors/AbstractActor.scala +++ b/src/actors/scala/actors/AbstractActor.scala @@ -6,9 +6,10 @@ ** |/ ** \* */ - package scala.actors +import language.higherKinds + /** * @author Philipp Haller * diff --git a/src/actors/scala/actors/Actor.scala b/src/actors/scala/actors/Actor.scala index bc9bbc6ef0..0b1e7fb1e9 100644 --- a/src/actors/scala/actors/Actor.scala +++ b/src/actors/scala/actors/Actor.scala @@ -1,5 +1,3 @@ - - /* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2005-2011, LAMP/EPFL ** @@ -12,6 +10,7 @@ package scala.actors import scala.util.control.ControlThrowable import java.util.{Timer, TimerTask} +import language.implicitConversions /** * Provides functions for the definition of actors, as well as actor diff --git a/src/actors/scala/actors/CanReply.scala b/src/actors/scala/actors/CanReply.scala index 5053f43e94..9bf0022247 100644 --- a/src/actors/scala/actors/CanReply.scala +++ b/src/actors/scala/actors/CanReply.scala @@ -6,9 +6,10 @@ ** |/ ** \* */ - package scala.actors +import language.higherKinds + /** * Defines result-bearing message send operations. * diff --git a/src/actors/scala/actors/Combinators.scala b/src/actors/scala/actors/Combinators.scala index c1a9095614..dd704436fc 100644 --- a/src/actors/scala/actors/Combinators.scala +++ b/src/actors/scala/actors/Combinators.scala @@ -10,6 +10,8 @@ package scala.actors +import language.implicitConversions + private[actors] trait Combinators { /** diff --git a/src/actors/scala/actors/MQueue.scala b/src/actors/scala/actors/MQueue.scala index 4a148d2cb3..43074649fd 100644 --- a/src/actors/scala/actors/MQueue.scala +++ b/src/actors/scala/actors/MQueue.scala @@ -121,7 +121,7 @@ private[actors] class MQueue[Msg >: Null](protected val label: String) { * or `'''null'''` if `p` fails for all of them. */ def extractFirst(p: (Msg, OutputChannel[Any]) => Boolean): MQueueElement[Msg] = - removeInternal(0)(p) orNull + removeInternal(0)(p).orNull def extractFirst(pf: PartialFunction[Msg, Any]): MQueueElement[Msg] = { if (isEmpty) // early return diff --git a/src/actors/scala/actors/Reactor.scala b/src/actors/scala/actors/Reactor.scala index 7a8d738758..c962bb9d3d 100644 --- a/src/actors/scala/actors/Reactor.scala +++ b/src/actors/scala/actors/Reactor.scala @@ -12,6 +12,7 @@ package scala.actors import scala.actors.scheduler.{DelegatingScheduler, ExecutorScheduler, ForkJoinScheduler, ThreadPoolConfig} import java.util.concurrent.{ThreadPoolExecutor, TimeUnit, LinkedBlockingQueue} +import language.implicitConversions private[actors] object Reactor { diff --git a/src/build/maven/scala-library-pom.xml b/src/build/maven/scala-library-pom.xml index e8db512125..d1192b2dd8 100644 --- a/src/build/maven/scala-library-pom.xml +++ b/src/build/maven/scala-library-pom.xml @@ -31,11 +31,11 @@ <url>https://issues.scala-lang.org/</url> </issueManagement> <dependencies> - <dependency> + <!--<dependency> <groupId>com.typesafe</groupId> <artifactId>config</artifactId> <version>0.4.0</version> - </dependency> + </dependency>--> </dependencies> <distributionManagement> <repository> diff --git a/src/compiler/scala/reflect/makro/runtime/AbortMacroException.scala b/src/compiler/scala/reflect/macros/runtime/AbortMacroException.scala index a68910859d..f45dde8a85 100644 --- a/src/compiler/scala/reflect/makro/runtime/AbortMacroException.scala +++ b/src/compiler/scala/reflect/macros/runtime/AbortMacroException.scala @@ -1,4 +1,4 @@ -package scala.reflect.makro +package scala.reflect.macros package runtime import scala.reflect.internal.util.Position diff --git a/src/compiler/scala/reflect/makro/runtime/Aliases.scala b/src/compiler/scala/reflect/macros/runtime/Aliases.scala index 760f7fc54d..8b742755cd 100644 --- a/src/compiler/scala/reflect/makro/runtime/Aliases.scala +++ b/src/compiler/scala/reflect/macros/runtime/Aliases.scala @@ -1,4 +1,4 @@ -package scala.reflect.makro +package scala.reflect.macros package runtime trait Aliases { diff --git a/src/compiler/scala/reflect/makro/runtime/CapturedVariables.scala b/src/compiler/scala/reflect/macros/runtime/CapturedVariables.scala index 021b93ceee..78fb7100b0 100644 --- a/src/compiler/scala/reflect/makro/runtime/CapturedVariables.scala +++ b/src/compiler/scala/reflect/macros/runtime/CapturedVariables.scala @@ -1,4 +1,4 @@ -package scala.reflect.makro +package scala.reflect.macros package runtime trait CapturedVariables { diff --git a/src/compiler/scala/reflect/makro/runtime/Context.scala b/src/compiler/scala/reflect/macros/runtime/Context.scala index 68964b7abb..8bbfef44a3 100644 --- a/src/compiler/scala/reflect/makro/runtime/Context.scala +++ b/src/compiler/scala/reflect/macros/runtime/Context.scala @@ -1,9 +1,9 @@ -package scala.reflect.makro +package scala.reflect.macros package runtime import scala.tools.nsc.Global -abstract class Context extends scala.reflect.makro.Context +abstract class Context extends scala.reflect.macros.Context with Aliases with CapturedVariables with Infrastructure diff --git a/src/compiler/scala/reflect/makro/runtime/Enclosures.scala b/src/compiler/scala/reflect/macros/runtime/Enclosures.scala index 360a4b8e8a..ebde4447d7 100644 --- a/src/compiler/scala/reflect/makro/runtime/Enclosures.scala +++ b/src/compiler/scala/reflect/macros/runtime/Enclosures.scala @@ -1,4 +1,4 @@ -package scala.reflect.makro +package scala.reflect.macros package runtime trait Enclosures { diff --git a/src/compiler/scala/reflect/makro/runtime/Evals.scala b/src/compiler/scala/reflect/macros/runtime/Evals.scala index 0574359a19..348e29cdd7 100644 --- a/src/compiler/scala/reflect/makro/runtime/Evals.scala +++ b/src/compiler/scala/reflect/macros/runtime/Evals.scala @@ -1,4 +1,4 @@ -package scala.reflect.makro +package scala.reflect.macros package runtime import scala.reflect.runtime.{universe => ru} diff --git a/src/compiler/scala/reflect/makro/runtime/ExprUtils.scala b/src/compiler/scala/reflect/macros/runtime/ExprUtils.scala index e301dfc2a4..672699f00e 100644 --- a/src/compiler/scala/reflect/makro/runtime/ExprUtils.scala +++ b/src/compiler/scala/reflect/macros/runtime/ExprUtils.scala @@ -1,4 +1,4 @@ -package scala.reflect.makro +package scala.reflect.macros package runtime trait ExprUtils { @@ -29,7 +29,7 @@ trait ExprUtils { def literal(x: Double) = Expr[Double](Literal(Constant(x)))(TypeTag.Double) - def literal(x: String) = Expr[String](Literal(Constant(x)))(TypeTag[String](definitions.StringClass.asTypeConstructor)) + def literal(x: String) = Expr[String](Literal(Constant(x)))(TypeTag[String](definitions.StringClass.toTypeConstructor)) def literal(x: Char) = Expr[Char](Literal(Constant(x)))(TypeTag.Char) } diff --git a/src/compiler/scala/reflect/makro/runtime/Exprs.scala b/src/compiler/scala/reflect/macros/runtime/Exprs.scala index b680b56bab..4217a6a404 100644 --- a/src/compiler/scala/reflect/makro/runtime/Exprs.scala +++ b/src/compiler/scala/reflect/macros/runtime/Exprs.scala @@ -1,4 +1,4 @@ -package scala.reflect.makro +package scala.reflect.macros package runtime trait Exprs { diff --git a/src/compiler/scala/reflect/makro/runtime/FrontEnds.scala b/src/compiler/scala/reflect/macros/runtime/FrontEnds.scala index 6644c579ac..69fa416f8f 100644 --- a/src/compiler/scala/reflect/makro/runtime/FrontEnds.scala +++ b/src/compiler/scala/reflect/macros/runtime/FrontEnds.scala @@ -1,4 +1,4 @@ -package scala.reflect.makro +package scala.reflect.macros package runtime trait FrontEnds extends scala.tools.reflect.FrontEnds { diff --git a/src/compiler/scala/reflect/makro/runtime/Infrastructure.scala b/src/compiler/scala/reflect/macros/runtime/Infrastructure.scala index 76c4b21731..19fb03364e 100644 --- a/src/compiler/scala/reflect/makro/runtime/Infrastructure.scala +++ b/src/compiler/scala/reflect/macros/runtime/Infrastructure.scala @@ -1,4 +1,4 @@ -package scala.reflect.makro +package scala.reflect.macros package runtime import scala.tools.nsc.util.ScalaClassLoader diff --git a/src/compiler/scala/reflect/makro/runtime/Names.scala b/src/compiler/scala/reflect/macros/runtime/Names.scala index 3f43b15d90..ee9f3a56d3 100644 --- a/src/compiler/scala/reflect/makro/runtime/Names.scala +++ b/src/compiler/scala/reflect/macros/runtime/Names.scala @@ -1,4 +1,4 @@ -package scala.reflect.makro +package scala.reflect.macros package runtime trait Names { diff --git a/src/compiler/scala/reflect/makro/runtime/Parsers.scala b/src/compiler/scala/reflect/macros/runtime/Parsers.scala index ac8d09f592..6d89b71f39 100644 --- a/src/compiler/scala/reflect/makro/runtime/Parsers.scala +++ b/src/compiler/scala/reflect/macros/runtime/Parsers.scala @@ -1,4 +1,4 @@ -package scala.reflect.makro +package scala.reflect.macros package runtime import language.existentials diff --git a/src/compiler/scala/reflect/makro/runtime/Reifiers.scala b/src/compiler/scala/reflect/macros/runtime/Reifiers.scala index 10b5ae5f42..056549578a 100644 --- a/src/compiler/scala/reflect/makro/runtime/Reifiers.scala +++ b/src/compiler/scala/reflect/macros/runtime/Reifiers.scala @@ -3,7 +3,7 @@ * @author Gilles Dubochet */ -package scala.reflect.makro +package scala.reflect.macros package runtime trait Reifiers { diff --git a/src/compiler/scala/reflect/makro/runtime/Settings.scala b/src/compiler/scala/reflect/macros/runtime/Settings.scala index 8288180b8d..b7dba665fa 100644 --- a/src/compiler/scala/reflect/makro/runtime/Settings.scala +++ b/src/compiler/scala/reflect/macros/runtime/Settings.scala @@ -1,4 +1,4 @@ -package scala.reflect.makro +package scala.reflect.macros package runtime trait Settings { diff --git a/src/compiler/scala/reflect/makro/runtime/Traces.scala b/src/compiler/scala/reflect/macros/runtime/Traces.scala index 225ee1f62b..0238e9f84e 100644 --- a/src/compiler/scala/reflect/makro/runtime/Traces.scala +++ b/src/compiler/scala/reflect/macros/runtime/Traces.scala @@ -1,4 +1,4 @@ -package scala.reflect.makro +package scala.reflect.macros package runtime trait Traces extends util.Traces { diff --git a/src/compiler/scala/reflect/makro/runtime/TypeTags.scala b/src/compiler/scala/reflect/macros/runtime/TypeTags.scala index 4f9b287674..2bc2fe6384 100644 --- a/src/compiler/scala/reflect/makro/runtime/TypeTags.scala +++ b/src/compiler/scala/reflect/macros/runtime/TypeTags.scala @@ -1,4 +1,4 @@ -package scala.reflect.makro +package scala.reflect.macros package runtime trait TypeTags { diff --git a/src/compiler/scala/reflect/makro/runtime/Typers.scala b/src/compiler/scala/reflect/macros/runtime/Typers.scala index 18c1714d15..9fa8567ada 100644 --- a/src/compiler/scala/reflect/makro/runtime/Typers.scala +++ b/src/compiler/scala/reflect/macros/runtime/Typers.scala @@ -1,4 +1,4 @@ -package scala.reflect.makro +package scala.reflect.macros package runtime trait Typers { @@ -10,8 +10,9 @@ trait Typers { def typeCheck(tree: Tree, pt: Type = universe.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = { macroLogVerbose("typechecking %s with expected type %s, implicit views = %s, macros = %s".format(tree, pt, !withImplicitViewsDisabled, !withMacrosDisabled)) - val wrapper1 = if (!withImplicitViewsDisabled) (callsiteTyper.context.withImplicitsEnabled[Tree] _) else (callsiteTyper.context.withImplicitsDisabled[Tree] _) - val wrapper2 = if (!withMacrosDisabled) (callsiteTyper.context.withMacrosEnabled[Tree] _) else (callsiteTyper.context.withMacrosDisabled[Tree] _) + val context = callsiteTyper.context + val wrapper1 = if (!withImplicitViewsDisabled) (context.withImplicitsEnabled[Tree] _) else (context.withImplicitsDisabled[Tree] _) + val wrapper2 = if (!withMacrosDisabled) (context.withMacrosEnabled[Tree] _) else (context.withMacrosDisabled[Tree] _) def wrapper (tree: => Tree) = wrapper1(wrapper2(tree)) // if you get a "silent mode is not available past typer" here // don't rush to change the typecheck not to use the silent method when the silent parameter is false @@ -31,29 +32,21 @@ trait Typers { def inferImplicitValue(pt: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: Position = enclosingPosition): Tree = { macroLogVerbose("inferring implicit value of type %s, macros = %s".format(pt, !withMacrosDisabled)) - import universe.analyzer.SearchResult - val context = callsiteTyper.context - val wrapper1 = if (!withMacrosDisabled) (context.withMacrosEnabled[SearchResult] _) else (context.withMacrosDisabled[SearchResult] _) - def wrapper (inference: => SearchResult) = wrapper1(inference) - wrapper(universe.analyzer.inferImplicit(universe.EmptyTree, pt, true, false, context, !silent, pos)) match { - case failure if failure.tree.isEmpty => - macroLogVerbose("implicit search has failed. to find out the reason, turn on -Xlog-implicits") - if (context.hasErrors) throw new universe.TypeError(context.errBuffer.head.errPos, context.errBuffer.head.errMsg) - universe.EmptyTree - case success => - success.tree - } + inferImplicit(universe.EmptyTree, pt, isView = false, silent = silent, withMacrosDisabled = withMacrosDisabled, pos = pos) + } + + def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: Position = enclosingPosition): Tree = { + macroLogVerbose("inferring implicit view from %s to %s for %s, macros = %s".format(from, to, tree, !withMacrosDisabled)) + val viewTpe = universe.appliedType(universe.definitions.FunctionClass(1).toTypeConstructor, List(from, to)) + inferImplicit(tree, viewTpe, isView = true, silent = silent, withMacrosDisabled = withMacrosDisabled, pos = pos) } - def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, reportAmbiguous: Boolean = true, pos: Position = enclosingPosition): Tree = { - macroLogVerbose("inferring implicit view from %s to %s for %s, macros = %s, reportAmbiguous = %s".format(from, to, tree, !withMacrosDisabled, reportAmbiguous)) + private def inferImplicit(tree: Tree, pt: Type, isView: Boolean, silent: Boolean, withMacrosDisabled: Boolean, pos: Position): Tree = { import universe.analyzer.SearchResult val context = callsiteTyper.context val wrapper1 = if (!withMacrosDisabled) (context.withMacrosEnabled[SearchResult] _) else (context.withMacrosDisabled[SearchResult] _) def wrapper (inference: => SearchResult) = wrapper1(inference) - val fun1 = universe.definitions.FunctionClass(1) - val viewTpe = universe.TypeRef(fun1.typeConstructor.prefix, fun1, List(from, to)) - wrapper(universe.analyzer.inferImplicit(tree, viewTpe, reportAmbiguous, true, context, !silent, pos)) match { + wrapper(universe.analyzer.inferImplicit(tree, pt, reportAmbiguous = true, isView = isView, context = context, saveAmbiguousDivergent = !silent, pos = pos)) match { case failure if failure.tree.isEmpty => macroLogVerbose("implicit search has failed. to find out the reason, turn on -Xlog-implicits") if (context.hasErrors) throw new universe.TypeError(context.errBuffer.head.errPos, context.errBuffer.head.errMsg) diff --git a/src/compiler/scala/reflect/makro/util/Traces.scala b/src/compiler/scala/reflect/macros/util/Traces.scala index 2363cc4bac..6c2f115994 100644 --- a/src/compiler/scala/reflect/makro/util/Traces.scala +++ b/src/compiler/scala/reflect/macros/util/Traces.scala @@ -1,4 +1,4 @@ -package scala.reflect.makro +package scala.reflect.macros package util trait Traces { diff --git a/src/compiler/scala/reflect/reify/Errors.scala b/src/compiler/scala/reflect/reify/Errors.scala index 1b72b3075b..5e15c5ad3a 100644 --- a/src/compiler/scala/reflect/reify/Errors.scala +++ b/src/compiler/scala/reflect/reify/Errors.scala @@ -1,7 +1,7 @@ package scala.reflect.reify -import scala.reflect.makro.ReificationError -import scala.reflect.makro.UnexpectedReificationError +import scala.reflect.macros.ReificationError +import scala.reflect.macros.UnexpectedReificationError trait Errors { self: Reifier => diff --git a/src/compiler/scala/reflect/reify/Reifier.scala b/src/compiler/scala/reflect/reify/Reifier.scala index 8fba7274be..53e01309cb 100644 --- a/src/compiler/scala/reflect/reify/Reifier.scala +++ b/src/compiler/scala/reflect/reify/Reifier.scala @@ -1,8 +1,8 @@ package scala.reflect.reify import scala.tools.nsc.Global -import scala.reflect.makro.ReificationError -import scala.reflect.makro.UnexpectedReificationError +import scala.reflect.macros.ReificationError +import scala.reflect.macros.UnexpectedReificationError import scala.reflect.reify.utils.Utils /** Given a tree or a type, generate a tree that when executed at runtime produces the original tree or type. @@ -115,7 +115,7 @@ abstract class Reifier extends States // todo. maybe try `resetLocalAttrs` once the dust settles var importantSymbols = Set[Symbol]( NothingClass, AnyClass, SingletonClass, PredefModule, ScalaRunTimeModule, TypeCreatorClass, TreeCreatorClass, MirrorOfClass, - BaseUniverseClass, ApiUniverseClass, JavaUniverseClass, ReflectRuntimePackage, ReflectRuntimeCurrentMirror) + BaseUniverseClass, JavaUniverseClass, ReflectRuntimePackage, ReflectRuntimeCurrentMirror) importantSymbols ++= importantSymbols map (_.companionSymbol) importantSymbols ++= importantSymbols map (_.moduleClass) importantSymbols ++= importantSymbols map (_.linkedClassOfClass) diff --git a/src/compiler/scala/reflect/reify/Taggers.scala b/src/compiler/scala/reflect/reify/Taggers.scala index 4e30d0acf8..a8523fe686 100644 --- a/src/compiler/scala/reflect/reify/Taggers.scala +++ b/src/compiler/scala/reflect/reify/Taggers.scala @@ -1,7 +1,7 @@ package scala.reflect.reify -import scala.reflect.makro.{ReificationError, UnexpectedReificationError} -import scala.reflect.makro.runtime.Context +import scala.reflect.macros.{ReificationError, UnexpectedReificationError} +import scala.reflect.macros.runtime.Context abstract class Taggers { val c: Context diff --git a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala index 38c8fedac5..59651bcdf9 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala @@ -36,7 +36,7 @@ trait GenSymbols { else if (sym.isEmptyPackageClass) mirrorMirrorSelect(nme.EmptyPackageClass) else if (sym.isModuleClass) - Select(Select(reify(sym.sourceModule), nme.asModuleSymbol), nme.moduleClass) + Select(Select(reify(sym.sourceModule), nme.asModule), nme.moduleClass) else if (sym.isPackage) mirrorMirrorCall(nme.staticPackage, reify(sym.fullName)) else if (sym.isLocatable) { diff --git a/src/compiler/scala/reflect/reify/codegen/GenTypes.scala b/src/compiler/scala/reflect/reify/codegen/GenTypes.scala index c49e5b3342..c762a28f99 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenTypes.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenTypes.scala @@ -30,7 +30,7 @@ trait GenTypes { val tsym = tpe.typeSymbolDirect if (tsym.isClass && tpe == tsym.typeConstructor && tsym.isStatic) - Select(Select(reify(tsym), nme.asTypeSymbol), nme.asTypeConstructor) + Select(Select(reify(tsym), nme.asType), nme.toTypeConstructor) else tpe match { case tpe @ NoType => reifyMirrorObject(tpe) @@ -42,7 +42,7 @@ trait GenTypes { mirrorBuildCall(nme.thisPrefix, mirrorMirrorSelect(nme.EmptyPackageClass)) case tpe @ ThisType(clazz) if clazz.isModuleClass && clazz.isStatic => val module = reify(clazz.sourceModule) - val moduleClass = Select(Select(module, nme.asModuleSymbol), nme.moduleClass) + val moduleClass = Select(Select(module, nme.asModule), nme.moduleClass) mirrorFactoryCall(nme.ThisType, moduleClass) case tpe @ ThisType(_) => reifyProduct(tpe) @@ -94,7 +94,7 @@ trait GenTypes { } case success => if (reifyDebug) println("implicit search has produced a result: " + success) - state.reificationIsConcrete &= concrete || success.tpe <:< TypeTagClass.asTypeConstructor + state.reificationIsConcrete &= concrete || success.tpe <:< TypeTagClass.toTypeConstructor Select(Apply(Select(success, nme.in), List(Ident(nme.MIRROR_SHORT))), nme.tpe) } if (result != EmptyTree) return result @@ -109,7 +109,7 @@ trait GenTypes { def searchForManifest(typer: analyzer.Typer): Tree = analyzer.inferImplicit( EmptyTree, - appliedType(FullManifestClass.asTypeConstructor, List(tpe)), + appliedType(FullManifestClass.toTypeConstructor, List(tpe)), reportAmbiguous = false, isView = false, context = typer.context, diff --git a/src/compiler/scala/reflect/reify/package.scala b/src/compiler/scala/reflect/reify/package.scala index 80011368a8..a253effc1c 100644 --- a/src/compiler/scala/reflect/reify/package.scala +++ b/src/compiler/scala/reflect/reify/package.scala @@ -1,9 +1,8 @@ package scala.reflect import language.implicitConversions -import language.experimental.macros import scala.reflect.base.{Universe => BaseUniverse} -import scala.reflect.makro.{Context, ReificationError, UnexpectedReificationError} +import scala.reflect.macros.{Context, ReificationError, UnexpectedReificationError} import scala.tools.nsc.Global package object reify { @@ -29,7 +28,7 @@ package object reify { import definitions._ val enclosingErasure = reifyEnclosingRuntimeClass(global)(typer0) // JavaUniverse is defined in scala-reflect.jar, so we must be very careful in case someone reifies stuff having only scala-library.jar on the classpath - val isJavaUniverse = JavaUniverseClass != NoSymbol && universe.tpe <:< JavaUniverseClass.asTypeConstructor + val isJavaUniverse = JavaUniverseClass != NoSymbol && universe.tpe <:< JavaUniverseClass.toTypeConstructor if (isJavaUniverse && !enclosingErasure.isEmpty) Apply(Select(universe, nme.runtimeMirror), List(Select(enclosingErasure, sn.GetClassLoader))) else Select(universe, nme.rootMirror) } @@ -69,7 +68,7 @@ package object reify { if (isThisInScope) { val enclosingClasses = typer0.context.enclosingContextChain map (_.tree) collect { case classDef: ClassDef => classDef } val classInScope = enclosingClasses.headOption getOrElse EmptyTree - if (!classInScope.isEmpty) reifyRuntimeClass(global)(typer0, classInScope.symbol.asTypeConstructor, concrete = true) + if (!classInScope.isEmpty) reifyRuntimeClass(global)(typer0, classInScope.symbol.toTypeConstructor, concrete = true) else Select(This(tpnme.EMPTY), sn.GetClass) } else EmptyTree } diff --git a/src/compiler/scala/reflect/reify/utils/Extractors.scala b/src/compiler/scala/reflect/reify/utils/Extractors.scala index 86265ec77a..ebe3957e69 100644 --- a/src/compiler/scala/reflect/reify/utils/Extractors.scala +++ b/src/compiler/scala/reflect/reify/utils/Extractors.scala @@ -20,11 +20,6 @@ trait Extractors { // () // }; // def apply[U >: Nothing <: scala.reflect.base.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Tree = { - // val $u: scala.reflect.api.Universe = $m$untyped.universe.asInstanceOf[scala.reflect.api.Universe]; - // val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror]; - // applyImpl($m).asInstanceOf[U#Tree]; - // } - // def applyImpl[U >: Nothing <: scala.reflect.api.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Tree = { // val $u: U = $m$untyped.universe; // val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror]; // $u.Apply($u.Select($u.Select($u.build.This($m.staticPackage("scala.collection.immutable").moduleClass), $u.newTermName("List")), $u.newTermName("apply")), List($u.Literal($u.Constant(1)), $u.Literal($u.Constant(2)))) @@ -40,7 +35,7 @@ trait Extractors { // def apply[U >: Nothing <: scala.reflect.base.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Type = { // val $u: U = $m$untyped.universe; // val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror]; - // $u.TypeRef($u.ThisType($m.staticPackage("scala.collection.immutable").moduleClass), $m.staticClass("scala.collection.immutable.List"), List($m.staticClass("scala.Int").asTypeConstructor)) + // $u.TypeRef($u.ThisType($m.staticPackage("scala.collection.immutable").moduleClass), $m.staticClass("scala.collection.immutable.List"), List($m.staticClass("scala.Int").toTypeConstructor)) // } // }; // new $typecreator1() @@ -51,23 +46,7 @@ trait Extractors { val tparamu = newTypeName("U") val (reifierBase, reifierName, reifierTpt, reifierUniverse) = flavor match { case tpnme.REIFY_TYPECREATOR_PREFIX => (TypeCreatorClass, nme.apply, SelectFromTypeTree(Ident(tparamu), tpnme.Type), BaseUniverseClass) - case tpnme.REIFY_TREECREATOR_PREFIX => (TreeCreatorClass, nme.applyImpl, SelectFromTypeTree(Ident(BaseUniverseClass), tpnme.Tree), ApiUniverseClass) - case _ => throw new Error(s"unexpected flavor $flavor") - } - val reifierPreamble = flavor match { - case tpnme.REIFY_TYPECREATOR_PREFIX => Nil - case tpnme.REIFY_TREECREATOR_PREFIX => List[Tree]( - DefDef(NoMods, - nme.apply, - List(TypeDef(Modifiers(PARAM), tparamu, List(), TypeBoundsTree(Ident(NothingClass), CompoundTypeTree(Template(List(Ident(BaseUniverseClass), Ident(SingletonClass)), emptyValDef, List()))))), - List(List(ValDef(Modifiers(PARAM), nme.MIRROR_UNTYPED, AppliedTypeTree(Ident(MirrorOfClass), List(Ident(tparamu))), EmptyTree))), - SelectFromTypeTree(Ident(tparamu), tpnme.Tree), - Block( - ValDef(NoMods, nme.UNIVERSE_SHORT, Ident(ApiUniverseClass), TypeApply(Select(Select(Ident(nme.MIRROR_UNTYPED), nme.universe), nme.asInstanceOf_), List(Ident(ApiUniverseClass)))), - ValDef(NoMods, nme.MIRROR_SHORT, Select(Ident(nme.UNIVERSE_SHORT), tpnme.Mirror), TypeApply(Select(Ident(nme.MIRROR_UNTYPED), nme.asInstanceOf_), List(Select(Ident(nme.UNIVERSE_SHORT), tpnme.Mirror)))), - TypeApply(Select(Apply(TypeApply(Ident(reifierName), List(SingletonTypeTree(Ident(nme.UNIVERSE_SHORT)))), List(Ident(nme.MIRROR_SHORT))), nme.asInstanceOf_), List(SelectFromTypeTree(Ident(tparamu), tpnme.Tree))) - )) - ) + case tpnme.REIFY_TREECREATOR_PREFIX => (TreeCreatorClass, nme.apply, SelectFromTypeTree(Ident(tparamu), tpnme.Tree), BaseUniverseClass) case _ => throw new Error(s"unexpected flavor $flavor") } val reifierBody = { @@ -98,8 +77,7 @@ trait Extractors { Template(List(Ident(reifierBase)), emptyValDef, List( - DefDef(NoMods, nme.CONSTRUCTOR, List(), List(List()), TypeTree(), Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), Literal(Constant(())))) - ) ++ reifierPreamble ++ List( + DefDef(NoMods, nme.CONSTRUCTOR, List(), List(List()), TypeTree(), Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), Literal(Constant(())))), DefDef(NoMods, reifierName, List(TypeDef(Modifiers(PARAM), tparamu, List(), TypeBoundsTree(Ident(NothingClass), CompoundTypeTree(Template(List(Ident(reifierUniverse), Ident(SingletonClass)), emptyValDef, List()))))), @@ -128,7 +106,7 @@ trait Extractors { case Block( List(udef @ ValDef(_, _, _, universe), mdef @ ValDef(_, _, _, mirror)), Apply( - Apply(TypeApply(_, List(ttpe @ TypeTree())), List(_, Block(List(ClassDef(_, _, _, Template(_, _, List(_, _, DefDef(_, _, _, _, _, Block(_ :: _ :: symbolTable1, rtree)))))), _))), + Apply(TypeApply(_, List(ttpe @ TypeTree())), List(_, Block(List(ClassDef(_, _, _, Template(_, _, List(_, DefDef(_, _, _, _, _, Block(_ :: _ :: symbolTable1, rtree)))))), _))), // todo. doesn't take into account optimizations such as $u.TypeTag.Int or the upcoming closure optimization List(Apply(TypeApply(tagFactory @ Select(_, _), _), List(_, Block(List(ClassDef(_, _, _, Template(_, _, List(_, DefDef(_, _, _, _, _, Block(_ :: _ :: symbolTable2, rtpe)))))), _)))))) if udef.name == nme.UNIVERSE_SHORT && mdef.name == nme.MIRROR_SHORT => diff --git a/src/compiler/scala/tools/cmd/CommandLine.scala b/src/compiler/scala/tools/cmd/CommandLine.scala index d9a74a698c..ced3a97380 100644 --- a/src/compiler/scala/tools/cmd/CommandLine.scala +++ b/src/compiler/scala/tools/cmd/CommandLine.scala @@ -7,7 +7,6 @@ package scala.tools package cmd import scala.collection.mutable.ListBuffer -import language.postfixOps trait CommandLineConfig { def enforceArity: Boolean = true diff --git a/src/compiler/scala/tools/cmd/FromString.scala b/src/compiler/scala/tools/cmd/FromString.scala index 415940b3fd..d473796f39 100644 --- a/src/compiler/scala/tools/cmd/FromString.scala +++ b/src/compiler/scala/tools/cmd/FromString.scala @@ -43,7 +43,7 @@ object FromString { else cmd.runAndExit(println("'%s' is not an existing directory." format s)) } def ExistingDirRelativeTo(root: Directory) = new FromString[Directory]()(tagOfDirectory) { - private def resolve(s: String) = toDir(s) toAbsoluteWithRoot root toDirectory + private def resolve(s: String) = (toDir(s) toAbsoluteWithRoot root).toDirectory override def isDefinedAt(s: String) = resolve(s).isDirectory def apply(s: String): Directory = if (isDefinedAt(s)) resolve(s) diff --git a/src/compiler/scala/tools/cmd/package.scala b/src/compiler/scala/tools/cmd/package.scala index 5786b00fd1..8e74e6169e 100644 --- a/src/compiler/scala/tools/cmd/package.scala +++ b/src/compiler/scala/tools/cmd/package.scala @@ -8,6 +8,10 @@ package scala.tools package object cmd { def returning[T](x: T)(f: T => Unit): T = { f(x) ; x } + // make some language features in this package compile without warning + implicit def implicitConversions = language.implicitConversions + implicit def postfixOps = language.postfixOps + private[cmd] def debug(msg: String) = println(msg) def runAndExit(body: => Unit): Nothing = { diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 1d29e33c50..9a6d32be01 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -95,11 +95,12 @@ trait Trees extends reflect.internal.Trees { self: Global => val (edefs, rest) = body span treeInfo.isEarlyDef val (evdefs, etdefs) = edefs partition treeInfo.isEarlyValDef val gvdefs = evdefs map { - case vdef @ ValDef(_, _, tpt, _) => copyValDef(vdef)( - // !!! I know "atPos in case" wasn't intentionally planted to - // add an air of mystery to this file, but it is the sort of - // comment which only its author could love. - tpt = atPos(vdef.pos.focus)(TypeTree() setOriginal tpt setPos tpt.pos.focus), // atPos in case + case vdef @ ValDef(_, _, tpt, _) => + copyValDef(vdef)( + // atPos for the new tpt is necessary, since the original tpt might have no position + // (when missing type annotation for ValDef for example), so even though setOriginal modifies the + // position of TypeTree, it would still be NoPosition. That's what the author meant. + tpt = atPos(vdef.pos.focus)(TypeTree() setOriginal tpt setPos tpt.pos.focus), rhs = EmptyTree ) } @@ -125,7 +126,7 @@ trait Trees extends reflect.internal.Trees { self: Global => DefDef(constrMods, nme.CONSTRUCTOR, List(), vparamss1, TypeTree(), Block(lvdefs ::: List(superCall), Literal(Constant()))))) } } - constrs foreach (ensureNonOverlapping(_, parents ::: gvdefs)) + constrs foreach (ensureNonOverlapping(_, parents ::: gvdefs, focus=false)) // Field definitions for the class - remove defaults. val fieldDefs = vparamss.flatten map (vd => copyValDef(vd)(mods = vd.mods &~ DEFAULTPARAM, rhs = EmptyTree)) diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index 982267097b..c46b650949 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -73,6 +73,14 @@ abstract class GenICode extends SubComponent { ctx1 } + /** If the selector type has a member with the right name, + * it is the host class; otherwise the symbol's owner. + */ + def findHostClass(selector: Type, sym: Symbol) = selector member sym.name match { + case NoSymbol => log(s"Rejecting $selector as host class for $sym") ; sym.owner + case _ => selector.typeSymbol + } + /////////////////// Code generation /////////////////////// def gen(tree: Tree, ctx: Context): Context = tree match { @@ -949,13 +957,14 @@ abstract class GenICode extends SubComponent { */ fun match { case Select(qual, _) => - val qualSym = qual.tpe.typeSymbol + val qualSym = findHostClass(qual.tpe, sym) + if (qualSym == ArrayClass) cm setTargetTypeKind toTypeKind(qual.tpe) else cm setHostClass qualSym - debuglog( + log( if (qualSym == ArrayClass) "Stored target type kind " + toTypeKind(qual.tpe) + " for " + sym.fullName - else "Set more precise host class for " + sym.fullName + " host: " + qualSym + else s"Set more precise host class for ${sym.fullName} hostClass: $qualSym" ) case _ => } @@ -1005,13 +1014,14 @@ abstract class GenICode extends SubComponent { case Select(qualifier, selector) => val sym = tree.symbol generatedType = toTypeKind(sym.info) - val hostClass = qualifier.tpe.typeSymbol.orElse(sym.owner) + val hostClass = findHostClass(qualifier.tpe, sym) + log(s"Host class of $sym with qual $qualifier (${qualifier.tpe}) is $hostClass") if (sym.isModule) { genLoadModule(ctx, tree) } else if (sym.isStaticMember) { - ctx.bb.emit(LOAD_FIELD(sym, true) setHostClass hostClass, tree.pos) + ctx.bb.emit(LOAD_FIELD(sym, true) setHostClass hostClass, tree.pos) ctx } else { diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala index 7a5615ac26..962c47f443 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala @@ -470,6 +470,8 @@ abstract class TypeFlowAnalysis { val isOnWatchlist = mutable.Set.empty[Instruction] + val warnIfInlineFails = mutable.Set.empty[opcodes.CALL_METHOD] // cache for a given IMethod (ie cleared on Inliner.analyzeMethod). + /* Each time CallerCalleeInfo.isSafeToInline determines a concrete callee is unsafe to inline in the current caller, the fact is recorded in this TFA instance for the purpose of avoiding devoting processing to that callsite next time. The condition of "being unsafe to inline in the current caller" sticks across inlinings and TFA re-inits @@ -510,6 +512,7 @@ abstract class TypeFlowAnalysis { // initially populate the watchlist with all callsites standing a chance of being inlined isOnWatchlist.clear() relevantBBs.clear() + warnIfInlineFails.clear() /* TODO Do we want to perform inlining in non-finally exception handlers? * Seems counterproductive (the larger the method the less likely it will be JITed. * It's not that putting on radar only `linearizer linearizeAt (m, m.startBlock)` makes for much shorter inlining times (a minor speedup nonetheless) @@ -533,11 +536,11 @@ abstract class TypeFlowAnalysis { private def putOnRadar(blocks: Traversable[BasicBlock]) { for(bb <- blocks) { - val preCands = bb.toList collect { - case cm : opcodes.CALL_METHOD - if isPreCandidate(cm) /* && !isReceiverKnown(cm) */ - => cm + val calls = bb.toList collect { case cm : opcodes.CALL_METHOD => cm } + for(c <- calls; if(inliner.hasInline(c.method))) { + warnIfInlineFails += c } + val preCands = calls filter isPreCandidate isOnWatchlist ++= preCands } relevantBBs ++= blocks diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 025046f19e..f681de93b6 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -993,8 +993,13 @@ abstract class GenASM extends SubComponent with BytecodeWriters { case sb@ScalaSigBytes(bytes) => // see http://www.scala-lang.org/sid/10 (Storage of pickled Scala signatures in class files) // also JVMS Sec. 4.7.16.1 The element_value structure and JVMS Sec. 4.4.7 The CONSTANT_Utf8_info Structure. - val assocValue = (if(sb.fitsInOneString) strEncode(sb) else arrEncode(sb)) - av.visit(name, assocValue) + if (sb.fitsInOneString) + av.visit(name, strEncode(sb)) + else { + val arrAnnotV: asm.AnnotationVisitor = av.visitArray(name) + for(arg <- arrEncode(sb)) { arrAnnotV.visit(name, arg) } + arrAnnotV.visitEnd() + } // for the lazy val in ScalaSigBytes to be GC'ed, the invoker of emitAnnotations() should hold the ScalaSigBytes in a method-local var that doesn't escape. case ArrayAnnotArg(args) => @@ -1159,7 +1164,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { val linkedClass = moduleClass.companionClass val linkedModule = linkedClass.companionSymbol lazy val conflictingNames: Set[Name] = { - linkedClass.info.members collect { case sym if sym.name.isTermName => sym.name } toSet + (linkedClass.info.members collect { case sym if sym.name.isTermName => sym.name }).toSet } debuglog("Potentially conflicting names for forwarders: " + conflictingNames) @@ -1351,7 +1356,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { val ps = c.symbol.info.parents val superInterfaces0: List[Symbol] = if(ps.isEmpty) Nil else c.symbol.mixinClasses; - val superInterfaces = superInterfaces0 ++ c.symbol.annotations.flatMap(ann => newParentForAttr(ann.symbol)) distinct + val superInterfaces = (superInterfaces0 ++ c.symbol.annotations.flatMap(ann => newParentForAttr(ann.symbol))).distinct if(superInterfaces.isEmpty) EMPTY_STRING_ARRAY else mkArray(minimizeInterfaces(superInterfaces) map javaName) @@ -3183,7 +3188,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { hops ::= prev if (hops.contains(dest)) { // leave infinite-loops in place - return (dest, hops filterNot (dest eq)) + return (dest, hops filterNot (dest eq _)) } prev = dest; false diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala index 44acfed411..cce18d436f 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala @@ -129,11 +129,15 @@ abstract class Inliners extends SubComponent { override def apply(c: IClass) { queue += c } override def run() { + knownLacksInline.clear() + knownHasInline.clear() try { super.run() for(c <- queue) { inliner analyzeClass c } } finally { inliner.clearCaches() + knownLacksInline.clear() + knownHasInline.clear() } } } @@ -157,7 +161,21 @@ abstract class Inliners extends SubComponent { } } - def hasInline(sym: Symbol) = sym hasAnnotation ScalaInlineClass + val knownLacksInline = mutable.Set.empty[Symbol] // cache to avoid multiple inliner.hasInline() calls. + val knownHasInline = mutable.Set.empty[Symbol] // as above. Motivated by the need to warn on "inliner failures". + + def hasInline(sym: Symbol) = { + if (knownLacksInline(sym)) false + else if(knownHasInline(sym)) true + else { + val b = (sym hasAnnotation ScalaInlineClass) + if(b) { knownHasInline += sym } + else { knownLacksInline += sym } + + b + } + } + def hasNoInline(sym: Symbol) = sym hasAnnotation ScalaNoInlineClass /** @@ -536,6 +554,10 @@ abstract class Inliners extends SubComponent { } while (retry && count < MAX_INLINE_RETRY) + for(inlFail <- tfa.warnIfInlineFails) { + warn(inlFail.pos, "At the end of the day, could not inline @inline-marked method " + inlFail.method.originalName.decode) + } + m.normalize if (sizeBeforeInlining > 0) { val instrAfterInlining = m.code.instructionCount @@ -731,6 +753,7 @@ abstract class Inliners extends SubComponent { tfa.remainingCALLs.remove(instr) // this bookkpeeping is done here and not in MTFAGrowable.reinit due to (1st) convenience and (2nd) necessity. tfa.isOnWatchlist.remove(instr) // ditto + tfa.warnIfInlineFails.remove(instr) val targetPos = instr.pos log("Inlining " + inc.m + " in " + caller.m + " at pos: " + posToStr(targetPos)) diff --git a/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala b/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala index bae61f1a3b..c46c33c1ee 100644 --- a/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala +++ b/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala @@ -333,7 +333,7 @@ class DotDiagramGenerator(settings: doc.Settings) extends DiagramGenerator { else NodeSeq.Empty } catch { - case exc => + case exc: Exception => if (settings.docDiagramsDebug.value) { settings.printMsg("\n\n**********************************************************************") settings.printMsg("Encountered an error while generating page for " + template.qualifiedName) diff --git a/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala index f4c96505a7..9d141efe0a 100755 --- a/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala @@ -8,7 +8,6 @@ package doc package model import scala.collection._ -import language.reflectiveCalls object IndexModelFactory { diff --git a/src/compiler/scala/tools/nsc/doc/model/Links.scala b/src/compiler/scala/tools/nsc/doc/model/LinkTo.scala index b76dee0f14..b76dee0f14 100644 --- a/src/compiler/scala/tools/nsc/doc/model/Links.scala +++ b/src/compiler/scala/tools/nsc/doc/model/LinkTo.scala diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala index 00e6f3769e..8805f68634 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala @@ -380,7 +380,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { if (settings.docImplicits.value) makeImplicitConversions(sym, this) else Nil // members as given by the compiler - lazy val memberSyms = sym.info.members.filter(s => membersShouldDocument(s, this)) + lazy val memberSyms = sym.info.members.filter(s => membersShouldDocument(s, this)).toList // the inherited templates (classes, traits or objects) var memberSymsLazy = memberSyms.filter(t => templateShouldDocument(t, this) && !inOriginalOwner(t, this)) @@ -712,7 +712,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { override def inheritedFrom = Nil override def isRootPackage = true override lazy val memberSyms = - (bSym.info.members ++ EmptyPackage.info.members) filter { s => + (bSym.info.members ++ EmptyPackage.info.members).toList filter { s => s != EmptyPackage && s != RootPackage } }) diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala index a12b67c9ed..5a0cc602e5 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala @@ -386,7 +386,7 @@ trait ModelFactoryImplicitSupport { lazy val memberImpls: List[MemberImpl] = { // Obtain the members inherited by the implicit conversion - val memberSyms = toType.members.filter(implicitShouldDocument(_)) + val memberSyms = toType.members.filter(implicitShouldDocument(_)).toList val existingSyms = sym.info.members // Debugging part :) diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala index 1a11964e37..85d6a8911e 100644 --- a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala @@ -660,7 +660,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member else if (check(",,")) subscript() else if (check("[[")) link() else { - readUntil { char == safeTagMarker || check("''") || char == '`' || check("__") || char == '^' || check(",,") || check("[[") || check("{{") || isInlineEnd || checkParaEnded || char == endOfLine } + readUntil { char == safeTagMarker || check("''") || char == '`' || check("__") || char == '^' || check(",,") || check("[[") || isInlineEnd || checkParaEnded || char == endOfLine } Text(getRead()) } } diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala index 801b4ad22b..aab1c8fb7e 100644 --- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala +++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala @@ -252,6 +252,19 @@ trait CompilerControl { self: Global => /** Asks for a computation to be done quickly on the presentation compiler thread */ def ask[A](op: () => A): A = if (self.onCompilerThread) op() else scheduler doQuickly op + /** Asks for a computation to be done on presentation compiler thread, returning + * a response with the result or an exception + */ + def askForResponse[A](op: () => A): Response[A] = { + val r = new Response[A] + val ir = scheduler askDoQuickly op + ir onComplete { + case Left(result) => r set result + case Right(exc) => r raise exc + } + r + } + def onCompilerThread = Thread.currentThread == compileRunner /** Info given for every member found by completion @@ -390,7 +403,7 @@ trait CompilerControl { self: Global => case _ => println("don't know what to do with this " + action.getClass) } } - + override def doQuickly[A](op: () => A): A = { throw new FailedInterrupt(new Exception("Posted a work item to a compiler that's shutting down")) } diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala index 2a435aa6f6..77bc77e966 100644 --- a/src/compiler/scala/tools/nsc/interactive/Global.scala +++ b/src/compiler/scala/tools/nsc/interactive/Global.scala @@ -749,12 +749,20 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") val originalTypeParams = sym.owner.typeParams parseAndEnter(unit) val pre = adaptToNewRunMap(ThisType(sym.owner)) - val newsym = pre.typeSymbol.info.decl(sym.name) filter { alt => + val rawsym = pre.typeSymbol.info.decl(sym.name) + val newsym = rawsym filter { alt => sym.isType || { try { val tp1 = pre.memberType(alt) onTypeError NoType val tp2 = adaptToNewRunMap(sym.tpe) substSym (originalTypeParams, sym.owner.typeParams) - matchesType(tp1, tp2, false) + matchesType(tp1, tp2, false) || { + debugLog(s"getLinkPos matchesType($tp1, $tp2) failed") + val tp3 = adaptToNewRunMap(sym.tpe) substSym (originalTypeParams, alt.owner.typeParams) + matchesType(tp1, tp3, false) || { + debugLog(s"getLinkPos fallback matchesType($tp1, $tp3) failed") + false + } + } } catch { case ex: ControlThrowable => throw ex @@ -766,8 +774,11 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") } } if (newsym == NoSymbol) { - debugLog("link not found " + sym + " " + source + " " + pre) - NoPosition + if (rawsym.exists && !rawsym.isOverloaded) rawsym.pos + else { + debugLog("link not found " + sym + " " + source + " " + pre) + NoPosition + } } else if (newsym.isOverloaded) { settings.uniqid.value = true debugLog("link ambiguous " + sym + " " + source + " " + pre + " " + newsym.alternatives) @@ -1030,11 +1041,15 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") } } - def getInstrumented(source: SourceFile, line: Int, response: Response[(String, Array[Char])]) { - respond(response) { - instrument(source, line) + def getInstrumented(source: SourceFile, line: Int, response: Response[(String, Array[Char])]) = + try { + interruptsEnabled = false + respond(response) { + instrument(source, line) + } + } finally { + interruptsEnabled = true } - } // ---------------- Helper classes --------------------------- diff --git a/src/compiler/scala/tools/nsc/interactive/REPL.scala b/src/compiler/scala/tools/nsc/interactive/REPL.scala index 1dcc979255..6876ea14e0 100644 --- a/src/compiler/scala/tools/nsc/interactive/REPL.scala +++ b/src/compiler/scala/tools/nsc/interactive/REPL.scala @@ -11,7 +11,7 @@ import scala.tools.nsc.symtab._ import scala.tools.nsc.ast._ import scala.tools.nsc.reporters._ import scala.tools.nsc.io._ -import scala.tools.nsc.scratchpad.{Executor, SourceInserter} +import scala.tools.nsc.scratchpad.SourceInserter import scala.tools.nsc.interpreter.AbstractFileClassLoader import java.io.{File, FileWriter} @@ -138,7 +138,6 @@ object REPL { * @param arguments Further argumenrs to pass to the compiler * @return Optionallu, if no -d option is given, the virtual directory * contained the generated bytecode classes - */ def compileInstrumented(iSourceName: String, arguments: List[String]): Option[AbstractFile] = { println("compiling "+iSourceName) val command = new CompilerCommand(iSourceName :: arguments, reporter.error(scala.reflect.internal.util.NoPosition, _)) @@ -176,6 +175,7 @@ object REPL { println("done") si.currentContents } + */ /** The method for implementing worksheet functionality. * @param arguments a file name, followed by optional command line arguments that are passed @@ -186,17 +186,22 @@ object REPL { * and outputs in the right column, or None if the presentation compiler * does not respond to askInstrumented. */ - def instrument(arguments: List[String], line: Int): Option[Array[Char]] = { + def instrument(arguments: List[String], line: Int): Option[String] = { val source = toSourceFile(arguments.head) // strip right hand side comment column and any trailing spaces from all lines val strippedSource = new BatchSourceFile(source.file, SourceInserter.stripRight(source.content)) + println("stripped source = "+strippedSource) comp.askReload(List(strippedSource), reloadResult) comp.askInstrumented(strippedSource, line, instrumentedResult) using(instrumentedResult) { case (iFullName, iContents) => + println(s"instrumented source $iFullName = ${iContents.mkString}") val iSourceName = writeInstrumented(iFullName, iContents) - val vdirOpt = compileInstrumented(iSourceName, arguments.tail) + iSourceName +/* + * val vdirOpt = compileInstrumented(iSourceName, arguments.tail) runInstrumented(vdirOpt, iFullName, strippedSource.content) + */ } } diff --git a/src/compiler/scala/tools/nsc/interactive/RangePositions.scala b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala index 06828f3a3a..b702d2787c 100644 --- a/src/compiler/scala/tools/nsc/interactive/RangePositions.scala +++ b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala @@ -41,11 +41,11 @@ self: scala.tools.nsc.Global => /** A position that wraps a set of trees. * The point of the wrapping position is the point of the default position. * If some of the trees are ranges, returns a range position enclosing all ranges - * Otherwise returns default position. + * Otherwise returns default position that is either focused or not. */ - override def wrappingPos(default: Position, trees: List[Tree]): Position = { + override def wrappingPos(default: Position, trees: List[Tree], focus: Boolean): Position = { val ranged = trees filter (_.pos.isRange) - if (ranged.isEmpty) default.focus + if (ranged.isEmpty) if (focus) default.focus else default else new RangePosition(default.source, (ranged map (_.pos.start)).min, default.point, (ranged map (_.pos.end)).max) } @@ -59,13 +59,25 @@ self: scala.tools.nsc.Global => if (headpos.isDefined) wrappingPos(headpos, trees) else headpos } -/* - override def integratePos(tree: Tree, pos: Position) = - if (pos.isSynthetic && !tree.pos.isSynthetic) tree.syntheticDuplicate - else tree -*/ - // -------------- ensuring no overlaps ------------------------------- + + /** Ensure that given tree has no positions that overlap with + * any of the positions of `others`. This is done by + * shortening the range, assigning TransparentPositions + * to some of the nodes in `tree` or focusing on the position. + */ + override def ensureNonOverlapping(tree: Tree, others: List[Tree], focus: Boolean) { + def isOverlapping(pos: Position) = + pos.isRange && (others exists (pos overlaps _.pos)) + if (isOverlapping(tree.pos)) { + val children = tree.children + children foreach (ensureNonOverlapping(_, others, focus)) + if (tree.pos.isOpaqueRange) { + val wpos = wrappingPos(tree.pos, children, focus) + tree setPos (if (isOverlapping(wpos)) tree.pos.makeTransparent else wpos) + } + } + } def solidDescendants(tree: Tree): List[Tree] = if (tree.pos.isTransparent) tree.children flatMap solidDescendants @@ -106,24 +118,6 @@ self: scala.tools.nsc.Global => if (ts.head == t) replacement ::: ts.tail else ts.head :: replace(ts.tail, t, replacement) - /** Ensure that given tree has no positions that overlap with - * any of the positions of `others`. This is done by - * shortening the range or assigning TransparentPositions - * to some of the nodes in `tree`. - */ - override def ensureNonOverlapping(tree: Tree, others: List[Tree]) { - def isOverlapping(pos: Position) = - pos.isRange && (others exists (pos overlaps _.pos)) - if (isOverlapping(tree.pos)) { - val children = tree.children - children foreach (ensureNonOverlapping(_, others)) - if (tree.pos.isOpaqueRange) { - val wpos = wrappingPos(tree.pos.focus, children) - tree setPos (if (isOverlapping(wpos)) tree.pos.makeTransparent else wpos) - } - } - } - /** Does given list of trees have mutually non-overlapping positions? * pre: None of the trees is transparent */ diff --git a/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala b/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala index c79248e1c1..bd1869e1a4 100644 --- a/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala +++ b/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala @@ -30,8 +30,12 @@ trait ScratchPadMaker { self: Global => private def literal(str: String) = "\"\"\""+str+"\"\"\"" + private val prologue = "import scala.runtime.WorksheetSupport._; def main(args: Array[String])=$execute{" + + private val epilogue = "}" + private def applyPendingPatches(offset: Int) = { - if (skipped == 0) patches += Patch(offset, "import scala.tools.nsc.scratchpad.Executor._; ") + if (skipped == 0) patches += Patch(offset, prologue) for (msg <- toPrint) patches += Patch(offset, ";System.out.println("+msg+")") toPrint.clear() } @@ -92,10 +96,12 @@ trait ScratchPadMaker { self: Global => case PackageDef(_, _) => super.traverse(tree) case ModuleDef(_, name, Template(_, _, body)) => - if (objectName.length == 0) - objectName = tree.symbol.fullName + val topLevel = objectName.isEmpty + if (topLevel) objectName = tree.symbol.fullName body foreach traverseStat applyPendingPatches(skipped) + if (topLevel) + patches += Patch(skipped, epilogue) case _ => } diff --git a/src/compiler/scala/tools/nsc/interpreter/Imports.scala b/src/compiler/scala/tools/nsc/interpreter/Imports.scala index d579e0369e..5e72d2b661 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Imports.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Imports.scala @@ -191,5 +191,5 @@ trait Imports { prevRequestList flatMap (req => req.handlers map (req -> _)) private def membersAtPickler(sym: Symbol): List[Symbol] = - beforePickler(sym.info.nonPrivateMembers) + beforePickler(sym.info.nonPrivateMembers.toList) }
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala index c429e3b196..b9849e40d1 100644 --- a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala +++ b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala @@ -52,10 +52,10 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput // XXX we'd like to say "filterNot (_.isDeprecated)" but this causes the // compiler to crash for reasons not yet known. - def members = afterTyper((effectiveTp.nonPrivateMembers ++ anyMembers) filter (_.isPublic)) - def methods = members filter (_.isMethod) - def packages = members filter (_.isPackage) - def aliases = members filter (_.isAliasType) + def members = afterTyper((effectiveTp.nonPrivateMembers.toList ++ anyMembers) filter (_.isPublic)) + def methods = members.toList filter (_.isMethod) + def packages = members.toList filter (_.isPackage) + def aliases = members.toList filter (_.isAliasType) def memberNames = members map tos def methodNames = methods map tos diff --git a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala index 236f3f23c5..5cea86d57d 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 scala.reflect.internal.Flags._ import language.implicitConversions trait MemberHandlers { @@ -126,7 +127,7 @@ trait MemberHandlers { class DefHandler(member: DefDef) extends MemberDefHandler(member) { private def vparamss = member.vparamss - private def isMacro = member.mods.hasFlag(scala.reflect.internal.Flags.MACRO) + private def isMacro = member.symbol hasFlag MACRO // true if not a macro and 0-arity override def definesValue = !isMacro && flattensToEmpty(vparamss) override def resultExtractionCode(req: Request) = @@ -211,7 +212,7 @@ trait MemberHandlers { beforePickler(individualNames map (targetType nonPrivateMember _)) lazy val wildcardSymbols: List[Symbol] = - if (importsWildcard) beforePickler(targetType.nonPrivateMembers) + if (importsWildcard) beforePickler(targetType.nonPrivateMembers.toList) else Nil /** Complete list of names imported by a wildcard */ diff --git a/src/compiler/scala/tools/nsc/interpreter/Power.scala b/src/compiler/scala/tools/nsc/interpreter/Power.scala index 57d7cef726..ebc02d98ed 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Power.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Power.scala @@ -62,7 +62,7 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re def discarded = seen.size - keep.size def members(x: Symbol): List[Symbol] = - if (x.rawInfo.isComplete) x.info.members + if (x.rawInfo.isComplete) x.info.members.toList else Nil var lastCount = -1 @@ -216,7 +216,7 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re def declsOriginal = membersDeclared filterNot (_.isOverride) def members = membersUnabridged filterNot excludeMember - def membersUnabridged = tpe.members + def membersUnabridged = tpe.members.toList def membersDeclared = members filterNot excludeMember def membersInherited = members filterNot (membersDeclared contains _) def memberTypes = members filter (_.name.isTypeName) diff --git a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala index 56b9c7011c..202d5d3f82 100644 --- a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala +++ b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala @@ -212,8 +212,7 @@ trait TypeStrings { } private def tparamString[T: ru.TypeTag] : String = { - // [Eugene++ to Paul] needs review!! - def typeArguments: List[ru.Type] = ru.typeOf[T].typeArguments + def typeArguments: List[ru.Type] = ru.typeOf[T] match { case ru.TypeRef(_, _, args) => args; case _ => Nil } // [Eugene++] todo. need to use not the `rootMirror`, but a mirror with the REPL's classloader // how do I get to it? acquiring context classloader seems unreliable because of multithreading def typeVariables: List[java.lang.Class[_]] = typeArguments map (targ => ru.rootMirror.runtimeClass(targ)) diff --git a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala index a37fdc3ed1..58c2426602 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala @@ -139,7 +139,7 @@ trait JavaScanners extends ast.parser.ScannersCommon { kwOffset = offset arr } - final val tokenName = allKeywords map (_.swap) toMap + final val tokenName = allKeywords.map(_.swap).toMap //Token representation ----------------------------------------------------- diff --git a/src/compiler/scala/tools/nsc/scratchpad/Executor.scala b/src/compiler/scala/tools/nsc/scratchpad/Executor.scala deleted file mode 100644 index 89523df71e..0000000000 --- a/src/compiler/scala/tools/nsc/scratchpad/Executor.scala +++ /dev/null @@ -1,55 +0,0 @@ -package scala.tools.nsc.scratchpad - -import java.io.{PrintStream, OutputStreamWriter, Writer} - -import scala.runtime.ScalaRunTime.stringOf -import java.lang.reflect.InvocationTargetException -import scala.reflect.runtime.ReflectionUtils._ - -object Executor { - - println("exec started") - - private var currentWriter: CommentWriter = null - - /** Execute module with given name, redirecting all output to given - * source inserter. Catch all exceptions and print stacktrace of underlying causes. - */ - def execute(name: String, si: SourceInserter, classLoader: ClassLoader = getClass.getClassLoader) { - val oldSysOut = System.out - val oldSysErr = System.err - val oldConsOut = Console.out - val oldConsErr = Console.err - val oldCwr = currentWriter - currentWriter = new CommentWriter(si) - val newOut = new PrintStream(new CommentOutputStream(currentWriter)) - System.setOut(newOut) - System.setErr(newOut) - Console.setOut(newOut) - Console.setErr(newOut) - try { - singletonInstance(classLoader, name) - } catch { - case ex: Throwable => - unwrapThrowable(ex) match { - case _: StopException => ; - case cause => cause.printStackTrace() - } - } finally { - currentWriter.close() - System.setOut(oldSysOut) - System.setErr(oldSysErr) - Console.setOut(oldConsOut) - Console.setErr(oldConsErr) - currentWriter = oldCwr - } - } - - def $skip(n: Int) = currentWriter.skip(n) - - def $stop() = throw new StopException - - def $show(x: Any): String = stringOf(x, scala.Int.MaxValue) -} - -class StopException extends Exception diff --git a/src/compiler/scala/tools/nsc/scratchpad/Mixer.scala b/src/compiler/scala/tools/nsc/scratchpad/Mixer.scala new file mode 100644 index 0000000000..46ccc32097 --- /dev/null +++ b/src/compiler/scala/tools/nsc/scratchpad/Mixer.scala @@ -0,0 +1,98 @@ +package scala.tools.nsc.scratchpad + +import java.io.{FileInputStream, InputStreamReader, IOException} + +import scala.runtime.ScalaRunTime.stringOf +import java.lang.reflect.InvocationTargetException +import scala.reflect.runtime.ReflectionUtils._ +import collection.mutable.ArrayBuffer + +class Mixer { + + protected val stdSeparator = "//> " + protected val ctdSeparator = "//| " + protected val sepColumn = 50 + protected val tabInc = 8 + + type Comments = Seq[(Int, Array[Char])] + + def parseComments(comments: Array[Char]): Iterator[(Int, Array[Char])] = new Iterator[(Int, Array[Char])] { + var idx = 0 + def hasNext = idx < comments.length + def next() = { + val nextSpace = comments indexOf (' ', idx) + var nextNL = comments indexOf ('\n', nextSpace + 1) + if (nextNL < 0) nextNL = comments.length + val result = + (new String(comments.slice(idx, nextSpace)).toInt, comments.slice(nextSpace + 1, nextNL)) + idx = nextNL + 1 + result + } + } + + def mix(source: Array[Char], comments: Array[Char]): Array[Char] = { + val mixed = new ArrayBuffer[Char] + var written = 0 + def align() = { + var idx = mixed.lastIndexOf('\n') + 1 + var col = 0 + while (idx < mixed.length) { + col = + if (mixed(idx) == '\t') (col / tabInc) * tabInc + tabInc + else col + 1 + idx += 1 + } + if (col > sepColumn) { + mixed += '\n' + col = 0 + } + mixed ++= (" " * (sepColumn - col)) + } + for ((offset, cs) <- parseComments(comments)) { + val sep = + if (written < offset) { + for (i <- written until offset) mixed += source(i) + written = offset + stdSeparator + } else { + mixed += '\n' + ctdSeparator + } + align() + mixed ++= sep ++= cs + } + mixed ++= source.view(written, source.length) + mixed.toArray + } + +} + +object Mixer extends Mixer { + + def contents(name: String): Array[Char] = { + val page = new Array[Char](2 << 14) + val buf = new ArrayBuffer[Char] + val in = new FileInputStream(name) + val rdr = new InputStreamReader(in) + var nread = 0 + do { + nread = rdr.read(page, 0, page.length) + buf ++= (if (nread == page.length) page else page.take(nread)) + } while (nread >= 0) + buf.toArray + } + + def main(args: Array[String]) { + val mixer = new Mixer + try { + require(args.length == 2, "required arguments: file1 file2") + val source = contents(args(0)) + val comments = contents(args(1)) + val mixed = mixer.mix(source, comments) + println(mixed.mkString) + } catch { + case ex: IOException => + println("error: "+ ex.getMessage) + } + } +} diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index aa30a7a45b..3906d7761f 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -205,8 +205,6 @@ trait ScalaSettings extends AbsScalaSettings // Feature extensions 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.", "") /** * IDE-specific settings diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala index 9b4e793241..46c52e68a2 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -112,11 +112,23 @@ abstract class SymbolLoaders { enterClassAndModule(root, name, new SourcefileLoader(src)) } + /** The package objects of scala and scala.reflect should always + * be loaded in binary if classfiles are available, even if sourcefiles + * are newer. Late-compiling these objects from source leads to compilation + * order issues. + * Note: We do a name-base comparison here because the method is called before we even + * have ReflectPackage defined. + */ + def binaryOnly(owner: Symbol, name: String): Boolean = + name == "package" && + (owner.fullName == "scala" || owner.fullName == "scala.reflect") + /** Initialize toplevel class and module symbols in `owner` from class path representation `classRep` */ def initializeFromClassPath(owner: Symbol, classRep: ClassPath[platform.BinaryRepr]#ClassRep) { ((classRep.binary, classRep.source) : @unchecked) match { - case (Some(bin), Some(src)) if platform.needCompile(bin, src) => + case (Some(bin), Some(src)) + if platform.needCompile(bin, src) && !binaryOnly(owner, classRep.name) => if (settings.verbose.value) inform("[symloader] picked up newer source file for " + src.path) global.loaders.enterToplevelsFromSource(owner, classRep.name, src) case (None, Some(src)) => diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index e672f1914a..108c5ced6f 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -58,23 +58,6 @@ abstract class CleanUp extends Transform with ast.TreeDSL { } private def mkTerm(prefix: String): TermName = unit.freshTermName(prefix) - /** Kludge to provide a safe fix for #4560: - * If we generate a reference in an implementation class, we - * watch out for embedded This(..) nodes that point to the interface. - * These must be wrong. We fix them by setting symbol and type to - * the enclosing implementation class instead. - */ - def safeREF(sym: Symbol) = { - def fix(tree: Tree): Unit = tree match { - case Select(qual @ This(_), name) if qual.symbol != currentClass => - qual.setSymbol(currentClass).setType(currentClass.tpe) - case _ => - } - val tree = REF(sym) - if (currentClass.isImplClass && sym.owner == currentClass) fix(tree) - tree - } - //private val classConstantMeth = new HashMap[String, Symbol] //private val symbolStaticFields = new HashMap[String, (Symbol, Tree, Tree)] @@ -164,7 +147,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { val varDef = typedPos( VAL(varSym) === forInit ) newStaticMembers append transform(varDef) - val varInit = typedPos( safeREF(varSym) === forInit ) + val varInit = typedPos( REF(varSym) === forInit ) newStaticInits append transform(varInit) varSym @@ -200,7 +183,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { addStaticVariableToClass(nme.reflParamsCacheName, arrayType(ClassClass.tpe), fromTypesToClassArrayLiteral(paramTypes), true) addStaticMethodToClass((_, forReceiverSym) => - gen.mkMethodCall(REF(forReceiverSym), Class_getMethod, Nil, List(LIT(method), safeREF(reflParamsCacheSym))) + gen.mkMethodCall(REF(forReceiverSym), Class_getMethod, Nil, List(LIT(method), REF(reflParamsCacheSym))) ) case MONO_CACHE => @@ -239,11 +222,11 @@ abstract class CleanUp extends Transform with ast.TreeDSL { addStaticMethodToClass((_, forReceiverSym) => BLOCK( IF (isCacheEmpty(forReceiverSym)) THEN BLOCK( - safeREF(reflMethodCacheSym) === ((REF(forReceiverSym) DOT Class_getMethod)(LIT(method), safeREF(reflParamsCacheSym))) , - safeREF(reflClassCacheSym) === gen.mkSoftRef(REF(forReceiverSym)), + REF(reflMethodCacheSym) === ((REF(forReceiverSym) DOT Class_getMethod)(LIT(method), REF(reflParamsCacheSym))) , + REF(reflClassCacheSym) === gen.mkSoftRef(REF(forReceiverSym)), UNIT ) ENDIF, - safeREF(reflMethodCacheSym) + REF(reflMethodCacheSym) ) ) @@ -277,22 +260,22 @@ abstract class CleanUp extends Transform with ast.TreeDSL { val reflPolyCacheSym: Symbol = ( addStaticVariableToClass(nme.reflPolyCacheName, SoftReferenceClass.tpe, mkNewPolyCache, false) ) - def getPolyCache = gen.mkCast(fn(safeREF(reflPolyCacheSym), nme.get), MethodCacheClass.tpe) + def getPolyCache = gen.mkCast(fn(REF(reflPolyCacheSym), nme.get), MethodCacheClass.tpe) addStaticMethodToClass((reflMethodSym, forReceiverSym) => { val methodSym = reflMethodSym.newVariable(mkTerm("method"), ad.pos) setInfo MethodClass.tpe BLOCK( - IF (getPolyCache OBJ_EQ NULL) THEN (safeREF(reflPolyCacheSym) === mkNewPolyCache) ENDIF, + IF (getPolyCache OBJ_EQ NULL) THEN (REF(reflPolyCacheSym) === mkNewPolyCache) ENDIF, VAL(methodSym) === ((getPolyCache DOT methodCache_find)(REF(forReceiverSym))) , IF (REF(methodSym) OBJ_!= NULL) . THEN (Return(REF(methodSym))) ELSE { - def methodSymRHS = ((REF(forReceiverSym) DOT Class_getMethod)(LIT(method), safeREF(reflParamsCacheSym))) + def methodSymRHS = ((REF(forReceiverSym) DOT Class_getMethod)(LIT(method), REF(reflParamsCacheSym))) def cacheRHS = ((getPolyCache DOT methodCache_add)(REF(forReceiverSym), REF(methodSym))) BLOCK( REF(methodSym) === (REF(ensureAccessibleMethod) APPLY (methodSymRHS)), - safeREF(reflPolyCacheSym) === gen.mkSoftRef(cacheRHS), + REF(reflPolyCacheSym) === gen.mkSoftRef(cacheRHS), Return(REF(methodSym)) ) } @@ -400,7 +383,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { def genDefaultCall = { // reflective method call machinery val invokeName = MethodClass.tpe member nme.invoke_ // reflect.Method.invoke(...) - def cache = safeREF(reflectiveMethodCache(ad.symbol.name.toString, paramTypes)) // cache Symbol + def cache = REF(reflectiveMethodCache(ad.symbol.name.toString, paramTypes)) // cache Symbol def lookup = Apply(cache, List(qual1() GETCLASS)) // get Method object from cache def invokeArgs = ArrayValue(TypeTree(ObjectClass.tpe), params) // args for invocation def invocation = (lookup DOT invokeName)(qual1(), invokeArgs) // .invoke(qual1, ...) @@ -495,7 +478,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { typedPos { val sym = currentOwner.newValue(mkTerm("qual"), ad.pos) setInfo qual0.tpe - qual = safeREF(sym) + qual = REF(sym) BLOCK( VAL(sym) === qual0, @@ -678,7 +661,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { val rhs = gen.mkMethodCall(Symbol_apply, arg :: Nil) val staticFieldSym = getSymbolStaticField(tree.pos, symname, rhs, tree) // create a reference to a static field - val ntree = typedWithPos(tree.pos)(safeREF(staticFieldSym)) + val ntree = typedWithPos(tree.pos)(REF(staticFieldSym)) super.transform(ntree) // This transform replaces Array(Predef.wrapArray(Array(...)), <tag>) @@ -711,7 +694,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { // create field definition and initialization val stfieldDef = theTyper.typedPos(pos)(VAL(stfieldSym) === rhs) - val stfieldInit = theTyper.typedPos(pos)(safeREF(stfieldSym) === rhs) + val stfieldInit = theTyper.typedPos(pos)(REF(stfieldSym) === rhs) // add field definition to new defs newStaticMembers append stfieldDef @@ -777,8 +760,8 @@ abstract class CleanUp extends Transform with ast.TreeDSL { val stfieldDef = localTyper.typedPos(tree.pos)(VAL(stfieldSym) === EmptyTree) val flattenedInit = fixedrhs match { - case Block(stats, expr) => Block(stats, safeREF(stfieldSym) === expr) - case rhs => safeREF(stfieldSym) === rhs + case Block(stats, expr) => Block(stats, REF(stfieldSym) === expr) + case rhs => REF(stfieldSym) === rhs } val stfieldInit = localTyper.typedPos(tree.pos)(flattenedInit) diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 5115c49c87..24a74722b0 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -563,8 +563,16 @@ abstract class Erasure extends AddInterfaces case _ => val clazz = tref.sym log("not boxed: "+tree) - val tree0 = adaptToType(tree, clazz.tpe) - cast(Apply(Select(tree0, clazz.derivedValueClassUnbox), List()), pt) + lazy val underlying = underlyingOfValueClass(clazz) + val tree0 = + if (tree.tpe.typeSymbol == NullClass && + isPrimitiveValueClass(underlying.typeSymbol)) { + // convert `null` directly to underlying type, as going + // via the unboxed type would yield a NPE (see SI-5866) + unbox1(tree, underlying) + } else + Apply(Select(adaptToType(tree, clazz.tpe), clazz.derivedValueClassUnbox), List()) + cast(tree0, pt) } case _ => pt.typeSymbol match { diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index afbe528b1f..1f7c34b8ad 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -377,6 +377,7 @@ abstract class ExplicitOuter extends InfoTransform } } + // requires settings.XoldPatmat.value def matchTranslation(tree: Match) = { val Match(selector, cases) = tree var nselector = transform(selector) @@ -519,33 +520,32 @@ abstract class ExplicitOuter extends InfoTransform super.transform(treeCopy.Apply(tree, sel, outerVal :: args)) // entry point for pattern matcher translation - case mch: Match if (!opt.virtPatmat) => // don't use old pattern matcher as fallback when the user wants the virtualizing one - matchTranslation(mch) - - case _ => - if (opt.virtPatmat) { // this turned out to be expensive, hence the hacky `if` and `return` - tree match { - // for patmatvirtualiser - // base.<outer>.eq(o) --> base.$outer().eq(o) if there's an accessor, else the whole tree becomes TRUE - // TODO remove the synthetic `<outer>` method from outerFor?? - case Apply(eqsel@Select(eqapp@Apply(sel@Select(base, outerAcc), Nil), eq), args) if outerAcc == nme.OUTER_SYNTH => - val outerFor = sel.symbol.owner.toInterface // TODO: toInterface necessary? - val acc = outerAccessor(outerFor) - if(acc == NoSymbol) { - // println("WARNING: no outer for "+ outerFor) - return transform(TRUE) // urgh... drop condition if there's no accessor - } else { - // println("(base, acc)= "+(base, acc)) - val outerSelect = localTyper typed Apply(Select(base, acc), Nil) - // achieves the same as: localTyper typed atPos(tree.pos)(outerPath(base, base.tpe.typeSymbol, outerFor.outerClass)) - // println("(b, tpsym, outerForI, outerFor, outerClass)= "+ (base, base.tpe.typeSymbol, outerFor, sel.symbol.owner, outerFor.outerClass)) - // println("outerSelect = "+ outerSelect) - return transform(treeCopy.Apply(tree, treeCopy.Select(eqsel, outerSelect, eq), args)) - } - case _ => - } + case m: Match if settings.XoldPatmat.value => // the new pattern matcher runs in its own phase right after typer + matchTranslation(m) + + // for the new pattern matcher + // base.<outer>.eq(o) --> base.$outer().eq(o) if there's an accessor, else the whole tree becomes TRUE + // TODO remove the synthetic `<outer>` method from outerFor?? + case Apply(eqsel@Select(eqapp@Apply(sel@Select(base, nme.OUTER_SYNTH), Nil), eq), args) if !settings.XoldPatmat.value => + val outerFor = sel.symbol.owner.toInterface // TODO: toInterface necessary? + val acc = outerAccessor(outerFor) + + if (acc == NoSymbol || + // since we can't fix SI-4440 properly (we must drop the outer accessors of final classes when there's no immediate reference to them in sight) + // at least don't crash... this duplicates maybeOmittable from constructors + (acc.owner.isEffectivelyFinal && !acc.isOverridingSymbol)) { + unit.uncheckedWarning(tree.pos, "The outer reference in this type test cannot be checked at run time.") + return transform(TRUE) // urgh... drop condition if there's no accessor (or if it may disappear after constructors) + } else { + // println("(base, acc)= "+(base, acc)) + val outerSelect = localTyper typed Apply(Select(base, acc), Nil) + // achieves the same as: localTyper typed atPos(tree.pos)(outerPath(base, base.tpe.typeSymbol, outerFor.outerClass)) + // println("(b, tpsym, outerForI, outerFor, outerClass)= "+ (base, base.tpe.typeSymbol, outerFor, sel.symbol.owner, outerFor.outerClass)) + // println("outerSelect = "+ outerSelect) + return transform(treeCopy.Apply(tree, treeCopy.Select(eqsel, outerSelect, eq), args)) } + case _ => if (settings.Xmigration28.value) tree match { case TypeApply(fn @ Select(qual, _), args) if fn.symbol == Object_isInstanceOf || fn.symbol == Any_isInstanceOf => if (isArraySeqTest(qual.tpe, args.head.tpe)) diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala index 5f66cadbc9..e937589f54 100644 --- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala +++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala @@ -78,13 +78,13 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { } /** This method removes the `$this` argument from the parameter list a method. - * + * * A method may be a `PolyType`, in which case we tear out the `$this` and the class * type params from its nested `MethodType`. * It may be a `MethodType`, either with a curried parameter list in which the first argument * is a `$this` - we just return the rest of the list. * This means that the corresponding symbol was generated during `extmethods`. - * + * * It may also be a `MethodType` in which the `$this` does not appear in a curried parameter list. * The curried lists disappear during `uncurry`, and the methods may be duplicated afterwards, * for instance, during `specialize`. @@ -105,6 +105,14 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { private val extensionDefs = mutable.Map[Symbol, mutable.ListBuffer[Tree]]() + def checkNonCyclic(pos: Position, seen: Set[Symbol], clazz: Symbol): Unit = + if (seen contains clazz) + unit.error(pos, "value class may not unbox to itself") + else { + val unboxed = erasure.underlyingOfValueClass(clazz).typeSymbol + if (unboxed.isDerivedValueClass) checkNonCyclic(pos, seen + clazz, unboxed) + } + def extensionMethInfo(extensionMeth: Symbol, origInfo: Type, clazz: Symbol): Type = { var newTypeParams = cloneSymbolsAtOwner(clazz.typeParams, extensionMeth) val thisParamType = appliedType(clazz.typeConstructor, newTypeParams map (_.tpeHK)) @@ -129,6 +137,7 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { tree match { case Template(_, _, _) => if (currentOwner.isDerivedValueClass) { + checkNonCyclic(currentOwner.pos, Set(), currentOwner) extensionDefs(currentOwner.companionModule) = new mutable.ListBuffer[Tree] currentOwner.primaryConstructor.makeNotPrivate(NoSymbol) super.transform(tree) diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index ffcb682cf7..63f93aa000 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -798,6 +798,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { var specializingOn = specializedParams(sym) val unusedStvars = specializingOn filterNot specializedTypeVars(sym.info) + // I think the last condition should be !sym.isHidden, but that made the + // compiler start warning about Tuple1.scala and Tuple2.scala claiming + // their type parameters are used in non-specializable positions. Why is + // unusedStvars.nonEmpty for these classes??? if (unusedStvars.nonEmpty && currentRun.compiles(sym) && !sym.isSynthetic) { reporter.warning(sym.pos, "%s %s unused or used in non-specializable positions.".format( diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 805f60ba87..c7dab69f62 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -360,7 +360,7 @@ trait Contexts { self: Analyzer => private def unitError(pos: Position, msg: String) = unit.error(pos, if (checking) "\n**** ERROR DURING INTERNAL CHECKING ****\n" + msg else msg) - + @inline private def issueCommon(err: AbsTypeError)(pf: PartialFunction[AbsTypeError, Unit]) { debugwarn("issue error: " + err.errMsg) if (settings.Yissuedebug.value) (new Exception).printStackTrace() @@ -552,7 +552,6 @@ trait Contexts { self: Analyzer => ( (ab.isTerm || ab == rootMirror.RootClass) || (accessWithin(ab) || accessWithinLinked(ab)) && ( !sym.hasLocalFlag - || sym.owner.isImplClass // allow private local accesses to impl classes || sym.isProtected && isSubThisType(pre, sym.owner) || pre =:= sym.owner.thisType ) @@ -612,8 +611,8 @@ trait Contexts { self: Analyzer => (e ne null) && (e.owner == scope) }) - private def collectImplicits(syms: List[Symbol], pre: Type, imported: Boolean = false): List[ImplicitInfo] = - for (sym <- syms if isQualifyingImplicit(sym.name, sym, pre, imported)) yield + private def collectImplicits(syms: Scope, pre: Type, imported: Boolean = false): List[ImplicitInfo] = + for (sym <- syms.toList if isQualifyingImplicit(sym.name, sym, pre, imported)) yield new ImplicitInfo(sym.name, pre, sym) private def collectImplicitImports(imp: ImportInfo): List[ImplicitInfo] = { @@ -658,7 +657,7 @@ trait Contexts { self: Analyzer => } } else if (scope != nextOuter.scope && !owner.isPackageClass) { debuglog("collect local implicits " + scope.toList)//DEBUG - collectImplicits(scope.toList, NoPrefix) + collectImplicits(scope, NoPrefix) } else if (imports != nextOuter.imports) { assert(imports.tail == nextOuter.imports, (imports, nextOuter.imports)) collectImplicitImports(imports.head) @@ -726,7 +725,7 @@ trait Contexts { self: Analyzer => result } - def allImportedSymbols: List[Symbol] = + def allImportedSymbols: Iterable[Symbol] = qual.tpe.members flatMap (transformImport(tree.selectors, _)) private def transformImport(selectors: List[ImportSelector], sym: Symbol): List[Symbol] = selectors match { diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index da045e1a48..b442d16b1c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -957,7 +957,7 @@ trait Implicits { companion.moduleClass match { case mc: ModuleClassSymbol => val infos = - for (im <- mc.implicitMembers) yield new ImplicitInfo(im.name, singleType(pre, companion), im) + for (im <- mc.implicitMembers.toList) yield new ImplicitInfo(im.name, singleType(pre, companion), im) if (infos.nonEmpty) infoMap += (sym -> infos) case _ => @@ -1196,7 +1196,7 @@ trait Implicits { gen.mkAttributedThis(thisSym) case _ => // if ``pre'' is not a PDT, e.g. if someone wrote - // implicitly[scala.reflect.makro.Context#TypeTag[Int]] + // implicitly[scala.reflect.macros.Context#TypeTag[Int]] // then we need to fail, because we don't know the prefix to use during type reification // upd. we also need to fail silently, because this is a very common situation // e.g. quite often we're searching for BaseUniverse#TypeTag, e.g. for a type tag in any universe diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index bcbcb96400..e096b75d6d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -1324,66 +1324,89 @@ trait Infer { } // if top-level abstract types can be checked using a classtag extractor, don't warn about them - def checkCheckable(tree: Tree, tp: Type, inPattern: Boolean, canRemedy: Boolean = false) = { - val kind = if (inPattern) "pattern " else "" + def checkCheckable(tree: Tree, typeToTest: Type, typeEnsured: Type, inPattern: Boolean, canRemedy: Boolean = false) = { + log(s"checkCheckable($tree, $typeToTest, $typeEnsured, inPattern = $inPattern, canRemedy = $canRemedy") - def patternWarning(tp0: Type, prefix: String) = { - context.unit.uncheckedWarning(tree.pos, prefix+tp0+" in type "+kind+tp+" is unchecked since it is eliminated by erasure") + sealed abstract class TypeConformance(check: (Type, Type) => Boolean) { + def apply(t1: Type, t2: Type): Boolean = check(t1, t2) && { + log(s"Skipping unchecked for statically verifiable condition $t1 ${this} $t2") + true + } } - def check(tp: Type, bound: List[Symbol]) { - def isLocalBinding(sym: Symbol) = - sym.isAbstractType && - ((bound contains sym) || - sym.name == tpnme.WILDCARD || { + // I tried to use varianceInType to track the variance implications + // but I could not make it work. + case object =:= extends TypeConformance(_ =:= _) + case object <:< extends TypeConformance(_ <:< _) + case object >:> extends TypeConformance((t1, t2) => t2 <:< t1) + case object =!= extends TypeConformance((t1, t2) => false) + + var bound: List[Symbol] = Nil + var warningMessages: List[String] = Nil + + def isLocalBinding(sym: Symbol) = ( + sym.isAbstractType && ( + (bound contains sym) + || (sym.name == tpnme.WILDCARD) + || { val e = context.scope.lookupEntry(sym.name) (e ne null) && e.sym == sym && !e.sym.isTypeParameterOrSkolem && e.owner == context.scope - }) - tp match { - case SingleType(pre, _) => - check(pre, bound) - case TypeRef(pre, sym, args) => - if (sym.isAbstractType) { - // we only use the extractor for top-level type tests, type arguments (see below) remain unchecked - if (!isLocalBinding(sym) && !canRemedy) patternWarning(tp, "abstract type ") - } else if (sym.isAliasType) { - check(tp.normalize, bound) - } else if (sym == NothingClass || sym == NullClass || sym == AnyValClass) { - TypePatternOrIsInstanceTestError(tree, tp) - } else { - for (arg <- args) { - if (sym == ArrayClass) check(arg, bound) - // avoid spurious warnings with higher-kinded types - else if (arg.typeArgs exists (_.typeSymbol.isTypeParameterOrSkolem)) () - // no way to suppress unchecked warnings on try/catch - else if (sym == NonLocalReturnControlClass) () - else arg match { - case TypeRef(_, sym, _) if isLocalBinding(sym) => - ; - case _ => - // Want to warn about type arguments, not type parameters. Otherwise we'll - // see warnings about "invisible" types, like: val List(x0) = x1 leading to "non - // variable type-argument A in type pattern List[A]..." - if (!arg.typeSymbol.isTypeParameterOrSkolem) - patternWarning(arg, "non variable type-argument ") - } - } - } - check(pre, bound) - case RefinedType(parents, decls) => - if (decls.isEmpty) for (p <- parents) check(p, bound) - else patternWarning(tp, "refinement ") - case ExistentialType(quantified, tp1) => - check(tp1, bound ::: quantified) - case ThisType(_) => - () - case NoPrefix => - () - case _ => - patternWarning(tp, "type ") - () + } + ) + ) + def check(tp0: Type, pt: Type, conformance: TypeConformance): Boolean = { + val tp = tp0.normalize + // Set the warning message to be issued when the top-level call fails. + def warn(what: String): Boolean = { + warningMessages ::= what + false + } + def checkArg(param: Symbol, arg: Type) = { + def conforms = ( + if (param.isCovariant) <:< + else if (param.isContravariant) >:> + else =:= + ) + val TypeRef(_, sym, args) = arg + + ( isLocalBinding(sym) + || arg.typeSymbol.isTypeParameterOrSkolem + || (sym.name == tpnme.WILDCARD) // avoid spurious warnings on HK types + || check(arg, param.tpe, conforms) + || warn("non-variable type argument " + arg) + ) } + + // Checking if pt (the expected type of the pattern, and the type + // we are guaranteed) conforms to tp (the type expressed in the pattern's + // type test.) If it does, then even if the type being checked for appears + // to be uncheckable, it is not a warning situation, because it is indeed + // checked: not at runtime, but statically. + conformance.apply(pt, tp) || (tp match { + case SingleType(pre, _) => check(pre, pt, =:=) + case ExistentialType(quantified, tp1) => bound :::= quantified ; check(tp1, pt, <:<) + case ThisType(_) | NoPrefix => true + case RefinedType(parents, decls) if decls.isEmpty => parents forall (p => check(p, pt, <:<)) + case RefinedType(_, _) => warn("refinement " + tp) + case TypeRef(_, ArrayClass, arg :: Nil) => check(arg, NoType, =!=) + case TypeRef(_, NonLocalReturnControlClass, _) => true // no way to suppress unchecked warnings on try/catch + // we only use the extractor for top-level type tests, type arguments remain unchecked + case TypeRef(_, sym, _) if sym.isAbstractType => isLocalBinding(sym) || canRemedy || warn("abstract type " + tp) + case TypeRef(_, _, Nil) => false // leaf node + case TypeRef(pre, sym, args) => forall2(sym.typeParams, args)(checkArg) && check(pre, pt.prefix, =:=) + case _ => warn("type " + tp) + }) + } + typeToTest match { + // Prohibit top-level type tests for these, but they are + // acceptable nested (e.g. case Foldable[Nothing] => ... ) + case TypeRef(_, NothingClass | NullClass | AnyValClass, _) => + TypePatternOrIsInstanceTestError(tree, typeToTest) + case _ => + def where = ( if (inPattern) "pattern " else "" ) + typeToTest + if (check(typeToTest, typeEnsured, =:=)) () + else warningMessages foreach (m => + context.unit.uncheckedWarning(tree.pos, s"$m in type $where is unchecked since it is eliminated by erasure")) } - check(tp, List()) } /** Type intersection of simple type tp1 with general type tp2. @@ -1420,7 +1443,7 @@ trait Infer { return ErrorType } - checkCheckable(tree0, pattp, inPattern = true, canRemedy) + checkCheckable(tree0, pattp, pt, inPattern = true, canRemedy) if (pattp <:< pt) () else { debuglog("free type params (1) = " + tpparams) diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index d33857371d..1381450970 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -8,7 +8,7 @@ import scala.reflect.runtime.ReflectionUtils import scala.collection.mutable.ListBuffer import scala.compat.Platform.EOL import reflect.internal.util.Statistics -import scala.reflect.makro.util._ +import scala.reflect.macros.util._ import java.lang.{Class => jClass} import java.lang.reflect.{Array => jArray, Method => jMethod} @@ -24,7 +24,7 @@ import java.lang.reflect.{Array => jArray, Method => jMethod} * Then fooBar needs to point to a static method of the following form: * * def fooBar[T: c.TypeTag] - * (c: scala.reflect.makro.Context) + * (c: scala.reflect.macros.Context) * (xs: c.Expr[List[T]]) * : c.Expr[T] = { * ... @@ -51,7 +51,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { /** A list of compatible macro implementation signatures. * * In the example above: - * (c: scala.reflect.makro.Context)(xs: c.Expr[List[T]]): c.Expr[T] + * (c: scala.reflect.macros.Context)(xs: c.Expr[List[T]]): c.Expr[T] * * @param macroDef The macro definition symbol * @param tparams The type parameters of the macro definition @@ -591,53 +591,34 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { runtimeType } - /** Primary classloader that is used to resolve and run macro implementations. - * Loads classes from -Xmacro-primary-classpath, or from -cp if the option is not specified. + /** Macro classloader that is used to resolve and run macro implementations. + * Loads classes from from -cp (aka the library classpath). * Is also capable of detecting REPL and reusing its classloader. */ - private lazy val primaryClassloader: ClassLoader = { + private lazy val macroClassloader: ClassLoader = { if (global.forMSIL) throw new UnsupportedOperationException("Scala reflection not available on this platform") - if (settings.XmacroPrimaryClasspath.value != "") { - macroLogVerbose("primary macro classloader: initializing from -Xmacro-primary-classpath: %s".format(settings.XmacroPrimaryClasspath.value)) - val classpath = toURLs(settings.XmacroPrimaryClasspath.value) - ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader) - } else { - macroLogVerbose("primary macro classloader: initializing from -cp: %s".format(global.classPath.asURLs)) - val classpath = global.classPath.asURLs - var loader: ClassLoader = ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader) - - // [Eugene] a heuristic to detect the REPL - if (global.settings.exposeEmptyPackage.value) { - macroLogVerbose("primary macro classloader: initializing from a REPL classloader".format(global.classPath.asURLs)) - import scala.tools.nsc.interpreter._ - val virtualDirectory = global.settings.outputDirs.getSingleOutput.get - loader = new AbstractFileClassLoader(virtualDirectory, loader) {} - } + val classpath = global.classPath.asURLs + macroLogVerbose("macro classloader: initializing from -cp: %s".format(classpath)) + val loader = ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader) + // [Eugene] a heuristic to detect the REPL + if (global.settings.exposeEmptyPackage.value) { + macroLogVerbose("macro classloader: initializing from a REPL classloader".format(global.classPath.asURLs)) + import scala.tools.nsc.interpreter._ + val virtualDirectory = global.settings.outputDirs.getSingleOutput.get + new AbstractFileClassLoader(virtualDirectory, loader) {} + } else { loader } } - /** Fallback classloader that is used to resolve and run macro implementations when `primaryClassloader` fails. - * Loads classes from -Xmacro-fallback-classpath. - */ - private lazy val fallbackClassloader: ClassLoader = { - if (global.forMSIL) - throw new UnsupportedOperationException("Scala reflection not available on this platform") - - macroLogVerbose("fallback macro classloader: initializing from -Xmacro-fallback-classpath: %s".format(settings.XmacroFallbackClasspath.value)) - val classpath = toURLs(settings.XmacroFallbackClasspath.value) - ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader) - } - /** Produces a function that can be used to invoke macro implementation for a given macro definition: * 1) Looks up macro implementation symbol in this universe. - * 2) Loads its enclosing class from the primary classloader. - * 3) Loads the companion of that enclosing class from the primary classloader. + * 2) Loads its enclosing class from the macro classloader. + * 3) Loads the companion of that enclosing class from the macro classloader. * 4) Resolves macro implementation within the loaded companion. - * 5) If 2-4 fails, repeats them for the fallback classloader. * * @return Some(runtime) if macro implementation can be loaded successfully from either of the mirrors, * None otherwise. @@ -742,25 +723,10 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { } } - val primary = loadMacroImpl(primaryClassloader) - primary match { - case Some((implObj, implMeth)) => + loadMacroImpl(macroClassloader) map { + case (implObj, implMeth) => def runtime(args: List[Any]) = implMeth.invoke(implObj, (args map (_.asInstanceOf[AnyRef])): _*).asInstanceOf[Any] - Some(runtime _) - case None => - if (settings.XmacroFallbackClasspath.value != "") { - macroLogVerbose("trying to load macro implementation from the fallback mirror: %s".format(settings.XmacroFallbackClasspath.value)) - val fallback = loadMacroImpl(fallbackClassloader) - fallback match { - case Some((implObj, implMeth)) => - def runtime(args: List[Any]) = implMeth.invoke(implObj, (args map (_.asInstanceOf[AnyRef])): _*).asInstanceOf[Any] - Some(runtime _) - case None => - None - } - } else { - None - } + runtime _ } } @@ -913,7 +879,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { } /** Keeps track of macros in-flight. - * See more informations in comments to ``openMacros'' in ``scala.reflect.makro.Context''. + * See more informations in comments to ``openMacros'' in ``scala.reflect.macros.Context''. */ var openMacros = List[MacroContext]() def enclosingMacroPosition = openMacros map (_.macroApplication.pos) find (_ ne NoPosition) getOrElse NoPosition @@ -1147,9 +1113,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { val macroDef = expandee.symbol def notFound() = { typer.context.error(expandee.pos, "macro implementation not found: " + macroDef.name + " " + - "(the most common reason for that is that you cannot use macro implementations in the same compilation run that defines them)\n" + - "if you do need to define macro implementations along with the rest of your program, consider two-phase compilation with -Xmacro-fallback-classpath " + - "in the second phase pointing to the output of the first phase") + "(the most common reason for that is that you cannot use macro implementations in the same compilation run that defines them)") None } def fallBackToOverridden(tree: Tree): Option[Tree] = { @@ -1191,7 +1155,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { // [Eugene] any ideas about how to improve this one? val realex = ReflectionUtils.unwrapThrowable(ex) realex match { - case realex: reflect.makro.runtime.AbortMacroException => + case realex: reflect.macros.runtime.AbortMacroException => macroLogVerbose("macro expansion has failed: %s".format(realex.msg)) fail(typer, expandee) // error has been reported by abort case err: TypeError => diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala index 7bd5f4caeb..bd2808d049 100644 --- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala +++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala @@ -70,11 +70,8 @@ trait MethodSynthesis { // [Eugene++->Martin] now this compiles, will soon check it out def newMethodType[F](owner: Symbol)(implicit t: TT[F]): Type = { val fnSymbol = compilerSymbolFromTag(t) - assert(fnSymbol isSubClass FunctionClass(t.tpe.typeArguments.size - 1), (owner, t)) - // [Eugene++ to Paul] needs review!! - // val symbols = m.typeArguments map (m => manifestToSymbol(m)) - // val formals = symbols.init map (_.typeConstructor) val formals = compilerTypeFromTag(t).typeArguments + assert(fnSymbol isSubClass FunctionClass(formals.size - 1), (owner, t)) val params = owner newSyntheticValueParams formals MethodType(params, formals.last) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index dc9f07cad9..44712ba286 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -983,15 +983,10 @@ trait Namers extends MethodSynthesis { } addDefaultGetters(meth, vparamss, tparams, overriddenSymbol) - // macro defs need to be typechecked in advance - // because @macroImpl annotation only gets assigned during typechecking - // otherwise we might find ourselves in the situation when we specified -Xmacro-fallback-classpath - // but macros still don't expand - // that might happen because macro def doesn't have its link a macro impl yet - if (ddef.symbol.isTermMacro) { - val pt = resultPt.substSym(tparamSyms, tparams map (_.symbol)) - typer.computeMacroDefType(ddef, pt) - } + // fast track macros, i.e. macros defined inside the compiler, are hardcoded + // hence we make use of that and let them have whatever right-hand side they need + // (either "macro ???" as they used to or just "???" to maximally simplify their compilation) + if (fastTrack contains ddef.symbol) ddef.symbol setFlag MACRO thisMethodType({ val rt = ( diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala index 256d8db095..a4457936c8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala @@ -412,8 +412,9 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL **/ // must treat Typed and Bind together -- we need to know the patBinder of the Bind pattern to get at the actual type case MaybeBoundTyped(subPatBinder, pt) => + val next = glb(List(patBinder.info.widen, pt)).normalize // a typed pattern never has any subtrees - noFurtherSubPats(TypeTestTreeMaker(subPatBinder, patBinder, pt, glb(List(patBinder.info.widen, pt)).normalize)(pos)) + noFurtherSubPats(TypeTestTreeMaker(subPatBinder, patBinder, pt, next)(pos)) /** A pattern binder x@p consists of a pattern variable x and a pattern p. The type of the variable x is the static type T of the pattern p. diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 254a2f2376..29ed8e6013 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -122,7 +122,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R val defaultGetters = clazz.info.findMembers(0L, DEFAULTPARAM) val defaultMethodNames = defaultGetters map (sym => nme.defaultGetterToMethod(sym.name)) - defaultMethodNames.distinct foreach { name => + defaultMethodNames.toList.distinct foreach { name => val methods = clazz.info.findMember(name, 0L, METHOD, false).alternatives val haveDefaults = methods filter (sym => sym.hasParamWhich(_.hasDefault) && !nme.isProtectedAccessorName(sym.name)) @@ -628,7 +628,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R matchingArity match { // So far so good: only one candidate method - case concrete :: Nil => + case Scope(concrete) => val mismatches = abstractParams zip concrete.tpe.paramTypes filterNot { case (x, y) => x =:= y } mismatches match { // Only one mismatched parameter: say something useful. diff --git a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala index 190b18711c..64c5b41638 100644 --- a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala +++ b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala @@ -4,7 +4,7 @@ package typechecker trait StdAttachments { self: Analyzer => - type UnaffiliatedMacroContext = scala.reflect.makro.runtime.Context + type UnaffiliatedMacroContext = scala.reflect.macros.runtime.Context type MacroContext = UnaffiliatedMacroContext { val universe: self.global.type } case class MacroRuntimeAttachment(delayed: Boolean, typerContext: Context, macroContext: Option[MacroContext]) }
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/typechecker/Tags.scala b/src/compiler/scala/tools/nsc/typechecker/Tags.scala index 052484e8e1..f82e009be8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Tags.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Tags.scala @@ -61,7 +61,7 @@ trait Tags { */ def resolveTypeTag(pos: Position, pre: Type, tp: Type, concrete: Boolean, allowMaterialization: Boolean = true): Tree = { val tagSym = if (concrete) TypeTagClass else AbsTypeTagClass - val tagTp = if (pre == NoType) TypeRef(BaseUniverseClass.asTypeConstructor, tagSym, List(tp)) else singleType(pre, pre member tagSym.name) + val tagTp = if (pre == NoType) TypeRef(BaseUniverseClass.toTypeConstructor, tagSym, List(tp)) else singleType(pre, pre member tagSym.name) val taggedTp = appliedType(tagTp, List(tp)) resolveTag(pos, taggedTp, allowMaterialization) } diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala index a378a95786..fe82af5b23 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala @@ -14,7 +14,7 @@ import util.returning abstract class TreeCheckers extends Analyzer { import global._ - private def classstr(x: AnyRef) = x.getClass.getName split """\\.|\\$""" last; + private def classstr(x: AnyRef) = (x.getClass.getName split """\\.|\\$""").last private def typestr(x: Type) = " (tpe = " + x + ")" private def treestr(t: Tree) = t + " [" + classstr(t) + "]" + typestr(t.tpe) private def ownerstr(s: Symbol) = "'" + s + "'" + s.locationString diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 80e7d0d474..b06ea639b0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1194,30 +1194,46 @@ trait Typers extends Modes with Adaptations with Tags { } val found = tree.tpe - val req = pt - if (!found.isErroneous && !req.isErroneous) { - if (!context.reportErrors && isPastTyper && req.skolemsExceptMethodTypeParams.nonEmpty) { - // Ignore type errors raised in later phases that are due to mismatching types with existential skolems - // We have lift crashing in 2.9 with an adapt failure in the pattern matcher. - // Here's my hypothsis why this happens. The pattern matcher defines a variable of type - // - // val x: T = expr - // - // where T is the type of expr, but T contains existential skolems ts. - // In that case, this value definition does not typecheck. - // The value definition - // - // val x: T forSome { ts } = expr - // - // would typecheck. Or one can simply leave out the type of the `val`: - // - // val x = expr - context.unit.warning(tree.pos, "recovering from existential Skolem type error in tree \n" + tree + "\nwith type " + tree.tpe + "\n expected type = " + pt + "\n context = " + context.tree) - adapt(tree, mode, deriveTypeWithWildcards(pt.skolemsExceptMethodTypeParams)(pt)) - } else { - // create an actual error - AdaptTypeError(tree, found, req) + if (!found.isErroneous && !pt.isErroneous) { + if (!context.reportErrors && isPastTyper) { + val (bound, req) = pt match { + case ExistentialType(qs, tpe) => (qs, tpe) + case _ => (Nil, pt) + } + val boundOrSkolems = bound ++ pt.skolemsExceptMethodTypeParams + if (boundOrSkolems.nonEmpty) { + // Ignore type errors raised in later phases that are due to mismatching types with existential skolems + // We have lift crashing in 2.9 with an adapt failure in the pattern matcher. + // Here's my hypothsis why this happens. The pattern matcher defines a variable of type + // + // val x: T = expr + // + // where T is the type of expr, but T contains existential skolems ts. + // In that case, this value definition does not typecheck. + // The value definition + // + // val x: T forSome { ts } = expr + // + // would typecheck. Or one can simply leave out the type of the `val`: + // + // val x = expr + // + // SI-6029 shows another case where we also fail (in uncurry), but this time the expected + // type is an existential type. + // + // The reason for both failures have to do with the way we (don't) transform + // skolem types along with the trees that contain them. We'd need a + // radically different approach to do it. But before investing a lot of time to + // to do this (I have already sunk 3 full days with in the end futile attempts + // to consistently transform skolems and fix 6029), I'd like to + // investigate ways to avoid skolems completely. + // + log("recovering from existential or skolem type error in tree \n" + tree + "\nwith type " + tree.tpe + "\n expected type = " + pt + "\n context = " + context.tree) + return adapt(tree, mode, deriveTypeWithWildcards(boundOrSkolems)(pt)) + } } + // create an actual error + AdaptTypeError(tree, found, pt) } setError(tree) } @@ -1385,6 +1401,15 @@ trait Typers extends Modes with Adaptations with Tags { unit.error(clazz.pos, "value class needs to have exactly one public val parameter") } } + body foreach { + case md: ModuleDef => + unit.error(md.pos, "value class may not have nested module definitions") + case cd: ClassDef => + unit.error(cd.pos, "value class may not have nested class definitions") + case md: DefDef if md.symbol.isConstructor && !md.symbol.isPrimaryConstructor => + unit.error(md.pos, "value class may not have secondary constructors") + case _ => + } for (tparam <- clazz.typeParams) if (tparam hasAnnotation definitions.SpecializedClass) unit.error(tparam.pos, "type parameter of value class may not be specialized") @@ -3672,7 +3697,8 @@ trait Typers extends Modes with Adaptations with Tags { typedClassOf(tree, args.head, true) else { if (!isPastTyper && fun.symbol == Any_isInstanceOf && !targs.isEmpty) - checkCheckable(tree, targs.head, inPattern = false) + checkCheckable(tree, targs.head, AnyClass.tpe, inPattern = false) + val resultpe = restpe.instantiateTypeParams(tparams, targs) //@M substitution in instantiateParams needs to be careful! //@M example: class Foo[a] { def foo[m[x]]: m[a] = error("") } (new Foo[Int]).foo[List] : List[Int] @@ -4530,7 +4556,7 @@ trait Typers extends Modes with Adaptations with Tags { assert(errorContainer == null, "Cannot set ambiguous error twice for identifier") errorContainer = tree } - + val fingerPrint: Long = name.fingerPrint var defSym: Symbol = tree.symbol // the directly found symbol @@ -4661,15 +4687,28 @@ trait Typers extends Modes with Adaptations with Tags { // If the ambiguous name is a monomorphic type, we can relax this far. def mt1 = t1 memberType impSym def mt2 = t2 memberType impSym1 + def characterize = List( + s"types: $t1 =:= $t2 ${t1 =:= t2} members: ${mt1 =:= mt2}", + s"member type 1: $mt1", + s"member type 2: $mt2", + s"$impSym == $impSym1 ${impSym == impSym1}", + s"${impSym.debugLocationString} ${impSym.getClass}", + s"${impSym1.debugLocationString} ${impSym1.getClass}" + ).mkString("\n ") + + // The symbol names are checked rather than the symbols themselves because + // each time an overloaded member is looked up it receives a new symbol. + // So foo.member("x") != foo.member("x") if x is overloaded. This seems + // likely to be the cause of other bugs too... + if (t1 =:= t2 && impSym.name == impSym1.name) + log(s"Suppressing ambiguous import: $t1 =:= $t2 && $impSym == $impSym1") // Monomorphism restriction on types is in part because type aliases could have the // same target type but attach different variance to the parameters. Maybe it can be // relaxed, but doesn't seem worth it at present. - if (t1 =:= t2 && impSym == impSym1) - log(s"Suppressing ambiguous import: $t1 =:= $t2 && $impSym == $impSym1") else if (mt1 =:= mt2 && name.isTypeName && impSym.isMonomorphicType && impSym1.isMonomorphicType) log(s"Suppressing ambiguous import: $mt1 =:= $mt2 && $impSym and $impSym1 are equivalent") else { - log(s"Import is genuinely ambiguous: !($t1 =:= $t2)") + log(s"Import is genuinely ambiguous:\n " + characterize) ambiguousError(s"it is imported twice in the same scope by\n${imports.head}\nand ${imports1.head}") } } @@ -4989,7 +5028,9 @@ trait Typers extends Modes with Adaptations with Tags { if (isPatternMode) { val uncheckedTypeExtractor = extractorForUncheckedType(tpt.pos, tptTyped.tpe) val ownType = inferTypedPattern(tptTyped, tptTyped.tpe, pt, canRemedy = uncheckedTypeExtractor.nonEmpty) - treeTyped setType ownType + // println(s"Typed($expr, ${tpt.tpe}) : $pt --> $ownType (${isFullyDefined(ownType)}, ${makeFullyDefined(ownType)})") + // make fully defined to avoid bounded wildcard types that may be in pt from calling dropExistential (SI-2038) + treeTyped setType (if (isFullyDefined(ownType)) ownType else makeFullyDefined(ownType)) //ownType uncheckedTypeExtractor match { case None => treeTyped @@ -5048,7 +5089,7 @@ trait Typers extends Modes with Adaptations with Tags { // convert new Array^N[T](len) for N > 1 to evidence[ClassTag[Array[...Array[T]...]]].newArray(len), where Array HK gets applied (N-1) times // [Eugene] no more MaxArrayDims. ClassTags are flexible enough to allow creation of arrays of arbitrary dimensionality (w.r.t JVM restrictions) val Some((level, componentType)) = erasure.GenericArray.unapply(tpt.tpe) - val tagType = List.iterate(componentType, level)(tpe => appliedType(ArrayClass.asType, List(tpe))).last + val tagType = List.iterate(componentType, level)(tpe => appliedType(ArrayClass.toTypeConstructor, List(tpe))).last val newArrayApp = atPos(tree.pos) { val tag = resolveClassTag(tree.pos, tagType) if (tag.isEmpty) MissingClassTagError(tree, tagType) diff --git a/src/compiler/scala/tools/nsc/util/InterruptReq.scala b/src/compiler/scala/tools/nsc/util/InterruptReq.scala index 61aaa1bdcb..816d16f767 100644 --- a/src/compiler/scala/tools/nsc/util/InterruptReq.scala +++ b/src/compiler/scala/tools/nsc/util/InterruptReq.scala @@ -2,6 +2,7 @@ package scala.tools.nsc package util /** A class of work items to be used in interrupt requests. + * Todo: we should replace the Eithers by Futures or Try's. */ abstract class InterruptReq { /** The result type of the operation @@ -11,9 +12,14 @@ abstract class InterruptReq { /** The operation to be performed */ protected val todo: () => R + type Continuation = Either[R, Throwable] => Unit + /** The result provided */ private var result: Option[Either[R, Throwable]] = None + /** The continuations waiting asynchronously on a provided result */ + private var waiting: List[Continuation] = Nil + /** To be called from interrupted server to execute demanded task */ def execute(): Unit = synchronized { try { @@ -22,6 +28,7 @@ abstract class InterruptReq { case t: Throwable => result = Some(Right(t)) } finally { notify() + for (k <- waiting.reverse) k(result.get) } } @@ -38,6 +45,10 @@ abstract class InterruptReq { case Right(t) => throw new FailedInterrupt(t) } } + + def onComplete(k: Continuation) = synchronized { + waiting = k :: waiting + } } class FailedInterrupt(cause: Throwable) extends Exception("Compiler exception during call to 'ask'", cause) diff --git a/src/compiler/scala/tools/nsc/util/WorkScheduler.scala b/src/compiler/scala/tools/nsc/util/WorkScheduler.scala index 8c037cbda5..b1f4696d3e 100644 --- a/src/compiler/scala/tools/nsc/util/WorkScheduler.scala +++ b/src/compiler/scala/tools/nsc/util/WorkScheduler.scala @@ -54,6 +54,11 @@ class WorkScheduler { /** Called from client: have interrupt executed by server and return result */ def doQuickly[A](op: () => A): A = { + val ir = askDoQuickly(op) + ir.getResult() + } + + def askDoQuickly[A](op: () => A): InterruptReq { type R = A } = { val ir = new InterruptReq { type R = A val todo = op @@ -62,7 +67,7 @@ class WorkScheduler { interruptReqs enqueue ir notify() } - ir.getResult() + ir } /** Called from client: have action executed by server */ diff --git a/src/compiler/scala/tools/reflect/FastTrack.scala b/src/compiler/scala/tools/reflect/FastTrack.scala index 237ef813c7..e093c64c72 100644 --- a/src/compiler/scala/tools/reflect/FastTrack.scala +++ b/src/compiler/scala/tools/reflect/FastTrack.scala @@ -38,7 +38,7 @@ trait FastTrack { MacroInternal_materializeClassTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeClassTag(u, tt.tpe) } MacroInternal_materializeAbsTypeTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeTypeTag(u, EmptyTree, tt.tpe, concrete = false) } MacroInternal_materializeTypeTag bindTo { case (c, Apply(TypeApply(_, List(tt)), List(u))) => c.materializeTypeTag(u, EmptyTree, tt.tpe, concrete = true) } - ApiUniverseReify bindTo { case (c, Apply(TypeApply(_, List(tt)), List(expr))) => c.materializeExpr(c.prefix.tree, EmptyTree, expr) } + BaseUniverseReify bindTo { case (c, Apply(TypeApply(_, List(tt)), List(expr))) => c.materializeExpr(c.prefix.tree, EmptyTree, expr) } ReflectRuntimeCurrentMirror bindTo { case (c, _) => scala.reflect.runtime.Macros.currentMirror(c).tree } StringContext_f bindTo { case (c, app@Apply(Select(Apply(_, parts), _), args)) => c.macro_StringInterpolation_f(parts, args, app.pos) } registry diff --git a/src/compiler/scala/tools/reflect/MacroImplementations.scala b/src/compiler/scala/tools/reflect/MacroImplementations.scala index e1b959cefa..40ceefcc70 100644 --- a/src/compiler/scala/tools/reflect/MacroImplementations.scala +++ b/src/compiler/scala/tools/reflect/MacroImplementations.scala @@ -1,7 +1,7 @@ package scala.tools.reflect -import scala.reflect.makro.{ReificationError, UnexpectedReificationError} -import scala.reflect.makro.runtime.Context +import scala.reflect.macros.{ReificationError, UnexpectedReificationError} +import scala.reflect.macros.runtime.Context import scala.collection.mutable.ListBuffer import scala.collection.mutable.Stack @@ -25,9 +25,9 @@ abstract class MacroImplementations { c.abort(args(parts.length-1).pos, "too many arguments for interpolated string") } - val stringParts = parts map { + val stringParts = parts map { case Literal(Constant(s: String)) => s; - case _ => throw new IllegalArgumentException("argument parts must be a list of string literals") + case _ => throw new IllegalArgumentException("argument parts must be a list of string literals") } val pi = stringParts.iterator diff --git a/src/compiler/scala/tools/reflect/StdTags.scala b/src/compiler/scala/tools/reflect/StdTags.scala index 25a42a82cd..0704189ddc 100644 --- a/src/compiler/scala/tools/reflect/StdTags.scala +++ b/src/compiler/scala/tools/reflect/StdTags.scala @@ -20,7 +20,7 @@ trait StdTags { def apply[U <: BaseUniverse with Singleton](m: MirrorOf[U]): U # Type = { val u = m.universe val pre = u.ThisType(m.staticPackage("scala.collection.immutable").moduleClass.asInstanceOf[u.Symbol]) - u.TypeRef(pre, u.definitions.ListClass, List(u.definitions.StringClass.asTypeConstructor)) + u.TypeRef(pre, u.definitions.ListClass, List(u.definitions.StringClass.toTypeConstructor)) } }) @@ -29,7 +29,7 @@ trait StdTags { m, new TypeCreator { def apply[U <: BaseUniverse with Singleton](m: MirrorOf[U]): U # Type = - m.staticClass(classTag[T].runtimeClass.getName).asTypeConstructor.asInstanceOf[U # Type] + m.staticClass(classTag[T].runtimeClass.getName).toTypeConstructor.asInstanceOf[U # Type] }) lazy val tagOfInt = u.TypeTag.Int lazy val tagOfString = tagOfStaticClass[String] @@ -52,7 +52,7 @@ object StdRuntimeTags extends StdTags { } abstract class StdContextTags extends StdTags { - val tc: scala.reflect.makro.Context + val tc: scala.reflect.macros.Context val u: tc.universe.type = tc.universe val m = tc.mirror } diff --git a/src/compiler/scala/tools/reflect/ToolBox.scala b/src/compiler/scala/tools/reflect/ToolBox.scala index edd22c60f4..2505c1afb7 100644 --- a/src/compiler/scala/tools/reflect/ToolBox.scala +++ b/src/compiler/scala/tools/reflect/ToolBox.scala @@ -24,40 +24,46 @@ trait ToolBox[U <: Universe] { /** Typechecks a tree using this ToolBox. * This populates symbols and types of the tree and possibly transforms it to reflect certain desugarings. * - * If the tree has unresolved type variables (represented as instances of ``FreeTypeSymbol'' symbols), - * then they might, might be partially or might not be specified in the ``freeTypes'' parameter. + * If the tree has unresolved type variables (represented as instances of `FreeTypeSymbol` symbols), + * then they all have to be resolved first using `Tree.substituteTypes`, or an error occurs. * - * If ``silent'' is false, ``TypeError'' will be thrown in case of a typecheck error. - * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs. + * If `silent` is false, `TypeError` will be thrown in case of a typecheck error. + * If `silent` is true, the typecheck is silent and will return `EmptyTree` if an error occurs. * Such errors don't vanish and can be inspected by turning on -Ydebug. * * Typechecking can be steered with the following optional parameters: - * ``withImplicitViewsDisabled'' recursively prohibits implicit views (though, implicit vals will still be looked up and filled in), default value is false - * ``withMacrosDisabled'' recursively prohibits macro expansions and macro-based implicits, default value is false + * `withImplicitViewsDisabled` recursively prohibits implicit views (though, implicit vals will still be looked up and filled in), default value is false + * `withMacrosDisabled` recursively prohibits macro expansions and macro-based implicits, default value is false */ - def typeCheck(tree: u.Tree, pt: u.Type = u.WildcardType, freeTypes: Map[u.FreeTypeSymbol, u.Type] = Map[u.FreeTypeSymbol, u.Type](), silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree + def typeCheck(tree: u.Tree, pt: u.Type = u.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree - - /** Infers an implicit value of the expected type ``pt'' in the macro callsite context. + /** Infers an implicit value of the expected type `pt` in top-level context. + * Optional `pos` parameter provides a position that will be associated with the implicit search. + * + * As mentioned in https://groups.google.com/forum/#!topic/scala-internals/ta-vbUT6JE8 + * this API won't take into account the lexical context of the callsite, because + * currently it's impossible to reify it. * - * If ``silent'' is false, ``TypeError'' will be thrown in case of an inference error. - * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs. + * If `silent` is false, `TypeError` will be thrown in case of an inference error. + * If `silent` is true, the typecheck is silent and will return `EmptyTree` if an error occurs. * Such errors don't vanish and can be inspected by turning on -Xlog-implicits. - * Unlike in ``typeCheck'', ``silent'' is true by default. + * Unlike in `typeCheck`, `silent` is true by default. */ - def inferImplicitValue(pt: u.Type, silent: Boolean = true, withMacrosDisabled: Boolean = false): u.Tree + def inferImplicitValue(pt: u.Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: u.Position = u.NoPosition): u.Tree - /** Infers an implicit view from the provided tree ``tree'' from the type ``from'' to the type ``to'' in the macro callsite context. + /** Infers an implicit view from the provided tree `tree` from the type `from` to the type `to` in the toplevel context. + * Optional `pos` parameter provides a position that will be associated with the implicit search. * - * Otional parameter, ``reportAmbiguous`` controls whether ambiguous implicit errors should be reported. - * If we search for a view simply to find out whether one type is coercible to another, it might be desirable to set this flag to ``false''. + * As mentioned in https://groups.google.com/forum/#!topic/scala-internals/ta-vbUT6JE8 + * this API won't take into account the lexical context of the callsite, because + * currently it's impossible to reify it. * - * If ``silent'' is false, ``TypeError'' will be thrown in case of an inference error. - * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs. + * If `silent` is false, `TypeError` will be thrown in case of an inference error. + * If `silent` is true, the typecheck is silent and will return `EmptyTree` if an error occurs. * Such errors don't vanish and can be inspected by turning on -Xlog-implicits. - * Unlike in ``typeCheck'', ``silent'' is true by default. + * Unlike in `typeCheck`, `silent` is true by default. */ - def inferImplicitView(tree: u.Tree, from: u.Type, to: u.Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, reportAmbiguous: Boolean = true): u.Tree + def inferImplicitView(tree: u.Tree, from: u.Type, to: u.Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: u.Position = u.NoPosition): u.Tree /** Recursively resets symbols and types in a given tree. * @@ -78,14 +84,14 @@ trait ToolBox[U <: Universe] { /** Compiles and runs a tree using this ToolBox. * - * If the tree has unresolved type variables (represented as instances of ``FreeTypeSymbol'' symbols), - * then they all have to be specified in the ``freeTypes'' parameter or an error occurs. + * If the tree has unresolved type variables (represented as instances of `FreeTypeSymbol` symbols), + * then they all have to be resolved first using `Tree.substituteTypes`, or an error occurs. * * This spawns the compiler at the Namer phase, and pipelines the tree through that compiler. - * Currently ``runExpr'' does not accept trees that already typechecked, because typechecking isn't idempotent. + * Currently `runExpr` does not accept trees that already typechecked, because typechecking isn't idempotent. * For more info, take a look at https://issues.scala-lang.org/browse/SI-5464. */ - def runExpr(tree: u.Tree, freeTypes: Map[u.FreeTypeSymbol, u.Type] = Map[u.FreeTypeSymbol, u.Type]()): Any + def runExpr(tree: u.Tree): Any } /** Represents an error during toolboxing diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index 589c5c7eb0..9987931cf3 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -85,7 +85,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => if (tree.hasSymbol && tree.symbol.isFreeTerm) { tree match { case Ident(_) => - val freeTermRef = Ident(freeTermNames(tree.symbol.asFreeTermSymbol)) + val freeTermRef = Ident(freeTermNames(tree.symbol.asFreeTerm)) if (wrapFreeTermRefs) Apply(freeTermRef, List()) else freeTermRef case _ => throw new Error("internal error: %s (%s, %s) is not supported".format(tree, tree.productPrefix, tree.getClass)) @@ -97,7 +97,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => (expr, freeTermNames) } - def typeCheckExpr(expr0: Tree, pt: Type, silent: Boolean = false, withImplicitViewsDisabled: Boolean, withMacrosDisabled: Boolean): Tree = { + def transformDuringTyper(expr0: Tree, withImplicitViewsDisabled: Boolean, withMacrosDisabled: Boolean)(transform: (analyzer.Typer, Tree) => Tree): Tree = { verifyExpr(expr0) // need to wrap the expr, because otherwise you won't be able to typecheck macros against something that contains free vars @@ -121,34 +121,56 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => currentTyper.context.setReportErrors() // need to manually set context mode, otherwise typer.silent will throw exceptions reporter.reset() - trace("typing (implicit views = %s, macros = %s): ".format(!withImplicitViewsDisabled, !withMacrosDisabled))(showAttributed(expr, true, true, settings.Yshowsymkinds.value)) - wrapper(currentTyper.silent(_.typed(expr, analyzer.EXPRmode, pt)) match { - case analyzer.SilentResultValue(result) => - trace("success: ")(showAttributed(result, true, true, settings.Yshowsymkinds.value)) - var (dummies, unwrapped) = result match { - case Block(dummies, unwrapped) => (dummies, unwrapped) - case unwrapped => (Nil, unwrapped) + val expr1 = wrapper(transform(currentTyper, expr)) + var (dummies1, unwrapped) = expr1 match { + case Block(dummies, unwrapped) => (dummies, unwrapped) + case unwrapped => (Nil, unwrapped) + } + var invertedIndex = freeTerms map (_.swap) + // todo. also fixup singleton types + unwrapped = new Transformer { + override def transform(tree: Tree): Tree = + tree match { + case Ident(name) if invertedIndex contains name => + Ident(invertedIndex(name)) setType tree.tpe + case _ => + super.transform(tree) } - var invertedIndex = freeTerms map (_.swap) - // todo. also fixup singleton types - unwrapped = new Transformer { - override def transform(tree: Tree): Tree = - tree match { - case Ident(name) if invertedIndex contains name => - Ident(invertedIndex(name)) setType tree.tpe - case _ => - super.transform(tree) - } - }.transform(unwrapped) - new TreeTypeSubstituter(dummies map (_.symbol), dummies map (dummy => SingleType(NoPrefix, invertedIndex(dummy.symbol.name)))).traverse(unwrapped) - unwrapped - case error @ analyzer.SilentTypeError(_) => - trace("failed: ")(error.err.errMsg) - if (!silent) throw ToolBoxError("reflective typecheck has failed: %s".format(error.err.errMsg)) - EmptyTree - }) + }.transform(unwrapped) + new TreeTypeSubstituter(dummies1 map (_.symbol), dummies1 map (dummy => SingleType(NoPrefix, invertedIndex(dummy.symbol.name)))).traverse(unwrapped) + unwrapped } + def typeCheckExpr(expr: Tree, pt: Type, silent: Boolean, withImplicitViewsDisabled: Boolean, withMacrosDisabled: Boolean): Tree = + transformDuringTyper(expr, withImplicitViewsDisabled = withImplicitViewsDisabled, withMacrosDisabled = withMacrosDisabled)( + (currentTyper, expr) => { + trace("typing (implicit views = %s, macros = %s): ".format(!withImplicitViewsDisabled, !withMacrosDisabled))(showAttributed(expr, true, true, settings.Yshowsymkinds.value)) + currentTyper.silent(_.typed(expr, analyzer.EXPRmode, pt)) match { + case analyzer.SilentResultValue(result) => + trace("success: ")(showAttributed(result, true, true, settings.Yshowsymkinds.value)) + result + case error @ analyzer.SilentTypeError(_) => + trace("failed: ")(error.err.errMsg) + if (!silent) throw ToolBoxError("reflective typecheck has failed: %s".format(error.err.errMsg)) + EmptyTree + } + }) + + def inferImplicit(tree: Tree, pt: Type, isView: Boolean, silent: Boolean, withMacrosDisabled: Boolean, pos: Position): Tree = + transformDuringTyper(tree, withImplicitViewsDisabled = false, withMacrosDisabled = withMacrosDisabled)( + (currentTyper, tree) => { + trace("inferring implicit %s (macros = %s): ".format(if (isView) "view" else "value", !withMacrosDisabled))(showAttributed(pt, true, true, settings.Yshowsymkinds.value)) + val context = currentTyper.context + analyzer.inferImplicit(tree, pt, reportAmbiguous = true, isView = isView, context = context, saveAmbiguousDivergent = !silent, pos = pos) match { + case failure if failure.tree.isEmpty => + trace("implicit search has failed. to find out the reason, turn on -Xlog-implicits: ")(failure.tree) + if (context.hasErrors) throw ToolBoxError("reflective implicit search has failed: %s".format(context.errBuffer.head.errMsg)) + EmptyTree + case success => + success.tree + } + }) + def compileExpr(expr: Tree): (Object, java.lang.reflect.Method) = { verifyExpr(expr) @@ -254,7 +276,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => } } - def showAttributed(tree: Tree, printTypes: Boolean = true, printIds: Boolean = true, printKinds: Boolean = false): String = { + def showAttributed(artifact: Any, printTypes: Boolean = true, printIds: Boolean = true, printKinds: Boolean = false): String = { val saved1 = settings.printtypes.value val saved2 = settings.uniqid.value val saved3 = settings.Yshowsymkinds.value @@ -262,7 +284,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => settings.printtypes.value = printTypes settings.uniqid.value = printIds settings.Yshowsymkinds.value = printKinds - tree.toString + artifact.toString } finally { settings.printtypes.value = saved1 settings.uniqid.value = saved2 @@ -312,29 +334,37 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => lazy val exporter = importer.reverse lazy val classLoader = new AbstractFileClassLoader(virtualDirectory, mirror.classLoader) - def typeCheck(tree: u.Tree, expectedType: u.Type, freeTypes: Map[u.FreeTypeSymbol, u.Type], silent: Boolean, withImplicitViewsDisabled: Boolean, withMacrosDisabled: Boolean): u.Tree = { - if (compiler.settings.verbose.value) println("typing "+tree+", expectedType = "+expectedType+", freeTypes = "+freeTypes) + def typeCheck(tree: u.Tree, expectedType: u.Type, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree = { + if (compiler.settings.verbose.value) println("importing "+tree+", expectedType = "+expectedType) var ctree: compiler.Tree = importer.importTree(tree) var cexpectedType: compiler.Type = importer.importType(expectedType) - if (compiler.settings.verbose.value) println("substituting "+ctree+", expectedType = "+expectedType) - val cfreeTypes: Map[compiler.FreeTypeSymbol, compiler.Type] = freeTypes map { case (k, v) => (importer.importSymbol(k).asInstanceOf[compiler.FreeTypeSymbol], importer.importType(v)) } - ctree = ctree.substituteTypes(cfreeTypes.keys.toList, cfreeTypes.values.toList) - cexpectedType = cexpectedType.substituteTypes(cfreeTypes.keys.toList, cfreeTypes.values.toList) - if (compiler.settings.verbose.value) println("typing "+ctree+", expectedType = "+expectedType) val ttree: compiler.Tree = compiler.typeCheckExpr(ctree, cexpectedType, silent = silent, withImplicitViewsDisabled = withImplicitViewsDisabled, withMacrosDisabled = withMacrosDisabled) val uttree = exporter.importTree(ttree) uttree } - def inferImplicitValue(pt: u.Type, silent: Boolean, withMacrosDisabled: Boolean): u.Tree = - // todo. implement this - ??? + def inferImplicitValue(pt: u.Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: u.Position = u.NoPosition): u.Tree = { + inferImplicit(u.EmptyTree, pt, isView = false, silent = silent, withMacrosDisabled = withMacrosDisabled, pos = pos) + } + + def inferImplicitView(tree: u.Tree, from: u.Type, to: u.Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: u.Position = u.NoPosition): u.Tree = { + val viewTpe = u.appliedType(u.definitions.FunctionClass(1).toTypeConstructor, List(from, to)) + inferImplicit(tree, viewTpe, isView = true, silent = silent, withMacrosDisabled = withMacrosDisabled, pos = pos) + } - def inferImplicitView(tree: u.Tree, from: u.Type, to: u.Type, silent: Boolean, withMacrosDisabled: Boolean, reportAmbiguous: Boolean): u.Tree = - // todo. implement this - ??? + private def inferImplicit(tree: u.Tree, pt: u.Type, isView: Boolean, silent: Boolean, withMacrosDisabled: Boolean, pos: u.Position): u.Tree = { + if (compiler.settings.verbose.value) println("importing "+pt, ", tree = "+tree+", pos = "+pos) + var ctree: compiler.Tree = importer.importTree(tree) + var cpt: compiler.Type = importer.importType(pt) + var cpos: compiler.Position = importer.importPosition(pos) + + if (compiler.settings.verbose.value) println("inferring implicit %s of type %s, macros = %s".format(if (isView) "view" else "value", pt, !withMacrosDisabled)) + val itree: compiler.Tree = compiler.inferImplicit(ctree, cpt, isView = isView, silent = silent, withMacrosDisabled = withMacrosDisabled, pos = cpos) + val uitree = exporter.importTree(itree) + uitree + } def resetAllAttrs(tree: u.Tree): u.Tree = { val ctree: compiler.Tree = importer.importTree(tree) @@ -360,14 +390,10 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => utree } - def runExpr(tree: u.Tree, freeTypes: Map[u.FreeTypeSymbol, u.Type]): Any = { - if (compiler.settings.verbose.value) println("running "+tree+", freeTypes = "+freeTypes) + def runExpr(tree: u.Tree): Any = { + if (compiler.settings.verbose.value) println("importing "+tree) var ctree: compiler.Tree = importer.importTree(tree) - if (compiler.settings.verbose.value) println("substituting "+ctree) - val cfreeTypes: Map[compiler.FreeTypeSymbol, compiler.Type] = freeTypes map { case (k, v) => (importer.importSymbol(k).asInstanceOf[compiler.FreeTypeSymbol], importer.importType(v)) } - ctree = ctree.substituteTypes(cfreeTypes.keys.toList, cfreeTypes.values.toList) - if (compiler.settings.verbose.value) println("running "+ctree) compiler.runExpr(ctree) } diff --git a/src/compiler/scala/tools/util/PathResolver.scala b/src/compiler/scala/tools/util/PathResolver.scala index 5f4e6d58c3..d89ebcb2a3 100644 --- a/src/compiler/scala/tools/util/PathResolver.scala +++ b/src/compiler/scala/tools/util/PathResolver.scala @@ -194,7 +194,7 @@ class PathResolver(settings: Settings, context: JavaContext) { def scalaBootClassPath = cmdLineOrElse("bootclasspath", Defaults.scalaBootClassPath) def scalaExtDirs = cmdLineOrElse("extdirs", Defaults.scalaExtDirs) /** Scaladoc doesn't need any bootstrapping, otherwise will create errors such as: - * [scaladoc] ../scala-trunk/src/reflect/scala/reflect/makro/Reifiers.scala:89: error: object api is not a member of package reflect + * [scaladoc] ../scala-trunk/src/reflect/scala/reflect/macros/Reifiers.scala:89: error: object api is not a member of package reflect * [scaladoc] case class ReificationError(val pos: reflect.api.PositionApi, val msg: String) extends Throwable(msg) * [scaladoc] ^ * because the bootstrapping will look at the sourcepath and create package "reflect" in "<root>" diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala index 7760568ac3..51760d2807 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala @@ -475,7 +475,7 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with val (prologue, rest) = (anfStats :+ anfExpr) span (s => !s.isInstanceOf[DefDef]) // find first case // println("rest: "+ rest) // val (defs, calls) = rest partition (_.isInstanceOf[DefDef]) - if (rest nonEmpty){ + if (rest.nonEmpty) { // the filter drops the ()'s emitted when transValue encountered a LabelDef val stats = prologue ++ (rest filter (_.isInstanceOf[DefDef])).reverse // ++ calls // println("REVERSED "+ (stats mkString ("{", "\n", "}"))) diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala index 6784b630c7..7511b5309d 100644 --- a/src/library/scala/Array.scala +++ b/src/library/scala/Array.scala @@ -439,10 +439,10 @@ object Array extends FallbackArrayBuilding { * example code. * Line 2 is translated into a call to `apply(Int)`, while line 3 is translated into a call to * `update(Int, T)`. - * + * * Two implicit conversions exist in [[scala.Predef]] that are frequently applied to arrays: a conversion * to [[scala.collection.mutable.ArrayOps]] (shown on line 4 of the example above) and a conversion - * to [[scala.collection.mutable.WrappedArray]] (a subtype of [[scala.collections.Seq]]). + * to [[scala.collection.mutable.WrappedArray]] (a subtype of [[scala.collection.Seq]]). * Both types make available many of the standard operations found in the Scala collections API. * The conversion to `ArrayOps` is temporary, as all operations defined on `ArrayOps` return an `Array`, * while the conversion to `WrappedArray` is permanent as all operations return a `WrappedArray`. diff --git a/src/library/scala/StringContext.scala b/src/library/scala/StringContext.scala index f11dfb72ae..723d95a499 100644 --- a/src/library/scala/StringContext.scala +++ b/src/library/scala/StringContext.scala @@ -8,8 +8,6 @@ package scala -import language.experimental.macros - /** A class to support string interpolation. * This class supports string interpolation as outlined in Scala SIP-11. * It needs to be fully documented once the SIP is accepted. @@ -26,7 +24,7 @@ case class StringContext(parts: String*) { * @param `args` The arguments to be checked. * @throws An `IllegalArgumentException` if this is not the case. */ - def checkLengths(args: Any*): Unit = + def checkLengths(args: Seq[Any]): Unit = if (parts.length != args.length + 1) throw new IllegalArgumentException("wrong number of arguments for interpolated string") @@ -42,11 +40,27 @@ case class StringContext(parts: String*) { * @throws A `StringContext.InvalidEscapeException` if if a `parts` string contains a backslash (`\`) character * that does not start a valid escape sequence. */ - def s(args: Any*): String = { - checkLengths(args: _*) + def s(args: Any*): String = standardInterpolator(treatEscapes, args) + + /** The raw string interpolator. + * + * It inserts its arguments between corresponding parts of the string context. + * As opposed to the simple string interpolator `s`, this one does not treat + * standard escape sequences as defined in the Scala specification. + * @param `args` The arguments to be inserted into the resulting string. + * @throws An `IllegalArgumentException` + * if the number of `parts` in the enclosing `StringContext` does not exceed + * the number of arguments `arg` by exactly 1. + * @throws A `StringContext.InvalidEscapeException` if if a `parts` string contains a backslash (`\`) character + * that does not start a valid escape sequence. + */ + def raw(args: Any*): String = standardInterpolator(identity, args) + + def standardInterpolator(process: String => String, args: Seq[Any]): String = { + checkLengths(args) val pi = parts.iterator val ai = args.iterator - val bldr = new java.lang.StringBuilder(treatEscapes(pi.next())) + val bldr = new java.lang.StringBuilder(process(pi.next())) while (ai.hasNext) { bldr append ai.next bldr append treatEscapes(pi.next()) @@ -83,7 +97,7 @@ case class StringContext(parts: String*) { * format specifier `%%`. */ // The implementation is magically hardwired into `scala.tools.reflect.MacroImplementations.macro_StringInterpolation_f` - def f(args: Any*): String = macro ??? + def f(args: Any*): String = ??? // macro } object StringContext { diff --git a/src/library/scala/collection/GenTraversableOnce.scala b/src/library/scala/collection/GenTraversableOnce.scala index 25edcfe19c..4e0f71ee8b 100644 --- a/src/library/scala/collection/GenTraversableOnce.scala +++ b/src/library/scala/collection/GenTraversableOnce.scala @@ -11,6 +11,7 @@ package scala.collection import scala.reflect.ClassTag import scala.collection.generic.CanBuildFrom import scala.annotation.unchecked.{ uncheckedVariance => uV } +import language.higherKinds /** A template trait for all traversable-once objects which may be * traversed in parallel. diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala index c87726ef2c..d7418de9c3 100644 --- a/src/library/scala/collection/SeqLike.scala +++ b/src/library/scala/collection/SeqLike.scala @@ -852,7 +852,7 @@ object SeqLike { /** Finds a particular index at which one sequence occurs in another sequence. * Like `indexOf`, but finds the latest occurrence rather than earliest. * - * @see [[scala.collection.SeqLike], method `indexOf` + * @see [[scala.collection.SeqLike]], method `indexOf` */ def lastIndexOf[B]( source: Seq[B], sourceOffset: Int, sourceCount: Int, diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala index 9356832afd..641dd095da 100644 --- a/src/library/scala/collection/TraversableLike.scala +++ b/src/library/scala/collection/TraversableLike.scala @@ -13,6 +13,7 @@ import mutable.{ Builder } import annotation.{tailrec, migration, bridge} import annotation.unchecked.{ uncheckedVariance => uV } import parallel.ParIterable +import language.higherKinds /** A template trait for traversable collections of type `Traversable[A]`. * diff --git a/src/library/scala/collection/concurrent/TrieMap.scala b/src/library/scala/collection/concurrent/TrieMap.scala index 2d8217551a..3d0aa6fd07 100644 --- a/src/library/scala/collection/concurrent/TrieMap.scala +++ b/src/library/scala/collection/concurrent/TrieMap.scala @@ -188,7 +188,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends if (sn.hc == hc && equal(sn.k, k, ct)) { if (GCAS(cn, cn.updatedAt(pos, new SNode(k, v, hc), gen), ct)) Some(sn.v) else null } else None - case otherv: V => + case otherv => if (sn.hc == hc && equal(sn.k, k, ct) && sn.v == otherv) { if (GCAS(cn, cn.updatedAt(pos, new SNode(k, v, hc), gen), ct)) Some(sn.v) else null } else None @@ -200,7 +200,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends val ncnode = rn.insertedAt(pos, flag, new SNode(k, v, hc), gen) if (GCAS(cn, ncnode, ct)) None else null case INode.KEY_PRESENT => None - case otherv: V => None + case otherv => None } case sn: TNode[K, V] => clean(parent, ct, lev - 5) @@ -224,9 +224,9 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends case Some(v0) => if (insertln()) Some(v0) else null case None => None } - case otherv: V => + case otherv => ln.get(k) match { - case Some(v0) if v0 == otherv => if (insertln()) Some(otherv) else null + case Some(v0) if v0 == otherv => if (insertln()) Some(otherv.asInstanceOf[V]) else null case _ => None } } diff --git a/src/library/scala/collection/parallel/ParIterableLike.scala b/src/library/scala/collection/parallel/ParIterableLike.scala index d4f1c2f39f..85758b29bc 100644 --- a/src/library/scala/collection/parallel/ParIterableLike.scala +++ b/src/library/scala/collection/parallel/ParIterableLike.scala @@ -30,7 +30,7 @@ import java.util.concurrent.atomic.AtomicBoolean import annotation.unchecked.uncheckedVariance import annotation.unchecked.uncheckedStable -import language.implicitConversions +import language.{ higherKinds, implicitConversions } /** A template trait for parallel collections of type `ParIterable[T]`. diff --git a/src/library/scala/reflect/ClassManifest.scala b/src/library/scala/reflect/ClassManifestDeprecatedApis.scala index d226e43e77..d226e43e77 100644 --- a/src/library/scala/reflect/ClassManifest.scala +++ b/src/library/scala/reflect/ClassManifestDeprecatedApis.scala diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala index 5255c44f10..7b6df6e31c 100644 --- a/src/library/scala/reflect/ClassTag.scala +++ b/src/library/scala/reflect/ClassTag.scala @@ -64,7 +64,6 @@ trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serial } object ClassTag { - private val NothingTYPE = classOf[scala.runtime.Nothing$] private val NullTYPE = classOf[scala.runtime.Null$] private val ObjectTYPE = classOf[java.lang.Object] @@ -81,7 +80,13 @@ object ClassTag { val Object : ClassTag[java.lang.Object] = new ClassTag[java.lang.Object]{ def runtimeClass = ObjectTYPE; private def readResolve() = ClassTag.Object } val AnyVal : ClassTag[scala.AnyVal] = ClassTag.Object.asInstanceOf[ClassTag[scala.AnyVal]] val AnyRef : ClassTag[scala.AnyRef] = ClassTag.Object.asInstanceOf[ClassTag[scala.AnyRef]] - val Nothing : ClassTag[scala.Nothing] = new ClassTag[scala.Nothing]{ def runtimeClass = NothingTYPE; private def readResolve() = ClassTag.Nothing } + val Nothing : ClassTag[scala.Nothing] = new ClassTag[scala.Nothing]{ + def runtimeClass = throw new Exception("Nothing is a bottom type, therefore its erasure does not return a value") + private def readResolve() = ClassTag.Nothing + override def equals(x: Any) = x.isInstanceOf[ClassTag[_]] && (x.asInstanceOf[AnyRef] eq ClassTag.Nothing) + override def hashCode = System.identityHashCode(this) + override def toString = "ClassTag[Nothing]" + } val Null : ClassTag[scala.Null] = new ClassTag[scala.Null]{ def runtimeClass = NullTYPE; private def readResolve() = ClassTag.Null } def apply[T](runtimeClass1: jClass[_]): ClassTag[T] = diff --git a/src/library/scala/reflect/base/Base.scala b/src/library/scala/reflect/base/Base.scala index 5df48307fe..714fd365ef 100644 --- a/src/library/scala/reflect/base/Base.scala +++ b/src/library/scala/reflect/base/Base.scala @@ -1,7 +1,6 @@ package scala.reflect package base -import language.experimental.macros import java.io.PrintWriter import scala.annotation.switch import scala.ref.WeakReference @@ -52,7 +51,6 @@ class Base extends Universe { self => else if (isFreeTerm) "free term" else if (isTerm) "value" else "symbol" - // [Eugene++ to Martin] base names should expose `decode` override def toString() = s"$kindString $name" } implicit val SymbolTag = ClassTag[Symbol](classOf[Symbol]) @@ -63,7 +61,9 @@ class Base extends Universe { self => class TypeSymbol(val owner: Symbol, override val name: TypeName, flags: FlagSet) extends Symbol(name, flags) with TypeSymbolBase { - override val asTypeConstructor = TypeRef(ThisType(owner), this, Nil) + override def toTypeConstructor = TypeRef(ThisType(owner), this, Nil) + override def toType = TypeRef(ThisType(owner), this, Nil) + override def toTypeIn(site: Type) = TypeRef(ThisType(owner), this, Nil) } implicit val TypeSymbolTag = ClassTag[TypeSymbol](classOf[TypeSymbol]) @@ -171,12 +171,17 @@ class Base extends Universe { self => object BoundedWildcardType extends BoundedWildcardTypeExtractor implicit val BoundedWildcardTypeTag = ClassTag[BoundedWildcardType](classOf[BoundedWildcardType]) - type Scope = Iterable[Symbol] + class Scope(elems: Iterable[Symbol]) extends ScopeBase with MemberScopeBase { + def iterator = elems.iterator + def sorted = elems.toList + } + type MemberScope = Scope implicit val ScopeTag = ClassTag[Scope](classOf[Scope]) + implicit val MemberScopeTag = ClassTag[MemberScope](classOf[MemberScope]) - def newScope = newScopeWith() - def newNestedScope(outer: Iterable[Symbol]) = newScope - def newScopeWith(elems: Symbol*): Scope = elems + def newScope: Scope = newScopeWith() + def newNestedScope(outer: Scope): Scope = newScope + def newScopeWith(elems: Symbol*): Scope = new Scope(elems) abstract class Name(str: String) extends NameBase { override def toString = str @@ -204,20 +209,22 @@ class Base extends Universe { self => object nme extends TermNamesBase { type NameType = TermName - val EMPTY = newTermName("") - val ROOT = newTermName("<root>") - val EMPTY_PACKAGE_NAME = newTermName("<empty>") - val CONSTRUCTOR = newTermName("<init>") + val WILDCARD = newTermName("_") + val CONSTRUCTOR = newTermName("<init>") + val ROOTPKG = newTermName("_root_") + val EMPTY = newTermName("") + val EMPTY_PACKAGE_NAME = newTermName("<empty>") + val ROOT = newTermName("<root>") val NO_NAME = newTermName("<none>") - val WILDCARD = newTermName("_") } object tpnme extends TypeNamesBase { type NameType = TypeName - val EMPTY = nme.EMPTY.toTypeName - val ROOT = nme.ROOT.toTypeName - val EMPTY_PACKAGE_NAME = nme.EMPTY_PACKAGE_NAME.toTypeName - val WILDCARD = nme.WILDCARD.toTypeName + val WILDCARD = nme.WILDCARD.toTypeName + val EMPTY = nme.EMPTY.toTypeName + val WILDCARD_STAR = newTypeName("_*") + val EMPTY_PACKAGE_NAME = nme.EMPTY_PACKAGE_NAME.toTypeName + val ROOT = nme.ROOT.toTypeName } type FlagSet = Long @@ -228,7 +235,6 @@ class Base extends Universe { self => override val privateWithin: Name, override val annotations: List[Tree]) extends ModifiersBase { def hasFlag(flags: FlagSet) = (this.flags & flags) != 0 - def hasAllFlags(flags: FlagSet) = (flags & ~this.flags) == 0 } implicit val ModifiersTag = ClassTag[Modifiers](classOf[Modifiers]) @@ -290,16 +296,16 @@ class Base extends Universe { self => object build extends BuildBase { def selectType(owner: Symbol, name: String): TypeSymbol = { val clazz = new ClassSymbol(owner, newTypeName(name), NoFlags) - cached(clazz.fullName)(clazz).asTypeSymbol + cached(clazz.fullName)(clazz).asType } def selectTerm(owner: Symbol, name: String): TermSymbol = { val valu = new MethodSymbol(owner, newTermName(name), NoFlags) - cached(valu.fullName)(valu).asTermSymbol + cached(valu.fullName)(valu).asTerm } def selectOverloadedMethod(owner: Symbol, name: String, index: Int): MethodSymbol = - selectTerm(owner, name).asMethodSymbol + selectTerm(owner, name).asMethod def newNestedSymbol(owner: Symbol, name: Name, pos: Position, flags: Long, isClass: Boolean): Symbol = if (name.isTypeName) @@ -379,7 +385,7 @@ class Base extends Universe { self => object definitions extends DefinitionsBase { lazy val ScalaPackage = staticModule("scala") - lazy val ScalaPackageClass = ScalaPackage.moduleClass.asClassSymbol + lazy val ScalaPackageClass = ScalaPackage.moduleClass.asClass lazy val AnyClass = staticClass("scala.Any") lazy val AnyValClass = staticClass("scala.Any") @@ -460,6 +466,8 @@ class Base extends Universe { self => def treeToString(tree: Tree) = s"<tree ${tree.getClass}>" + def treeType(tree: Tree) = NoType + trait TermTree extends Tree trait TypTree extends Tree diff --git a/src/reflect/scala/reflect/api/Exprs.scala b/src/library/scala/reflect/base/Exprs.scala index 8b2a3b4ea8..8e429afb21 100644 --- a/src/reflect/scala/reflect/api/Exprs.scala +++ b/src/library/scala/reflect/base/Exprs.scala @@ -4,9 +4,7 @@ */ package scala.reflect -package api - -import scala.reflect.base.TreeCreator +package base trait Exprs { self: Universe => @@ -46,7 +44,7 @@ trait Exprs { self: Universe => // !!! remove when we have improved type inference for singletons // search for .type] to find other instances lazy val staticTpe: Type = implicitly[AbsTypeTag[T]].tpe - def actualTpe: Type = tree.tpe + def actualTpe: Type = treeType(tree) def splice: T = throw new UnsupportedOperationException(""" |the function you're calling has not been spliced by the compiler. @@ -58,5 +56,24 @@ trait Exprs { self: Universe => |if you want to splice the underlying expression, use `<your expr>.splice`. |if you want to get a value of the underlying expression, add scala-compiler.jar to the classpath, |import `scala.tools.reflect.Eval` and call `<your expr>.eval` instead.""".trim.stripMargin) + + private def writeReplace(): AnyRef = new SerializedExpr(treec, implicitly[AbsTypeTag[T]].in(scala.reflect.basis.rootMirror)) + } +} + +private[scala] class SerializedExpr(var treec: TreeCreator, var tag: scala.reflect.basis.AbsTypeTag[_]) extends Serializable { + private def writeObject(out: java.io.ObjectOutputStream): Unit = { + out.writeObject(treec) + out.writeObject(tag) + } + + private def readObject(in: java.io.ObjectInputStream): Unit = { + treec = in.readObject().asInstanceOf[TreeCreator] + tag = in.readObject().asInstanceOf[scala.reflect.basis.AbsTypeTag[_]] + } + + private def readResolve(): AnyRef = { + import scala.reflect.basis._ + Expr(rootMirror, treec)(tag) } }
\ No newline at end of file diff --git a/src/library/scala/reflect/base/FlagSets.scala b/src/library/scala/reflect/base/FlagSets.scala index 57946d0f27..43de9970c0 100644 --- a/src/library/scala/reflect/base/FlagSets.scala +++ b/src/library/scala/reflect/base/FlagSets.scala @@ -13,5 +13,11 @@ trait FlagSets { self: Universe => /** The empty set of flags */ val NoFlags: FlagSet + + /** The base API all flag bearers support */ + trait HasFlagsBase { + def flags: FlagSet + def hasFlag(flags: FlagSet): Boolean + } } diff --git a/src/library/scala/reflect/base/Names.scala b/src/library/scala/reflect/base/Names.scala index 280a6ce8a2..532b780e7e 100644 --- a/src/library/scala/reflect/base/Names.scala +++ b/src/library/scala/reflect/base/Names.scala @@ -1,6 +1,8 @@ package scala.reflect package base +import language.implicitConversions + /** A trait that manages names. * A name is a string in one of two name universes: terms and types. * The same string can be a name in both universes. diff --git a/src/library/scala/reflect/base/Scopes.scala b/src/library/scala/reflect/base/Scopes.scala index a5db01c0ce..a388fdc392 100644 --- a/src/library/scala/reflect/base/Scopes.scala +++ b/src/library/scala/reflect/base/Scopes.scala @@ -3,13 +3,33 @@ package base trait Scopes { self: Universe => - type Scope >: Null <: Iterable[Symbol] + type Scope >: Null <: ScopeBase + + /** The base API that all scopes support */ + trait ScopeBase extends Iterable[Symbol] /** A tag that preserves the identity of the `Scope` abstract type from erasure. * Can be used for pattern matching, instance tests, serialization and likes. */ implicit val ScopeTag: ClassTag[Scope] + type MemberScope >: Null <: Scope with MemberScopeBase + + /** The base API that all member scopes support */ + trait MemberScopeBase extends ScopeBase { + /** Sorts the symbols included in this scope so that: + * 1) Symbols appear the linearization order of their owners. + * 2) Symbols with the same owner appear in reverse order of their declarations. + * 3) Synthetic members (e.g. getters/setters for vals/vars) might appear in arbitrary order. + */ + def sorted: List[Symbol] + } + + /** A tag that preserves the identity of the `MemberScope` abstract type from erasure. + * Can be used for pattern matching, instance tests, serialization and likes. + */ + implicit val MemberScopeTag: ClassTag[MemberScope] + /** Create a new scope */ def newScope: Scope diff --git a/src/library/scala/reflect/base/StandardNames.scala b/src/library/scala/reflect/base/StandardNames.scala index 8a3fbe9683..50399a4a1e 100644 --- a/src/library/scala/reflect/base/StandardNames.scala +++ b/src/library/scala/reflect/base/StandardNames.scala @@ -6,6 +6,11 @@ package scala.reflect package base +// Q: I have a pretty name. Where do I put it - into base.StandardNames or into api.StandardNames? +// A: Is it necessary to construct trees (like EMPTY or WILDCARD_STAR)? If yes, then it goes to base.StandardNames. +// Is it necessary to perform reflection (like ERROR or LOCAL_SUFFIX_STRING)? If yes, then it goes to api.StandardNames. +// Otherwise it goes nowhere - reflection API should stay minimalistic. + trait StandardNames { self: Universe => @@ -14,16 +19,16 @@ trait StandardNames { trait NamesBase { type NameType >: Null <: Name - val EMPTY: NameType - val ROOT: NameType - val EMPTY_PACKAGE_NAME: NameType val WILDCARD: NameType } - trait TypeNamesBase extends NamesBase - trait TermNamesBase extends NamesBase { val CONSTRUCTOR: TermName - val NO_NAME: NameType + val ROOTPKG: TermName + } + + trait TypeNamesBase extends NamesBase { + val EMPTY: NameType + val WILDCARD_STAR: NameType } } diff --git a/src/library/scala/reflect/base/Symbols.scala b/src/library/scala/reflect/base/Symbols.scala index ced1f33395..45f7c0c1bd 100644 --- a/src/library/scala/reflect/base/Symbols.scala +++ b/src/library/scala/reflect/base/Symbols.scala @@ -80,10 +80,6 @@ trait Symbols { self: Universe => /** The base API that all symbols support */ trait SymbolBase { this: Symbol => - /** An id number which is unique for all symbols in this universe */ - // [Eugene++ to Martin] do we leave this here? - def id: Int - /** The owner of this symbol. This is the symbol * that directly contains the current symbol's definition. * The `NoSymbol` symbol does not have an owner, and calling this method @@ -112,18 +108,6 @@ trait Symbols { self: Universe => */ def fullName: String - /** If this symbol is a class, this symbol; otherwise the next enclosing - * class, or `NoSymbol` if none exists. - */ - def enclosingClass: Symbol = - if (isClass || this == NoSymbol) this else owner.enclosingClass - - /** If this symbol is a method, this symbol; otherwise the next enclosing - * method, or `NoSymbol` if none exists. - */ - def enclosingMethod: Symbol = - if (isMethod || this == NoSymbol) this else owner.enclosingMethod - /** Does this symbol represent the definition of a type? * Note that every symbol is either a term or a type. * So for every symbol `sym`, either `sym.isTerm` is true @@ -134,7 +118,7 @@ trait Symbols { self: Universe => /** This symbol cast to a TypeSymbol. * Returns ClassCastException if `isType` is false. */ - def asTypeSymbol: TypeSymbol = throw new ClassCastException(toString) + def asType: TypeSymbol = throw new ClassCastException(toString) /** Does this symbol represent the definition of a term? * Note that every symbol is either a term or a term. @@ -146,7 +130,7 @@ trait Symbols { self: Universe => /** This symbol cast to a TermSymbol. * Returns ClassCastException if `isTerm` is false. */ - def asTermSymbol: TermSymbol = throw new ClassCastException(toString) + def asTerm: TermSymbol = throw new ClassCastException(toString) /** Does this symbol represent the definition of a method? * If yes, `isTerm` is also guaranteed to be true. @@ -156,7 +140,7 @@ trait Symbols { self: Universe => /** This symbol cast to a MethodSymbol. * Returns ClassCastException if `isMethod` is false. */ - def asMethodSymbol: MethodSymbol = throw new ClassCastException(toString) + def asMethod: MethodSymbol = throw new ClassCastException(toString) /** Does this symbol represent the definition of a module (i.e. it * results from an object definition?). @@ -167,7 +151,7 @@ trait Symbols { self: Universe => /** This symbol cast to a ModuleSymbol defined by an object definition. * Returns ClassCastException if `isModule` is false. */ - def asModuleSymbol: ModuleSymbol = throw new ClassCastException(toString) + def asModule: ModuleSymbol = throw new ClassCastException(toString) /** Does this symbol represent the definition of a class or trait? * If yes, `isType` is also guaranteed to be true. @@ -183,7 +167,7 @@ trait Symbols { self: Universe => /** This symbol cast to a ClassSymbol representing a class or trait. * Returns ClassCastException if `isClass` is false. */ - def asClassSymbol: ClassSymbol = throw new ClassCastException(toString) + def asClass: ClassSymbol = throw new ClassCastException(toString) /** Does this symbol represent a free term captured by reification? * If yes, `isTerm` is also guaranteed to be true. @@ -193,7 +177,7 @@ trait Symbols { self: Universe => /** This symbol cast to a free term symbol. * Returns ClassCastException if `isFreeTerm` is false. */ - def asFreeTermSymbol: FreeTermSymbol = throw new ClassCastException(toString) + def asFreeTerm: FreeTermSymbol = throw new ClassCastException(toString) /** Does this symbol represent a free type captured by reification? * If yes, `isType` is also guaranteed to be true. @@ -203,7 +187,7 @@ trait Symbols { self: Universe => /** This symbol cast to a free type symbol. * Returns ClassCastException if `isFreeType` is false. */ - def asFreeTypeSymbol: FreeTypeSymbol = throw new ClassCastException(toString) + def asFreeType: FreeTypeSymbol = throw new ClassCastException(toString) def newTermSymbol(name: TermName, pos: Position = NoPosition, flags: FlagSet = NoFlags): TermSymbol def newModuleAndClassSymbol(name: Name, pos: Position = NoPosition, flags: FlagSet = NoFlags): (ModuleSymbol, ClassSymbol) @@ -219,16 +203,34 @@ trait Symbols { self: Universe => final type NameType = TypeName /** The type constructor corresponding to this type symbol. - * This is different from `asType` in that type parameters - * are part of results of `asType`, but not of `asTypeConstructor`. + * This is different from `toType` in that type parameters + * are part of results of `toType`, but not of `toTypeConstructor`. * * Example: Given a class declaration `class C[T] { ... } `, that generates a symbol - * `C`. Then `C.asType` is the type `C[T]`, but `C.asTypeConstructor` is `C`. + * `C`. Then `C.toType` is the type `C[T]`, but `C.toTypeConstructor` is `C`. + */ + def toTypeConstructor: Type + + /** A type reference that refers to this type symbol seen + * as a member of given type `site`. */ - def asTypeConstructor: Type + def toTypeIn(site: Type): Type + + /** A type reference that refers to this type symbol + * Note if symbol is a member of a class, one almost always is interested + * in `asTypeIn` with a site type instead. + * + * Example: Given a class declaration `class C[T] { ... } `, that generates a symbol + * `C`. Then `C.toType` is the type `C[T]`. + * + * By contrast, `C.typeSignature` would be a type signature of form + * `PolyType(ClassInfoType(...))` that describes type parameters, value + * parameters, parent types, and members of `C`. + */ + def toType: Type override def isType = true - override def asTypeSymbol = this + override def asType = this } /** The base API that all term symbols support */ @@ -238,13 +240,13 @@ trait Symbols { self: Universe => final type NameType = TermName final override def isTerm = true - final override def asTermSymbol = this + final override def asTerm = this } /** The base API that all method symbols support */ trait MethodSymbolBase extends TermSymbolBase { this: MethodSymbol => final override def isMethod = true - final override def asMethodSymbol = this + final override def asMethod = this } /** The base API that all module symbols support */ @@ -257,24 +259,24 @@ trait Symbols { self: Universe => // [Eugene++] when this becomes `moduleClass: ClassSymbol`, it will be the happiest day in my life final override def isModule = true - final override def asModuleSymbol = this + final override def asModule = this } /** The base API that all class symbols support */ trait ClassSymbolBase extends TypeSymbolBase { this: ClassSymbol => final override def isClass = true - final override def asClassSymbol = this + final override def asClass = this } /** The base API that all free type symbols support */ trait FreeTypeSymbolBase extends TypeSymbolBase { this: FreeTypeSymbol => final override def isFreeType = true - final override def asFreeTypeSymbol = this + final override def asFreeType = this } /** The base API that all free term symbols support */ trait FreeTermSymbolBase extends TermSymbolBase { this: FreeTermSymbol => final override def isFreeTerm = true - final override def asFreeTermSymbol = this + final override def asFreeTerm = this } } diff --git a/src/library/scala/reflect/base/Trees.scala b/src/library/scala/reflect/base/Trees.scala index 2814450ae3..4e8a520625 100644 --- a/src/library/scala/reflect/base/Trees.scala +++ b/src/library/scala/reflect/base/Trees.scala @@ -34,6 +34,9 @@ trait Trees { self: Universe => /** Obtains string representation of a tree */ protected def treeToString(tree: Tree): String + /** Obtains the type of the tree (we intentionally don't expose `tree.tpe` in base) */ + protected def treeType(tree: Tree): Type + /** Tree is the basis for scala's abstract syntax. The nodes are * implemented as case classes, and the parameters which initialize * a given tree are immutable: however Trees have several mutable @@ -1356,10 +1359,7 @@ trait Trees { self: Universe => implicit val ModifiersTag: ClassTag[Modifiers] /** ... */ - abstract class ModifiersBase { - def flags: FlagSet - def hasFlag(flags: FlagSet): Boolean - def hasAllFlags(flags: FlagSet): Boolean + abstract class ModifiersBase extends HasFlagsBase { def privateWithin: Name // default: EmptyTypeName def annotations: List[Tree] // default: List() def mapAnnotations(f: List[Tree] => List[Tree]): Modifiers = diff --git a/src/library/scala/reflect/base/TypeTags.scala b/src/library/scala/reflect/base/TypeTags.scala index 05b1a079d7..3f7024366e 100644 --- a/src/library/scala/reflect/base/TypeTags.scala +++ b/src/library/scala/reflect/base/TypeTags.scala @@ -169,6 +169,7 @@ trait TypeTags { self: Universe => val otherMirror1 = otherMirror.asInstanceOf[MirrorOf[otherMirror.universe.type]] otherMirror.universe.AbsTypeTag[T](otherMirror1, tpec) } + private def writeReplace(): AnyRef = new SerializedTypeTag(tpec, concrete = false) } /** @@ -233,13 +234,18 @@ trait TypeTags { self: Universe => val otherMirror1 = otherMirror.asInstanceOf[MirrorOf[otherMirror.universe.type]] otherMirror.universe.TypeTag[T](otherMirror1, tpec) } + private def writeReplace(): AnyRef = new SerializedTypeTag(tpec, concrete = true) } - private class PredefTypeTag[T](_tpe: Type, copyIn: Universe => Universe # TypeTag[T]) extends TypeTagImpl[T](rootMirror, null) { + private class PredefTypeCreator[T](copyIn: Universe => Universe # TypeTag[T]) extends TypeCreator { + def apply[U <: Universe with Singleton](m: MirrorOf[U]): U # Type = { + copyIn(m.universe).asInstanceOf[U # TypeTag[T]].tpe + } + } + + private class PredefTypeTag[T](_tpe: Type, copyIn: Universe => Universe # TypeTag[T]) extends TypeTagImpl[T](rootMirror, new PredefTypeCreator(copyIn)) { override lazy val tpe: Type = _tpe - override def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # TypeTag[T] = - copyIn(otherMirror.universe).asInstanceOf[U # TypeTag[T]] - private def readResolve() = copyIn(self) + private def writeReplace(): AnyRef = new SerializedTypeTag(tpec, concrete = true) } // incantations @@ -248,3 +254,21 @@ trait TypeTags { self: Universe => // big thanks to Viktor Klang for this brilliant idea! def typeOf[T](implicit ttag: TypeTag[T]): Type = ttag.tpe } + +private[scala] class SerializedTypeTag(var tpec: TypeCreator, var concrete: Boolean) extends Serializable { + private def writeObject(out: java.io.ObjectOutputStream): Unit = { + out.writeObject(tpec) + out.writeBoolean(concrete) + } + + private def readObject(in: java.io.ObjectInputStream): Unit = { + tpec = in.readObject().asInstanceOf[TypeCreator] + concrete = in.readBoolean() + } + + private def readResolve(): AnyRef = { + import scala.reflect.basis._ + if (concrete) TypeTag(rootMirror, tpec) + else AbsTypeTag(rootMirror, tpec) + } +}
\ No newline at end of file diff --git a/src/library/scala/reflect/base/Universe.scala b/src/library/scala/reflect/base/Universe.scala index 93ddcb9f55..6f37214fa8 100644 --- a/src/library/scala/reflect/base/Universe.scala +++ b/src/library/scala/reflect/base/Universe.scala @@ -10,9 +10,57 @@ abstract class Universe extends Symbols with Constants with AnnotationInfos with Positions + with Exprs with TypeTags with TagInterop with StandardDefinitions with StandardNames with BuildUtils - with Mirrors
\ No newline at end of file + with Mirrors +{ + /** Given an expression, generate a tree that when compiled and executed produces the original tree. + * The produced tree will be bound to the Universe it was called from. + * + * For instance, given the abstract syntax tree representation of the <[ x + 1 ]> expression: + * + * {{{ + * Apply(Select(Ident("x"), "+"), List(Literal(Constant(1)))) + * }}} + * + * The reifier transforms it to the following expression: + * + * {{{ + * <[ + * val $u: u.type = u // where u is a reference to the Universe that calls the reify + * $u.Expr[Int]($u.Apply($u.Select($u.Ident($u.newFreeVar("x", <Int>, x), "+"), List($u.Literal($u.Constant(1)))))) + * ]> + * }}} + * + * Reification performs expression splicing (when processing Expr.splice) + * and type splicing (for every type T that has a TypeTag[T] implicit in scope): + * + * {{{ + * val two = mirror.reify(2) // Literal(Constant(2)) + * val four = mirror.reify(two.splice + two.splice) // Apply(Select(two.tree, newTermName("$plus")), List(two.tree)) + * + * def macroImpl[T](c: Context) = { + * ... + * // T here is just a type parameter, so the tree produced by reify won't be of much use in a macro expansion + * // however, if T were annotated with c.TypeTag (which would declare an implicit parameter for macroImpl) + * // then reification would subtitute T with the TypeTree that was used in a TypeApply of this particular macro invocation + * val factory = c.reify{ new Queryable[T] } + * ... + * } + * }}} + * + * The transformation looks mostly straightforward, but it has its tricky parts: + * * Reifier retains symbols and types defined outside the reified tree, however + * locally defined entities get erased and replaced with their original trees + * * Free variables are detected and wrapped in symbols of the type FreeVar + * * Mutable variables that are accessed from a local function are wrapped in refs + * * Since reified trees can be compiled outside of the scope they've been created in, + * special measures are taken to ensure that all members accessed in the reifee remain visible + */ + // implementation is magically hardwired to `scala.reflect.reify.Taggers` + def reify[T](expr: T): Expr[T] = ??? // macro +}
\ No newline at end of file diff --git a/src/library/scala/reflect/makro/internal/macroImpl.scala b/src/library/scala/reflect/macros/internal/macroImpl.scala index 0dfa8d1654..a7b2bf482c 100644 --- a/src/library/scala/reflect/makro/internal/macroImpl.scala +++ b/src/library/scala/reflect/macros/internal/macroImpl.scala @@ -1,4 +1,4 @@ -package scala.reflect.makro +package scala.reflect.macros package internal /** Links macro definitions with their implementation. diff --git a/src/library/scala/reflect/makro/internal/package.scala b/src/library/scala/reflect/macros/internal/package.scala index 78cb0ffb10..912db53ed4 100644 --- a/src/library/scala/reflect/makro/internal/package.scala +++ b/src/library/scala/reflect/macros/internal/package.scala @@ -1,8 +1,7 @@ -package scala.reflect -package makro +package scala.reflect.macros -import language.experimental.macros import scala.reflect.base.{Universe => BaseUniverse} +import scala.reflect.ClassTag // anchors for materialization macros emitted during tag materialization in Implicits.scala // implementation is magically hardwired into `scala.reflect.reify.Taggers` @@ -10,7 +9,7 @@ import scala.reflect.base.{Universe => BaseUniverse} // todo. once we have implicit macros for tag generation, we can remove these anchors // [Eugene++] how do I hide this from scaladoc? package object internal { - private[scala] def materializeClassTag[T](u: BaseUniverse): ClassTag[T] = macro ??? - private[scala] def materializeAbsTypeTag[T](u: BaseUniverse): u.AbsTypeTag[T] = macro ??? - private[scala] def materializeTypeTag[T](u: BaseUniverse): u.TypeTag[T] = macro ??? + private[scala] def materializeClassTag[T](u: BaseUniverse): ClassTag[T] = ??? // macro + private[scala] def materializeAbsTypeTag[T](u: BaseUniverse): u.AbsTypeTag[T] = ??? // macro + private[scala] def materializeTypeTag[T](u: BaseUniverse): u.TypeTag[T] = ??? // macro } diff --git a/src/library/scala/runtime/Tuple2Zipped.scala b/src/library/scala/runtime/Tuple2Zipped.scala index 5ad364c8a5..dce7eef08d 100644 --- a/src/library/scala/runtime/Tuple2Zipped.scala +++ b/src/library/scala/runtime/Tuple2Zipped.scala @@ -10,6 +10,7 @@ package scala.runtime import scala.collection.{ TraversableLike, IterableLike } import scala.collection.generic.{ CanBuildFrom => CBF } +import language.{ higherKinds, implicitConversions } /** This interface is intended as a minimal interface, not complicated * by the requirement to resolve type constructors, for implicit search (which only diff --git a/src/library/scala/runtime/Tuple3Zipped.scala b/src/library/scala/runtime/Tuple3Zipped.scala index 4e9c542c58..f3ca08649d 100644 --- a/src/library/scala/runtime/Tuple3Zipped.scala +++ b/src/library/scala/runtime/Tuple3Zipped.scala @@ -10,6 +10,7 @@ package scala.runtime import scala.collection.{ TraversableLike, IterableLike } import scala.collection.generic.{ CanBuildFrom => CBF } +import language.{ higherKinds, implicitConversions } /** See comment on ZippedTraversable2. */ trait ZippedTraversable3[+El1, +El2, +El3] { diff --git a/src/library/scala/runtime/WorksheetSupport.scala b/src/library/scala/runtime/WorksheetSupport.scala new file mode 100644 index 0000000000..db6d6359a3 --- /dev/null +++ b/src/library/scala/runtime/WorksheetSupport.scala @@ -0,0 +1,87 @@ +package scala.runtime +import java.io.{OutputStream, PrintStream} +import scala.runtime.ScalaRunTime.stringOf + +/** A utility object that's needed by the code that executes a worksheet. + */ +object WorksheetSupport { + + /** The offset in the source which should be printed */ + private var currentOffset = 0 + + /** A stream that flushes in regular intervals so that output can be captured + * in real time. The flush interval is determined by the field "flushInterval". + * By default it is 30ms. + */ + private class FlushedOutputStream(out: OutputStream) extends OutputStream { + private var lastFlush: Long = 0L + protected val flushInterval = 30000000L // 30ms + private var lastCh: Int = '\n' + override def write(b: Array[Byte], off: Int, len: Int) = { + for (idx <- off until (off + len min b.length)) writeOne(b(idx)) + flush() + } + override def write(c: Int) { + writeOne(c) + flush() + } + override def flush() { + val current = System.nanoTime + if (current - lastFlush >= flushInterval) { + out.flush() + lastFlush = current + } + } + def writeOne(c: Int) { + if (lastCh == '\n') { + lastCh = 0 + write((currentOffset+" ").getBytes) + } + out.write(c) + lastCh = c + } + def ensureNewLine() = if (lastCh != '\n') writeOne('\n') + } + + private val flushedOut = new FlushedOutputStream(System.out) + private val printOut = new PrintStream(flushedOut) + + private def redirected(op: => Unit) = { + val oldSysOut = System.out + val oldSysErr = System.err + val oldConsOut = Console.out + val oldConsErr = Console.err + System.setOut(printOut) + System.setErr(printOut) + Console.setOut(printOut) + Console.setErr(printOut) + try op + finally { + printOut.close() + System.setOut(oldSysOut) + System.setErr(oldSysErr) + Console.setOut(oldConsOut) + Console.setErr(oldConsErr) + } + } + + def $execute(op: => Unit) = redirected { + try op + catch { + case ex: StopException => ; + case ex => ex.printStackTrace() + } + } + + def $skip(n: Int) = { + flushedOut.ensureNewLine() + currentOffset += n + } + + def $stop() = throw new StopException + + def $show(x: Any): String = stringOf(x, scala.Int.MaxValue) +} + +class StopException extends Exception + diff --git a/src/library/scala/util/Try.scala b/src/library/scala/util/Try.scala index 9475a05d5a..f85bac0b84 100644 --- a/src/library/scala/util/Try.scala +++ b/src/library/scala/util/Try.scala @@ -8,11 +8,9 @@ package scala.util - - import collection.Seq import scala.util.control.NonFatal - +import language.implicitConversions /** * The `Try` type represents a computation that may either result in an exception, or return a @@ -208,7 +206,7 @@ final case class Success[+T](value: T) extends Try[T] { def flatMap[U](f: T => Try[U]): Try[U] = try f(value) catch { - case e => Failure(e) + case e: Throwable => Failure(e) } def flatten[U](implicit ev: T <:< Try[U]): Try[U] = value def foreach[U](f: T => U): Unit = f(value) diff --git a/src/library/scala/util/automata/WordBerrySethi.scala b/src/library/scala/util/automata/WordBerrySethi.scala index 1d4d1f971f..235a74dd7a 100644 --- a/src/library/scala/util/automata/WordBerrySethi.scala +++ b/src/library/scala/util/automata/WordBerrySethi.scala @@ -11,7 +11,7 @@ package scala.util.automata import scala.collection.{ immutable, mutable } import scala.util.regexp.WordExp -/** This class turns a regular expression into a [[scala.util.automata.NondetWorkAutom]] +/** This class turns a regular expression into a [[scala.util.automata.NondetWordAutom]] * celebrated position automata construction (also called ''Berry-Sethi'' or ''Glushkov''). * * @author Burak Emir diff --git a/src/library/scala/xml/dtd/ElementValidator.scala b/src/library/scala/xml/dtd/ElementValidator.scala index 111c1b5e78..f97da1c8a3 100644 --- a/src/library/scala/xml/dtd/ElementValidator.scala +++ b/src/library/scala/xml/dtd/ElementValidator.scala @@ -115,6 +115,7 @@ class ElementValidator() extends Function1[Node,Boolean] { (dfa delta q).getOrElse(e, throw ValidationException("element %s not allowed here" format e)) } } + case _ => false } /** applies various validations - accumulates error messages in exc diff --git a/src/library/scala/xml/parsing/XhtmlParser.scala b/src/library/scala/xml/parsing/XhtmlParser.scala index de9a3f2243..e7e3cc38c9 100644 --- a/src/library/scala/xml/parsing/XhtmlParser.scala +++ b/src/library/scala/xml/parsing/XhtmlParser.scala @@ -12,7 +12,7 @@ package parsing import scala.io.Source /** An XML Parser that preserves `CDATA` blocks and knows about - * [[scala.xml.parsing.HtmlEntities]]. + * [[scala.xml.parsing.XhtmlEntities]]. * * @author (c) David Pollak, 2007 WorldWide Conferencing, LLC. */ diff --git a/src/partest/scala/tools/partest/DirectTest.scala b/src/partest/scala/tools/partest/DirectTest.scala index 5b4e1b4b25..323705b695 100644 --- a/src/partest/scala/tools/partest/DirectTest.scala +++ b/src/partest/scala/tools/partest/DirectTest.scala @@ -70,7 +70,7 @@ abstract class DirectTest extends App { /** Constructor/main body **/ try show() - catch { case t => println(t.getMessage) ; t.printStackTrace ; sys.exit(1) } + catch { case t: Exception => println(t.getMessage) ; t.printStackTrace ; sys.exit(1) } /** Debugger interest only below this line **/ protected def isDebug = (sys.props contains "partest.debug") || (sys.env contains "PARTEST_DEBUG") diff --git a/src/partest/scala/tools/partest/ScaladocModelTest.scala b/src/partest/scala/tools/partest/ScaladocModelTest.scala index ffc5e74cc0..7117d7c715 100644 --- a/src/partest/scala/tools/partest/ScaladocModelTest.scala +++ b/src/partest/scala/tools/partest/ScaladocModelTest.scala @@ -72,7 +72,7 @@ abstract class ScaladocModelTest extends DirectTest { testModel(universe.rootPackage) println("Done.") } catch { - case e => + case e: Exception => println(e) e.printStackTrace } @@ -102,7 +102,7 @@ abstract class ScaladocModelTest extends DirectTest { // finally, enable easy navigation inside the entities object access { - class TemplateAccess(tpl: DocTemplateEntity) { + implicit class TemplateAccess(tpl: DocTemplateEntity) { def _class(name: String): DocTemplateEntity = getTheFirst(_classes(name), tpl.qualifiedName + ".class(" + name + ")") def _classes(name: String): List[DocTemplateEntity] = tpl.templates.filter(_.name == name).collect({ case c: DocTemplateEntity with Class => c}) @@ -143,21 +143,21 @@ abstract class ScaladocModelTest extends DirectTest { def _aliasTypeTpls(name: String): List[DocTemplateEntity] = tpl.members.collect({ case dtpl: DocTemplateEntity with AliasType if dtpl.name == name => dtpl }) } - class PackageAccess(pack: Package) extends TemplateAccess(pack) { + trait WithMembers { + def members: List[MemberEntity] + def _member(name: String): MemberEntity = getTheFirst(_members(name), this.toString + ".member(" + name + ")") + def _members(name: String): List[MemberEntity] = members.filter(_.name == name) + } + implicit class PackageAccess(pack: Package) extends TemplateAccess(pack) { def _package(name: String): Package = getTheFirst(_packages(name), pack.qualifiedName + ".package(" + name + ")") def _packages(name: String): List[Package] = pack.packages.filter(_.name == name) } - - class MemberAccess(mbrs: WithMembers) { - def _member(name: String): MemberEntity = getTheFirst(_members(name), mbrs.toString + ".member(" + name + ")") - def _members(name: String): List[MemberEntity] = mbrs.members.filter(_.name == name) + implicit class DocTemplateEntityMembers(val underlying: DocTemplateEntity) extends WithMembers { + def members = underlying.members + } + implicit class ImplicitConversionMembers(val underlying: ImplicitConversion) extends WithMembers { + def members = underlying.members } - - type WithMembers = { def members: List[MemberEntity]; def toString: String } /* DocTemplates and ImplicitConversions */ - - implicit def templateAccess(tpl: DocTemplateEntity) = new TemplateAccess(tpl) - implicit def packageAccess(pack: Package) = new PackageAccess(pack) - implicit def membersAccess(mbrs: WithMembers) = new MemberAccess(mbrs) def getTheFirst[T](list: List[T], expl: String): T = list.length match { case 1 => list.head diff --git a/src/partest/scala/tools/partest/instrumented/Instrumentation.scala b/src/partest/scala/tools/partest/instrumented/Instrumentation.scala index f29a7f90fd..3589df60f6 100644 --- a/src/partest/scala/tools/partest/instrumented/Instrumentation.scala +++ b/src/partest/scala/tools/partest/instrumented/Instrumentation.scala @@ -54,14 +54,20 @@ object Instrumentation { def startProfiling(): Unit = Profiler.startProfiling() def stopProfiling(): Unit = Profiler.stopProfiling() def resetProfiling(): Unit = Profiler.resetProfiling() + def isProfiling(): Boolean = Profiler.isProfiling() def getStatistics: Statistics = { - Profiler.stopProfiling() + val isProfiling = Profiler.isProfiling() + if (isProfiling) { + Profiler.stopProfiling() + } val stats = Profiler.getStatistics().asScala.toSeq.map { case (trace, count) => MethodCallTrace(trace.className, trace.methodName, trace.methodDescriptor) -> count.intValue } val res = Map(stats: _*) - Profiler.startProfiling() + if (isProfiling) { + Profiler.startProfiling() + } res } diff --git a/src/partest/scala/tools/partest/instrumented/Profiler.java b/src/partest/scala/tools/partest/instrumented/Profiler.java index 215bdbba08..0c87060794 100644 --- a/src/partest/scala/tools/partest/instrumented/Profiler.java +++ b/src/partest/scala/tools/partest/instrumented/Profiler.java @@ -55,6 +55,10 @@ public class Profiler { isProfiling = false; } + public static boolean isProfiling() { + return isProfiling; + } + public static void resetProfiling() { counts = new HashMap<MethodCallTrace, Integer>(); } diff --git a/src/partest/scala/tools/partest/javaagent/ASMTransformer.java b/src/partest/scala/tools/partest/javaagent/ASMTransformer.java index 643c683002..09cd485d6b 100644 --- a/src/partest/scala/tools/partest/javaagent/ASMTransformer.java +++ b/src/partest/scala/tools/partest/javaagent/ASMTransformer.java @@ -21,7 +21,9 @@ public class ASMTransformer implements ClassFileTransformer { // we instrument all classes from empty package (!className.contains("/") || // we instrument all classes from scala package - className.startsWith("scala/")); + className.startsWith("scala/") || + // we instrument all classes from `instrumented` package + className.startsWith("instrumented/")); } public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { diff --git a/src/partest/scala/tools/partest/nest/RunnerManager.scala b/src/partest/scala/tools/partest/nest/RunnerManager.scala index dc15d4475b..5a7684dc61 100644 --- a/src/partest/scala/tools/partest/nest/RunnerManager.scala +++ b/src/partest/scala/tools/partest/nest/RunnerManager.scala @@ -82,7 +82,7 @@ class RunnerManager(kind: String, val fileManager: FileManager, params: TestRunP private def compareFiles(f1: File, f2: File): String = try fileManager.compareFiles(f1, f2) - catch { case t => t.toString } + catch { case t: Exception => t.toString } /** This does something about absolute paths and file separator * chars before diffing. @@ -779,11 +779,11 @@ class RunnerManager(kind: String, val fileManager: FileManager, params: TestRunP logStackTrace(logFile, t, "Possible compiler crash during test of: " + testFile + "\n") LogContext(logFile) } - catch { case t => LogContext(null) } + catch { case t: Throwable => LogContext(null) } } def run(): (Boolean, LogContext) = { - val result = try processSingleFile(testFile) catch { case t => (false, crashContext(t)) } + val result = try processSingleFile(testFile) catch { case t: Throwable => (false, crashContext(t)) } passed = Some(result._1) result } diff --git a/src/partest/scala/tools/partest/package.scala b/src/partest/scala/tools/partest/package.scala index 9b510eacd6..9f45b380eb 100644 --- a/src/partest/scala/tools/partest/package.scala +++ b/src/partest/scala/tools/partest/package.scala @@ -30,6 +30,9 @@ package object partest { implicit private[partest] def temporaryPath2File(x: Path): JFile = x.jfile implicit private[partest] def temporaryFile2Path(x: JFile): Path = Path(x) + implicit lazy val postfixOps = language.postfixOps + implicit lazy val implicitConversions = language.implicitConversions + def timed[T](body: => T): (T, Long) = { val t1 = System.currentTimeMillis val result = body @@ -60,7 +63,7 @@ package object partest { def allPropertiesString = { import collection.JavaConversions._ - System.getProperties.toList.sorted map { case (k, v) => "%s -> %s\n".format(k, v) } mkString + System.getProperties.toList.sorted map { case (k, v) => "%s -> %s\n".format(k, v) } mkString "" } def showAllJVMInfo() { diff --git a/src/reflect/scala/reflect/api/FlagSets.scala b/src/reflect/scala/reflect/api/FlagSets.scala index 969176d641..6d105c9d20 100644 --- a/src/reflect/scala/reflect/api/FlagSets.scala +++ b/src/reflect/scala/reflect/api/FlagSets.scala @@ -9,8 +9,7 @@ trait FlagSets { self: Universe => trait FlagOps extends Any { def | (right: FlagSet): FlagSet - def & (right: FlagSet): FlagSet - def containsAll (right: FlagSet): Boolean + def hasFlag(flags: FlagSet): Boolean } implicit def addFlagOps(left: FlagSet): FlagOps @@ -19,8 +18,6 @@ trait FlagSets { self: Universe => type FlagValues >: Null <: FlagValuesApi - // [Eugene++] any other flags we would like to expose? - trait FlagValuesApi { /** Flag indicating that symbol or tree represents a trait */ @@ -100,13 +97,5 @@ trait FlagSets { self: Universe => /** Flag indicating that parameter has a default value */ val DEFAULTPARAM: FlagSet - - /** Flag indicating that trait has neither method implementations nor fields. - * This means the trait can be represented as a Java interface. */ - val INTERFACE: FlagSet - - def union(flags: FlagSet*): FlagSet - def intersection(flag: FlagSet*): FlagSet - def containsAll(superset: FlagSet, subset: FlagSet): Boolean } } diff --git a/src/reflect/scala/reflect/api/Importers.scala b/src/reflect/scala/reflect/api/Importers.scala index 69d6414f4f..de540a9605 100644 --- a/src/reflect/scala/reflect/api/Importers.scala +++ b/src/reflect/scala/reflect/api/Importers.scala @@ -17,5 +17,7 @@ trait Importers { self: Universe => def importType(tpe: from.Type): Type def importTree(tree: from.Tree): Tree + + def importPosition(pos: from.Position): Position } }
\ No newline at end of file diff --git a/src/reflect/scala/reflect/api/Mirrors.scala b/src/reflect/scala/reflect/api/Mirrors.scala index 27176a2a2d..a4d86cf1fd 100644 --- a/src/reflect/scala/reflect/api/Mirrors.scala +++ b/src/reflect/scala/reflect/api/Mirrors.scala @@ -34,7 +34,7 @@ trait Mirrors { self: Universe => * that can be used to get and, if appropriate, set the value of the field. * * To get a field symbol by the name of the field you would like to reflect, - * use `<this mirror>.symbol.typeSignature.member(newTermName(<name of the field>)).asTermSymbol`. + * use `<this mirror>.symbol.typeSignature.member(newTermName(<name of the field>)).asTerm.accessed`. * For further information about member lookup refer to `Symbol.typeSignature`. * * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility). @@ -54,7 +54,7 @@ trait Mirrors { self: Universe => * that can be used to invoke the method provided. * * To get a method symbol by the name of the method you would like to reflect, - * use `<this mirror>.symbol.typeSignature.member(newTermName(<name of the method>)).asMethodSymbol`. + * use `<this mirror>.symbol.typeSignature.member(newTermName(<name of the method>)).asMethod`. * For further information about member lookup refer to `Symbol.typeSignature`. * * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility). @@ -66,7 +66,7 @@ trait Mirrors { self: Universe => * that can be used to create instances of the class, inspect its companion object or perform further reflections. * * To get a class symbol by the name of the class you would like to reflect, - * use `<this mirror>.symbol.typeSignature.member(newTypeName(<name of the class>)).asClassSymbol`. + * use `<this mirror>.symbol.typeSignature.member(newTypeName(<name of the class>)).asClass`. * For further information about member lookup refer to `Symbol.typeSignature`. * * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility). @@ -78,7 +78,7 @@ trait Mirrors { self: Universe => * that can be used to get the instance of the object or inspect its companion class. * * To get a module symbol by the name of the object you would like to reflect, - * use `<this mirror>.symbol.typeSignature.member(newTermName(<name of the object>)).asModuleSymbol`. + * use `<this mirror>.symbol.typeSignature.member(newTermName(<name of the object>)).asModule`. * For further information about member lookup refer to `Symbol.typeSignature`. * * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility). @@ -201,7 +201,7 @@ trait Mirrors { self: Universe => * that can be used to invoke it and construct instances of this mirror's symbols. * * To get a constructor symbol you would like to reflect, - * use `<this mirror>.symbol.typeSignature.member(nme.CONSTRUCTOR).asMethodSymbol`. + * use `<this mirror>.symbol.typeSignature.member(nme.CONSTRUCTOR).asMethod`. * For further information about member lookup refer to `Symbol.typeSignature`. * * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility). diff --git a/src/reflect/scala/reflect/api/Names.scala b/src/reflect/scala/reflect/api/Names.scala index 222ee5024b..d6868c26ab 100644 --- a/src/reflect/scala/reflect/api/Names.scala +++ b/src/reflect/scala/reflect/api/Names.scala @@ -20,9 +20,6 @@ trait Names extends base.Names { */ abstract class NameApi extends NameBase { - // [Eugene++] this functionality should be in base - // this is because stuff will be reified in mangled state, and people will need a way to figure it out - /** Replaces all occurrences of \$op_names in this name by corresponding operator symbols. * Example: `foo_\$plus\$eq` becomes `foo_+=` */ diff --git a/src/reflect/scala/reflect/api/StandardNames.scala b/src/reflect/scala/reflect/api/StandardNames.scala index eb1ecda900..24d803a24a 100644 --- a/src/reflect/scala/reflect/api/StandardNames.scala +++ b/src/reflect/scala/reflect/api/StandardNames.scala @@ -5,6 +5,9 @@ package scala.reflect package api +// Q: I have a pretty name. Where do I put it - into base.StandardNames or into api.StandardNames? +// A: <see base.StandardNames> + trait StandardNames extends base.StandardNames { self: Universe => @@ -12,151 +15,16 @@ trait StandardNames extends base.StandardNames { val tpnme: TypeNamesApi trait NamesApi extends NamesBase { - val ANON_CLASS_NAME: NameType - val ANON_FUN_NAME: NameType + val ROOT: NameType val EMPTY: NameType val ERROR: NameType - val IMPORT: NameType - val MODULE_VAR_SUFFIX: NameType val PACKAGE: NameType - val ROOT: NameType - val SPECIALIZED_SUFFIX: NameType - - def flattenedName(segments: Name*): NameType } trait TermNamesApi extends NamesApi with TermNamesBase { - val EXPAND_SEPARATOR_STRING: String - val IMPL_CLASS_SUFFIX: String - val INTERPRETER_IMPORT_WRAPPER: String - val INTERPRETER_LINE_PREFIX: String - val INTERPRETER_VAR_PREFIX: String - val INTERPRETER_WRAPPER_SUFFIX: String - val LOCALDUMMY_PREFIX: String val LOCAL_SUFFIX_STRING: String - val MODULE_SUFFIX_NAME: TermName - val NAME_JOIN_NAME: TermName - val PROTECTED_PREFIX: String - val PROTECTED_SET_PREFIX: String - val SETTER_SUFFIX: TermName - val SINGLETON_SUFFIX: String - val SUPER_PREFIX_STRING: String - val TRAIT_SETTER_SEPARATOR_STRING: String - - val FAKE_LOCAL_THIS: TermName - val INITIALIZER: TermName - val LAZY_LOCAL: TermName - val UNIVERSE_BUILD: NameType - val UNIVERSE_BUILD_PREFIX: NameType - val UNIVERSE_PREFIX: NameType - val UNIVERSE_SHORT: NameType - val MIRROR_PREFIX: NameType - val MIRROR_SHORT: NameType - val MIRROR_UNTYPED: NameType - val REIFY_FREE_PREFIX: NameType - val REIFY_FREE_THIS_SUFFIX: NameType - val REIFY_FREE_VALUE_SUFFIX: NameType - val REIFY_SYMDEF_PREFIX: NameType - val MIXIN_CONSTRUCTOR: TermName - val MODULE_INSTANCE_FIELD: TermName - val OUTER: TermName - val OUTER_LOCAL: TermName - val OUTER_SYNTH: TermName - val SELECTOR_DUMMY: TermName - val SELF: TermName - val SPECIALIZED_INSTANCE: TermName - val STAR: TermName - val THIS: TermName - - val BITMAP_NORMAL: TermName - val BITMAP_TRANSIENT: TermName - val BITMAP_CHECKINIT: TermName - val BITMAP_CHECKINIT_TRANSIENT: TermName - - val ROOTPKG: TermName - - val ADD: TermName - val AND: TermName - val ASR: TermName - val DIV: TermName - val EQ: TermName - val EQL: TermName - val GE: TermName - val GT: TermName - val HASHHASH: TermName - val LE: TermName - val LSL: TermName - val LSR: TermName - val LT: TermName - val MINUS: TermName - val MOD: TermName - val MUL: TermName - val NE: TermName - val OR: TermName - val PLUS : TermName - val SUB: TermName - val XOR: TermName - val ZAND: TermName - val ZOR: TermName - - val UNARY_~ : TermName - val UNARY_+ : TermName - val UNARY_- : TermName - val UNARY_! : TermName - - val ??? : TermName - - def isConstructorName(name: Name): Boolean - def isExceptionResultName(name: Name): Boolean - def isImplClassName(name: Name): Boolean - def isLocalDummyName(name: Name): Boolean - def isLocalName(name: Name): Boolean - def isLoopHeaderLabel(name: Name): Boolean - def isModuleName(name: Name): Boolean - def isOpAssignmentName(name: Name): Boolean - def isProtectedAccessorName(name: Name): Boolean - def isReplWrapperName(name: Name): Boolean - def isSetterName(name: Name): Boolean - def isSingletonName(name: Name): Boolean - def isSuperAccessorName(name: Name): Boolean - def isTraitSetterName(name: Name): Boolean - - def defaultGetterName(name: Name, pos: Int): TermName - def defaultGetterToMethod(name: Name): TermName - def expandedName(name: TermName, base: Symbol, separator: String): TermName - def expandedSetterName(name: TermName, base: Symbol): TermName - def getterName(name: TermName): TermName - def getterToLocal(name: TermName): TermName - def getterToSetter(name: TermName): TermName - def localDummyName(clazz: Symbol): TermName - def localToGetter(name: TermName): TermName - def protName(name: Name): TermName - def protSetterName(name: Name): TermName - def setterToGetter(name: TermName): TermName - def superName(name: Name): TermName - - def dropLocalSuffix(name: Name): Name - def originalName(name: Name): Name - def stripModuleSuffix(name: Name): Name - def unspecializedName(name: Name): Name - def segments(name: String, assumeTerm: Boolean): List[Name] - def splitSpecializedName(name: Name): (Name, String, String) } trait TypeNamesApi extends NamesApi with TypeNamesBase { - val BYNAME_PARAM_CLASS_NAME: TypeName - val EQUALS_PATTERN_NAME: TypeName - val JAVA_REPEATED_PARAM_CLASS_NAME: TypeName - val LOCAL_CHILD: TypeName - val REFINE_CLASS_NAME: TypeName - val REPEATED_PARAM_CLASS_NAME: TypeName - val WILDCARD_STAR: TypeName - val REIFY_TYPECREATOR_PREFIX: NameType - val REIFY_TREECREATOR_PREFIX: NameType - - def dropSingletonName(name: Name): TypeName - def implClassName(name: Name): TypeName - def interfaceName(implname: Name): TypeName - def singletonName(name: Name): TypeName } } diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala index 1d2888961b..13f5f743f1 100644 --- a/src/reflect/scala/reflect/api/Symbols.scala +++ b/src/reflect/scala/reflect/api/Symbols.scala @@ -12,15 +12,8 @@ trait Symbols extends base.Symbols { self: Universe => override type FreeTermSymbol >: Null <: TermSymbol with FreeTermSymbolApi override type FreeTypeSymbol >: Null <: TypeSymbol with FreeTypeSymbolApi - trait HasFlagsApi { - def flags: FlagSet - def hasFlag(fs: FlagSet): Boolean - def hasAllFlags(fs: FlagSet): Boolean - def flagString: String - } - /** The API of symbols */ - trait SymbolApi extends SymbolBase with HasFlagsApi { this: Symbol => + trait SymbolApi extends SymbolBase with HasFlagsBase { this: Symbol => /** The position of this symbol */ @@ -50,22 +43,52 @@ trait Symbols extends base.Symbols { self: Universe => */ def hasAnnotation(sym: Symbol): Boolean - /** ... + /** For a class: the module or case class factory with the same name in the same package. + * For a module: the class with the same name in the same package. + * For all others: NoSymbol */ - def orElse(alt: => Symbol): Symbol + def companionSymbol: Symbol - /** ... + /** The type signature of this symbol seen as a member of given type `site`. */ - def filter(cond: Symbol => Boolean): Symbol + def typeSignatureIn(site: Type): Type - /** If this is a NoSymbol, returns NoSymbol, otherwise - * returns the result of applying `f` to this symbol. + /** The type signature of this symbol. + * Note if the symbol is a member of a class, one almost always is interested + * in `typeSignatureIn` with a site type instead. */ - def map(f: Symbol => Symbol): Symbol + def typeSignature: Type - /** ... + /******************* tests *******************/ + + /** Does this symbol represent a synthetic (i.e. a compiler-generated) entity? + * Examples of synthetic entities are accessors for vals and vars + * or mixin constructors in trait implementation classes. */ - def suchThat(cond: Symbol => Boolean): Symbol + def isSynthetic: Boolean + + /** Does this symbol represent a local declaration or definition? + * + * If yes, either `isPrivate` or `isProtected` are guaranteed to be true. + * Local symbols can only be accessed from the same object instance. + * + * If yes, `privateWithin` might tell more about this symbol's visibility scope. + */ + def isLocal: Boolean + + /** Does this symbol represent a private declaration or definition? + * If yes, `privateWithin` might tell more about this symbol's visibility scope. + */ + def isPrivate: Boolean + + /** Does this symbol represent a protected declaration or definition? + * If yes, `privateWithin` might tell more about this symbol's visibility scope. + */ + def isProtected: Boolean + + /** Does this symbol represent a public declaration or definition? + */ + def isPublic: Boolean /** * Set when symbol has a modifier of the form private[X], NoSymbol otherwise. @@ -94,24 +117,77 @@ trait Symbols extends base.Symbols { self: Universe => */ def privateWithin: Symbol - /** For a class: the module or case class factory with the same name in the same package. - * For a module: the class with the same name in the same package. - * For all others: NoSymbol + /** Does this symbol represent the definition of a package? + * If yes, `isTerm` is also guaranteed to be true. */ - def companionSymbol: Symbol + def isPackage: Boolean + + /** Does this symbol represent a package class? + * If yes, `isClass` is also guaranteed to be true. + */ + def isPackageClass: Boolean + + /** Does this symbol or its underlying type represent a typechecking error? + */ + def isErroneous : Boolean + + /** Can this symbol be loaded by a reflective mirror? + * + * Scalac relies on `ScalaSignature' annotation to retain symbols across compilation runs. + * Such annotations (also called "pickles") are applied on top-level classes and include information + * about all symbols reachable from the annotee. However, local symbols (e.g. classes or definitions local to a block) + * are typically unreachable and information about them gets lost. + * + * This method is useful for macro writers who wish to save certain ASTs to be used at runtime. + * With `isLocatable' it's possible to check whether a tree can be retained as is, or it needs special treatment. + */ + def isLocatable: Boolean - /** If this symbol is a package class, this symbol; otherwise the next enclosing - * package class, or `NoSymbol` if none exists. + /** Is this symbol static (i.e. with no outer instance)? + * Q: When exactly is a sym marked as STATIC? + * A: If it's a member of a toplevel object, or of an object contained in a toplevel object, or any number of levels deep. + * http://groups.google.com/group/scala-internals/browse_thread/thread/d385bcd60b08faf6 + */ + def isStatic: Boolean + + /** Is this symbol final? + */ + def isFinal: Boolean + + /** Is this symbol overriding something? */ - def enclosingPackageClass: Symbol + def isOverride: Boolean - /** If this symbol is a top-level class, this symbol; otherwise the next enclosing - * top-level class, or `NoSymbol` if none exists. + /** Is this symbol a macro? */ - def enclosingTopLevelClass: Symbol + def isMacro: Boolean + /******************* helpers *******************/ + + /** ... + */ + def orElse(alt: => Symbol): Symbol + + /** ... + */ + def filter(cond: Symbol => Boolean): Symbol + + /** If this is a NoSymbol, returns NoSymbol, otherwise + * returns the result of applying `f` to this symbol. + */ + def map(f: Symbol => Symbol): Symbol + + /** ... + */ + def suchThat(cond: Symbol => Boolean): Symbol + + /** The string discriminator of this symbol; useful for debugging */ + def kind: String + } + + /** The API of term symbols */ + trait TermSymbolApi extends SymbolApi with TermSymbolBase { this: TermSymbol => /** Does this symbol represent a value, i.e. not a module and not a method? - * If yes, `isTerm` is also guaranteed to be true. * [Eugene++] I need a review of the implementation */ def isValue: Boolean @@ -120,7 +196,6 @@ trait Symbols extends base.Symbols { self: Universe => def isStable: Boolean /** Does this symbol represent a mutable value? - * If yes, `isTerm` and `isValue` are also guaranteed to be true. */ def isVariable: Boolean @@ -129,179 +204,131 @@ trait Symbols extends base.Symbols { self: Universe => def isAccessor: Boolean /** Does this symbol represent a getter of a field? - * If yes, `isTerm` and `isMethod` are also guaranteed to be true. + * If yes, `isMethod` is also guaranteed to be true. */ def isGetter: Boolean /** Does this symbol represent a setter of a field? - * If yes, `isTerm` and `isMethod` are also guaranteed to be true. + * If yes, `isMethod` is also guaranteed to be true. */ def isSetter: Boolean - /** Does this symbol represent the definition of a package? - * If yes, `isTerm` is also guaranteed to be true. + /** Does this symbol represent an overloaded method? + * If yes, `isMethod` is false, and the list of the enclosed alternatives can be found out via `alternatives`. */ - def isPackage: Boolean + def isOverloaded : Boolean - /** Does this symbol represent a package class? - * If yes, `isClass` is also guaranteed to be true. + /** Does this symbol represent an implicit value, definition or parameter? */ - def isPackageClass: Boolean + def isImplicit: Boolean - /** Is this symbol an overloaded method? + /** Does this symbol represent a lazy value? */ - def isOverloaded : Boolean + def isLazy: Boolean - /** Does this symbol represent the definition of a primitive class? - * Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]], - * [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]? + /** The overloaded alternatives of this symbol */ + def alternatives: List[Symbol] + + /** Backing field for an accessor method, NoSymbol for all other term symbols. */ - def isPrimitiveValueClass: Boolean + def accessed: Symbol - /** Does this symbol represent the definition of a numeric value class? - * Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]], - * [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]? + /** Getter method for a backing field of a val or a val, NoSymbol for all other term symbols. */ - def isNumericValueClass: Boolean + def getter: Symbol - /** Does this symbol represent the definition of a custom value class? - * Namely, is AnyVal among its parent classes? - * TODO: Why not just have in reflect.internal? - * [Eugene++] because it's useful for macros + /** Setter method for a backing field of a val or a val, NoSymbol for all other term symbols. */ - def isDerivedValueClass: Boolean + def setter: Symbol + } + + /** The API of type symbols */ + trait TypeSymbolApi extends SymbolApi with TypeSymbolBase { this: TypeSymbol => + /** Is the type parameter represented by this symbol contravariant? + */ + def isContravariant : Boolean + + /** Is the type parameter represented by this symbol contravariant? + */ + def isCovariant : Boolean + + /** Does this symbol represent the definition of a skolem? + * Skolems are used during typechecking to represent type parameters viewed from inside their scopes. + */ + def isSkolem : Boolean /** Does this symbol represent the definition of a type alias? - * If yes, `isType` is also guaranteed to be true. */ def isAliasType : Boolean /** Does this symbol represent the definition of an abstract type? - * If yes, `isType` is also guaranteed to be true. */ def isAbstractType : Boolean /** Does this symbol represent an existentially bound type? - * If yes, `isType` is also guaranteed to be true. */ def isExistential : Boolean - /** Does this symbol represent a free type captured by reification? - */ - def isFreeType : Boolean + /** For a polymorphic type, its type parameters, the empty list for all other types */ + def typeParams: List[Symbol] + } - /** Does this symbol or its underlying type represent a typechecking error? - */ - def isErroneous : Boolean + /** The API of method symbols */ + trait MethodSymbolApi extends TermSymbolApi with MethodSymbolBase { this: MethodSymbol => + /** For a polymorphic method, its type parameters, the empty list for all other methods */ + def typeParams: List[Symbol] - /** Can this symbol be loaded by a reflective mirror? - * - * Scalac relies on `ScalaSignature' annotation to retain symbols across compilation runs. - * Such annotations (also called "pickles") are applied on top-level classes and include information - * about all symbols reachable from the annotee. However, local symbols (e.g. classes or definitions local to a block) - * are typically unreachable and information about them gets lost. + /** All parameter lists of the method. * - * This method is useful for macro writers who wish to save certain ASTs to be used at runtime. - * With `isLocatable' it's possible to check whether a tree can be retained as is, or it needs special treatment. + * Can be used to distinguish nullary methods and methods with empty parameter lists. + * For a nullary method, returns the empty list (i.e. `List()`). + * For a method with an empty parameter list, returns a list that contains the empty list (i.e. `List(List())`). */ - def isLocatable: Boolean + def params: List[List[Symbol]] - /** Is this symbol static (i.e. with no outer instance)? - * Q: When exactly is a sym marked as STATIC? - * A: If it's a member of a toplevel object, or of an object contained in a toplevel object, or any number of levels deep. - * http://groups.google.com/group/scala-internals/browse_thread/thread/d385bcd60b08faf6 - */ - def isStatic: Boolean - - /** The type signature of this symbol seen as a member of given type `site`. - */ - def typeSignatureIn(site: Type): Type - - /** The type signature of this symbol. - * Note if the symbol is a member of a class, one almost always is interested - * in `typeSignatureIn` with a site type instead. - */ - def typeSignature: Type - - /** The string discriminator of this symbol; useful for debugging */ - def kind: String + /** The return type of the method */ + def returnType: Type } - /** The API of term symbols */ - trait TermSymbolApi extends SymbolApi with HasFlagsApi with TermSymbolBase { this: TermSymbol => - /** The overloaded alternatives of this symbol */ - def alternatives: List[Symbol] - - /** Performs method overloading resolution. More precisely, resolves an overloaded TermSymbol - * to a single, non-overloaded TermSymbol that accepts the specified argument types. - * @param pre The prefix type, i.e. the type of the value the method is dispatched on. - * This is required when resolving references to type parameters of the type - * the method is declared in. For example if the method is declared in class `List[A]`, - * providing the prefix as `List[Int]` allows the overloading resolution to use - * `Int` instead of `A`. - * @param targs Type arguments that a candidate alternative must be able to accept. Candidates - * will be considered with these arguments substituted for their corresponding - * type parameters. - * @param posVargs Positional argument types that a candidate alternative must be able to accept. - * @param nameVargs Named argument types that a candidate alternative must be able to accept. - * Each element in the sequence should be a pair of a parameter name and an - * argument type. - * @param expected Return type that a candidate alternative has to be compatible with. - * @return Either a single, non-overloaded Symbol referring to the selected alternative - * or NoSymbol if no single member could be selected given the passed arguments. - */ - def resolveOverloaded( - pre: Type = NoPrefix, - targs: Seq[Type] = List(), - posVargs: Seq[Type] = List(), - nameVargs: Seq[(TermName, Type)] = List(), - expected: Type = NoType - ): Symbol + /** The API of module symbols */ + trait ModuleSymbolApi extends TermSymbolApi with ModuleSymbolBase { this: ModuleSymbol => } - /** The API of type symbols */ - trait TypeSymbolApi extends SymbolApi with HasFlagsApi with TypeSymbolBase { this: TypeSymbol => - /** Is the type parameter represented by this symbol contravariant? + /** The API of class symbols */ + trait ClassSymbolApi extends TypeSymbolApi with ClassSymbolBase { this: ClassSymbol => + /** Does this symbol represent the definition of a primitive class? + * Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]], + * [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]? */ - def isContravariant : Boolean + def isPrimitive: Boolean - /** Is the type parameter represented by this symbol contravariant? + /** Does this symbol represent the definition of a numeric value class? + * Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]], + * [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]? */ - def isCovariant : Boolean + def isNumeric: Boolean - /** Does this symbol represent the definition of a skolem? - * Skolems are used during typechecking to represent type parameters viewed from inside their scopes. - * If yes, `isType` is also guaranteed to be true. + /** Does this symbol represent the definition of a custom value class? + * Namely, is AnyVal among its parent classes? */ - def isSkolem : Boolean + def isDerivedValueClass: Boolean - /** A type reference that refers to this type symbol seen - * as a member of given type `site`. - */ - def asTypeIn(site: Type): Type - - /** A type reference that refers to this type symbol - * Note if symbol is a member of a class, one almost always is interested - * in `asTypeIn` with a site type instead. - * - * Example: Given a class declaration `class C[T] { ... } `, that generates a symbol - * `C`. Then `C.asType` is the type `C[T]`. - * - * By contrast, `C.typeSignature` would be a type signature of form - * `PolyType(ClassInfoType(...))` that describes type parameters, value - * parameters, parent types, and members of `C`. - */ - def asType: Type // !!! Same as typeSignature. - } + /** Does this symbol represent a trait? + */ + def isTrait: Boolean - /** The API of method symbols */ - type MethodSymbolApi = MethodSymbolBase + /** Does this symbol represent an abstract class? + */ + def isAbstractClass: Boolean - /** The API of module symbols */ - type ModuleSymbolApi = ModuleSymbolBase + /** Does this symbol represent a case class? + */ + def isCaseClass: Boolean + + /** Does this symbol represent a sealed class? + */ + def isSealed: Boolean - /** The API of class symbols */ - trait ClassSymbolApi extends TypeSymbolApi with ClassSymbolBase { this: ClassSymbol => /** If this symbol is a class or trait, its self type, otherwise the type * of the symbol itself. */ @@ -309,6 +336,9 @@ trait Symbols extends base.Symbols { self: Universe => /** The type `C.this`, where `C` is the current class */ def thisPrefix: Type + + /** For a polymorphic class/trait, its type parameters, the empty list for all other classes/trait */ + def typeParams: List[Symbol] } /** The API of free term symbols */ diff --git a/src/reflect/scala/reflect/api/TagInterop.scala b/src/reflect/scala/reflect/api/TagInterop.scala index f1938083b5..4d2254cb9f 100644 --- a/src/reflect/scala/reflect/api/TagInterop.scala +++ b/src/reflect/scala/reflect/api/TagInterop.scala @@ -27,8 +27,8 @@ trait TagInterop { self: JavaUniverse => val jm = mirror.asInstanceOf[ju.Mirror] val sym = jm.classSymbol(manifest.erasure) val tpe = - if (manifest.typeArguments.isEmpty) sym.asType - else ju.appliedType(sym.asTypeConstructor, manifest.typeArguments map (targ => ju.manifestToTypeTag(jm, targ)) map (_.in(jm).tpe)) + if (manifest.typeArguments.isEmpty) sym.toType + else ju.appliedType(sym.toTypeConstructor, manifest.typeArguments map (targ => ju.manifestToTypeTag(jm, targ)) map (_.in(jm).tpe)) tpe.asInstanceOf[U # Type] case u => u.manifestToTypeTag(mirror.asInstanceOf[u.Mirror], manifest).in(mirror).tpe diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala index 2d130daa4e..06c7ddeda4 100644 --- a/src/reflect/scala/reflect/api/Trees.scala +++ b/src/reflect/scala/reflect/api/Trees.scala @@ -109,6 +109,8 @@ trait Trees extends base.Trees { self: Universe => def duplicate: this.type } + override protected def treeType(tree: Tree) = tree.tpe + override type TermTree >: Null <: Tree with TermTreeApi /** The API that all term trees support */ @@ -640,8 +642,16 @@ trait Trees extends base.Trees { self: Universe => abstract class Transformer { val treeCopy: TreeCopier = newLazyTreeCopier protected[scala] var currentOwner: Symbol = rootMirror.RootClass - protected def currentMethod = currentOwner.enclosingMethod - protected def currentClass = currentOwner.enclosingClass + protected def currentMethod = { + def enclosingMethod(sym: Symbol): Symbol = + if (sym.isMethod || sym == NoSymbol) sym else enclosingMethod(sym.owner) + enclosingMethod(currentOwner) + } + protected def currentClass = { + def enclosingClass(sym: Symbol): Symbol = + if (sym.isClass || sym == NoSymbol) sym else enclosingClass(sym.owner) + enclosingClass(currentOwner) + } // protected def currentPackage = currentOwner.enclosingTopLevelClass.owner def transform(tree: Tree): Tree = itransform(this, tree) @@ -683,7 +693,7 @@ trait Trees extends base.Trees { self: Universe => type Modifiers >: Null <: ModifiersApi - abstract class ModifiersApi extends ModifiersBase with HasFlagsApi + abstract class ModifiersApi extends ModifiersBase } diff --git a/src/reflect/scala/reflect/api/Types.scala b/src/reflect/scala/reflect/api/Types.scala index 01de5fa9a7..199cf9b9e5 100644 --- a/src/reflect/scala/reflect/api/Types.scala +++ b/src/reflect/scala/reflect/api/Types.scala @@ -24,73 +24,35 @@ trait Types extends base.Types { self: Universe => */ def declaration(name: Name): Symbol - /** The collection of declarations in this type - * [Eugene++] why not List? + /** A `Scope` containing directly declared members of this type. + * Unlike `members` this method doesn't returns inherited members. + * + * Members in the returned scope might appear in arbitrary order. + * Use `declarations.sorted` to get an ordered list of members. */ - def declarations: Iterable[Symbol] + def declarations: MemberScope /** The member with given name, either directly declared or inherited, * an OverloadedSymbol if several exist, NoSymbol if none exist. */ def member(name: Name): Symbol - /** The non-private member with given name, either directly declared or inherited, - * an OverloadedSymbol if several exist, NoSymbol if none exist. - */ - def nonPrivateMember(name: Name): Symbol - - /** An iterable containing all members of this type (directly declared or inherited) - * Members appear in the linearization order of their owners. - * Members with the same owner appear in reverse order of their declarations. - * [Eugene++] the order needs to be reversed back, at least in the public API - */ - def members: Iterable[Symbol] - - /** An iterable containing all non-private members of this type (directly declared or inherited) - * Members appear in the linearization order of their owners. - * Members with the same owner appear in reverse order of their declarations. - */ - def nonPrivateMembers: Iterable[Symbol] - - /** Substitute symbols in `to` for corresponding occurrences of references to - * symbols `from` in this type. - */ - def substituteSymbols(from: List[Symbol], to: List[Symbol]): Type - - /** Substitute types in `to` for corresponding occurrences of references to - * symbols `from` in this type. - */ - def substituteTypes(from: List[Symbol], to: List[Type]): Type - - /** If this is a parameterized types, the type arguments. - * Otherwise the empty list + /** A `Scope` containing all members of this type (directly declared or inherited). + * Unlike `declarations` this method also returns inherited members. + * + * Members in the returned scope might appear in arbitrary order. + * Use `declarations.sorted` to get an ordered list of members. */ - def typeArguments: List[Type] - - /** For a (potentially wrapped) poly type, its type parameters, - * the empty list for all other types */ - def typeParams: List[Symbol] - - /** For a (nullary) method or poly type, its direct result type, - * the type itself for all other types. */ - def resultType: Type + def members: MemberScope /** Is this type a type constructor that is missing its type arguments? */ - def isHigherKinded: Boolean // !!! This should be called "isTypeConstructor", no? + def takesTypeArgs: Boolean /** Returns the corresponding type constructor (e.g. List for List[T] or List[String]) */ def typeConstructor: Type - /** Does this type refer to spliceable types or is a spliceable type? - */ - def isConcrete: Boolean - - /** Is this type an abstract type that needs to be resolved? - */ - def isSpliceable: Boolean - /** * Expands type aliases and converts higher-kinded TypeRefs to PolyTypes. * Functions on types are also implemented as PolyTypes. @@ -99,7 +61,7 @@ trait Types extends base.Types { self: Universe => * TypeRef(pre, <List>, List()) is replaced by * PolyType(X, TypeRef(pre, <List>, List(X))) */ - def normalize: Type // !!! Alternative name? "normalize" is used to mean too many things. + def normalize: Type /** Does this type conform to given type argument `that`? */ def <:< (that: Type): Boolean @@ -111,7 +73,7 @@ trait Types extends base.Types { self: Universe => * in reverse linearization order, starting with the class itself and ending * in class Any. */ - def baseClasses: List[Symbol] // !!! Alternative name, perhaps linearization? + def baseClasses: List[Symbol] /** The least type instance of given class which is a supertype * of this type. Example: @@ -141,36 +103,7 @@ trait Types extends base.Types { self: Universe => /** The erased type corresponding to this type after * all transformations from Scala to Java have been performed. */ - def erasure: Type // !!! "erasedType", compare with "widen" (so "erase") or "underlying" (so "erased") - // why not name it "erasure"? - - /** Apply `f` to each part of this type, returning - * a new type. children get mapped before their parents */ - def map(f: Type => Type): Type - - /** Apply `f` to each part of this type, for side effects only */ - def foreach(f: Type => Unit) - - /** Returns optionally first type (in a preorder traversal) which satisfies predicate `p`, - * or None if none exists. - */ - def find(p: Type => Boolean): Option[Type] - - /** Is there part of this type which satisfies predicate `p`? */ - def exists(p: Type => Boolean): Boolean - - /** Does this type contain a reference to given symbol? */ - def contains(sym: Symbol): Boolean - - /** If this is a compound type, the list of its parent types; - * otherwise the empty list - */ - def parents: List[Type] - - /** If this is a singleton type, returns the type underlying it; - * otherwise returns this type itself. - */ - def underlying: Type + def erasure: Type /** If this is a singleton type, widen it to its nearest underlying non-singleton * base type by applying one or more `underlying` dereferences. @@ -193,6 +126,36 @@ trait Types extends base.Types { self: Universe => */ def narrow: Type + /******************* helpers *******************/ + + /** Substitute symbols in `to` for corresponding occurrences of references to + * symbols `from` in this type. + */ + def substituteSymbols(from: List[Symbol], to: List[Symbol]): Type + + /** Substitute types in `to` for corresponding occurrences of references to + * symbols `from` in this type. + */ + def substituteTypes(from: List[Symbol], to: List[Type]): Type + + /** Apply `f` to each part of this type, returning + * a new type. children get mapped before their parents */ + def map(f: Type => Type): Type + + /** Apply `f` to each part of this type, for side effects only */ + def foreach(f: Type => Unit) + + /** Returns optionally first type (in a preorder traversal) which satisfies predicate `p`, + * or None if none exists. + */ + def find(p: Type => Boolean): Option[Type] + + /** Is there part of this type which satisfies predicate `p`? */ + def exists(p: Type => Boolean): Boolean + + /** Does this type contain a reference to given symbol? */ + def contains(sym: Symbol): Boolean + /** The string discriminator of this type; useful for debugging */ def kind: String } diff --git a/src/reflect/scala/reflect/api/Universe.scala b/src/reflect/scala/reflect/api/Universe.scala index 85d8adc44f..3dce0f218e 100644 --- a/src/reflect/scala/reflect/api/Universe.scala +++ b/src/reflect/scala/reflect/api/Universe.scala @@ -1,8 +1,6 @@ package scala.reflect package api -import language.experimental.macros - abstract class Universe extends base.Universe with Symbols with Types @@ -16,53 +14,4 @@ abstract class Universe extends base.Universe with StandardDefinitions with StandardNames with Importers - with Exprs with AnnotationInfos -{ - - /** Given an expression, generate a tree that when compiled and executed produces the original tree. - * The produced tree will be bound to the Universe it was called from. - * - * For instance, given the abstract syntax tree representation of the <[ x + 1 ]> expression: - * - * {{{ - * Apply(Select(Ident("x"), "+"), List(Literal(Constant(1)))) - * }}} - * - * The reifier transforms it to the following expression: - * - * {{{ - * <[ - * val $u: u.type = u // where u is a reference to the Universe that calls the reify - * $u.Expr[Int]($u.Apply($u.Select($u.Ident($u.newFreeVar("x", <Int>, x), "+"), List($u.Literal($u.Constant(1)))))) - * ]> - * }}} - * - * Reification performs expression splicing (when processing Expr.splice) - * and type splicing (for every type T that has a TypeTag[T] implicit in scope): - * - * {{{ - * val two = mirror.reify(2) // Literal(Constant(2)) - * val four = mirror.reify(two.splice + two.splice) // Apply(Select(two.tree, newTermName("$plus")), List(two.tree)) - * - * def macroImpl[T](c: Context) = { - * ... - * // T here is just a type parameter, so the tree produced by reify won't be of much use in a macro expansion - * // however, if T were annotated with c.TypeTag (which would declare an implicit parameter for macroImpl) - * // then reification would subtitute T with the TypeTree that was used in a TypeApply of this particular macro invocation - * val factory = c.reify{ new Queryable[T] } - * ... - * } - * }}} - * - * The transformation looks mostly straightforward, but it has its tricky parts: - * * Reifier retains symbols and types defined outside the reified tree, however - * locally defined entities get erased and replaced with their original trees - * * Free variables are detected and wrapped in symbols of the type FreeVar - * * Mutable variables that are accessed from a local function are wrapped in refs - * * Since reified trees can be compiled outside of the scope they've been created in, - * special measures are taken to ensure that all members accessed in the reifee remain visible - */ - // implementation is magically hardwired to `scala.reflect.reify.Taggers` - def reify[T](expr: T): Expr[T] = macro ??? -}
\ No newline at end of file diff --git a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala index fa758edf05..19f70ba785 100644 --- a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala +++ b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala @@ -226,7 +226,7 @@ trait BaseTypeSeqs { override def map(g: Type => Type) = lateMap(g) override def lateMap(g: Type => Type) = orig.lateMap(x => g(f(x))) override def exists(p: Type => Boolean) = elems exists (x => p(f(x))) - override protected def maxDepthOfElems: Int = elems map (x => typeDepth(f(x))) max + override protected def maxDepthOfElems: Int = elems.map(x => typeDepth(f(x))).max override def toString = elems.mkString("MBTS(", ",", ")") } diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala index ad59605760..74b9442076 100644 --- a/src/reflect/scala/reflect/internal/BuildUtils.scala +++ b/src/reflect/scala/reflect/internal/BuildUtils.scala @@ -8,11 +8,11 @@ trait BuildUtils extends base.BuildUtils { self: SymbolTable => class BuildImpl extends BuildBase { def selectType(owner: Symbol, name: String): TypeSymbol = - select(owner, newTypeName(name)).asTypeSymbol + select(owner, newTypeName(name)).asType def selectTerm(owner: Symbol, name: String): TermSymbol = { - val result = select(owner, newTermName(name)).asTermSymbol - if (result.isOverloaded) result.suchThat(!_.isMethod).asTermSymbol + val result = select(owner, newTermName(name)).asTerm + if (result.isOverloaded) result.suchThat(!_.isMethod).asTerm else result } @@ -26,7 +26,7 @@ trait BuildUtils extends base.BuildUtils { self: SymbolTable => def selectOverloadedMethod(owner: Symbol, name: String, index: Int): MethodSymbol = { val result = owner.info.decl(newTermName(name)).alternatives(index) - if (result ne NoSymbol) result.asMethodSymbol + if (result ne NoSymbol) result.asMethod else MissingRequirementError.notFound("overloaded method %s #%d in %s".format(name, index, owner.fullName)) } diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 90aa0b732c..bc2120a738 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -20,21 +20,21 @@ trait Definitions extends api.StandardDefinitions { object definitions extends DefinitionsClass // [Eugene] find a way to make these non-lazy - lazy val ByteTpe = definitions.ByteClass.asType - lazy val ShortTpe = definitions.ShortClass.asType - lazy val CharTpe = definitions.CharClass.asType - lazy val IntTpe = definitions.IntClass.asType - lazy val LongTpe = definitions.LongClass.asType - lazy val FloatTpe = definitions.FloatClass.asType - lazy val DoubleTpe = definitions.DoubleClass.asType - lazy val BooleanTpe = definitions.BooleanClass.asType - lazy val UnitTpe = definitions.UnitClass.asType - lazy val AnyTpe = definitions.AnyClass.asType - lazy val ObjectTpe = definitions.ObjectClass.asType - lazy val AnyValTpe = definitions.AnyValClass.asType - lazy val AnyRefTpe = definitions.AnyRefClass.asType - lazy val NothingTpe = definitions.NothingClass.asType - lazy val NullTpe = definitions.NullClass.asType + lazy val ByteTpe = definitions.ByteClass.toTypeConstructor + lazy val ShortTpe = definitions.ShortClass.toTypeConstructor + lazy val CharTpe = definitions.CharClass.toTypeConstructor + lazy val IntTpe = definitions.IntClass.toTypeConstructor + lazy val LongTpe = definitions.LongClass.toTypeConstructor + lazy val FloatTpe = definitions.FloatClass.toTypeConstructor + lazy val DoubleTpe = definitions.DoubleClass.toTypeConstructor + lazy val BooleanTpe = definitions.BooleanClass.toTypeConstructor + lazy val UnitTpe = definitions.UnitClass.toTypeConstructor + lazy val AnyTpe = definitions.AnyClass.toTypeConstructor + lazy val ObjectTpe = definitions.ObjectClass.toTypeConstructor + lazy val AnyValTpe = definitions.AnyValClass.toTypeConstructor + lazy val AnyRefTpe = definitions.AnyRefClass.toTypeConstructor + lazy val NothingTpe = definitions.NothingClass.toTypeConstructor + lazy val NullTpe = definitions.NullClass.toTypeConstructor /** Since both the value parameter types and the result type may * require access to the type parameter symbols, we model polymorphic @@ -183,11 +183,11 @@ trait Definitions extends api.StandardDefinitions { // It becomes tricky to create dedicated objects for other symbols because // of initialization order issues. lazy val JavaLangPackage = getRequiredPackage(sn.JavaLang) - lazy val JavaLangPackageClass = JavaLangPackage.moduleClass.asClassSymbol + lazy val JavaLangPackageClass = JavaLangPackage.moduleClass.asClass lazy val ScalaPackage = getRequiredPackage(nme.scala_) - lazy val ScalaPackageClass = ScalaPackage.moduleClass.asClassSymbol + lazy val ScalaPackageClass = ScalaPackage.moduleClass.asClass lazy val RuntimePackage = getRequiredPackage("scala.runtime") - lazy val RuntimePackageClass = RuntimePackage.moduleClass.asClassSymbol + lazy val RuntimePackageClass = RuntimePackage.moduleClass.asClass lazy val JavaLangEnumClass = requiredClass[java.lang.Enum[_]] @@ -471,11 +471,11 @@ trait Definitions extends api.StandardDefinitions { lazy val OptManifestClass = requiredClass[scala.reflect.OptManifest[_]] lazy val NoManifest = requiredModule[scala.reflect.NoManifest.type] - lazy val ExprsClass = getClassIfDefined("scala.reflect.api.Exprs") // defined in scala-reflect.jar, so we need to be careful - lazy val ExprClass = if (ExprsClass != NoSymbol) getMemberClass(ExprsClass, tpnme.Expr) else NoSymbol - def ExprSplice = if (ExprsClass != NoSymbol) getMemberMethod(ExprClass, nme.splice) else NoSymbol - def ExprValue = if (ExprsClass != NoSymbol) getMemberMethod(ExprClass, nme.value) else NoSymbol - lazy val ExprModule = if (ExprsClass != NoSymbol) getMemberModule(ExprsClass, nme.Expr) else NoSymbol + lazy val ExprsClass = requiredClass[scala.reflect.base.Exprs] + lazy val ExprClass = getMemberClass(ExprsClass, tpnme.Expr) + def ExprSplice = getMemberMethod(ExprClass, nme.splice) + def ExprValue = getMemberMethod(ExprClass, nme.value) + lazy val ExprModule = getMemberModule(ExprsClass, nme.Expr) lazy val ClassTagModule = requiredModule[scala.reflect.ClassTag[_]] lazy val ClassTagClass = requiredClass[scala.reflect.ClassTag[_]] @@ -486,8 +486,7 @@ trait Definitions extends api.StandardDefinitions { lazy val TypeTagModule = getMemberModule(TypeTagsClass, nme.TypeTag) lazy val BaseUniverseClass = requiredClass[scala.reflect.base.Universe] - lazy val ApiUniverseClass = getClassIfDefined("scala.reflect.api.Universe") // defined in scala-reflect.jar, so we need to be careful - def ApiUniverseReify = if (ApiUniverseClass != NoSymbol) getMemberMethod(ApiUniverseClass, nme.reify) else NoSymbol + def BaseUniverseReify = getMemberMethod(BaseUniverseClass, nme.reify) lazy val JavaUniverseClass = getClassIfDefined("scala.reflect.api.JavaUniverse") // defined in scala-reflect.jar, so we need to be careful lazy val MirrorOfClass = requiredClass[scala.reflect.base.MirrorOf[_]] @@ -495,13 +494,13 @@ trait Definitions extends api.StandardDefinitions { lazy val TypeCreatorClass = requiredClass[scala.reflect.base.TypeCreator] lazy val TreeCreatorClass = requiredClass[scala.reflect.base.TreeCreator] - lazy val MacroContextClass = getClassIfDefined("scala.reflect.makro.Context") // defined in scala-reflect.jar, so we need to be careful + lazy val MacroContextClass = getClassIfDefined("scala.reflect.macros.Context") // defined in scala-reflect.jar, so we need to be careful def MacroContextPrefix = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.prefix) else NoSymbol def MacroContextPrefixType = if (MacroContextClass != NoSymbol) getMemberType(MacroContextClass, tpnme.PrefixType) else NoSymbol def MacroContextUniverse = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.universe) else NoSymbol def MacroContextMirror = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.mirror) else NoSymbol - lazy val MacroImplAnnotation = requiredClass[scala.reflect.makro.internal.macroImpl] - lazy val MacroInternalPackage = getPackageObject("scala.reflect.makro.internal") + lazy val MacroImplAnnotation = requiredClass[scala.reflect.macros.internal.macroImpl] + lazy val MacroInternalPackage = getPackageObject("scala.reflect.macros.internal") def MacroInternal_materializeClassTag = getMemberMethod(MacroInternalPackage, nme.materializeClassTag) def MacroInternal_materializeAbsTypeTag = getMemberMethod(MacroInternalPackage, nme.materializeAbsTypeTag) def MacroInternal_materializeTypeTag = getMemberMethod(MacroInternalPackage, nme.materializeTypeTag) @@ -1045,7 +1044,7 @@ trait Definitions extends api.StandardDefinitions { // System.err.println("isMethod = " + result.isMethod) // System.err.println("isTerm = " + result.isTerm) // System.err.println("isValue = " + result.isValue) - // result.asMethodSymbol + // result.asMethod // // prints this: // @@ -1074,8 +1073,8 @@ trait Definitions extends api.StandardDefinitions { // [scalacfork] // [scalacfork] uncaught exception during compilation: java.lang.ClassCastException // [scalacfork] error: java.lang.ClassCastException: value apply - // [scalacfork] at scala.reflect.base.Symbols$SymbolBase$class.asMethodSymbol(Symbols.scala:118) - // [scalacfork] at scala.reflect.internal.Symbols$SymbolContextApiImpl.asMethodSymbol(Symbols.scala:63) + // [scalacfork] at scala.reflect.base.Symbols$SymbolBase$class.asMethod(Symbols.scala:118) + // [scalacfork] at scala.reflect.internal.Symbols$SymbolContextApiImpl.asMethod(Symbols.scala:63) // [scalacfork] at scala.reflect.internal.Definitions$DefinitionsClass.Symbol_apply(Definitions.scala:381) // [Eugene++] should be a ClassCastException instead? diff --git a/src/reflect/scala/reflect/internal/FlagSets.scala b/src/reflect/scala/reflect/internal/FlagSets.scala index 0354d2513c..6e77741355 100644 --- a/src/reflect/scala/reflect/internal/FlagSets.scala +++ b/src/reflect/scala/reflect/internal/FlagSets.scala @@ -13,8 +13,7 @@ trait FlagSets extends api.FlagSets { self: SymbolTable => private class FlagOpsImpl(left: Long) extends FlagOps { def | (right: Long): Long = left | right - def & (right: Long): Long = left & right - def containsAll (right: Long): Boolean = (right & ~left) == 0 + def hasFlag(right: Long): Boolean = (left & right) != 0 } val NoFlags: FlagSet = 0L @@ -47,20 +46,5 @@ trait FlagSets extends api.FlagSets { self: SymbolTable => val CONTRAVARIANT : FlagSet = Flags.CONTRAVARIANT val DEFAULTPARAM : FlagSet = Flags.DEFAULTPARAM val INTERFACE : FlagSet = Flags.INTERFACE - - def union(flags: FlagSet*): FlagSet = { - var acc = 0L - for (flag <- flags) acc |= flag - acc - } - - def intersection(flags: FlagSet*): FlagSet = { - var acc = -1L - for (flag <- flags) acc &= flag - acc - } - - def containsAll(superset: FlagSet, subset: FlagSet): Boolean = - (subset & ~superset) == 0 } } diff --git a/src/reflect/scala/reflect/internal/Importers.scala b/src/reflect/scala/reflect/internal/Importers.scala index 431d9819a5..00017e087a 100644 --- a/src/reflect/scala/reflect/internal/Importers.scala +++ b/src/reflect/scala/reflect/internal/Importers.scala @@ -14,6 +14,7 @@ trait Importers { self: SymbolTable => def importSymbol(sym: from.Symbol) = sym.asInstanceOf[self.Symbol] def importType(tpe: from.Type) = tpe.asInstanceOf[self.Type] def importTree(tree: from.Tree) = tree.asInstanceOf[self.Tree] + def importPosition(pos: from.Position) = pos.asInstanceOf[self.Position] } } else { // todo. fix this loophole diff --git a/src/reflect/scala/reflect/internal/Positions.scala b/src/reflect/scala/reflect/internal/Positions.scala index 6ae9b40fcb..faa161d6b1 100644 --- a/src/reflect/scala/reflect/internal/Positions.scala +++ b/src/reflect/scala/reflect/internal/Positions.scala @@ -10,23 +10,25 @@ trait Positions extends api.Positions { self: SymbolTable => /** A position that wraps a set of trees. * The point of the wrapping position is the point of the default position. * If some of the trees are ranges, returns a range position enclosing all ranges - * Otherwise returns default position. + * Otherwise returns default position that is either focused or not. */ - def wrappingPos(default: Position, trees: List[Tree]): Position = default + def wrappingPos(default: Position, trees: List[Tree]) = wrappingPos(default, trees, true) + def wrappingPos(default: Position, trees: List[Tree], focus: Boolean): Position = default /** A position that wraps the non-empty set of trees. * The point of the wrapping position is the point of the first trees' position. - * If all some the trees are non-synthetic, returns a range position enclosing the non-synthetic trees + * If some of the trees are non-synthetic, returns a range position enclosing the non-synthetic trees * Otherwise returns a synthetic offset position to point. */ def wrappingPos(trees: List[Tree]): Position = trees.head.pos /** Ensure that given tree has no positions that overlap with * any of the positions of `others`. This is done by - * shortening the range or assigning TransparentPositions - * to some of the nodes in `tree`. + * shortening the range, assigning TransparentPositions + * to some of the nodes in `tree` or focusing on the position. */ - def ensureNonOverlapping(tree: Tree, others: List[Tree]) {} + def ensureNonOverlapping(tree: Tree, others: List[Tree]){ ensureNonOverlapping(tree, others, true) } + def ensureNonOverlapping(tree: Tree, others: List[Tree], focus: Boolean) {} trait PosAssigner extends Traverser { var pos: Position diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala index c018ddc88e..8571ac1110 100644 --- a/src/reflect/scala/reflect/internal/Printers.scala +++ b/src/reflect/scala/reflect/internal/Printers.scala @@ -649,19 +649,18 @@ trait Printers extends api.Printers { self: SymbolTable => } def show(name: Name): String = name match { - // base.StandardNames case tpnme.EMPTY => "tpnme.EMPTY" case tpnme.ROOT => "tpnme.ROOT" + case tpnme.PACKAGE => "tpnme.PACKAGE" case tpnme.EMPTY_PACKAGE_NAME => "tpnme.EMPTY_PACKAGE_NAME" case tpnme.WILDCARD => "tpnme.WILDCARD" - case nme.CONSTRUCTOR => "nme.CONSTRUCTOR" - case nme.NO_NAME => "nme.NO_NAME" - // api.StandardNames - case tpnme.ERROR => "tpnme.ERROR" - case nme.ERROR => "nme.ERROR" case nme.EMPTY => "nme.EMPTY" - case tpnme.PACKAGE => "tpnme.PACKAGE" + case nme.ROOT => "nme.ROOT" case nme.PACKAGE => "nme.PACKAGE" + case nme.EMPTY_PACKAGE_NAME => "nme.EMPTY_PACKAGE_NAME" + case nme.WILDCARD => "nme.WILDCARD" + case nme.CONSTRUCTOR => "nme.CONSTRUCTOR" + case nme.ROOTPKG => "nme.ROOTPKG" case _ => val prefix = if (name.isTermName) "newTermName(\"" else "newTypeName(\"" prefix + name.toString + "\")" @@ -671,7 +670,7 @@ trait Printers extends api.Printers { self: SymbolTable => if (flags == NoFlags) nme.NoFlags.toString else { val s_flags = new collection.mutable.ListBuffer[String] - for (i <- 0 to 63 if (flags containsAll (1L << i))) + for (i <- 0 to 63 if (flags hasFlag (1L << i))) s_flags += flagToString(1L << i).replace("<", "").replace(">", "").toUpperCase s_flags mkString " | " } diff --git a/src/reflect/scala/reflect/internal/Scopes.scala b/src/reflect/scala/reflect/internal/Scopes.scala index 89e3c52de6..ed390b5a3b 100644 --- a/src/reflect/scala/reflect/internal/Scopes.scala +++ b/src/reflect/scala/reflect/internal/Scopes.scala @@ -41,9 +41,9 @@ trait Scopes extends api.Scopes { self: SymbolTable => * This is necessary because when run from reflection every scope needs to have a * SynchronizedScope as mixin. */ - class Scope protected[Scopes] (initElems: ScopeEntry = null, initFingerPrints: Long = 0L) extends Iterable[Symbol] { - - /** A bitset containing the last 6 bits of the start value of every name + class Scope protected[Scopes] (initElems: ScopeEntry = null, initFingerPrints: Long = 0L) extends ScopeBase with MemberScopeBase { + + /** A bitset containing the last 6 bits of the start value of every name * stored in this scope. */ var fingerPrints: Long = initFingerPrints @@ -118,10 +118,10 @@ trait Scopes extends api.Scopes { self: SymbolTable => * * @param sym ... */ - def enter[T <: Symbol](sym: T): T = { + def enter[T <: Symbol](sym: T): T = { fingerPrints |= sym.name.fingerPrint - enterEntry(newScopeEntry(sym, this)) - sym + enterEntry(newScopeEntry(sym, this)) + sym } /** enter a symbol, asserting that no symbol with same name exists in scope @@ -282,6 +282,10 @@ trait Scopes extends api.Scopes { self: SymbolTable => elemsCache } + /** Vanilla scope - symbols are stored in declaration order. + */ + def sorted: List[Symbol] = toList + /** Return the nesting level of this scope, i.e. the number of times this scope * was nested in another */ def nestingLevel = nestinglevel @@ -324,14 +328,46 @@ trait Scopes extends api.Scopes { self: SymbolTable => toList.map(_.defString).mkString(start, sep, end) override def toString(): String = mkString("Scope{\n ", ";\n ", "\n}") - } implicit val ScopeTag = ClassTag[Scope](classOf[Scope]) + type MemberScope = Scope + + implicit val MemberScopeTag = ClassTag[MemberScope](classOf[MemberScope]) + /** Create a new scope */ def newScope: Scope = new Scope() + /** Create a new scope to be used in `findMembers`. + * + * But why do we need a special scope for `findMembers`? + * Let me tell you a story. + * + * `findMembers` creates a synthetic scope and then iterates over + * base classes in linearization order, and for every scrutinized class + * iterates over `decls`, the collection of symbols declared in that class. + * Declarations that fit the filter get appended to the created scope. + * + * The problem is that `decls` returns a Scope, and to iterate a scope performantly + * one needs to go from its end to its beginning. + * + * Hence the `findMembers` scope is populated in a wicked order: + * symbols that belong to the same declaring class come in reverse order of their declaration, + * however, the scope itself is ordered w.r.t the linearization of the target type. + * + * Once `members` became a public API, this has been confusing countless numbers of users. + * Therefore we introduce a special flavor of scopes to accommodate this quirk of `findMembers` + */ + private[scala] def newFindMemberScope: Scope = new Scope() { + override def sorted = { + val members = toList + val owners = members.map(_.owner).distinct + val grouped = members groupBy (_.owner) + owners.flatMap(owner => grouped(owner).reverse) + } + } + /** Create a new scope nested in another one with which it shares its elements */ def newNestedScope(outer: Scope): Scope = new Scope(outer) diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 75962ff9d0..67456cf86b 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -616,7 +616,6 @@ trait StdNames { val apply: NameType = "apply" val applyDynamic: NameType = "applyDynamic" val applyDynamicNamed: NameType = "applyDynamicNamed" - val applyImpl: NameType = "applyImpl" val applyOrElse: NameType = "applyOrElse" val args : NameType = "args" val argv : NameType = "argv" @@ -628,14 +627,13 @@ trait StdNames { val array_length : NameType = "array_length" val array_update : NameType = "array_update" val arraycopy: NameType = "arraycopy" - val asTermSymbol: NameType = "asTermSymbol" - val asModuleSymbol: NameType = "asModuleSymbol" - val asMethodSymbol: NameType = "asMethodSymbol" - val asTypeSymbol: NameType = "asTypeSymbol" - val asClassSymbol: NameType = "asClassSymbol" + val asTerm: NameType = "asTerm" + val asModule: NameType = "asModule" + val asMethod: NameType = "asMethod" + val asType: NameType = "asType" + val asClass: NameType = "asClass" val asInstanceOf_ : NameType = "asInstanceOf" val asInstanceOf_Ob : NameType = "$asInstanceOf" - val asTypeConstructor: NameType = "asTypeConstructor" val assert_ : NameType = "assert" val assume_ : NameType = "assume" val basis : NameType = "basis" @@ -767,6 +765,7 @@ trait StdNames { val toObjectArray : NameType = "toObjectArray" val toSeq: NameType = "toSeq" val toString_ : NameType = if (forMSIL) "ToString" else "toString" + val toTypeConstructor: NameType = "toTypeConstructor" val tpe : NameType = "tpe" val tree : NameType = "tree" val true_ : NameType = "true" diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index 5ae8f22c64..dfb434300d 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -9,7 +9,7 @@ package internal import scala.collection.{ mutable, immutable } import util._ -abstract class SymbolTable extends makro.Universe +abstract class SymbolTable extends macros.Universe with Collections with Names with Symbols diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index b82d483893..c356416112 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -75,289 +75,17 @@ trait Symbols extends api.Symbols { self: SymbolTable => def typeSignature: Type = info def typeSignatureIn(site: Type): Type = site memberInfo this - def asType: Type = tpe - def asTypeIn(site: Type): Type = site.memberType(this) - def asTypeConstructor: Type = typeConstructor + def toType: Type = tpe + def toTypeIn(site: Type): Type = site.memberType(this) + def toTypeConstructor: Type = typeConstructor + def setFlags(flags: FlagSet): this.type = setInternalFlags(flags) def setInternalFlags(flag: Long): this.type = { setFlag(flag); this } def setTypeSignature(tpe: Type): this.type = { setInfo(tpe); this } def getAnnotations: List[AnnotationInfo] = { initialize; annotations } def setAnnotations(annots: AnnotationInfo*): this.type = { setAnnotations(annots.toList); this } - def resolveOverloaded( - pre: Type, - targs: Seq[Type], - posVargTypes: Seq[Type], - nameVargTypes: Seq[(TermName, Type)], - expected: Type - ): Symbol = { - - // Begin Correlation Helpers - - def isCompatible(tp: Type, pt: Type): Boolean = { - def isCompatibleByName(tp: Type, pt: Type): Boolean = pt match { - case TypeRef(_, ByNameParamClass, List(res)) if !definitions.isByNameParamType(tp) => - isCompatible(tp, res) - case _ => - false - } - (tp weak_<:< pt) || isCompatibleByName(tp, pt) - } - - def signatureAsSpecific(method1: MethodSymbol, method2: MethodSymbol): Boolean = { - (substituteTypeParams(method1), substituteTypeParams(method2)) match { - case (NullaryMethodType(r1), NullaryMethodType(r2)) => - r1 weak_<:< r2 - case (NullaryMethodType(_), MethodType(_, _)) => - true - case (MethodType(_, _), NullaryMethodType(_)) => - false - case (MethodType(p1, _), MethodType(p2, _)) => - val len = p1.length max p2.length - val sub = extend(p1 map (_.typeSignature), len) - val sup = extend(p2 map (_.typeSignature), len) - (sub corresponds sup)(isCompatible) - } - } - - def scopeMoreSpecific(method1: MethodSymbol, method2: MethodSymbol): Boolean = { - val o1 = method1.owner.asClassSymbol - val o2 = method2.owner.asClassSymbol - val c1 = if (o1.hasFlag(Flag.MODULE)) o1.companionSymbol else o1 - val c2 = if (o2.hasFlag(Flag.MODULE)) o2.companionSymbol else o2 - c1.typeSignature <:< c2.typeSignature - } - - def moreSpecific(method1: MethodSymbol, method2: MethodSymbol): Boolean = { - def points(m1: MethodSymbol, m2: MethodSymbol) = { - val p1 = if (signatureAsSpecific(m1, m2)) 1 else 0 - val p2 = if (scopeMoreSpecific(m1, m2)) 1 else 0 - p1 + p2 - } - points(method1, method2) > points(method2, method1) - } - - def combineInto ( - variadic: Boolean - )( - positional: Seq[Type], - named: Seq[(TermName, Type)] - )( - target: Seq[TermName], - defaults: Map[Int, Type] - ): Option[Seq[Type]] = { - - val offset = positional.length - val unfilled = target.zipWithIndex drop offset - val canAcceptAllNameVargs = named forall { case (argName, _) => - unfilled exists (_._1 == argName) - } - - val paramNamesUnique = { - named.length == named.map(_._1).distinct.length - } - - if (canAcceptAllNameVargs && paramNamesUnique) { - - val rest = unfilled map { case (paramName, paramIndex) => - val passedIn = named.collect { - case (argName, argType) if argName == paramName => argType - }.headOption - if (passedIn isDefined) passedIn - else defaults.get(paramIndex).map(_.asInstanceOf[Type]) - } - - val rest1 = { - if (variadic && !rest.isEmpty && !rest.last.isDefined) rest.init - else rest - } - - - if (rest1 forall (_.isDefined)) { - val joined = positional ++ rest1.map(_.get) - val repeatedCollapsed = { - if (variadic) { - val (normal, repeated) = joined.splitAt(target.length - 1) - if (repeated.forall(_ =:= repeated.head)) Some(normal ++ repeated.headOption) - else None - } - else Some(joined) - } - if (repeatedCollapsed.exists(_.length == target.length)) - repeatedCollapsed - else if (variadic && repeatedCollapsed.exists(_.length == target.length - 1)) - repeatedCollapsed - else None - } else None - - } else None - } - - // Begin Reflection Helpers - - // Replaces a repeated parameter type at the end of the parameter list - // with a number of non-repeated parameter types in order to pad the - // list to be nargs in length - def extend(types: Seq[Type], nargs: Int): Seq[Type] = { - if (isVarArgTypes(types)) { - val repeatedType = types.last.normalize.typeArgs.head - types.init ++ Seq.fill(nargs - (types.length - 1))(repeatedType) - } else types - } - - // Replaces by-name parameters with their result type and - // TypeRefs with the thing they reference - def unwrap(paramType: Type): Type = paramType match { - case TypeRef(_, IntClass, _) => typeOf[Int] - case TypeRef(_, LongClass, _) => typeOf[Long] - case TypeRef(_, ShortClass, _) => typeOf[Short] - case TypeRef(_, ByteClass, _) => typeOf[Byte] - case TypeRef(_, CharClass, _) => typeOf[Char] - case TypeRef(_, FloatClass, _) => typeOf[Float] - case TypeRef(_, DoubleClass, _) => typeOf[Double] - case TypeRef(_, BooleanClass, _) => typeOf[Boolean] - case TypeRef(_, UnitClass, _) => typeOf[Unit] - case TypeRef(_, NullClass, _) => typeOf[Null] - case TypeRef(_, AnyClass, _) => typeOf[Any] - case TypeRef(_, NothingClass, _) => typeOf[Nothing] - case TypeRef(_, AnyRefClass, _) => typeOf[AnyRef] - case TypeRef(_, ByNameParamClass, List(resultType)) => unwrap(resultType) - case t: Type => t - } - - // Gives the names of the parameters to a method - def paramNames(signature: Type): Seq[TermName] = signature match { - case PolyType(_, resultType) => paramNames(resultType) - case MethodType(params, _) => params.map(_.name.asInstanceOf[TermName]) - case NullaryMethodType(_) => Seq.empty - } - - def valParams(signature: Type): Seq[TermSymbol] = signature match { - case PolyType(_, resultType) => valParams(resultType) - case MethodType(params, _) => params.map(_.asTermSymbol) - case NullaryMethodType(_) => Seq.empty - } - - // Returns a map from parameter index to default argument type - def defaultTypes(method: MethodSymbol): Map[Int, Type] = { - val typeSig = substituteTypeParams(method) - val owner = method.owner - valParams(typeSig).zipWithIndex.filter(_._1.hasFlag(Flag.DEFAULTPARAM)).map { case(_, index) => - val name = nme.defaultGetterName(method.name.decodedName, index + 1) - val default = owner.asType member name - index -> default.typeSignature.asInstanceOf[NullaryMethodType].resultType - }.toMap - } - - // True if any of method's parameters have default values. False otherwise. - def usesDefault(method: MethodSymbol): Boolean = valParams(method.typeSignature) drop(posVargTypes).length exists { param => - (param hasFlag Flag.DEFAULTPARAM) && nameVargTypes.forall { case (argName, _) => - param.name != argName - } - } - - // The number of type parameters that the method takes - def numTypeParams(x: MethodSymbol): Int = { - x.typeSignature.typeParams.length - } - - def substituteTypeParams(m: MethodSymbol): Type = { - (pre memberType m) match { - case m: MethodType => m - case n: NullaryMethodType => n - case PolyType(tparams, rest) => rest.substituteTypes(tparams, targs.toList) - } - } - - // Begin Selection Helpers - - def select( - alternatives: Seq[MethodSymbol], - filters: Seq[Seq[MethodSymbol] => Seq[MethodSymbol]] - ): Seq[MethodSymbol] = - filters.foldLeft(alternatives)((a, f) => { - if (a.size > 1) f(a) else a - }) - - // Drop arguments that take the wrong number of type - // arguments. - val posTargLength: Seq[MethodSymbol] => Seq[MethodSymbol] = _.filter { alt => - numTypeParams(alt) == targs.length - } - - // Drop methods that are not applicable to the arguments - val applicable: Seq[MethodSymbol] => Seq[MethodSymbol] = _.filter { alt => - // Note: combine returns None if a is not applicable and - // None.exists(_ => true) == false - val paramTypes = - valParams(substituteTypeParams(alt)).map(p => unwrap(p.typeSignature)) - val variadic = isVarArgTypes(paramTypes) - val maybeArgTypes = - combineInto(variadic)(posVargTypes, nameVargTypes)(paramNames(alt.typeSignature), defaultTypes(alt)) - maybeArgTypes exists { argTypes => - if (isVarArgTypes(argTypes) && !isVarArgTypes(paramTypes)) false - else { - val a = argTypes - val p = extend(paramTypes, argTypes.length) - (a corresponds p)(_ weak_<:< _) - } - } - } - - // Always prefer methods that don't need to use default - // arguments over those that do. - // e.g. when resolving foo(1), prefer def foo(x: Int) over - // def foo(x: Int, y: Int = 4) - val noDefaults: Seq[MethodSymbol] => Seq[MethodSymbol] = - _ filterNot usesDefault - - // Try to select the most specific method. If that's not possible, - // return all of the candidates (this will likely cause an error - // higher up in the call stack) - val mostSpecific: Seq[MethodSymbol] => Seq[MethodSymbol] = { alts => - val sorted = alts.sortWith(moreSpecific) - val mostSpecific = sorted.head - val agreeTest: MethodSymbol => Boolean = - moreSpecific(mostSpecific, _) - val disagreeTest: MethodSymbol => Boolean = - moreSpecific(_, mostSpecific) - if (!sorted.tail.forall(agreeTest)) { - mostSpecific +: sorted.tail.filterNot(agreeTest) - } else if (sorted.tail.exists(disagreeTest)) { - mostSpecific +: sorted.tail.filter(disagreeTest) - } else { - Seq(mostSpecific) - } - } - - def finalResult(t: Type): Type = t match { - case PolyType(_, rest) => finalResult(rest) - case MethodType(_, result) => finalResult(result) - case NullaryMethodType(result) => finalResult(result) - case t: Type => t - } - - // If a result type is given, drop alternatives that don't meet it - val resultType: Seq[MethodSymbol] => Seq[MethodSymbol] = - if (expected == NoType) identity - else _.filter { alt => - finalResult(substituteTypeParams(alt)) <:< expected - } - - def defaultFilteringOps = - Seq(posTargLength, resultType, applicable, noDefaults, mostSpecific) - - // Begin Method Proper - - - val alts = alternatives.map(_.asMethodSymbol) - - val selection = select(alts, defaultFilteringOps) - - val knownApplicable = applicable(selection) - - if (knownApplicable.size == 1) knownApplicable.head - else NoSymbol - } + def getter: Symbol = getter(owner) + def setter: Symbol = setter(owner) } /** The class for all symbols */ @@ -734,6 +462,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def isAliasType = false def isAbstractType = false def isSkolem = false + def isMacro = this hasFlag MACRO /** A Type, but not a Class. */ def isNonClassType = false @@ -2040,7 +1769,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Is this symbol defined in the same scope and compilation unit as `that` symbol? */ def isCoDefinedWith(that: Symbol) = { - import language.reflectiveCalls (this.rawInfo ne NoType) && (this.effectiveOwner == that.effectiveOwner) && { !this.effectiveOwner.isPackageClass || @@ -2711,7 +2439,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def moduleClass = referenced override def companionClass = - flatOwnerInfo.decl(name.toTypeName).suchThat(_ isCoDefinedWith this) + flatOwnerInfo.decl(name.toTypeName).suchThat(sym => sym.isClass && (sym isCoDefinedWith this)) override def owner = { Statistics.incCounter(ownerCount) @@ -2765,6 +2493,19 @@ trait Symbols extends api.Symbols { self: SymbolTable => mtpeResult = res res } + + override def params: List[List[Symbol]] = paramss + + override def returnType: Type = { + def loop(tpe: Type): Type = + tpe match { + case NullaryMethodType(ret) => loop(ret) + case MethodType(_, ret) => loop(ret) + case PolyType(_, tpe) => loop(tpe) + case tpe => tpe + } + loop(info) + } } implicit val MethodSymbolTag = ClassTag[MethodSymbol](classOf[MethodSymbol]) @@ -3028,8 +2769,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def isJavaInterface = hasAllFlags(JAVA | TRAIT) override def isNestedClass = !owner.isPackageClass override def isNumericValueClass = definitions.isNumericValueClass(this) + override def isNumeric = isNumericValueClass override def isPackageObjectClass = isModuleClass && (name == tpnme.PACKAGE) override def isPrimitiveValueClass = definitions.isPrimitiveValueClass(this) + override def isPrimitive = isPrimitiveValueClass // The corresponding interface is the last parent by convention. private def lastParent = if (tpe.parents.isEmpty) NoSymbol else tpe.parents.last.typeSymbol @@ -3076,7 +2819,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ protected final def companionModule0: Symbol = flatOwnerInfo.decl(name.toTermName).suchThat( - sym => sym.hasFlag(MODULE) && (sym isCoDefinedWith this) && !sym.isMethod) + sym => sym.isModule && (sym isCoDefinedWith this) && !sym.isMethod) override def companionModule = companionModule0 override def companionSymbol = companionModule0 @@ -3171,7 +2914,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => private[this] var typeOfThisCache: Type = _ private[this] var typeOfThisPeriod = NoPeriod - private var implicitMembersCacheValue: List[Symbol] = Nil + private var implicitMembersCacheValue: Scope = EmptyScope private var implicitMembersCacheKey1: Type = NoType private var implicitMembersCacheKey2: ScopeEntry = null @@ -3190,7 +2933,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => typeOfThisCache } - def implicitMembers: List[Symbol] = { + def implicitMembers: Scope = { val tp = info if ((implicitMembersCacheKey1 ne tp) || (implicitMembersCacheKey2 ne tp.decls.elems)) { // Skip a package object class, because the members are also in @@ -3399,7 +3142,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => } 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 }) { diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala index c3a6fce164..d160695e67 100644 --- a/src/reflect/scala/reflect/internal/TreeGen.scala +++ b/src/reflect/scala/reflect/internal/TreeGen.scala @@ -1,7 +1,7 @@ package scala.reflect package internal -abstract class TreeGen extends makro.TreeBuilder { +abstract class TreeGen extends macros.TreeBuilder { val global: SymbolTable import global._ @@ -143,6 +143,8 @@ abstract class TreeGen extends makro.TreeBuilder { /** Computes stable type for a tree if possible */ def stableTypeFor(tree: Tree): Option[Type] = tree match { + case This(_) if tree.symbol != null && !tree.symbol.isError => + Some(ThisType(tree.symbol)) case Ident(_) if tree.symbol.isStable => Some(singleType(tree.symbol.owner.thisType, tree.symbol)) case Select(qual, _) if ((tree.symbol ne null) && (qual.tpe ne null)) && // turned assert into guard for #4064 diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index 619e3bc170..ddc40b2e9f 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -1024,14 +1024,14 @@ trait Trees extends api.Trees { self: SymbolTable => } } - + /** Delegate for a TypeTree symbol. This operation is unsafe because * it may trigger type checking when forcing the type symbol of the * underlying type. */ protected def typeTreeSymbol(tree: TypeTree): Symbol = if (tree.tpe == null) null else tree.tpe.typeSymbol - + // --- generic traversers and transformers override protected def itraverse(traverser: Traverser, tree: Tree): Unit = { @@ -1266,7 +1266,7 @@ trait Trees extends api.Trees { self: SymbolTable => } } - private def mclass(sym: Symbol) = sym map (_.asModuleSymbol.moduleClass) + private def mclass(sym: Symbol) = sym map (_.asModule.moduleClass) // --- specific traversers and transformers diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 01679a777d..442a91774d 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -323,6 +323,7 @@ trait Types extends api.Types { self: SymbolTable => /** Is this type higher-kinded, i.e., is it a type constructor @M */ def isHigherKinded: Boolean = false + def takesTypeArgs: Boolean = this.isHigherKinded /** Does this type denote a stable reference (i.e. singleton type)? */ def isStable: Boolean = false @@ -600,7 +601,7 @@ trait Types extends api.Types { self: SymbolTable => def decl(name: Name): Symbol = findDecl(name, 0) /** A list of all non-private members defined or declared in this type. */ - def nonPrivateDecls: List[Symbol] = decls filter (x => !x.isPrivate) toList + def nonPrivateDecls: List[Symbol] = decls.filterNot(_.isPrivate).toList /** The non-private defined or declared members with name `name` in this type; * an OverloadedSymbol if several exist, NoSymbol if none exist. @@ -612,21 +613,21 @@ trait Types extends api.Types { self: SymbolTable => * Members appear in linearization order of their owners. * Members with the same owner appear in reverse order of their declarations. */ - def members: List[Symbol] = membersBasedOnFlags(0, 0) + def members: Scope = membersBasedOnFlags(0, 0) /** A list of all non-private members of this type (defined or inherited) */ - def nonPrivateMembers: List[Symbol] = membersBasedOnFlags(BridgeAndPrivateFlags, 0) + def nonPrivateMembers: Scope = membersBasedOnFlags(BridgeAndPrivateFlags, 0) /** A list of all non-private members of this type (defined or inherited), * admitting members with given flags `admit` */ - def nonPrivateMembersAdmitting(admit: Long): List[Symbol] = membersBasedOnFlags(BridgeAndPrivateFlags & ~admit, 0) + def nonPrivateMembersAdmitting(admit: Long): Scope = membersBasedOnFlags(BridgeAndPrivateFlags & ~admit, 0) /** A list of all implicit symbols of this type (defined or inherited) */ - def implicitMembers: List[Symbol] = membersBasedOnFlags(BridgeFlags, IMPLICIT) + def implicitMembers: Scope = membersBasedOnFlags(BridgeFlags, IMPLICIT) /** A list of all deferred symbols of this type (defined or inherited) */ - def deferredMembers: List[Symbol] = membersBasedOnFlags(BridgeFlags, DEFERRED) + def deferredMembers: Scope = membersBasedOnFlags(BridgeFlags, DEFERRED) /** The member with given name, * an OverloadedSymbol if several exist, NoSymbol if none exist */ @@ -642,12 +643,12 @@ trait Types extends api.Types { self: SymbolTable => /** All members with the given flags, excluding bridges. */ - def membersWithFlags(requiredFlags: Long): List[Symbol] = + def membersWithFlags(requiredFlags: Long): Scope = membersBasedOnFlags(BridgeFlags, requiredFlags) /** All non-private members with the given flags, excluding bridges. */ - def nonPrivateMembersWithFlags(requiredFlags: Long): List[Symbol] = + def nonPrivateMembersWithFlags(requiredFlags: Long): Scope = membersBasedOnFlags(BridgeAndPrivateFlags, requiredFlags) /** The non-private member with given name, admitting members with given flags `admit`. @@ -668,7 +669,7 @@ trait Types extends api.Types { self: SymbolTable => /** Members excluding and requiring the given flags. * Note: unfortunately it doesn't work to exclude DEFERRED this way. */ - def membersBasedOnFlags(excludedFlags: Long, requiredFlags: Long): List[Symbol] = + def membersBasedOnFlags(excludedFlags: Long, requiredFlags: Long): Scope = findMembers(excludedFlags, requiredFlags) // findMember(nme.ANYNAME, excludedFlags, requiredFlags, false).alternatives @@ -1020,7 +1021,7 @@ trait Types extends api.Types { self: SymbolTable => else (baseClasses.head.newOverloaded(this, alts)) } - def findMembers(excludedFlags: Long, requiredFlags: Long): List[Symbol] = { + def findMembers(excludedFlags: Long, requiredFlags: Long): Scope = { // if this type contains type variables, put them to sleep for a while -- don't just wipe them out by // replacing them by the corresponding type parameter, as that messes up (e.g.) type variables in type refinements // without this, the matchesType call would lead to type variables on both sides @@ -1054,7 +1055,7 @@ trait Types extends api.Types { self: SymbolTable => (bcs eq bcs0) || (flags & PrivateLocal) != PrivateLocal || (bcs0.head.hasTransOwner(bcs.head)))) { - if (members eq null) members = newScope + if (members eq null) members = newFindMemberScope var others: ScopeEntry = members.lookupEntry(sym.name) var symtpe: Type = null while ((others ne null) && { @@ -1083,7 +1084,7 @@ trait Types extends api.Types { self: SymbolTable => } // while (continue) Statistics.popTimer(typeOpsStack, start) if (suspension ne null) suspension foreach (_.suspended = false) - if (members eq null) Nil else members.toList + if (members eq null) EmptyScope else members } /** @@ -1392,11 +1393,9 @@ trait Types extends api.Types { self: SymbolTable => final class UniqueThisType(sym: Symbol) extends ThisType(sym) with UniqueType { } object ThisType extends ThisTypeExtractor { - def apply(sym: Symbol): Type = { - if (!phase.erasedTypes) unique(new UniqueThisType(sym)) - else if (sym.isImplClass) sym.typeOfThis - else sym.tpe - } + def apply(sym: Symbol): Type = + if (phase.erasedTypes) sym.tpe + else unique(new UniqueThisType(sym)) } /** A class for singleton types of the form `<prefix>.<sym.name>.type`. @@ -2080,7 +2079,8 @@ trait Types extends api.Types { self: SymbolTable => override protected def finishPrefix(rest: String) = objectPrefix + rest override def directObjectString = super.safeToString override def toLongString = toString - override def safeToString = narrow.toString + override def safeToString = prefixString + "type" + override def prefixString = if (sym.isOmittablePrefix) "" else prefix.prefixString + sym.nameString + "." } class PackageTypeRef(pre0: Type, sym0: Symbol) extends ModuleTypeRef(pre0, sym0) { require(sym.isPackageClass, sym) @@ -2613,7 +2613,7 @@ trait Types extends api.Types { self: SymbolTable => case class PolyType(override val typeParams: List[Symbol], override val resultType: Type) extends Type with PolyTypeApi { //assert(!(typeParams contains NoSymbol), this) - assert(typeParams nonEmpty, this) // used to be a marker for nullary method type, illegal now (see @NullaryMethodType) + assert(typeParams.nonEmpty, this) // used to be a marker for nullary method type, illegal now (see @NullaryMethodType) override def paramSectionCount: Int = resultType.paramSectionCount override def paramss: List[List[Symbol]] = resultType.paramss @@ -3275,7 +3275,7 @@ trait Types extends api.Types { self: SymbolTable => // to never be resumed with the current implementation assert(!suspended, this) TypeVar.trace("clone", originLocation)( - TypeVar(origin, constr cloneInternal, typeArgs, params) // @M TODO: clone args/params? + TypeVar(origin, constr.cloneInternal, typeArgs, params) // @M TODO: clone args/params? ) } } @@ -3637,7 +3637,7 @@ trait Types extends api.Types { self: SymbolTable => */ object GenPolyType { def apply(tparams: List[Symbol], tpe: Type): Type = ( - if (tparams nonEmpty) typeFun(tparams, tpe) + if (tparams.nonEmpty) typeFun(tparams, tpe) else tpe // it's okay to be forgiving here ) def unapply(tpe: Type): Option[(List[Symbol], Type)] = tpe match { @@ -4652,14 +4652,14 @@ trait Types extends api.Types { self: SymbolTable => // dependent method types object IsDependentCollector extends TypeCollector(false) { def traverse(tp: Type) { - if(tp isImmediatelyDependent) result = true + if (tp.isImmediatelyDependent) result = true else if (!result) mapOver(tp) } } object ApproximateDependentMap extends TypeMap { def apply(tp: Type): Type = - if(tp isImmediatelyDependent) WildcardType + if (tp.isImmediatelyDependent) WildcardType else mapOver(tp) } @@ -6159,7 +6159,7 @@ trait Types extends api.Types { self: SymbolTable => } val sorted = btsMap.toList.sortWith((x, y) => x._1.typeSymbol isLess y._1.typeSymbol) - val maxSeqLength = sorted map (_._2.size) max + val maxSeqLength = sorted.map(_._2.size).max val padded = sorted map (_._2.padTo(maxSeqLength, NoType)) val transposed = padded.transpose @@ -6265,7 +6265,7 @@ trait Types extends api.Types { self: SymbolTable => }).mkString("") println("Frontier(\n" + str + ")") - printLubMatrix(ts zip tsBts toMap, lubListDepth) + printLubMatrix((ts zip tsBts).toMap, lubListDepth) } loop(newtps) @@ -6275,7 +6275,7 @@ trait Types extends api.Types { self: SymbolTable => val initialBTSes = ts map (_.baseTypeSeq.toList) if (printLubs) - printLubMatrix(ts zip initialBTSes toMap, depth) + printLubMatrix((ts zip initialBTSes).toMap, depth) loop(initialBTSes) } @@ -6483,7 +6483,7 @@ trait Types extends api.Types { self: SymbolTable => map2(narrowts, syms)((t, sym) => t.memberInfo(sym).substThis(t.typeSymbol, lubThisType)) if (proto.isTerm) // possible problem: owner of info is still the old one, instead of new refinement class proto.cloneSymbol(lubRefined.typeSymbol).setInfoOwnerAdjusted(lub(symtypes, decr(depth))) - else if (symtypes.tail forall (symtypes.head =:=)) + else if (symtypes.tail forall (symtypes.head =:= _)) proto.cloneSymbol(lubRefined.typeSymbol).setInfoOwnerAdjusted(symtypes.head) else { def lubBounds(bnds: List[TypeBounds]): TypeBounds = @@ -6857,7 +6857,7 @@ trait Types extends api.Types { self: SymbolTable => tps map { case MethodType(params1, res) if (isSameTypes(params1 map (_.tpe), pts)) => res - case NullaryMethodType(res) if pts isEmpty => + case NullaryMethodType(res) if pts.isEmpty => res case _ => throw new NoCommonType(tps) @@ -6952,8 +6952,13 @@ trait Types extends api.Types { self: SymbolTable => private var tostringRecursions = 0 protected def typeToString(tpe: Type): String = - if (tostringRecursions >= maxTostringRecursions) + if (tostringRecursions >= maxTostringRecursions) { + debugwarn("Exceeded recursion depth attempting to print type.") + if (settings.debug.value) + (new Throwable).printStackTrace + "..." + } else try { tostringRecursions += 1 diff --git a/src/reflect/scala/reflect/internal/util/Origins.scala b/src/reflect/scala/reflect/internal/util/Origins.scala index 0bd5ad55ca..3111730f76 100644 --- a/src/reflect/scala/reflect/internal/util/Origins.scala +++ b/src/reflect/scala/reflect/internal/util/Origins.scala @@ -96,7 +96,7 @@ object Origins { || (el.getClassName startsWith "java.lang.") ) private def findCutoff() = { - val cutoff = Thread.currentThread.getStackTrace dropWhile preCutoff head; + val cutoff = (Thread.currentThread.getStackTrace dropWhile preCutoff).head OriginId(cutoff.getClassName, cutoff.getMethodName) } diff --git a/src/reflect/scala/reflect/internal/util/SourceFile.scala b/src/reflect/scala/reflect/internal/util/SourceFile.scala index df4a3336c3..793ef0ac22 100644 --- a/src/reflect/scala/reflect/internal/util/SourceFile.scala +++ b/src/reflect/scala/reflect/internal/util/SourceFile.scala @@ -41,7 +41,7 @@ abstract class SourceFile { (content drop offset) startsWith text def lineToString(index: Int): String = - content drop lineToOffset(index) takeWhile (c => !isLineBreakChar(c.toChar)) mkString + content drop lineToOffset(index) takeWhile (c => !isLineBreakChar(c.toChar)) mkString "" @tailrec final def skipWhitespace(offset: Int): Int = @@ -98,7 +98,7 @@ class ScriptSourceFile(underlying: BatchSourceFile, content: Array[Char], overri override def positionInUltimateSource(pos: Position) = if (!pos.isDefined) super.positionInUltimateSource(pos) - else new OffsetPosition(underlying, pos.point + start) + else pos.withSource(underlying, start) } /** a file whose contents do not change over time */ diff --git a/src/reflect/scala/reflect/internal/util/TableDef.scala b/src/reflect/scala/reflect/internal/util/TableDef.scala index d692a6d8f5..2e60ce3bcc 100644 --- a/src/reflect/scala/reflect/internal/util/TableDef.scala +++ b/src/reflect/scala/reflect/internal/util/TableDef.scala @@ -1,6 +1,7 @@ package scala.reflect.internal.util import TableDef._ +import language.postfixOps /** A class for representing tabular data in a way that preserves * its inner beauty. See Exceptional for an example usage. diff --git a/src/reflect/scala/reflect/internal/util/TraceSymbolActivity.scala b/src/reflect/scala/reflect/internal/util/TraceSymbolActivity.scala index 5fbeb5f576..cecf8e4658 100644 --- a/src/reflect/scala/reflect/internal/util/TraceSymbolActivity.scala +++ b/src/reflect/scala/reflect/internal/util/TraceSymbolActivity.scala @@ -8,7 +8,8 @@ trait TraceSymbolActivity { val global: SymbolTable import global._ - if (traceSymbolActivity && global.isCompilerUniverse) + private[this] var enabled = traceSymbolActivity + if (enabled && global.isCompilerUniverse) scala.sys addShutdownHook showAllSymbols() private type Set[T] = scala.collection.immutable.Set[T] @@ -21,23 +22,26 @@ trait TraceSymbolActivity { val allTrees = mutable.Set[Tree]() def recordSymbolsInTree(tree: Tree) { - allTrees += tree + if (enabled) + allTrees += tree } def recordNewSymbol(sym: Symbol) { - if (sym.id > 1) { + if (enabled && sym.id > 1) { allSymbols(sym.id) = sym allChildren(sym.owner.id) ::= sym.id } } def recordNewSymbolOwner(sym: Symbol, newOwner: Symbol) { - val sid = sym.id - val oid = sym.owner.id - val nid = newOwner.id - - prevOwners(sid) ::= (oid -> phase) - allChildren(oid) = allChildren(oid) filterNot (_ == sid) - allChildren(nid) ::= sid + if (enabled) { + val sid = sym.id + val oid = sym.owner.id + val nid = newOwner.id + + prevOwners(sid) ::= (oid -> phase) + allChildren(oid) = allChildren(oid) filterNot (_ == sid) + allChildren(nid) ::= sid + } } /** TODO. @@ -86,7 +90,7 @@ trait TraceSymbolActivity { def prefix = (" " * (sym.ownerChain.length - 1)) + sym.id try println("%s#%s %s".format(prefix, sym.accurateKindString, sym.name.decode)) catch { - case x => println(prefix + " failed: " + x) + case x: Throwable => println(prefix + " failed: " + x) } allChildren(sym.id).sorted foreach showIdAndRemove } @@ -128,7 +132,8 @@ trait TraceSymbolActivity { private def runBeforeErasure[T](body: => T): T = atPhase(findErasurePhase)(body) def showAllSymbols() { - if (!traceSymbolActivity) return + if (!enabled) return + enabled = false allSymbols(1) = NoSymbol println("" + allSymbols.size + " symbols created.") diff --git a/src/reflect/scala/reflect/makro/Aliases.scala b/src/reflect/scala/reflect/macros/Aliases.scala index 4bd246572f..46b7066902 100644 --- a/src/reflect/scala/reflect/makro/Aliases.scala +++ b/src/reflect/scala/reflect/macros/Aliases.scala @@ -1,5 +1,5 @@ package scala.reflect -package makro +package macros trait Aliases { self: Context => diff --git a/src/reflect/scala/reflect/makro/CapturedVariables.scala b/src/reflect/scala/reflect/macros/CapturedVariables.scala index 592e28b3b2..60ed6f5e7b 100644 --- a/src/reflect/scala/reflect/makro/CapturedVariables.scala +++ b/src/reflect/scala/reflect/macros/CapturedVariables.scala @@ -1,5 +1,5 @@ package scala.reflect -package makro +package macros trait CapturedVariables { self: Context => diff --git a/src/reflect/scala/reflect/makro/Context.scala b/src/reflect/scala/reflect/macros/Context.scala index f093016a38..37c8f9057e 100644 --- a/src/reflect/scala/reflect/makro/Context.scala +++ b/src/reflect/scala/reflect/macros/Context.scala @@ -1,11 +1,9 @@ package scala.reflect -package makro - -import language.experimental.macros +package macros // todo. introduce context hierarchy // the most lightweight context should just expose the stuff from the SIP -// the full context should include all traits from scala.reflect.makro (and probably reside in scala-compiler.jar) +// the full context should include all traits from scala.reflect.macros (and probably reside in scala-compiler.jar) trait Context extends Aliases with CapturedVariables diff --git a/src/reflect/scala/reflect/makro/Enclosures.scala b/src/reflect/scala/reflect/macros/Enclosures.scala index ff5c13a785..a07ff85a08 100644 --- a/src/reflect/scala/reflect/makro/Enclosures.scala +++ b/src/reflect/scala/reflect/macros/Enclosures.scala @@ -1,5 +1,5 @@ package scala.reflect -package makro +package macros trait Enclosures { self: Context => diff --git a/src/reflect/scala/reflect/makro/Evals.scala b/src/reflect/scala/reflect/macros/Evals.scala index 4e5fc2f97f..3837d749da 100644 --- a/src/reflect/scala/reflect/makro/Evals.scala +++ b/src/reflect/scala/reflect/macros/Evals.scala @@ -1,5 +1,5 @@ package scala.reflect -package makro +package macros trait Evals { self: Context => diff --git a/src/reflect/scala/reflect/makro/ExprUtils.scala b/src/reflect/scala/reflect/macros/ExprUtils.scala index c3e5cc6bc1..adcdc78c78 100644 --- a/src/reflect/scala/reflect/makro/ExprUtils.scala +++ b/src/reflect/scala/reflect/macros/ExprUtils.scala @@ -1,5 +1,5 @@ package scala.reflect -package makro +package macros trait ExprUtils { self: Context => diff --git a/src/reflect/scala/reflect/makro/Exprs.scala b/src/reflect/scala/reflect/macros/Exprs.scala index 91d3dafbf2..ceaab06d12 100644 --- a/src/reflect/scala/reflect/makro/Exprs.scala +++ b/src/reflect/scala/reflect/macros/Exprs.scala @@ -1,5 +1,5 @@ package scala.reflect -package makro +package macros trait Exprs { self: Context => diff --git a/src/reflect/scala/reflect/makro/FrontEnds.scala b/src/reflect/scala/reflect/macros/FrontEnds.scala index 5087f90174..d15db0725f 100644 --- a/src/reflect/scala/reflect/makro/FrontEnds.scala +++ b/src/reflect/scala/reflect/macros/FrontEnds.scala @@ -1,5 +1,5 @@ package scala.reflect -package makro +package macros trait FrontEnds extends scala.reflect.api.FrontEnds { self: Context => diff --git a/src/reflect/scala/reflect/makro/Infrastructure.scala b/src/reflect/scala/reflect/macros/Infrastructure.scala index e6bfe33366..1f1bd160a1 100644 --- a/src/reflect/scala/reflect/makro/Infrastructure.scala +++ b/src/reflect/scala/reflect/macros/Infrastructure.scala @@ -1,5 +1,5 @@ package scala.reflect -package makro +package macros trait Infrastructure { self: Context => diff --git a/src/reflect/scala/reflect/makro/Names.scala b/src/reflect/scala/reflect/macros/Names.scala index 909976d83c..fab9bbbca5 100644 --- a/src/reflect/scala/reflect/makro/Names.scala +++ b/src/reflect/scala/reflect/macros/Names.scala @@ -1,5 +1,5 @@ package scala.reflect -package makro +package macros trait Names { self: Context => diff --git a/src/reflect/scala/reflect/makro/Parsers.scala b/src/reflect/scala/reflect/macros/Parsers.scala index 9866b7e491..ea87c5842e 100644 --- a/src/reflect/scala/reflect/makro/Parsers.scala +++ b/src/reflect/scala/reflect/macros/Parsers.scala @@ -1,5 +1,5 @@ package scala.reflect -package makro +package macros trait Parsers { self: Context => diff --git a/src/reflect/scala/reflect/makro/Reifiers.scala b/src/reflect/scala/reflect/macros/Reifiers.scala index f39f56f935..1bee17d548 100644 --- a/src/reflect/scala/reflect/makro/Reifiers.scala +++ b/src/reflect/scala/reflect/macros/Reifiers.scala @@ -1,5 +1,5 @@ package scala.reflect -package makro +package macros trait Reifiers { self: Context => diff --git a/src/reflect/scala/reflect/makro/Settings.scala b/src/reflect/scala/reflect/macros/Settings.scala index c6c7e5870b..8d166056c3 100644 --- a/src/reflect/scala/reflect/makro/Settings.scala +++ b/src/reflect/scala/reflect/macros/Settings.scala @@ -1,5 +1,5 @@ package scala.reflect -package makro +package macros trait Settings { self: Context => diff --git a/src/reflect/scala/reflect/makro/TreeBuilder.scala b/src/reflect/scala/reflect/macros/TreeBuilder.scala index c4179b9c80..06f5caf68b 100644 --- a/src/reflect/scala/reflect/makro/TreeBuilder.scala +++ b/src/reflect/scala/reflect/macros/TreeBuilder.scala @@ -1,5 +1,5 @@ package scala.reflect -package makro +package macros // [Eugene] I added some stuff that was necessary for typetag materialization macros // but we should think it over and pick other generally useful stuff diff --git a/src/reflect/scala/reflect/makro/TypeTags.scala b/src/reflect/scala/reflect/macros/TypeTags.scala index 53a9b116e3..8f590d1de4 100644 --- a/src/reflect/scala/reflect/makro/TypeTags.scala +++ b/src/reflect/scala/reflect/macros/TypeTags.scala @@ -1,5 +1,5 @@ package scala.reflect -package makro +package macros trait TypeTags { self: Context => diff --git a/src/reflect/scala/reflect/makro/Typers.scala b/src/reflect/scala/reflect/macros/Typers.scala index 2610d7dd50..eef6507418 100644 --- a/src/reflect/scala/reflect/makro/Typers.scala +++ b/src/reflect/scala/reflect/macros/Typers.scala @@ -1,5 +1,5 @@ package scala.reflect -package makro +package macros trait Typers { self: Context => @@ -10,8 +10,8 @@ trait Typers { * Can be useful for interoperating with other macros and for imposing compiler-friendly limits on macro expansion. * * Is also priceless for emitting sane error messages for macros that are called by other macros on synthetic (i.e. position-less) trees. - * In that dire case navigate the ``openMacros'' stack, and it will most likely contain at least one macro with a position-ful macro application. - * See ``enclosingPosition'' for a default implementation of this logic. + * In that dire case navigate the `openMacros` stack, and it will most likely contain at least one macro with a position-ful macro application. + * See `enclosingPosition` for a default implementation of this logic. * * Unlike `enclosingMacros`, this is a def, which means that it gets recalculated on every invocation, * so it might change depending on what is going on during macro expansion. @@ -26,41 +26,38 @@ trait Typers { */ def openImplicits: List[(Type, Tree)] - /** Typechecks the provided tree against the expected type ``pt'' in the macro callsite context. + /** Typechecks the provided tree against the expected type `pt` in the macro callsite context. * - * If ``silent'' is false, ``TypeError'' will be thrown in case of a typecheck error. - * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs. + * If `silent` is false, `TypeError` will be thrown in case of a typecheck error. + * If `silent` is true, the typecheck is silent and will return `EmptyTree` if an error occurs. * Such errors don't vanish and can be inspected by turning on -Ymacro-debug-verbose. - * Unlike in ``inferImplicitValue'' and ``inferImplicitView'', ``silent'' is false by default. + * Unlike in `inferImplicitValue` and `inferImplicitView`, `silent` is false by default. * * Typechecking can be steered with the following optional parameters: - * ``withImplicitViewsDisabled'' recursively prohibits implicit views (though, implicit vals will still be looked up and filled in), default value is false - * ``withMacrosDisabled'' recursively prohibits macro expansions and macro-based implicits, default value is false + * `withImplicitViewsDisabled` recursively prohibits implicit views (though, implicit vals will still be looked up and filled in), default value is false + * `withMacrosDisabled` recursively prohibits macro expansions and macro-based implicits, default value is false */ def typeCheck(tree: Tree, pt: Type = WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree - /** Infers an implicit value of the expected type ``pt'' in the macro callsite context. - * Optional ``pos'' parameter provides a position that will be associated with the implicit search. + /** Infers an implicit value of the expected type `pt` in the macro callsite context. + * Optional `pos` parameter provides a position that will be associated with the implicit search. * - * If ``silent'' is false, ``TypeError'' will be thrown in case of an inference error. - * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs. + * If `silent` is false, `TypeError` will be thrown in case of an inference error. + * If `silent` is true, the typecheck is silent and will return `EmptyTree` if an error occurs. * Such errors don't vanish and can be inspected by turning on -Xlog-implicits. - * Unlike in ``typeCheck'', ``silent'' is true by default. + * Unlike in `typeCheck`, `silent` is true by default. */ def inferImplicitValue(pt: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: Position = enclosingPosition): Tree - /** Infers an implicit view from the provided tree ``tree'' from the type ``from'' to the type ``to'' in the macro callsite context. + /** Infers an implicit view from the provided tree `tree` of the type `from` to the type `to` in the macro callsite context. + * Optional `pos` parameter provides a position that will be associated with the implicit search. * - * Optional ``pos'' parameter provides a position that will be associated with the implicit search. - * Another optional parameter, ``reportAmbiguous`` controls whether ambiguous implicit errors should be reported. - * If we search for a view simply to find out whether one type is coercible to another, it might be desirable to set this flag to ``false''. - * - * If ``silent'' is false, ``TypeError'' will be thrown in case of an inference error. - * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs. + * If `silent` is false, `TypeError` will be thrown in case of an inference error. + * If `silent` is true, the typecheck is silent and will return `EmptyTree` if an error occurs. * Such errors don't vanish and can be inspected by turning on -Xlog-implicits. - * Unlike in ``typeCheck'', ``silent'' is true by default. + * Unlike in `typeCheck`, `silent` is true by default. */ - def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, reportAmbiguous: Boolean = true, pos: Position = enclosingPosition): Tree + def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: Position = enclosingPosition): Tree /** Recursively resets symbols and types in a given tree. * diff --git a/src/reflect/scala/reflect/makro/Universe.scala b/src/reflect/scala/reflect/macros/Universe.scala index a676f7f1de..4074dd9e93 100644 --- a/src/reflect/scala/reflect/makro/Universe.scala +++ b/src/reflect/scala/reflect/macros/Universe.scala @@ -1,5 +1,5 @@ package scala.reflect -package makro +package macros abstract class Universe extends scala.reflect.api.Universe { @@ -24,8 +24,15 @@ abstract class Universe extends scala.reflect.api.Universe { */ trait SymbolContextApi extends SymbolApi with AttachableApi { this: Symbol => - // [Eugene++ to Martin] should we also add mutability methods here (similarly to what's done below for trees)? - // I'm talking about `setAnnotations` and friends + def setFlags(flags: FlagSet): this.type + + def setTypeSignature(tpe: Type): this.type + + def setAnnotations(annots: AnnotationInfo*): this.type + + def setName(name: Name): this.type + + def setPrivateWithin(sym: Symbol): this.type } // Tree extensions --------------------------------------------------------------- diff --git a/src/reflect/scala/reflect/makro/package.scala b/src/reflect/scala/reflect/macros/package.scala index 3c0e51030e..06ce0b3244 100644 --- a/src/reflect/scala/reflect/makro/package.scala +++ b/src/reflect/scala/reflect/macros/package.scala @@ -1,6 +1,6 @@ package scala.reflect -package object makro { +package object macros { type MirrorOf[U <: base.Universe with Singleton] = base.MirrorOf[U] } diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 0878801715..64c47a5502 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -150,7 +150,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym def classSymbol(rtcls: RuntimeClass): ClassSymbol = classToScala(rtcls) - def moduleSymbol(rtcls: RuntimeClass): ModuleSymbol = classToScala(rtcls).companionModule.asModuleSymbol + def moduleSymbol(rtcls: RuntimeClass): ModuleSymbol = classToScala(rtcls).companionModule.asModule private def checkMemberOf(wannabe: Symbol, owner: Symbol) = if (!owner.info.member(wannabe.name).alternatives.contains(wannabe)) ErrorNotMember(wannabe, owner) @@ -166,7 +166,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym if (field.isGetter) nme.getterToLocal(field.name) else if (field.isSetter) nme.getterToLocal(nme.setterToGetter(field.name)) else field.name - val field1 = (field.owner.info decl name).asTermSymbol + val field1 = (field.owner.info decl name).asTerm try fieldToJava(field1) catch { case _: NoSuchFieldException => ErrorNonExistentField(field1) @@ -187,6 +187,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym checkMemberOf(mod, symbol) new JavaModuleMirror(instance, mod) } + override def toString = s"instance mirror for $obj" } private class JavaFieldMirror(val receiver: AnyRef, val symbol: TermSymbol) @@ -201,6 +202,32 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym if (!symbol.isMutable) ErrorSetImmutableField(symbol) jfield.set(receiver, value) } + override def toString = s"field mirror for ${symbol.fullName} (bound to $receiver)" + } + + private def showMethodSig(symbol: MethodSymbol): String = { + var sig = s"${symbol.fullName}" + if (symbol.typeParams.nonEmpty) { + def showTparam(tparam: Symbol) = + tparam.typeSignature match { + case tpe @ TypeBounds(_, _) => s"${tparam.name}$tpe" + case _ => tparam.name + } + def showTparams(tparams: List[Symbol]) = "[" + (tparams map showTparam mkString ", ") + "]" + sig += showTparams(symbol.typeParams) + } + if (symbol.params.nonEmpty) { + def showParam(param: Symbol) = s"${param.name}: ${param.typeSignature}" + def showParams(params: List[Symbol]) = { + val s_mods = if (params.nonEmpty && params(0).hasFlag(IMPLICIT)) "implicit " else "" + val s_params = params map showParam mkString ", " + "(" + s_mods + s_params + ")" + } + def showParamss(paramss: List[List[Symbol]]) = paramss map showParams mkString "" + sig += showParamss(symbol.params) + } + sig += s": ${symbol.returnType}" + sig } private class JavaMethodMirror(val receiver: AnyRef, val symbol: MethodSymbol) @@ -220,6 +247,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym } else jmeth.invoke(receiver, args.asInstanceOf[Seq[AnyRef]]: _*) + override def toString = s"method mirror for ${showMethodSig(symbol)} (bound to $receiver)" } private class JavaConstructorMirror(val outer: AnyRef, val symbol: MethodSymbol) @@ -236,9 +264,9 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym else outer +: args.asInstanceOf[Seq[AnyRef]] jconstr.newInstance(effectiveArgs: _*) } + override def toString = s"constructor mirror for ${showMethodSig(symbol)} (bound to $outer)" } - private abstract class JavaTemplateMirror extends TemplateMirror { def outer: AnyRef @@ -256,11 +284,12 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym case module: ModuleSymbol => Some(new JavaModuleMirror(outer, module)) case _ => None } + override def toString = s"class mirror for ${symbol.fullName} (bound to $outer)" } private class JavaModuleMirror(val outer: AnyRef, val symbol: ModuleSymbol) extends JavaTemplateMirror with ModuleMirror { - def erasure = symbol.moduleClass.asClassSymbol + def erasure = symbol.moduleClass.asClass def isStatic = true def instance = { if (!symbol.owner.isPackageClass) throw new Error("inner and nested modules are not supported yet") @@ -270,6 +299,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym case cls: ClassSymbol => Some(new JavaClassMirror(outer, cls)) case _ => None } + override def toString = s"module mirror for ${symbol.fullName} (bound to $outer)" } // -------------------- Java to Scala ----------------------------------- @@ -629,7 +659,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym val preOwner = classToScala(jOwner) val owner = followStatic(preOwner, jmeth.getModifiers) (lookup(owner, jmeth.getName) suchThat (erasesTo(_, jmeth)) orElse jmethodAsScala(jmeth)) - .asMethodSymbol + .asMethod } /** @@ -643,7 +673,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym private def constructorToScala1(jconstr: jConstructor[_]): MethodSymbol = { val owner = followStatic(classToScala(jconstr.getDeclaringClass), jconstr.getModifiers) (lookup(owner, jconstr.getName) suchThat (erasesTo(_, jconstr)) orElse jconstrAsScala(jconstr)) - .asMethodSymbol + .asMethod } /** @@ -657,8 +687,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym private def fieldToScala1(jfield: jField): TermSymbol = { val owner = followStatic(classToScala(jfield.getDeclaringClass), jfield.getModifiers) - (lookup(owner, jfield.getName) suchThat (!_.isMethod) orElse jfieldAsScala(jfield)) - .asTermSymbol + (lookup(owner, jfield.getName) suchThat (!_.isMethod) orElse jfieldAsScala(jfield)).asTerm } /** @@ -691,7 +720,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym val name = (fullname: TermName) drop split + 1 val opkg = owner.info decl name if (opkg.isPackage) - opkg.asModuleSymbol + opkg.asModule else if (opkg == NoSymbol) { val pkg = owner.newPackage(name) pkg.moduleClass setInfo new LazyPackageType @@ -758,7 +787,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym s"""${if (cls == NoSymbol) "not a type: symbol" else "no symbol could be"} | loaded from $jclazz in $owner with name $simpleName and classloader $classLoader""".stripMargin) - cls.asClassSymbol + cls.asClass } } @@ -773,7 +802,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym private def typeParamToScala1(jparam: jTypeVariable[_ <: GenericDeclaration]): TypeSymbol = { val owner = genericDeclarationToScala(jparam.getGenericDeclaration) owner.info match { - case PolyType(tparams, _) => tparams.find(_.name.toString == jparam.getName).get.asTypeSymbol + case PolyType(tparams, _) => tparams.find(_.name.toString == jparam.getName).get.asType } } @@ -941,7 +970,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym else if (clazz.owner.isPackageClass) javaClass(clazz.javaClassName) else if (clazz.owner.isClass) - classToJava(clazz.owner.asClassSymbol) + classToJava(clazz.owner.asClass) .getDeclaredClasses .find(_.getSimpleName == clazz.name.toString) .getOrElse(noClass) @@ -957,7 +986,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym * @param meth The Scala field. */ def fieldToJava(fld: TermSymbol): jField = fieldCache.toJava(fld) { - val jclazz = classToJava(fld.owner.asClassSymbol) + val jclazz = classToJava(fld.owner.asClass) val jname = nme.dropLocalSuffix(fld.name).toString try jclazz getDeclaredField jname catch { @@ -969,7 +998,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym * @param meth The Scala method */ def methodToJava(meth: MethodSymbol): jMethod = methodCache.toJava(meth) { - val jclazz = classToJava(meth.owner.asClassSymbol) + val jclazz = classToJava(meth.owner.asClass) val paramClasses = transformedType(meth).paramTypes map typeToJavaClass val jname = nme.dropLocalSuffix(meth.name).toString try jclazz getDeclaredMethod (jname, paramClasses: _*) @@ -983,7 +1012,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym * @param constr The Scala constructor */ def constructorToJava(constr: MethodSymbol): jConstructor[_] = constructorCache.toJava(constr) { - val jclazz = classToJava(constr.owner.asClassSymbol) + val jclazz = classToJava(constr.owner.asClass) val paramClasses = transformedType(constr).paramTypes map typeToJavaClass val effectiveParamClasses = if (!constr.owner.owner.isStaticOwner) jclazz.getEnclosingClass +: paramClasses @@ -1001,7 +1030,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym def typeToJavaClass(tpe: Type): jClass[_] = tpe match { case ExistentialType(_, rtpe) => typeToJavaClass(rtpe) case TypeRef(_, ArrayClass, List(elemtpe)) => jArrayClass(typeToJavaClass(elemtpe)) - case TypeRef(_, sym: ClassSymbol, _) => classToJava(sym.asClassSymbol) + case TypeRef(_, sym: ClassSymbol, _) => classToJava(sym.asClass) case tpe @ TypeRef(_, sym: AliasTypeSymbol, _) => typeToJavaClass(tpe.dealias) case _ => throw new NoClassDefFoundError("no Java class corresponding to "+tpe+" found") } diff --git a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala index 7839850529..f696aceb93 100644 --- a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala +++ b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala @@ -38,6 +38,8 @@ object ReflectionUtils { ) def show(cl: ClassLoader): String = { + import language.reflectiveCalls + def isAbstractFileClassLoader(clazz: Class[_]): Boolean = { if (clazz == null) return false if (clazz.getName == "scala.tools.nsc.interpreter.AbstractFileClassLoader") return true diff --git a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala index 3b28ddf42c..c65357b652 100644 --- a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala @@ -110,6 +110,8 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => trait SynchronizedMethodSymbol extends MethodSymbol with SynchronizedTermSymbol { override def typeAsMemberOf(pre: Type): Type = synchronized { super.typeAsMemberOf(pre) } + override def params: List[List[Symbol]] = synchronized { super.params } + override def returnType: Type = synchronized { super.returnType } } trait SynchronizedTypeSymbol extends TypeSymbol with SynchronizedSymbol { @@ -134,7 +136,7 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => override def sourceModule = synchronized { super.sourceModule } // [Eugene++ to Martin] doesn't override anything. no longer necessary? // def sourceModule_=(module: ModuleSymbol) = synchronized { super.sourceModule_=(module) } - override def implicitMembers: List[Symbol] = synchronized { super.implicitMembers } + override def implicitMembers: Scope = synchronized { super.implicitMembers } } } diff --git a/src/reflect/scala/reflect/runtime/TwoWayCache.scala b/src/reflect/scala/reflect/runtime/TwoWayCache.scala index c7bfb3435d..e2bf5773d2 100644 --- a/src/reflect/scala/reflect/runtime/TwoWayCache.scala +++ b/src/reflect/scala/reflect/runtime/TwoWayCache.scala @@ -1,27 +1,40 @@ package scala.reflect package runtime +import collection.mutable.WeakHashMap +import java.lang.ref.WeakReference + /** A cache that maintains a bijection between Java reflection type `J` * and Scala reflection type `S`. + * + * The cache is two-way weak (i.e. is powered by weak references), + * so that neither Java artifacts prevent Scala artifacts from being garbage collected, + * nor the other way around. */ -import collection.mutable.HashMap - private[runtime] class TwoWayCache[J, S] { - private val toScalaMap = new HashMap[J, S] - private val toJavaMap = new HashMap[S, J] + private val toScalaMap = new WeakHashMap[J, WeakReference[S]] + private val toJavaMap = new WeakHashMap[S, WeakReference[J]] def enter(j: J, s: S) = synchronized { // debugInfo("cached: "+j+"/"+s) - toScalaMap(j) = s - toJavaMap(s) = j + toScalaMap(j) = new WeakReference(s) + toJavaMap(s) = new WeakReference(j) + } + + private object SomeRef { + def unapply[T](optRef: Option[WeakReference[T]]): Option[T] = + if (optRef.nonEmpty) { + val result = optRef.get.get + if (result != null) Some(result) else None + } else None } def toScala(key: J)(body: => S): S = synchronized { toScalaMap get key match { - case Some(v) => + case SomeRef(v) => v - case none => + case _ => val result = body enter(key, result) result @@ -30,9 +43,9 @@ private[runtime] class TwoWayCache[J, S] { def toJava(key: S)(body: => J): J = synchronized { toJavaMap get key match { - case Some(v) => + case SomeRef(v) => v - case none => + case _ => val result = body enter(result, key) result @@ -41,11 +54,12 @@ private[runtime] class TwoWayCache[J, S] { def toJavaOption(key: S)(body: => Option[J]): Option[J] = synchronized { toJavaMap get key match { - case None => + case SomeRef(v) => + Some(v) + case _ => val result = body for (value <- result) enter(value, key) result - case some => some } } } diff --git a/src/reflect/scala/reflect/runtime/package.scala b/src/reflect/scala/reflect/runtime/package.scala index a5809a2629..2cb72d3824 100644 --- a/src/reflect/scala/reflect/runtime/package.scala +++ b/src/reflect/scala/reflect/runtime/package.scala @@ -1,7 +1,5 @@ package scala.reflect -import language.experimental.macros - package object runtime { // type is api.JavaUniverse because we only want to expose the `scala.reflect.api.*` subset of reflection @@ -9,12 +7,13 @@ package object runtime { // [Eugene++ to Martin] removed `mirrorOfLoader`, because one can use `universe.runtimeMirror` instead - def currentMirror: universe.Mirror = macro Macros.currentMirror + // implementation magically hardwired to the `currentMirror` method below + def currentMirror: universe.Mirror = ??? // macro } package runtime { object Macros { - def currentMirror(c: scala.reflect.makro.Context): c.Expr[universe.Mirror] = { + def currentMirror(c: scala.reflect.macros.Context): c.Expr[universe.Mirror] = { import c.universe._ val runtimeClass = c.reifyEnclosingRuntimeClass if (runtimeClass.isEmpty) c.abort(c.enclosingPosition, "call site does not have an enclosing class") diff --git a/src/reflect/scala/tools/nsc/io/File.scala b/src/reflect/scala/tools/nsc/io/File.scala index eedf92ef98..1f3cac7ee1 100644 --- a/src/reflect/scala/tools/nsc/io/File.scala +++ b/src/reflect/scala/tools/nsc/io/File.scala @@ -120,13 +120,13 @@ class File(jfile: JFile)(implicit constructorCodec: Codec) extends Path(jfile) w def writeAll(strings: String*): Unit = { val out = bufferedWriter() try strings foreach (out write _) - finally out close + finally out.close() } def writeBytes(bytes: Array[Byte]): Unit = { val out = bufferedOutput() try out write bytes - finally out close + finally out.close() } def appendAll(strings: String*): Unit = { @@ -139,7 +139,7 @@ class File(jfile: JFile)(implicit constructorCodec: Codec) extends Path(jfile) w def printlnAll(strings: String*): Unit = { val out = printWriter() try strings foreach (out println _) - finally out close + finally out.close() } def safeSlurp(): Option[String] = diff --git a/src/reflect/scala/tools/nsc/io/Path.scala b/src/reflect/scala/tools/nsc/io/Path.scala index 984c96dfbb..74bd6cf16b 100644 --- a/src/reflect/scala/tools/nsc/io/Path.scala +++ b/src/reflect/scala/tools/nsc/io/Path.scala @@ -78,7 +78,7 @@ object Path { else new Path(jfile) /** Avoiding any shell/path issues by only using alphanumerics. */ - private[io] def randomPrefix = alphanumeric take 6 mkString + private[io] def randomPrefix = alphanumeric take 6 mkString "" private[io] def fail(msg: String) = throw FileOperationException(msg) } import Path._ diff --git a/src/reflect/scala/tools/nsc/io/Streamable.scala b/src/reflect/scala/tools/nsc/io/Streamable.scala index 03318674ee..4d872c0221 100644 --- a/src/reflect/scala/tools/nsc/io/Streamable.scala +++ b/src/reflect/scala/tools/nsc/io/Streamable.scala @@ -112,7 +112,7 @@ object Streamable { finally stream.close() def bytes(is: => InputStream): Array[Byte] = - new Bytes { def inputStream() = is } toByteArray + (new Bytes { def inputStream() = is }).toByteArray def slurp(is: => InputStream)(implicit codec: Codec): String = new Chars { def inputStream() = is } slurp codec diff --git a/src/reflect/scala/tools/nsc/io/VirtualDirectory.scala b/src/reflect/scala/tools/nsc/io/VirtualDirectory.scala index 0bcb2de43f..7272921054 100644 --- a/src/reflect/scala/tools/nsc/io/VirtualDirectory.scala +++ b/src/reflect/scala/tools/nsc/io/VirtualDirectory.scala @@ -48,7 +48,7 @@ extends AbstractFile { def iterator = files.values.toList.iterator override def lookupName(name: String, directory: Boolean): AbstractFile = - files get name filter (_.isDirectory == directory) orNull + (files get name filter (_.isDirectory == directory)).orNull override def fileNamed(name: String): AbstractFile = Option(lookupName(name, false)) getOrElse { diff --git a/src/scalap/scala/tools/scalap/Arguments.scala b/src/scalap/scala/tools/scalap/Arguments.scala index 37f6cd84ac..53f722994d 100644 --- a/src/scalap/scala/tools/scalap/Arguments.scala +++ b/src/scalap/scala/tools/scalap/Arguments.scala @@ -48,7 +48,7 @@ object Arguments { def parseBinding(str: String, separator: Char): (String, String) = (str indexOf separator) match { case -1 => argumentError("missing '" + separator + "' in binding '" + str + "'") ; Pair("", "") - case idx => Pair(str take idx trim, str drop (idx + 1) trim) + case idx => Pair((str take idx).trim, (str drop (idx + 1)).trim) } def parse(args: Array[String]): Arguments = { diff --git a/src/scalap/scala/tools/scalap/CodeWriter.scala b/src/scalap/scala/tools/scalap/CodeWriter.scala index d895ce3836..f5db183abb 100644 --- a/src/scalap/scala/tools/scalap/CodeWriter.scala +++ b/src/scalap/scala/tools/scalap/CodeWriter.scala @@ -58,7 +58,7 @@ class CodeWriter(writer: Writer) { try { writer.write(nl) } catch { - case e => sys.error("IO error") + case e: Exception => sys.error("IO error") } line = align align = true @@ -127,7 +127,7 @@ class CodeWriter(writer: Writer) { line = false this } catch { - case e => sys.error("IO error") + case e: Exception => sys.error("IO error") } override def toString(): String = writer.toString() diff --git a/src/scalap/scala/tools/scalap/Decode.scala b/src/scalap/scala/tools/scalap/Decode.scala index 4e12075541..26cea76893 100644 --- a/src/scalap/scala/tools/scalap/Decode.scala +++ b/src/scalap/scala/tools/scalap/Decode.scala @@ -49,7 +49,7 @@ object Decode { import classFile._ classFile annotation SCALA_SIG_ANNOTATION map { case Annotation(_, els) => - val bytesElem = els find (x => constant(x.elementNameIndex) == BYTES_VALUE) get + val bytesElem = els find (x => constant(x.elementNameIndex) == BYTES_VALUE) getOrElse null val _bytes = bytesElem.elementValue match { case ConstValueIndex(x) => constantWrapped(x) } val bytes = _bytes.asInstanceOf[StringBytesPair].bytes val length = ByteCodecs.decode(bytes) @@ -81,7 +81,7 @@ object Decode { xs.toList map (_.name dropRight 1) } - (ssig.symbols collect f).flatten toList + (ssig.symbols collect f).flatten.toList } } diff --git a/src/scalap/scala/tools/scalap/MetaParser.scala b/src/scalap/scala/tools/scalap/MetaParser.scala index ca9bd93f86..036738c5e9 100644 --- a/src/scalap/scala/tools/scalap/MetaParser.scala +++ b/src/scalap/scala/tools/scalap/MetaParser.scala @@ -61,7 +61,7 @@ class MetaParser(meta: String) { else None } catch { - case _ => None + case _: Exception => None } } else None; diff --git a/src/scalap/scala/tools/scalap/scalax/rules/package.scala b/src/scalap/scala/tools/scalap/scalax/rules/package.scala new file mode 100644 index 0000000000..324e87435e --- /dev/null +++ b/src/scalap/scala/tools/scalap/scalax/rules/package.scala @@ -0,0 +1,9 @@ +package scala.tools.scalap +package scalax + +package object rules { + implicit lazy val higherKinds = language.higherKinds + implicit lazy val postfixOps = language.postfixOps + implicit lazy val implicitConversions = language.implicitConversions + implicit lazy val reflectiveCalls = language.reflectiveCalls +} diff --git a/src/swing/scala/swing/Action.scala b/src/swing/scala/swing/Action.scala index 9deea0f3d4..a609329510 100644 --- a/src/swing/scala/swing/Action.scala +++ b/src/swing/scala/swing/Action.scala @@ -135,7 +135,7 @@ abstract class Action(title0: String) { def accelerator: Option[KeyStroke] = toOption(peer.getValue(javax.swing.Action.ACCELERATOR_KEY)) def accelerator_=(k: Option[KeyStroke]) { - peer.putValue(javax.swing.Action.ACCELERATOR_KEY, k orNull) + peer.putValue(javax.swing.Action.ACCELERATOR_KEY, k.orNull) } /** diff --git a/src/swing/scala/swing/ComboBox.scala b/src/swing/scala/swing/ComboBox.scala index 75f981064b..c7a457d082 100644 --- a/src/swing/scala/swing/ComboBox.scala +++ b/src/swing/scala/swing/ComboBox.scala @@ -6,8 +6,6 @@ ** |/ ** \* */ - - package scala.swing import event._ @@ -205,6 +203,6 @@ class ComboBox[A](items: Seq[A]) extends Component with Publisher { def prototypeDisplayValue: Option[A] = toOption[A](peer.getPrototypeDisplayValue) def prototypeDisplayValue_=(v: Option[A]) { - peer.setPrototypeDisplayValue(v map toAnyRef orNull) + peer.setPrototypeDisplayValue((v map toAnyRef).orNull) } } diff --git a/src/swing/scala/swing/GridBagPanel.scala b/src/swing/scala/swing/GridBagPanel.scala index d5b2472e38..dd4cbe3bcf 100644 --- a/src/swing/scala/swing/GridBagPanel.scala +++ b/src/swing/scala/swing/GridBagPanel.scala @@ -6,13 +6,10 @@ ** |/ ** \* */ - - package scala.swing import java.awt.{GridBagConstraints, GridBagLayout} - object GridBagPanel { object Fill extends Enumeration { val None = Value(GridBagConstraints.NONE) diff --git a/src/swing/scala/swing/RichWindow.scala b/src/swing/scala/swing/RichWindow.scala index 977aab300a..8eb58d56c9 100644 --- a/src/swing/scala/swing/RichWindow.scala +++ b/src/swing/scala/swing/RichWindow.scala @@ -145,7 +145,7 @@ object Dialog { initial: Int): Result.Value = { val r = JOptionPane.showOptionDialog(nullPeer(parent), message, title, optionType.id, messageType.id, Swing.wrapIcon(icon), - entries map toAnyRef toArray, entries(initial)) + (entries map toAnyRef).toArray, entries(initial)) Result(r) } @@ -157,7 +157,7 @@ object Dialog { entries: Seq[A] = Nil, initial: A): Option[A] = { val e = if (entries.isEmpty) null - else entries map toAnyRef toArray + else (entries map toAnyRef).toArray val r = JOptionPane.showInputDialog(nullPeer(parent), message, title, messageType.id, Swing.wrapIcon(icon), e, initial) diff --git a/src/swing/scala/swing/ScrollPane.scala b/src/swing/scala/swing/ScrollPane.scala index 5c18bb138a..966d5889e2 100644 --- a/src/swing/scala/swing/ScrollPane.scala +++ b/src/swing/scala/swing/ScrollPane.scala @@ -65,17 +65,17 @@ class ScrollPane extends Component with Container { def rowHeaderView: Option[Component] = Option(peer.getRowHeader.getView) map UIElement.cachedWrapper[Component] def rowHeaderView_=(c: Component) = peer.setRowHeaderView(c.peer) - def rowHeaderView_=(c: Option[Component]) = peer.setRowHeaderView(c map (_.peer) orNull) + def rowHeaderView_=(c: Option[Component]) = peer.setRowHeaderView(c.map(_.peer).orNull) def columnHeaderView: Option[Component] = Option(peer.getColumnHeader.getView) map UIElement.cachedWrapper[Component] def columnHeaderView_=(c: Component) = peer.setColumnHeaderView(c.peer) - def columnHeaderView_=(c: Option[Component]) = peer.setColumnHeaderView(c map (_.peer) orNull) + def columnHeaderView_=(c: Option[Component]) = peer.setColumnHeaderView(c.map(_.peer).orNull) def viewportView: Option[Component] = Option(peer.getViewport.getView) map UIElement.cachedWrapper[Component] def viewportView_=(c: Component) = peer.setViewportView(c.peer) - def viewportView_=(c: Option[Component]) = peer.setViewportView(c map (_.peer) orNull) + def viewportView_=(c: Option[Component]) = peer.setViewportView(c.map(_.peer).orNull) def verticalScrollBarPolicy = BarPolicy.wrap(peer.getVerticalScrollBarPolicy) def verticalScrollBarPolicy_=(p: BarPolicy.Value) = peer.setVerticalScrollBarPolicy(p.verticalPeer) diff --git a/src/swing/scala/swing/Swing.scala b/src/swing/scala/swing/Swing.scala index 519ccbaf33..05291f9aee 100644 --- a/src/swing/scala/swing/Swing.scala +++ b/src/swing/scala/swing/Swing.scala @@ -15,6 +15,7 @@ import javax.swing.event._ import javax.swing.border._ import javax.swing.{JComponent, Icon, BorderFactory, SwingUtilities} + /** * Helpers for this package. */ diff --git a/src/swing/scala/swing/UIElement.scala b/src/swing/scala/swing/UIElement.scala index 04e2217943..a83496fff0 100644 --- a/src/swing/scala/swing/UIElement.scala +++ b/src/swing/scala/swing/UIElement.scala @@ -37,7 +37,7 @@ object UIElement { case c: javax.swing.JComponent => c.getClientProperty(ClientKey) case _ => wrapperCache.get(c) } - try { w.asInstanceOf[C] } catch { case _ => null } + try { w.asInstanceOf[C] } catch { case _: Exception => null } } /** diff --git a/src/swing/scala/swing/Window.scala b/src/swing/scala/swing/Window.scala index 7991026a69..db911be0d7 100644 --- a/src/swing/scala/swing/Window.scala +++ b/src/swing/scala/swing/Window.scala @@ -51,7 +51,7 @@ abstract class Window extends UIElement with RootPanel with Publisher { outer => peer.getRootPane.setDefaultButton(b.peer) } def defaultButton_=(b: Option[Button]) { - peer.getRootPane.setDefaultButton(b map (_.peer) orNull) + peer.getRootPane.setDefaultButton(b.map(_.peer).orNull) } def dispose() { peer.dispose() } diff --git a/src/swing/scala/swing/package.scala b/src/swing/scala/swing/package.scala index d5095f021b..96530e2e94 100644 --- a/src/swing/scala/swing/package.scala +++ b/src/swing/scala/swing/package.scala @@ -14,6 +14,9 @@ package object swing { type Image = java.awt.Image type Font = java.awt.Font + implicit lazy val reflectiveCalls = language.reflectiveCalls + implicit lazy val implicitConversions = language.implicitConversions + private[swing] def ifNull[A](o: Object, a: A): A = if(o eq null) a else o.asInstanceOf[A] private[swing] def toOption[A](o: Object): Option[A] = if(o eq null) None else Some(o.asInstanceOf[A]) private[swing] def toAnyRef(x: Any): AnyRef = x.asInstanceOf[AnyRef] |