diff options
Diffstat (limited to 'src/compiler')
47 files changed, 397 insertions, 288 deletions
diff --git a/src/compiler/scala/reflect/macros/contexts/Context.scala b/src/compiler/scala/reflect/macros/contexts/Context.scala index 87dac18849..f3dd29d8b2 100644 --- a/src/compiler/scala/reflect/macros/contexts/Context.scala +++ b/src/compiler/scala/reflect/macros/contexts/Context.scala @@ -15,7 +15,8 @@ abstract class Context extends scala.reflect.macros.blackbox.Context with Parsers with Evals with ExprUtils - with Traces { + with Traces + with Internals { val universe: Global diff --git a/src/compiler/scala/reflect/macros/contexts/Evals.scala b/src/compiler/scala/reflect/macros/contexts/Evals.scala index 180a998c39..a715af986c 100644 --- a/src/compiler/scala/reflect/macros/contexts/Evals.scala +++ b/src/compiler/scala/reflect/macros/contexts/Evals.scala @@ -9,7 +9,7 @@ trait Evals { private lazy val evalMirror = ru.runtimeMirror(universe.analyzer.defaultMacroClassloader) private lazy val evalToolBox = evalMirror.mkToolBox() - private lazy val evalImporter = ru.mkImporter(universe).asInstanceOf[ru.Importer { val from: universe.type }] + private lazy val evalImporter = ru.internal.createImporter(universe).asInstanceOf[ru.Importer { val from: universe.type }] def eval[T](expr: Expr[T]): T = { expr.tree match { diff --git a/src/compiler/scala/reflect/macros/contexts/Internals.scala b/src/compiler/scala/reflect/macros/contexts/Internals.scala new file mode 100644 index 0000000000..8c784d7e54 --- /dev/null +++ b/src/compiler/scala/reflect/macros/contexts/Internals.scala @@ -0,0 +1,47 @@ +package scala.reflect.macros +package contexts + +trait Internals extends scala.tools.nsc.transform.TypingTransformers { + self: Context => + + import global._ + + lazy val internal: ContextInternalApi = new global.SymbolTableInternal with ContextInternalApi { + val enclosingOwner = callsiteTyper.context.owner + + class HofTransformer(hof: (Tree, TransformApi) => Tree) extends Transformer { + val api = new TransformApi { + def recur(tree: Tree): Tree = hof(tree, this) + def default(tree: Tree): Tree = superTransform(tree) + } + def superTransform(tree: Tree) = super.transform(tree) + override def transform(tree: Tree): Tree = hof(tree, api) + } + + def transform(tree: Tree)(transformer: (Tree, TransformApi) => Tree): Tree = new HofTransformer(transformer).transform(tree) + + class HofTypingTransformer(hof: (Tree, TypingTransformApi) => Tree) extends TypingTransformer(callsiteTyper.context.unit) { self => + currentOwner = callsiteTyper.context.owner + curTree = EmptyTree + localTyper = global.analyzer.newTyper(callsiteTyper.context.make(unit = callsiteTyper.context.unit)) + + val api = new TypingTransformApi { + def recur(tree: Tree): Tree = hof(tree, this) + def default(tree: Tree): Tree = superTransform(tree) + def atOwner[T](owner: Symbol)(op: => T): T = self.atOwner(owner)(op) + def atOwner[T](tree: Tree, owner: Symbol)(op: => T): T = self.atOwner(tree, owner)(op) + def currentOwner: Symbol = self.currentOwner + def typecheck(tree: Tree): Tree = localTyper.typed(tree) + } + def superTransform(tree: Tree) = super.transform(tree) + override def transform(tree: Tree): Tree = hof(tree, api) + } + + def typingTransform(tree: Tree)(transformer: (Tree, TypingTransformApi) => Tree): Tree = new HofTypingTransformer(transformer).transform(tree) + + def typingTransform(tree: Tree, owner: Symbol)(transformer: (Tree, TypingTransformApi) => Tree): Tree = { + val trans = new HofTypingTransformer(transformer) + trans.atOwner(owner)(trans.transform(tree)) + } + } +}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/macros/contexts/Typers.scala b/src/compiler/scala/reflect/macros/contexts/Typers.scala index f80b43b636..28c1e3ddb3 100644 --- a/src/compiler/scala/reflect/macros/contexts/Typers.scala +++ b/src/compiler/scala/reflect/macros/contexts/Typers.scala @@ -1,8 +1,6 @@ package scala.reflect.macros package contexts -import scala.reflect.internal.Mode - trait Typers { self: Context => @@ -10,17 +8,24 @@ trait Typers { def openImplicits: List[ImplicitCandidate] = callsiteTyper.context.openImplicits.map(_.toImplicitCandidate) + type TypecheckMode = scala.reflect.internal.Mode + val TypecheckMode = scala.reflect.internal.Mode + val TERMmode = TypecheckMode.EXPRmode + val TYPEmode = TypecheckMode.TYPEmode | TypecheckMode.FUNmode + val PATTERNmode = TypecheckMode.PATTERNmode + /** * @see [[scala.tools.reflect.ToolBox.typeCheck]] */ - def typecheck(tree: Tree, pt: Type = universe.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = { + def typecheck(tree: Tree, mode: TypecheckMode = TERMmode, 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 context = callsiteTyper.context val withImplicitFlag = if (!withImplicitViewsDisabled) (context.withImplicitsEnabled[Tree] _) else (context.withImplicitsDisabled[Tree] _) val withMacroFlag = if (!withMacrosDisabled) (context.withMacrosEnabled[Tree] _) else (context.withMacrosDisabled[Tree] _) def withContext(tree: => Tree) = withImplicitFlag(withMacroFlag(tree)) - def typecheckInternal(tree: Tree) = callsiteTyper.silent(_.typed(universe.duplicateAndKeepPositions(tree), pt), reportAmbiguousErrors = false) - universe.wrappingIntoTerm(tree)(wrappedTree => withContext(typecheckInternal(wrappedTree) match { + def withWrapping(tree: Tree)(op: Tree => Tree) = if (mode == TERMmode) universe.wrappingIntoTerm(tree)(op) else op(tree) + def typecheckInternal(tree: Tree) = callsiteTyper.silent(_.typed(universe.duplicateAndKeepPositions(tree), mode, pt), reportAmbiguousErrors = false) + withWrapping(tree)(wrappedTree => withContext(typecheckInternal(wrappedTree) match { case universe.analyzer.SilentResultValue(result) => macroLogVerbose(result) result diff --git a/src/compiler/scala/reflect/reify/Reifier.scala b/src/compiler/scala/reflect/reify/Reifier.scala index 6b0a0ee8d7..b1cc797389 100644 --- a/src/compiler/scala/reflect/reify/Reifier.scala +++ b/src/compiler/scala/reflect/reify/Reifier.scala @@ -110,10 +110,18 @@ abstract class Reifier extends States // todo. this is a common problem with non-trivial macros in our current macro system // needs to be solved some day // upd. a new hope: https://groups.google.com/forum/#!topic/scala-internals/TtCTPlj_qcQ - val untyped = resetAttrs(result, leaveAlone = { + var importantSymbols = Set[Symbol]( + NothingClass, AnyClass, SingletonClass, PredefModule, ScalaRunTimeModule, TypeCreatorClass, TreeCreatorClass, MirrorClass, + ApiUniverseClass, JavaUniverseClass, ReflectRuntimePackage, runDefinitions.ReflectRuntimeCurrentMirror) + importantSymbols ++= importantSymbols map (_.companionSymbol) + importantSymbols ++= importantSymbols map (_.moduleClass) + importantSymbols ++= importantSymbols map (_.linkedClassOfClass) + def isImportantSymbol(sym: Symbol): Boolean = sym != null && sym != NoSymbol && importantSymbols(sym) + val untyped = brutallyResetAttrs(result, leaveAlone = { case ValDef(_, u, _, _) if u == nme.UNIVERSE_SHORT => true case ValDef(_, m, _, _) if m == nme.MIRROR_SHORT => true case tree if symtab.syms contains tree.symbol => true + case tree if isImportantSymbol(tree.symbol) => true case _ => false }) diff --git a/src/compiler/scala/reflect/reify/States.scala b/src/compiler/scala/reflect/reify/States.scala index 29bfa19845..65f3f424e8 100644 --- a/src/compiler/scala/reflect/reify/States.scala +++ b/src/compiler/scala/reflect/reify/States.scala @@ -35,7 +35,7 @@ trait States { if (!value && concrete) { current match { case tpe: Type => CannotReifyWeakType(s" having unresolved type parameter $tpe") - case sym: Symbol => CannotReifyWeakType(s" referring to local ${sym.kindString} ${sym.fullName}") + case sym: Symbol => CannotReifyWeakType(s" referring to ${sym.kindString} ${sym.fullName} local to the reifee") case _ => CannotReifyWeakType("") } } diff --git a/src/compiler/scala/reflect/reify/codegen/GenAnnotationInfos.scala b/src/compiler/scala/reflect/reify/codegen/GenAnnotationInfos.scala index bd60faf4cd..ce26232e5f 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenAnnotationInfos.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenAnnotationInfos.scala @@ -38,19 +38,10 @@ trait GenAnnotationInfos { } } - def reifyClassfileAnnotArg(arg: ClassfileAnnotArg): Tree = arg match { - case LiteralAnnotArg(const) => - mirrorFactoryCall(nme.LiteralAnnotArg, reifyProduct(const)) - case ArrayAnnotArg(args) => - mirrorFactoryCall(nme.ArrayAnnotArg, scalaFactoryCall(nme.Array, args map reifyClassfileAnnotArg: _*)) - case NestedAnnotArg(ann) => - mirrorFactoryCall(nme.NestedAnnotArg, reifyAnnotationInfo(ann)) - case _ => - sys.error(s"Don't know what to do with $arg") - } - // if you reify originals of anns, you get SO when trying to reify AnnotatedTypes, so screw it - after all, it's not that important - val reifiedAssocs = ann.assocs map (assoc => scalaFactoryCall(nme.Tuple2, reify(assoc._1), reifyClassfileAnnotArg(assoc._2))) - mirrorFactoryCall(nme.Annotation, reify(ann.atp), mkList(reifiedArgs), mkListMap(reifiedAssocs)) + val Apply(Select(New(tpt), name), args) = annotationToTree(ann) + val reifiedAtp = mirrorCall(nme.Select, mirrorCall(nme.New, mirrorCall(nme.TypeTree, reifyType(tpt.tpe))), reify(name)) + val reifiedAnnRepr = mirrorCall(nme.Apply, reifiedAtp, reifyList(args)) + mirrorFactoryCall(nme.Annotation, reifiedAnnRepr) } } diff --git a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala index 2965db17c6..52ddcb154b 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala @@ -13,7 +13,7 @@ trait GenSymbols { * Keeps track of auxiliary symbols that are necessary for this reification session. * These include: * 1) Free vars (terms, types and existentials), - * 2) Non-locatable symbols (sometimes, e.g. for RefinedTypes, we need to reify these; to do that we create their local copies in the reificode) + * 2) Non-locatable symbols (sometimes, e.g. for RefinedTypes, we need to reify these; to do that we create their copies in the reificode) * 3) Non-locatable symbols that are referred by #1, #2 and #3 * * Exposes three main methods: @@ -90,7 +90,7 @@ trait GenSymbols { mirrorBuildCall(nme.selectTerm, rowner, rname) } } else { - // todo. make sure that free methods and free local defs work correctly + // todo. make sure that free methods work correctly if (sym.isExistential) reifySymDef(sym) else if (sym.isTerm) reifyFreeTerm(Ident(sym)) else reifyFreeType(Ident(sym)) // TODO: reify refinement classes diff --git a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala index b082796757..743fe131c4 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala @@ -39,7 +39,7 @@ trait GenTrees { // // why bother? because this brings method to the madness // the first prototype of reification reified all types and symbols for all trees => this quickly became unyieldy - // the second prototype reified external types, but avoided reifying local ones => this created an ugly irregularity + // the second prototype reified external types, but avoided reifying ones local to the reifee => this created an ugly irregularity // current approach is uniform and compact var rtree: Tree = tree match { case FreeDef(_, _, _, _, _) => reifyNestedFreeDef(tree) @@ -102,7 +102,7 @@ trait GenTrees { if (reifyDebug) println("inlining the splicee") // all free vars local to the enclosing reifee should've already been inlined by `Metalevels` for (sym <- inlinedSymtab.syms if sym.isLocalToReifee) - abort("local free var, should have already been inlined by Metalevels: " + inlinedSymtab.symDef(sym)) + abort("free var local to the reifee, should have already been inlined by Metalevels: " + inlinedSymtab.symDef(sym)) state.symtab ++= inlinedSymtab rtree case tree => @@ -129,11 +129,11 @@ trait GenTrees { else if (sym.isClass && !sym.isModuleClass) { if (reifyDebug) println("This for %s, reified as freeVar".format(sym)) if (reifyDebug) println("Free: " + sym) - mirrorBuildCall(nme.Ident, reifyFreeTerm(This(sym))) + mirrorBuildCall(nme.mkIdent, reifyFreeTerm(This(sym))) } else { if (reifyDebug) println("This for %s, reified as This".format(sym)) - mirrorBuildCall(nme.This, reify(sym)) + mirrorBuildCall(nme.mkThis, reify(sym)) } case Ident(name) => @@ -146,15 +146,15 @@ trait GenTrees { else if (!sym.isLocalToReifee) { if (sym.isVariable && sym.owner.isTerm) { captureVariable(sym) // Note order dependency: captureVariable needs to come before reification here. - mirrorCall(nme.Select, mirrorBuildCall(nme.Ident, reify(sym)), reify(nme.elem)) + mirrorCall(nme.Select, mirrorBuildCall(nme.mkIdent, reify(sym)), reify(nme.elem)) } - else mirrorBuildCall(nme.Ident, reify(sym)) + else mirrorBuildCall(nme.mkIdent, reify(sym)) } else mirrorCall(nme.Ident, reify(name)) case Select(qual, name) => if (qual.symbol != null && qual.symbol.isPackage) { - mirrorBuildCall(nme.Ident, reify(sym)) + mirrorBuildCall(nme.mkIdent, reify(sym)) } else { val effectiveName = if (sym != null && sym != NoSymbol) sym.name else name reifyProduct(Select(qual, effectiveName)) @@ -173,7 +173,7 @@ trait GenTrees { assert(tpe != null, "unexpected: bound type that doesn't have a tpe: " + showRaw(tree)) // if a symbol or a type of the scrutinee are local to reifee - // (e.g. point to a locally declared class or to a path-dependent thingie that depends on a local variable) + // (e.g. point to a locally declared class or to a path-dependent thingie that depends on a variable defined within the reifee) // then we can reify the scrutinee as a symless AST and that will definitely be hygienic // why? because then typechecking of a scrutinee doesn't depend on the environment external to the quasiquote // otherwise we need to reify the corresponding type @@ -187,7 +187,7 @@ trait GenTrees { if (spliced == EmptyTree) { if (reifyDebug) println("splicing failed: reify as is") - mirrorBuildCall(nme.TypeTree, reify(tpe)) + mirrorBuildCall(nme.mkTypeTree, reify(tpe)) } else spliced match { case TypeRefToFreeType(freeType) => @@ -195,7 +195,7 @@ trait GenTrees { Ident(freeType) case _ => if (reifyDebug) println("splicing succeeded: " + spliced) - mirrorBuildCall(nme.TypeTree, spliced) + mirrorBuildCall(nme.mkTypeTree, spliced) } } else tree match { @@ -207,10 +207,10 @@ trait GenTrees { mirrorCall(nme.SelectFromTypeTree, reify(qual), reify(name)) case _ if sym.isLocatable => if (reifyDebug) println(s"tpe is locatable: reify as Ident($sym)") - mirrorBuildCall(nme.Ident, reify(sym)) + mirrorBuildCall(nme.mkIdent, reify(sym)) case _ => if (reifyDebug) println(s"tpe is not locatable: reify as TypeTree($tpe)") - mirrorBuildCall(nme.TypeTree, reify(tpe)) + mirrorBuildCall(nme.mkTypeTree, reify(tpe)) } } } diff --git a/src/compiler/scala/reflect/reify/codegen/GenTypes.scala b/src/compiler/scala/reflect/reify/codegen/GenTypes.scala index a90a3a338b..a6b69e239f 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenTypes.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenTypes.scala @@ -45,21 +45,21 @@ trait GenTypes { case tpe @ ThisType(clazz) if clazz.isModuleClass && clazz.isStatic => val module = reify(clazz.sourceModule) val moduleClass = Select(Select(module, nme.asModule), nme.moduleClass) - mirrorFactoryCall(nme.ThisType, moduleClass) - case tpe @ ThisType(_) => - reifyProduct(tpe) + mirrorBuildCall(nme.ThisType, moduleClass) + case tpe @ ThisType(sym) => + reifyBuildCall(nme.ThisType, sym) case tpe @ SuperType(thistpe, supertpe) => - reifyProduct(tpe) + reifyBuildCall(nme.SuperType, thistpe, supertpe) case tpe @ SingleType(pre, sym) => - reifyProduct(tpe) + reifyBuildCall(nme.SingleType, pre, sym) case tpe @ ConstantType(value) => - mirrorFactoryCall(nme.ConstantType, reifyProduct(value)) + mirrorBuildCall(nme.ConstantType, reifyProduct(value)) case tpe @ TypeRef(pre, sym, args) => - reifyProduct(tpe) + reifyBuildCall(nme.TypeRef, pre, sym, args) case tpe @ TypeBounds(lo, hi) => - reifyProduct(tpe) + reifyBuildCall(nme.TypeBounds, lo, hi) case tpe @ NullaryMethodType(restpe) => - reifyProduct(tpe) + reifyBuildCall(nme.NullaryMethodType, restpe) case tpe @ AnnotatedType(anns, underlying) => reifyAnnotatedType(tpe) case _ => @@ -119,7 +119,8 @@ trait GenTypes { // todo. write a test for this if (ReflectRuntimeUniverse == NoSymbol) CannotConvertManifestToTagWithoutScalaReflect(tpe, manifestInScope) val cm = typer.typed(Ident(ReflectRuntimeCurrentMirror)) - val tagTree = gen.mkMethodCall(ReflectRuntimeUniverse, nme.manifestToTypeTag, List(tpe), List(cm, manifestInScope)) + val internal = gen.mkAttributedSelect(gen.mkAttributedRef(ReflectRuntimeUniverse), UniverseInternal) + val tagTree = gen.mkMethodCall(Select(internal, nme.manifestToTypeTag), List(tpe), List(cm, manifestInScope)) Select(Apply(Select(tagTree, nme.in), List(Ident(nme.MIRROR_SHORT))), nme.tpe) case _ => EmptyTree @@ -157,13 +158,13 @@ trait GenTypes { */ private def reifySemiConcreteTypeMember(tpe: Type): Tree = tpe match { case tpe @ TypeRef(pre @ SingleType(prepre, presym), sym, args) if sym.isAbstractType && !sym.isExistential => - mirrorFactoryCall(nme.TypeRef, reify(pre), mirrorBuildCall(nme.selectType, reify(sym.owner), reify(sym.name.toString)), reify(args)) + mirrorBuildCall(nme.TypeRef, reify(pre), mirrorBuildCall(nme.selectType, reify(sym.owner), reify(sym.name.toString)), reify(args)) } /** Reify an annotated type, i.e. the one that makes us deal with AnnotationInfos */ private def reifyAnnotatedType(tpe: AnnotatedType): Tree = { val AnnotatedType(anns, underlying) = tpe - mirrorFactoryCall(nme.AnnotatedType, mkList(anns map reifyAnnotationInfo), reify(underlying)) + mirrorBuildCall(nme.AnnotatedType, mkList(anns map reifyAnnotationInfo), reify(underlying)) } /** Reify a tough type, i.e. the one that leads to creation of auxiliary symbols */ @@ -172,25 +173,25 @@ trait GenTypes { def reifyScope(scope: Scope): Tree = { scope foreach reifySymDef - mirrorCall(nme.newScopeWith, scope.toList map reify: _*) + mirrorBuildCall(nme.newScopeWith, scope.toList map reify: _*) } tpe match { case tpe @ RefinedType(parents, decls) => reifySymDef(tpe.typeSymbol) - mirrorFactoryCall(tpe, reify(parents), reifyScope(decls), reify(tpe.typeSymbol)) + mirrorBuildCall(nme.RefinedType, reify(parents), reifyScope(decls), reify(tpe.typeSymbol)) case tpe @ ExistentialType(tparams, underlying) => tparams foreach reifySymDef - mirrorFactoryCall(tpe, reify(tparams), reify(underlying)) + reifyBuildCall(nme.ExistentialType, tparams, underlying) case tpe @ ClassInfoType(parents, decls, clazz) => reifySymDef(clazz) - mirrorFactoryCall(tpe, reify(parents), reifyScope(decls), reify(tpe.typeSymbol)) + mirrorBuildCall(nme.ClassInfoType, reify(parents), reifyScope(decls), reify(tpe.typeSymbol)) case tpe @ MethodType(params, restpe) => params foreach reifySymDef - mirrorFactoryCall(tpe, reify(params), reify(restpe)) + reifyBuildCall(nme.MethodType, params, restpe) case tpe @ PolyType(tparams, underlying) => tparams foreach reifySymDef - mirrorFactoryCall(tpe, reify(tparams), reify(underlying)) + reifyBuildCall(nme.PolyType, tparams, underlying) case _ => throw new Error("internal error: %s (%s) is not supported".format(tpe, tpe.kind)) } diff --git a/src/compiler/scala/reflect/reify/codegen/GenUtils.scala b/src/compiler/scala/reflect/reify/codegen/GenUtils.scala index de9fec0df5..4512b2cb6f 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenUtils.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenUtils.scala @@ -5,6 +5,10 @@ trait GenUtils { self: Reifier => import global._ + import treeInfo._ + import definitions._ + private val runDefinitions = currentRun.runDefinitions + import runDefinitions._ def reifyList(xs: List[Any]): Tree = mkList(xs map reify) diff --git a/src/compiler/scala/reflect/reify/phases/Calculate.scala b/src/compiler/scala/reflect/reify/phases/Calculate.scala index abd179b24b..a0035d73d6 100644 --- a/src/compiler/scala/reflect/reify/phases/Calculate.scala +++ b/src/compiler/scala/reflect/reify/phases/Calculate.scala @@ -26,7 +26,7 @@ trait Calculate { } /** - * Merely traverses the reifiee and records local symbols along with their metalevels. + * Merely traverses the reifiee and records symbols local to the reifee along with their metalevels. */ val calculate = new Traverser { // see the explanation of metalevels in `Metalevels` diff --git a/src/compiler/scala/reflect/reify/utils/Extractors.scala b/src/compiler/scala/reflect/reify/utils/Extractors.scala index d052127956..4ec4de28c4 100644 --- a/src/compiler/scala/reflect/reify/utils/Extractors.scala +++ b/src/compiler/scala/reflect/reify/utils/Extractors.scala @@ -183,12 +183,12 @@ trait Extractors { tree match { case ValDef(_, name, _, Apply( - Select(Select(uref1 @ Ident(_), build1), freeTermFactory), + Select(Select(Select(uref1 @ Ident(_), internal1), rs1), freeTermFactory), _ :+ - ApplyCall(Select(Select(uref2 @ Ident(_), build2), flagsRepr), List(Literal(Constant(flags: Long)))) :+ + ApplyCall(Select(Select(Select(uref2 @ Ident(_), internal2), rs2), flagsRepr), List(Literal(Constant(flags: Long)))) :+ Literal(Constant(origin: String)))) - if uref1.name == nme.UNIVERSE_SHORT && build1 == nme.build && acceptFreeTermFactory(freeTermFactory) && - uref2.name == nme.UNIVERSE_SHORT && build2 == nme.build && flagsRepr == nme.FlagsRepr => + if uref1.name == nme.UNIVERSE_SHORT && internal1 == nme.internal && rs1 == nme.reificationSupport && acceptFreeTermFactory(freeTermFactory) && + uref2.name == nme.UNIVERSE_SHORT && internal2 == nme.internal && rs2 == nme.reificationSupport && flagsRepr == nme.FlagsRepr => Some((uref1, name, reifyBinding(tree), flags, origin)) case _ => None @@ -201,8 +201,8 @@ trait Extractors { object FreeRef { def unapply(tree: Tree): Option[(Tree, TermName)] = tree match { - case Apply(Select(Select(uref @ Ident(_), build), ident), List(Ident(name: TermName))) - if build == nme.build && ident == nme.Ident && name.startsWith(nme.REIFY_FREE_PREFIX) => + case Apply(Select(Select(Select(uref @ Ident(_), internal), rs), mkIdent), List(Ident(name: TermName))) + if internal == nme.internal && rs == nme.reificationSupport && mkIdent == nme.mkIdent && name.startsWith(nme.REIFY_FREE_PREFIX) => Some((uref, name)) case _ => None @@ -213,15 +213,15 @@ trait Extractors { def unapply(tree: Tree): Option[(Tree, TermName, Long, Boolean)] = tree match { case ValDef(_, name, _, Apply( - Select(Select(uref1 @ Ident(_), build1), newNestedSymbol), + Select(Select(Select(uref1 @ Ident(_), internal1), rs1), newNestedSymbol), List( _, _, _, - ApplyCall(Select(Select(uref2 @ Ident(_), build2), flagsRepr), List(Literal(Constant(flags: Long)))), + ApplyCall(Select(Select(Select(uref2 @ Ident(_), internal2), rs2), flagsRepr), List(Literal(Constant(flags: Long)))), Literal(Constant(isClass: Boolean))))) - if uref1.name == nme.UNIVERSE_SHORT && build1 == nme.build && newNestedSymbol == nme.newNestedSymbol && - uref2.name == nme.UNIVERSE_SHORT && build2 == nme.build && flagsRepr == nme.FlagsRepr => + if uref1.name == nme.UNIVERSE_SHORT && internal1 == nme.internal && rs1 == nme.reificationSupport && newNestedSymbol == nme.newNestedSymbol && + uref2.name == nme.UNIVERSE_SHORT && internal2 == nme.internal && rs2 == nme.reificationSupport && flagsRepr == nme.FlagsRepr => Some((uref1, name, flags, isClass)) case _ => None diff --git a/src/compiler/scala/reflect/reify/utils/NodePrinters.scala b/src/compiler/scala/reflect/reify/utils/NodePrinters.scala index e37b861461..3b91d28360 100644 --- a/src/compiler/scala/reflect/reify/utils/NodePrinters.scala +++ b/src/compiler/scala/reflect/reify/utils/NodePrinters.scala @@ -32,7 +32,7 @@ trait NodePrinters { s = "List\\[List\\[.*?\\].*?\\]".r.replaceAllIn(s, "List") s = "List\\[.*?\\]".r.replaceAllIn(s, "List") s = s.replace("immutable.this.Nil", "List()") - s = """build\.FlagsRepr\((\d+)[lL]\)""".r.replaceAllIn(s, m => { + s = """internal\.reificationSupport\.FlagsRepr\((\d+)[lL]\)""".r.replaceAllIn(s, m => { flagsAreUsed = true show(m.group(1).toLong) }) @@ -76,7 +76,6 @@ trait NodePrinters { if (mirrorIsUsed) printout += mirror.replace("Mirror[", "scala.reflect.api.Mirror[").trim val imports = scala.collection.mutable.ListBuffer[String]() imports += nme.UNIVERSE_SHORT.toString - // if (buildIsUsed) imports += nme.build if (mirrorIsUsed) imports += nme.MIRROR_SHORT.toString if (flagsAreUsed) imports += nme.Flag.toString printout += s"""import ${imports map (_ + "._") mkString ", "}""" diff --git a/src/compiler/scala/reflect/reify/utils/SymbolTables.scala b/src/compiler/scala/reflect/reify/utils/SymbolTables.scala index 5f8de9894f..b6ae3b8952 100644 --- a/src/compiler/scala/reflect/reify/utils/SymbolTables.scala +++ b/src/compiler/scala/reflect/reify/utils/SymbolTables.scala @@ -162,7 +162,7 @@ trait SymbolTables { else if (isFreeTerm) sym.tpe else sym.info } else NoType - val rset = reifier.mirrorBuildCall(nme.setTypeSignature, currtab.symRef(sym), reifier.reify(signature)) + val rset = reifier.mirrorBuildCall(nme.setInfo, currtab.symRef(sym), reifier.reify(signature)) // `Symbol.annotations` doesn't initialize the symbol, so we don't need to do anything special here // also since we call `sym.info` a few lines above, by now the symbol will be initialized (if possible) // so the annotations will be filled in and will be waiting to be reified (unless symbol initialization is prohibited as described above) diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 81e96b76ac..03b76ed99e 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -15,6 +15,7 @@ import scala.collection.{ mutable, immutable } import io.{ SourceReader, AbstractFile, Path } import reporters.{ Reporter, ConsoleReporter } import util.{ ClassPath, MergedClassPath, StatisticsInfo, returning, stackTraceString } +import scala.reflect.ClassTag import scala.reflect.internal.util.{ OffsetPosition, SourceFile, NoSourceFile, BatchSourceFile, ScriptSourceFile } import scala.reflect.internal.pickling.{ PickleBuffer, PickleFormat } import scala.reflect.io.VirtualFile @@ -33,6 +34,7 @@ import backend.jvm.GenASM import backend.opt.{ Inliners, InlineExceptionHandlers, ConstantOptimization, ClosureElimination, DeadCodeElimination } import backend.icode.analysis._ import scala.language.postfixOps +import scala.tools.nsc.ast.{TreeGen => AstTreeGen} class Global(var currentSettings: Settings, var reporter: Reporter) extends SymbolTable @@ -49,11 +51,15 @@ class Global(var currentSettings: Settings, var reporter: Reporter) override def isCompilerUniverse = true override val useOffsetPositions = !currentSettings.Yrangepos + type RuntimeClass = java.lang.Class[_] + implicit val RuntimeClassTag: ClassTag[RuntimeClass] = ClassTag[RuntimeClass](classOf[RuntimeClass]) + class GlobalMirror extends Roots(NoSymbol) { val universe: self.type = self def rootLoader: LazyType = new loaders.PackageLoader(classPath) override def toString = "compiler mirror" } + implicit val MirrorTag: ClassTag[Mirror] = ClassTag[Mirror](classOf[GlobalMirror]) lazy val rootMirror: Mirror = { val rm = new GlobalMirror @@ -100,13 +106,10 @@ class Global(var currentSettings: Settings, var reporter: Reporter) // sub-components -------------------------------------------------- - /** Generate ASTs */ - type TreeGen = scala.tools.nsc.ast.TreeGen - /** Tree generation, usually based on existing symbols. */ override object gen extends { val global: Global.this.type = Global.this - } with TreeGen { + } with AstTreeGen { def mkAttributedCast(tree: Tree, pt: Type): Tree = typer.typed(mkCast(tree, pt)) } @@ -1348,7 +1351,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) val toReload = mutable.Set[String]() for (sym <- root.info.decls) { if (sym.isInitialized && clearOnNextRun(sym)) - if (sym.isPackage) { + if (sym.hasPackageFlag) { resetProjectClasses(sym.moduleClass) openPackageModule(sym.moduleClass) } else { diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index a87a04472a..0575b9703e 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -142,7 +142,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { * x.asInstanceOf[`pt`]() if after uncurry but before erasure * x.$asInstanceOf[`pt`]() if at or after erasure */ - def mkCast(tree: Tree, pt: Type): Tree = { + override def mkCast(tree: Tree, pt: Type): Tree = { debuglog("casting " + tree + ":" + tree.tpe + " to " + pt + " at phase: " + phase) assert(!tree.tpe.isInstanceOf[MethodType], tree) assert(pt eq pt.normalize, tree +" : "+ debugString(pt) +" ~>"+ debugString(pt.normalize)) diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 7a7d4ac0b2..9ca06427e8 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -6,6 +6,7 @@ package scala.tools.nsc package ast +import scala.reflect.ClassTag import scala.reflect.internal.Flags.BYNAMEPARAM import scala.reflect.internal.Flags.DEFAULTPARAM import scala.reflect.internal.Flags.IMPLICIT @@ -102,6 +103,7 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => def InjectDerivedValue(tree: Tree, arg: Tree): InjectDerivedValue def TypeTreeWithDeferredRefCheck(tree: Tree): TypeTreeWithDeferredRefCheck } + implicit val TreeCopierTag: ClassTag[TreeCopier] = ClassTag[TreeCopier](classOf[TreeCopier]) def newStrictTreeCopier: TreeCopier = new StrictTreeCopier def newLazyTreeCopier: TreeCopier = new LazyTreeCopier @@ -192,8 +194,18 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => // // def resetAllAttrs(x: Tree, leaveAlone: Tree => Boolean = null): Tree = new ResetAttrs(localOnly = false, leaveAlone).transform(x) + // upd. Unfortunately this didn't work out quite as we expected. The last two users of resetAllAttrs: + // reification and typedLabelDef broke in very weird ways when we replaced resetAllAttrs with resetLocalAttrs + // (see SI-8316 change from resetAllAttrs to resetLocalAttrs in reifiers broke Slick and + // SI-8318 NPE in mixin in scala-continuations for more information). + // Given that we're supposed to release 2.11.0-RC1 in less than a week, I'm temporarily reinstating resetAllAttrs + // until we have time to better understand what's going on. In order to dissuade people from using it, + // it now comes with a new, ridiculous name. /** @see ResetAttrs */ - def resetAttrs(x: Tree, leaveAlone: Tree => Boolean = null): Tree = new ResetAttrs(leaveAlone).transform(x) + def brutallyResetAttrs(x: Tree, leaveAlone: Tree => Boolean = null): Tree = new ResetAttrs(brutally = true, leaveAlone).transform(x) + + /** @see ResetAttrs */ + def resetAttrs(x: Tree): Tree = new ResetAttrs(brutally = false, leaveAlone = null).transform(x) /** A transformer which resets symbol and tpe fields of all nodes in a given tree, * with special treatment of: @@ -204,7 +216,7 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => * * (bq:) This transformer has mutable state and should be discarded after use */ - private class ResetAttrs(leaveAlone: Tree => Boolean = null) { + private class ResetAttrs(brutally: Boolean, leaveAlone: Tree => Boolean) { // this used to be based on -Ydebug, but the need for logging in this code is so situational // that I've reverted to a hard-coded constant here. val debug = false @@ -297,7 +309,7 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => // if we move these trees into lexical contexts different from their original locations. if (dupl.hasSymbol) { val sym = dupl.symbol - val vetoScope = !(locals contains sym) + val vetoScope = !brutally && !(locals contains sym) val vetoThis = dupl.isInstanceOf[This] && sym.isPackageClass if (!(vetoScope || vetoThis)) dupl.symbol = NoSymbol } diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 8271363527..3542fe5945 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -2231,7 +2231,7 @@ self => } else { // XX-METHOD-INFER accept(COLON) if (in.token == ARROW) { - if (owner.isTypeName && !mods.hasLocalFlag) + if (owner.isTypeName && !mods.isLocalToThis) syntaxError( in.offset, (if (mods.isMutable) "`var'" else "`val'") + diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index b650cdfa09..81fbbfcabf 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -869,7 +869,7 @@ abstract class GenICode extends SubComponent { case Ident(name) => def genLoadIdent = { val sym = tree.symbol - if (!sym.isPackage) { + if (!sym.hasPackageFlag) { if (sym.isModule) { genLoadModule(ctx, tree) generatedType = toTypeKind(sym.info) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala index c8845344e9..53142fbd87 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala @@ -350,7 +350,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { case Ident(name) => val sym = tree.symbol - if (!sym.isPackage) { + if (!sym.hasPackageFlag) { val tk = symInfoTK(sym) if (sym.isModule) { genLoadModule(tree) } else { locals.load(sym) } diff --git a/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala b/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala index 64a0727440..1fadcb8920 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala @@ -492,7 +492,10 @@ abstract class ConstantOptimization extends SubComponent { case SWITCH(tags, labels) => val in1 = in peek 0 val reachableNormalLabels = tags zip labels collect { case (tagSet, label) if canSwitch(in1, tagSet) => label } - val reachableLabels = if (labels.lengthCompare(tags.length) > 0) { + val reachableLabels = if (tags.isEmpty) { + assert(labels.size == 1, s"When SWITCH node has empty array of tags it should have just one (default) label: $labels") + labels + } else if (labels.lengthCompare(tags.length) > 0) { // if we've got an extra label then it's the default val defaultLabel = labels.last // see if the default is reachable by seeing if the input might be out of the set diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 2f9cc01c0b..ea600bc586 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -561,14 +561,14 @@ abstract class ClassfileParser { // if this is a non-static inner class, remove the explicit outer parameter val paramsNoOuter = innerClasses getEntry currentClass match { case Some(entry) if !isScalaRaw && !entry.jflags.isStatic => - /* About `clazz.owner.isPackage` below: SI-5957 + /* About `clazz.owner.hasPackageFlag` below: SI-5957 * For every nested java class A$B, there are two symbols in the scala compiler. * 1. created by SymbolLoader, because of the existence of the A$B.class file, owner: package * 2. created by ClassfileParser of A when reading the inner classes, owner: A * If symbol 1 gets completed (e.g. because the compiled source mentions `A$B`, not `A#B`), the * ClassfileParser for 1 executes, and clazz.owner is the package. */ - assert(params.head.tpe.typeSymbol == clazz.owner || clazz.owner.isPackage, params.head.tpe.typeSymbol + ": " + clazz.owner) + assert(params.head.tpe.typeSymbol == clazz.owner || clazz.owner.hasPackageFlag, params.head.tpe.typeSymbol + ": " + clazz.owner) params.tail case _ => params diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala index 55f45257dc..592c5497b5 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala @@ -99,7 +99,7 @@ abstract class Pickler extends SubComponent { * added to fix that bug, but there may be a better way. */ private def localizedOwner(sym: Symbol) = - if (isLocal(sym) && !isRootSym(sym) && !isLocal(sym.owner)) + if (isLocalToPickle(sym) && !isRootSym(sym) && !isLocalToPickle(sym.owner)) // don't use a class as the localized owner for type parameters that are not owned by a class: those are not instantiated by asSeenFrom // however, they would suddenly be considered by asSeenFrom if their localized owner became a class (causing the crashes of #4079, #2741) (if ((sym.isTypeParameter || sym.isValueParameter) && !sym.owner.isClass) nonClassRoot @@ -110,14 +110,14 @@ abstract class Pickler extends SubComponent { * anyway? This is the case if symbol is a refinement class, * an existentially bound variable, or a higher-order type parameter. */ - private def isLocal(sym: Symbol): Boolean = (sym != NoSymbol) && !sym.isPackageClass && ( + private def isLocalToPickle(sym: Symbol): Boolean = (sym != NoSymbol) && !sym.isPackageClass && ( isRootSym(sym) || sym.isRefinementClass || sym.isAbstractType && sym.hasFlag(EXISTENTIAL) // existential param || sym.isParameter - || isLocal(sym.owner) + || isLocalToPickle(sym.owner) ) - private def isExternalSymbol(sym: Symbol): Boolean = (sym != NoSymbol) && !isLocal(sym) + private def isExternalSymbol(sym: Symbol): Boolean = (sym != NoSymbol) && !isLocalToPickle(sym) // Phase 1 methods: Populate entries/index ------------------------------------ @@ -174,7 +174,7 @@ abstract class Pickler extends SubComponent { val sym = deskolemize(sym0) if (putEntry(sym)) { - if (isLocal(sym)) { + if (isLocalToPickle(sym)) { putEntry(sym.name) putSymbol(sym.owner) putSymbol(sym.privateWithin) @@ -428,7 +428,7 @@ abstract class Pickler extends SubComponent { } def writeSymbolBody(sym: Symbol) { if (sym ne NoSymbol) { - if (isLocal(sym)) + if (isLocalToPickle(sym)) writeLocalSymbolBody(sym) else writeExtSymbolBody(sym) diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala index d81a5d5755..1468680fe0 100644 --- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala +++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala @@ -130,7 +130,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre if (!thisProxy.exists) { target setFlag STATIC } - val params = ((optionSymbol(thisProxy) map {proxy:Symbol => ValDef(proxy)}) ++ (target.paramss.flatten map ValDef)).toList + val params = ((optionSymbol(thisProxy) map {proxy:Symbol => ValDef(proxy)}) ++ (target.paramss.flatten map ValDef.apply)).toList val methSym = oldClass.newMethod(unit.freshTermName(nme.accessor.toString()), target.pos, FINAL | BRIDGE | SYNTHETIC | PROTECTED | STATIC) @@ -393,7 +393,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre declared += tree.symbol case Ident(_) => val sym = tree.symbol - if ((sym != NoSymbol) && sym.isLocal && sym.isTerm && !sym.isMethod && !declared.contains(sym)) freeVars += sym + if ((sym != NoSymbol) && sym.isLocalToBlock && sym.isTerm && !sym.isMethod && !declared.contains(sym)) freeVars += sym case _ => } super.traverse(tree) diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 4db74e70f2..bd2f6f0018 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -600,7 +600,7 @@ abstract class Erasure extends AddInterfaces if (tree.symbol == NoSymbol) { tree } else if (name == nme.CONSTRUCTOR) { - if (tree.symbol.owner == AnyValClass) tree.symbol = ObjectClass.primaryConstructor + if (tree.symbol.owner == AnyValClass) tree.symbol = ObjectClass.info.decl(nme.CONSTRUCTOR) tree } else if (tree.symbol == Any_asInstanceOf) adaptMember(atPos(tree.pos)(Select(qual, Object_asInstanceOf))) @@ -740,7 +740,7 @@ abstract class Erasure extends AddInterfaces /** TODO - adapt SymbolPairs so it can be used here. */ private def checkNoDeclaredDoubleDefs(base: Symbol) { val decls = base.info.decls - + // SI-8010 force infos, otherwise makeNotPrivate in ExplicitOuter info transformer can trigger // a scope rehash while were iterating and we can see the same entry twice! // Inspection of SymbolPairs (the basis of OverridingPairs), suggests that it is immune @@ -751,13 +751,13 @@ abstract class Erasure extends AddInterfaces // we do these checks, so that we're comparing same-named methods based on the expanded names that actually // end up in the bytecode. exitingPostErasure(decls.foreach(_.info)) - + var e = decls.elems while (e ne null) { if (e.sym.isTerm) { var e1 = decls lookupNextEntry e while (e1 ne null) { - assert(e.sym ne e1.sym, s"Internal error: encountered ${e.sym.debugLocationString} twice during scope traversal. This might be related to SI-8010.") + assert(e.sym ne e1.sym, s"Internal error: encountered ${e.sym.debugLocationString} twice during scope traversal. This might be related to SI-8010.") if (sameTypeAfterErasure(e.sym, e1.sym)) doubleDefError(new SymbolPair(base, e.sym, e1.sym)) diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index b2e071579e..0447e23e9e 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -206,7 +206,7 @@ abstract class ExplicitOuter extends InfoTransform // On the other hand, mixing in the trait into a separately compiled // class needs to have a common naming scheme, independently of whether // the field was accessed from an inner class or not. See #2946 - if (sym.owner.isTrait && sym.hasLocalFlag && + if (sym.owner.isTrait && sym.isLocalToThis && (sym.getter(sym.owner.toInterface) == NoSymbol)) sym.makeNotPrivate(sym.owner) tp diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala index acef2a50d8..e38c034f4d 100644 --- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala +++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala @@ -122,7 +122,7 @@ abstract class LambdaLift extends InfoTransform { * and the owner of `sym`. * Return `true` if there is no class between `enclosure` and * the owner of sym. - * pre: sym.isLocal, (enclosure.isMethod || enclosure.isClass) + * pre: sym.isLocalToBlock, (enclosure.isMethod || enclosure.isClass) * * The idea of `markFree` is illustrated with an example: * @@ -180,7 +180,7 @@ abstract class LambdaLift extends InfoTransform { tree match { case ClassDef(_, _, _, _) => liftedDefs(tree.symbol) = Nil - if (sym.isLocal) { + if (sym.isLocalToBlock) { // Don't rename implementation classes independently of their interfaces. If // the interface is to be renamed, then we will rename the implementation // class at that time. You'd think we could call ".implClass" on the trait @@ -201,7 +201,7 @@ abstract class LambdaLift extends InfoTransform { } } case DefDef(_, _, _, _, _, _) => - if (sym.isLocal) { + if (sym.isLocalToBlock) { renamable += sym sym setFlag (PrivateLocal | FINAL) } else if (sym.isPrimaryConstructor) { @@ -210,14 +210,14 @@ abstract class LambdaLift extends InfoTransform { case Ident(name) => if (sym == NoSymbol) { assert(name == nme.WILDCARD) - } else if (sym.isLocal) { + } else if (sym.isLocalToBlock) { val owner = currentOwner.logicallyEnclosingMember if (sym.isTerm && !sym.isMethod) markFree(sym, owner) else if (sym.isMethod) markCalled(sym, owner) //symSet(called, owner) += sym } case Select(_, _) => - if (sym.isConstructor && sym.owner.isLocal) + if (sym.isConstructor && sym.owner.isLocalToBlock) markCalled(sym, currentOwner.logicallyEnclosingMember) case _ => } @@ -362,7 +362,7 @@ abstract class LambdaLift extends InfoTransform { private def proxyRef(sym: Symbol) = { val psym = proxy(sym) - if (psym.isLocal) gen.mkAttributedIdent(psym) else memberRef(psym) + if (psym.isLocalToBlock) gen.mkAttributedIdent(psym) else memberRef(psym) } private def addFreeArgs(pos: Position, sym: Symbol, args: List[Tree]) = { @@ -459,10 +459,10 @@ abstract class LambdaLift extends InfoTransform { tree match { case ClassDef(_, _, _, _) => val tree1 = addFreeParams(tree, sym) - if (sym.isLocal) liftDef(tree1) else tree1 + if (sym.isLocalToBlock) liftDef(tree1) else tree1 case DefDef(_, _, _, _, _, _) => val tree1 = addFreeParams(tree, sym) - if (sym.isLocal) liftDef(tree1) else tree1 + if (sym.isLocalToBlock) liftDef(tree1) else tree1 case ValDef(mods, name, tpt, rhs) => if (sym.isCapturedVariable) { val tpt1 = TypeTree(sym.tpe) setPos tpt.pos @@ -499,7 +499,7 @@ abstract class LambdaLift extends InfoTransform { if (sym.isTerm && !sym.isLabel) if (sym.isMethod) atPos(tree.pos)(memberRef(sym)) - else if (sym.isLocal && !isSameOwnerEnclosure(sym)) + else if (sym.isLocalToBlock && !isSameOwnerEnclosure(sym)) atPos(tree.pos)(proxyRef(sym)) else tree else tree diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index c59b726076..02e55241b3 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -716,7 +716,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { enterMember(specVal) // create accessors - // debuglog("m: " + m + " isLocal: " + nme.isLocalName(m.name) + " specVal: " + specVal.name + " isLocal: " + nme.isLocalName(specVal.name)) if (nme.isLocalName(m.name)) { val specGetter = mkAccessor(specVal, specVal.getterName) setInfo MethodType(Nil, specVal.info) @@ -1653,7 +1652,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { case SpecialOverload(original, env) => debuglog("completing specialized " + symbol.fullName + " calling " + original) debuglog("special overload " + original + " -> " + env) - val t = DefDef(symbol, { vparamss => + val t = DefDef(symbol, { vparamss: List[List[Symbol]] => val fun = Apply(Select(This(symbol.owner), original), makeArguments(original, vparamss.head)) @@ -1751,7 +1750,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { // flag. nobody has to see this anyway :) sym.setFlag(SPECIALIZED) // create empty bodies for specializations - localTyper.typed(Block(norm.tail.map(sym => DefDef(sym, { vparamss => EmptyTree })), ddef)) + localTyper.typed(Block(norm.tail.map(sym => DefDef(sym, { vparamss: List[List[Symbol]] => EmptyTree })), ddef)) } else tree case _ => @@ -1816,7 +1815,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { val newBody = symSubstituter(body(source).duplicate) tpt modifyType (_.substSym(oldtparams, newtparams)) - copyDefDef(tree)(vparamss = List(newSyms map ValDef), rhs = newBody) + copyDefDef(tree)(vparamss = List(newSyms map ValDef.apply), rhs = newBody) } /** Create trees for specialized members of 'sClass', based on the @@ -1853,9 +1852,9 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } // ctor - mbrs += DefDef(m, Modifiers(m.flags), mmap(List(vparams))(ValDef), EmptyTree) + mbrs += DefDef(m, Modifiers(m.flags), mmap(List(vparams))(ValDef.apply), EmptyTree) } else { - mbrs += DefDef(m, { paramss => EmptyTree }) + mbrs += DefDef(m, { paramss: List[List[Symbol]] => EmptyTree }) } } else if (m.isValue) { mbrs += ValDef(m).setType(NoType) diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index e7ea686bc8..8a7d30235f 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -412,7 +412,7 @@ abstract class UnCurry extends InfoTransform val sym = tree.symbol // true if the taget is a lambda body that's been lifted into a method - def isLiftedLambdaBody(target: Tree) = target.symbol.isLocal && target.symbol.isArtifact && target.symbol.name.containsName(nme.ANON_FUN_NAME) + def isLiftedLambdaBody(target: Tree) = target.symbol.isLocalToBlock && target.symbol.isArtifact && target.symbol.name.containsName(nme.ANON_FUN_NAME) val result = ( // TODO - settings.noassertions.value temporarily retained to avoid diff --git a/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala b/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala index 7858cb5586..d10eff1d8d 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala @@ -139,8 +139,8 @@ trait ScalacPatternExpanders { def acceptMessage = if (extractor.isErroneous) "" else s" to hold ${extractor.offeringString}" val requiresTupling = isUnapply && patterns.totalArity == 1 && productArity > 1 - if (settings.lint && requiresTupling && effectivePatternArity(args) == 1) - currentUnit.warning(sel.pos, s"${sel.symbol.owner} expects $productArity patterns$acceptMessage but crushing into $productArity-tuple to fit single pattern (SI-6675)") + if (requiresTupling && effectivePatternArity(args) == 1) + currentUnit.deprecationWarning(sel.pos, s"${sel.symbol.owner} expects $productArity patterns$acceptMessage but crushing into $productArity-tuple to fit single pattern (SI-6675)") val normalizedExtractor = if (requiresTupling) tupleExtractor(extractor) else extractor validateAligned(fn, Aligned(patterns, normalizedExtractor)) diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 974c0842d3..98ee4ad94d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -516,7 +516,7 @@ trait Contexts { self: Analyzer => argContext.scope enter e.sym } } - if (c.isLocal && !c.owner.isLocalDummy) { + if (c.owner.isTerm && !c.owner.isLocalDummy) { enterElems(c.outer) enterLocalElems(c.scope.elems) } @@ -589,9 +589,6 @@ trait Contexts { self: Analyzer => else if (bufferErrors) reportBuffer += (pos -> msg) } - /** Is the owning symbol of this context a term? */ - final def isLocal: Boolean = owner.isTerm - // nextOuter determines which context is searched next for implicits // (after `this`, which contributes `newImplicits` below.) In // most cases, it is simply the outer context: if we're owned by @@ -714,7 +711,7 @@ trait Contexts { self: Analyzer => ( (ab.isTerm || ab == rootMirror.RootClass) || (accessWithin(ab) || accessWithinLinked(ab)) && - ( !sym.hasLocalFlag + ( !sym.isLocalToThis || sym.owner.isImplClass // allow private local accesses to impl classes || sym.isProtected && isSubThisType(pre, sym.owner) || pre =:= sym.owner.thisType @@ -980,7 +977,7 @@ trait Contexts { self: Analyzer => // 2) sym.owner is inherited by the correct package object class // We try to establish 1) by inspecting the owners directly, and then we try // to rule out 2), and only if both those fail do we resort to looking in the info. - !sym.isPackage && sym.owner.exists && ( + !sym.hasPackageFlag && sym.owner.exists && ( if (sym.owner.isPackageObjectClass) sym.owner.owner == pkgClass else diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 8f5778862d..2bb874a8aa 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -402,8 +402,8 @@ trait Implicits { } def complexity(tp: Type): Int = tp.dealias match { case NoPrefix => 0 - case SingleType(pre, sym) => if (sym.isPackage) 0 else complexity(tp.dealiasWiden) - case ThisType(sym) => if (sym.isPackage) 0 else 1 + case SingleType(pre, sym) => if (sym.hasPackageFlag) 0 else complexity(tp.dealiasWiden) + case ThisType(sym) => if (sym.hasPackageFlag) 0 else 1 case TypeRef(pre, sym, args) => complexity(pre) + (args map complexity).sum + 1 case RefinedType(parents, _) => (parents map complexity).sum + 1 case _ => 1 @@ -425,11 +425,11 @@ trait Implicits { * expected type. * Detect infinite search trees for implicits. * - * @param info The given implicit info describing the implicit definition - * @param isLocal Is the implicit in the local scope of the call site? - * @pre `info.tpe` does not contain an error + * @param info The given implicit info describing the implicit definition + * @param isLocalToCallsite Is the implicit in the local scope of the call site? + * @pre `info.tpe` does not contain an error */ - private def typedImplicit(info: ImplicitInfo, ptChecked: Boolean, isLocal: Boolean): SearchResult = { + private def typedImplicit(info: ImplicitInfo, ptChecked: Boolean, isLocalToCallsite: Boolean): SearchResult = { // SI-7167 let implicit macros decide what amounts for a divergent implicit search // imagine a macro writer which wants to synthesize a complex implicit Complex[T] by making recursive calls to Complex[U] for its parts // e.g. we have `class Foo(val bar: Bar)` and `class Bar(val x: Int)` @@ -450,7 +450,7 @@ trait Implicits { try { context.openImplicits = OpenImplicit(info, pt, tree) :: context.openImplicits // println(" "*context.openImplicits.length+"typed implicit "+info+" for "+pt) //@MDEBUG - val result = typedImplicit0(info, ptChecked, isLocal) + val result = typedImplicit0(info, ptChecked, isLocalToCallsite) if (result.isDivergent) { //println("DivergentImplicit for pt:"+ pt +", open implicits:"+context.openImplicits) //@MDEBUG if (context.openImplicits.tail.isEmpty && !pt.isErroneous) @@ -574,24 +574,24 @@ trait Implicits { case _ => false } - private def typedImplicit0(info: ImplicitInfo, ptChecked: Boolean, isLocal: Boolean): SearchResult = { + private def typedImplicit0(info: ImplicitInfo, ptChecked: Boolean, isLocalToCallsite: Boolean): SearchResult = { if (Statistics.canEnable) Statistics.incCounter(plausiblyCompatibleImplicits) val ok = ptChecked || matchesPt(info) && { - def word = if (isLocal) "local " else "" + def word = if (isLocalToCallsite) "local " else "" typingLog("match", s"$word$info") true } - if (ok) typedImplicit1(info, isLocal) else SearchFailure + if (ok) typedImplicit1(info, isLocalToCallsite) else SearchFailure } - private def typedImplicit1(info: ImplicitInfo, isLocal: Boolean): SearchResult = { + private def typedImplicit1(info: ImplicitInfo, isLocalToCallsite: Boolean): SearchResult = { if (Statistics.canEnable) Statistics.incCounter(matchingImplicits) // workaround for deficient context provided by ModelFactoryImplicitSupport#makeImplicitConstraints val isScalaDoc = context.tree == EmptyTree val itree0 = atPos(pos.focus) { - if (isLocal && !isScalaDoc) { + if (isLocalToCallsite && !isScalaDoc) { // SI-4270 SI-5376 Always use an unattributed Ident for implicits in the local scope, // rather than an attributed Select, to detect shadowing. Ident(info.name) @@ -661,7 +661,7 @@ trait Implicits { fail("hasMatchingSymbol reported error: " + context.firstError.get.errMsg) else if (itree3.isErroneous) fail("error typechecking implicit candidate") - else if (isLocal && !hasMatchingSymbol(itree2)) + else if (isLocalToCallsite && !hasMatchingSymbol(itree2)) fail("candidate implicit %s is shadowed by %s".format( info.sym.fullLocationString, itree2.symbol.fullLocationString)) else { @@ -776,12 +776,12 @@ trait Implicits { /** Prune ImplicitInfos down to either all the eligible ones or the best one. * - * @param iss list of list of infos - * @param isLocal if true, `iss` represents in-scope implicits, which must respect the normal rules of - * shadowing. The head of the list `iss` must represent implicits from the closest - * enclosing scope, and so on. + * @param iss list of list of infos + * @param isLocalToCallsite if true, `iss` represents in-scope implicits, which must respect the normal rules of + * shadowing. The head of the list `iss` must represent implicits from the closest + * enclosing scope, and so on. */ - class ImplicitComputation(iss: Infoss, isLocal: Boolean) { + class ImplicitComputation(iss: Infoss, isLocalToCallsite: Boolean) { abstract class Shadower { def addInfos(infos: Infos) def isShadowed(name: Name): Boolean @@ -800,7 +800,7 @@ trait Implicits { def addInfos(infos: Infos) {} def isShadowed(name: Name) = false } - if (isLocal) new LocalShadower else NoShadower + if (isLocalToCallsite) new LocalShadower else NoShadower } private var best: SearchResult = SearchFailure @@ -870,7 +870,7 @@ trait Implicits { @tailrec private def rankImplicits(pending: Infos, acc: Infos): Infos = pending match { case Nil => acc case i :: is => - DivergentImplicitRecovery(typedImplicit(i, ptChecked = true, isLocal), i) match { + DivergentImplicitRecovery(typedImplicit(i, ptChecked = true, isLocalToCallsite), i) match { case sr if sr.isDivergent => Nil case sr if sr.isFailure => @@ -898,7 +898,7 @@ trait Implicits { /** Returns all eligible ImplicitInfos and their SearchResults in a map. */ - def findAll() = mapFrom(eligible)(typedImplicit(_, ptChecked = false, isLocal)) + def findAll() = mapFrom(eligible)(typedImplicit(_, ptChecked = false, isLocalToCallsite)) /** Returns the SearchResult of the best match. */ @@ -940,15 +940,15 @@ trait Implicits { /** Computes from a list of lists of implicit infos a map which takes * infos which are applicable for given expected type `pt` to their attributed trees. * - * @param iss The given list of lists of implicit infos - * @param isLocal Is implicit definition visible without prefix? - * If this is the case then symbols in preceding lists shadow - * symbols of the same name in succeeding lists. - * @return map from infos to search results + * @param iss The given list of lists of implicit infos + * @param isLocalToCallsite Is implicit definition visible without prefix? + * If this is the case then symbols in preceding lists shadow + * symbols of the same name in succeeding lists. + * @return map from infos to search results */ - def applicableInfos(iss: Infoss, isLocal: Boolean): Map[ImplicitInfo, SearchResult] = { + def applicableInfos(iss: Infoss, isLocalToCallsite: Boolean): Map[ImplicitInfo, SearchResult] = { val start = if (Statistics.canEnable) Statistics.startCounter(subtypeAppInfos) else null - val computation = new ImplicitComputation(iss, isLocal) { } + val computation = new ImplicitComputation(iss, isLocalToCallsite) { } val applicable = computation.findAll() if (Statistics.canEnable) Statistics.stopCounter(subtypeAppInfos, start) @@ -959,14 +959,14 @@ trait Implicits { * If found return a search result with a tree from found implicit info * which is typed with expected type `pt`. Otherwise return SearchFailure. * - * @param implicitInfoss The given list of lists of implicit infos - * @param isLocal Is implicit definition visible without prefix? - * If this is the case then symbols in preceding lists shadow - * symbols of the same name in succeeding lists. + * @param implicitInfoss The given list of lists of implicit infos + * @param isLocalToCallsite Is implicit definition visible without prefix? + * If this is the case then symbols in preceding lists shadow + * symbols of the same name in succeeding lists. */ - def searchImplicit(implicitInfoss: Infoss, isLocal: Boolean): SearchResult = + def searchImplicit(implicitInfoss: Infoss, isLocalToCallsite: Boolean): SearchResult = if (implicitInfoss.forall(_.isEmpty)) SearchFailure - else new ImplicitComputation(implicitInfoss, isLocal) findBest() + else new ImplicitComputation(implicitInfoss, isLocalToCallsite) findBest() /** Produce an implicict info map, i.e. a map from the class symbols C of all parts of this type to * the implicit infos in the companion objects of these class symbols C. @@ -1271,7 +1271,8 @@ trait Implicits { return SearchFailure } val cm = typed(Ident(ReflectRuntimeCurrentMirror)) - val interop = gen.mkMethodCall(ReflectRuntimeUniverse, nme.typeTagToManifest, List(tp), List(cm, tagInScope)) + val internal = gen.mkAttributedSelect(gen.mkAttributedRef(ReflectRuntimeUniverse), UniverseInternal) + val interop = gen.mkMethodCall(Select(internal, nme.typeTagToManifest), List(tp), List(cm, tagInScope)) wrapResult(interop) } } else { @@ -1326,7 +1327,7 @@ trait Implicits { val failstart = if (Statistics.canEnable) Statistics.startTimer(inscopeFailNanos) else null val succstart = if (Statistics.canEnable) Statistics.startTimer(inscopeSucceedNanos) else null - var result = searchImplicit(context.implicitss, isLocal = true) + var result = searchImplicit(context.implicitss, isLocalToCallsite = true) if (result.isFailure) { if (Statistics.canEnable) Statistics.stopTimer(inscopeFailNanos, failstart) @@ -1344,7 +1345,7 @@ trait Implicits { // `materializeImplicit` does some preprocessing for `pt` // is it only meant for manifests/tags or we need to do the same for `implicitsOfExpectedType`? if (result.isFailure && !wasAmbigious) - result = searchImplicit(implicitsOfExpectedType, isLocal = false) + result = searchImplicit(implicitsOfExpectedType, isLocalToCallsite = false) if (result.isFailure) { context.updateBuffer(previousErrs) @@ -1383,8 +1384,11 @@ trait Implicits { } def allImplicits: List[SearchResult] = { - def search(iss: Infoss, isLocal: Boolean) = applicableInfos(iss, isLocal).values - (search(context.implicitss, isLocal = true) ++ search(implicitsOfExpectedType, isLocal = false)).toList.filter(_.tree ne EmptyTree) + def search(iss: Infoss, isLocalToCallsite: Boolean) = applicableInfos(iss, isLocalToCallsite).values + ( + search(context.implicitss, isLocalToCallsite = true) ++ + search(implicitsOfExpectedType, isLocalToCallsite = false) + ).toList.filter(_.tree ne EmptyTree) } // find all implicits for some type that contains type variables @@ -1392,8 +1396,8 @@ trait Implicits { def allImplicitsPoly(tvars: List[TypeVar]): List[(SearchResult, List[TypeConstraint])] = { def resetTVars() = tvars foreach { _.constr = new TypeConstraint } - def eligibleInfos(iss: Infoss, isLocal: Boolean) = { - val eligible = new ImplicitComputation(iss, isLocal).eligible + def eligibleInfos(iss: Infoss, isLocalToCallsite: Boolean) = { + val eligible = new ImplicitComputation(iss, isLocalToCallsite).eligible eligible.toList.flatMap { (ii: ImplicitInfo) => // each ImplicitInfo contributes a distinct set of constraints (generated indirectly by typedImplicit) @@ -1402,12 +1406,13 @@ trait Implicits { // any previous errors should not affect us now context.flushBuffer() - val res = typedImplicit(ii, ptChecked = false, isLocal) + val res = typedImplicit(ii, ptChecked = false, isLocalToCallsite) if (res.tree ne EmptyTree) List((res, tvars map (_.constr))) else Nil } } - eligibleInfos(context.implicitss, isLocal = true) ++ eligibleInfos(implicitsOfExpectedType, isLocal = false) + eligibleInfos(context.implicitss, isLocalToCallsite = true) ++ + eligibleInfos(implicitsOfExpectedType, isLocalToCallsite = false) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 9b5b0e1f37..23dc57d5b9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -374,7 +374,7 @@ trait Namers extends MethodSynthesis { } val existing = pkgOwner.info.decls.lookup(pid.name) - if (existing.isPackage && pkgOwner == existing.owner) + if (existing.hasPackageFlag && pkgOwner == existing.owner) existing else { val pkg = pkgOwner.newPackage(pid.name.toTermName, pos) diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 916b8a3e0c..b166bf988d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -908,7 +908,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans var index = -1 for (stat <- stats) { index = index + 1 - def enterSym(sym: Symbol) = if (sym.isLocal) { + def enterSym(sym: Symbol) = if (sym.isLocalToBlock) { currentLevel.scope.enter(sym) symIndex(sym) = index } @@ -925,7 +925,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans } private def enterReference(pos: Position, sym: Symbol) { - if (sym.isLocal) { + if (sym.isLocalToBlock) { val e = currentLevel.scope.lookupEntry(sym.name) if ((e ne null) && sym == e.sym) { var l = currentLevel @@ -1230,7 +1230,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans if (tree1.symbol.isLazy) tree1 :: Nil else { val lazySym = tree.symbol.lazyAccessorOrSelf - if (lazySym.isLocal && index <= currentLevel.maxindex) { + if (lazySym.isLocalToBlock && index <= currentLevel.maxindex) { debuglog("refsym = " + currentLevel.refsym) unit.error(currentLevel.refpos, "forward reference extends over definition of " + lazySym) } @@ -1549,7 +1549,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans if (!sym.exists) devWarning("Select node has NoSymbol! " + tree + " / " + tree.tpe) - else if (sym.hasLocalFlag) + else if (sym.isLocalToThis) varianceValidator.checkForEscape(sym, currentClass) def checkSuper(mix: Name) = @@ -1758,7 +1758,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans result match { case ClassDef(_, _, _, _) | TypeDef(_, _, _, _) => - if (result.symbol.isLocal || result.symbol.isTopLevel) + if (result.symbol.isLocalToBlock || result.symbol.isTopLevel) varianceValidator.traverse(result) case tt @ TypeTree() if tt.original != null => varianceValidator.traverse(tt.original) // See SI-7872 diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index 06796eca8e..87da565142 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -71,7 +71,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT acc setInfoAndEnter (tpe cloneInfo acc) // Diagnostic for SI-7091 if (!accDefs.contains(clazz)) - reporter.error(sel.pos, s"Internal error: unable to store accessor definition in ${clazz}. clazz.isPackage=${clazz.isPackage}. Accessor required for ${sel} (${showRaw(sel)})") + reporter.error(sel.pos, s"Internal error: unable to store accessor definition in ${clazz}. clazz.hasPackageFlag=${clazz.hasPackageFlag}. Accessor required for ${sel} (${showRaw(sel)})") else storeAccessorDefinition(clazz, DefDef(acc, EmptyTree)) acc } @@ -224,7 +224,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT if (settings.lint) { if (sym.isPrivateLocal && sym.paramss.isEmpty) { qual.symbol.ancestors foreach { parent => - parent.info.decls filterNot (x => x.isPrivate || x.hasLocalFlag) foreach { m2 => + parent.info.decls filterNot (x => x.isPrivate || x.isLocalToThis) foreach { m2 => if (sym.name == m2.name && m2.isGetter && m2.accessed.isMutable) { unit.warning(sel.pos, sym.accessString + " " + sym.fullLocationString + " shadows mutable " + m2.name diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala index fd8f9bebba..a2f52e1905 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala @@ -376,7 +376,7 @@ abstract class TreeCheckers extends Analyzer { def isOk(sym: Symbol) = treeSym hasTransOwner sym.enclosingSuchThat(x => !x.isTypeParameterOrSkolem) // account for higher order type params def isEligible(sym: Symbol) = (sym ne NoSymbol) && ( sym.isTypeParameter - || sym.isLocal + || sym.isLocalToBlock ) val referencedSymbols = (treeSym :: referencesInType(treeInfo)).distinct filter (sym => isEligible(sym) && !isOk(sym)) def mk[T](what: String, x: T, str: T => String = (x: T) => "" + x): ((Any, String)) = diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala index dfa1b6db0f..60346e7be1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala @@ -452,10 +452,10 @@ trait TypeDiagnostics { val treeTypes = mutable.Set[Type]() def defnSymbols = defnTrees.toList map (_.symbol) - def localVars = defnSymbols filter (t => t.isLocal && t.isVar) + def localVars = defnSymbols filter (t => t.isLocalToBlock && t.isVar) def qualifiesTerm(sym: Symbol) = ( - (sym.isModule || sym.isMethod || sym.isPrivateLocal || sym.isLocal) + (sym.isModule || sym.isMethod || sym.isPrivateLocal || sym.isLocalToBlock) && !nme.isLocalName(sym.name) && !sym.isParameter && !sym.isParamAccessor // could improve this, but it's a pain @@ -499,12 +499,12 @@ trait TypeDiagnostics { def isUnusedType(m: Symbol): Boolean = ( m.isType && !m.isTypeParameterOrSkolem // would be nice to improve this - && (m.isPrivate || m.isLocal) + && (m.isPrivate || m.isLocalToBlock) && !(treeTypes.exists(tp => tp exists (t => t.typeSymbolDirect == m))) ) def isUnusedTerm(m: Symbol): Boolean = ( (m.isTerm) - && (m.isPrivate || m.isLocal) + && (m.isPrivate || m.isLocalToBlock) && !targets(m) && !(m.name == nme.WILDCARD) // e.g. val _ = foo && !ignoreNames(m.name.toTermName) // serialization methods diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index f4d2a2cea0..fa96d98bcc 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -393,7 +393,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper if (sym.isPrivate && !sym.hasFlag(SYNTHETIC_PRIVATE)) { var o = owner while (o != NoSymbol && o != sym.owner && o != sym.owner.linkedClassOfClass && - !o.isLocal && !o.isPrivate && + !o.isLocalToBlock && !o.isPrivate && !o.privateWithin.hasTransOwner(sym.owner)) o = o.owner if (o == sym.owner || o == sym.owner.linkedClassOfClass) @@ -2288,7 +2288,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper val sym2 = namer.enterInScope( context.owner.newLabel(ldef.name, ldef.pos) setInfo MethodType(List(), restpe)) val LabelDef(_, _, rhs1) = resetAttrs(ldef) - val rhs2 = typed(rhs1, restpe) + val rhs2 = typed(brutallyResetAttrs(rhs1), restpe) ldef.params foreach (param => param setType param.symbol.tpe) deriveLabelDef(ldef)(_ => rhs2) setSymbol sym2 setType restpe } @@ -3015,7 +3015,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper /* 'accessor' and 'accessed' are so similar it becomes very difficult to * follow the logic, so I renamed one to something distinct. */ - def accesses(looker: Symbol, accessed: Symbol) = accessed.hasLocalFlag && ( + def accesses(looker: Symbol, accessed: Symbol) = accessed.isLocalToThis && ( (accessed.isParamAccessor) || (looker.hasAccessorFlag && !accessed.hasAccessorFlag && accessed.isPrivate) ) diff --git a/src/compiler/scala/tools/reflect/ReflectGlobal.scala b/src/compiler/scala/tools/reflect/ReflectGlobal.scala index 6f369212ad..ac63232967 100644 --- a/src/compiler/scala/tools/reflect/ReflectGlobal.scala +++ b/src/compiler/scala/tools/reflect/ReflectGlobal.scala @@ -37,5 +37,13 @@ class ReflectGlobal(currentSettings: Settings, reporter: Reporter, override val // (each mirror has its own set package symbols, because of the peculiarities of symbol loading in scala), // that `Predef` symbol only has a single owner, and this messes up visibility, which is calculated based on owners, not scopes. override def runtimeMirror(cl: ClassLoader): Mirror = rootMirror + + // Mirror and RuntimeClass come from both Global and reflect.runtime.SymbolTable + // so here the compiler needs an extra push to help decide between those (in favor of the latter) + import scala.reflect.ClassTag + override type Mirror = JavaMirror + override implicit val MirrorTag: ClassTag[Mirror] = ClassTag[Mirror](classOf[Mirror]) + override type RuntimeClass = java.lang.Class[_] + override implicit val RuntimeClassTag: ClassTag[RuntimeClass] = ClassTag[RuntimeClass](classOf[RuntimeClass]) } diff --git a/src/compiler/scala/tools/reflect/StdTags.scala b/src/compiler/scala/tools/reflect/StdTags.scala index 5c53c81e8b..ee352c5e02 100644 --- a/src/compiler/scala/tools/reflect/StdTags.scala +++ b/src/compiler/scala/tools/reflect/StdTags.scala @@ -18,8 +18,7 @@ trait StdTags { new TypeCreator { def apply[U <: ApiUniverse with Singleton](m: Mirror[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.toTypeConstructor)) + u.appliedType(u.definitions.ListClass.toType, List(u.definitions.StringClass.toType)) } }) diff --git a/src/compiler/scala/tools/reflect/ToolBox.scala b/src/compiler/scala/tools/reflect/ToolBox.scala index 4a3db09909..dfe53be6c9 100644 --- a/src/compiler/scala/tools/reflect/ToolBox.scala +++ b/src/compiler/scala/tools/reflect/ToolBox.scala @@ -21,19 +21,39 @@ trait ToolBox[U <: scala.reflect.api.Universe] { */ def frontEnd: FrontEnd + /** Represents mode of operations of the typechecker underlying `c.typecheck` calls. + * Is necessary since the shape of the typechecked tree alone is not enough to guess how it should be typechecked. + * Can be EXPRmode (typecheck as a term), TYPEmode (typecheck as a type) or PATTERNmode (typecheck as a pattern). + */ + type TypecheckMode + + /** Indicates that an argument to `c.typecheck` should be typechecked as a term. + * This is the default typechecking mode in Scala 2.11 and the only one supported in Scala 2.10. + */ + val TERMmode: TypecheckMode + + /** Indicates that an argument to `c.typecheck` should be typechecked as a type. + */ + val TYPEmode: TypecheckMode + + /** Indicates that an argument to `c.typecheck` should be typechecked as a pattern. + */ + val PATTERNmode: TypecheckMode + /** @see `Typers.typecheck` */ @deprecated("Use `tb.typecheck` instead", "2.11.0") def typeCheck(tree: u.Tree, pt: u.Type = u.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree = - typecheck(tree, pt, silent, withImplicitViewsDisabled, withMacrosDisabled) + typecheck(tree, TERMmode, pt, silent, withImplicitViewsDisabled, withMacrosDisabled) - /** Typechecks a tree using this ToolBox. + /** Typechecks a tree against the expected type `pt` + * under typechecking mode specified in `mode` with [[EXPRmode]] being default. * 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 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 false, `ToolBoxError` 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. * @@ -41,7 +61,7 @@ trait ToolBox[U <: scala.reflect.api.Universe] { * `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, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree + def typecheck(tree: u.Tree, mode: TypecheckMode = TERMmode, 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 top-level context. * Optional `pos` parameter provides a position that will be associated with the implicit search. @@ -50,7 +70,7 @@ trait ToolBox[U <: scala.reflect.api.Universe] { * 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 false, `ToolBoxError` 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. @@ -64,7 +84,7 @@ trait ToolBox[U <: scala.reflect.api.Universe] { * 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 false, `ToolBoxError` 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. diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index 6fabac9fe8..3b12086cc7 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -116,8 +116,9 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => (expr, freeTermNames) } - def transformDuringTyper(expr: Tree, withImplicitViewsDisabled: Boolean, withMacrosDisabled: Boolean)(transform: (analyzer.Typer, Tree) => Tree): Tree = { - wrappingIntoTerm(verify(expr))(expr1 => { + def transformDuringTyper(expr: Tree, mode: scala.reflect.internal.Mode, withImplicitViewsDisabled: Boolean, withMacrosDisabled: Boolean)(transform: (analyzer.Typer, Tree) => Tree): Tree = { + def withWrapping(tree: Tree)(op: Tree => Tree) = if (mode == TERMmode) wrappingIntoTerm(tree)(op) else op(tree) + withWrapping(verify(expr))(expr1 => { // need to extract free terms, because otherwise you won't be able to typecheck macros against something that contains them val exprAndFreeTerms = extractFreeTerms(expr1, wrapFreeTermRefs = false) var expr2 = exprAndFreeTerms._1 @@ -130,7 +131,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => // rather than polluting the empty package with synthetics. // [Eugene] how can we implement that? val ownerClass = rootMirror.EmptyPackageClass.newClassSymbol(newTypeName("<expression-owner>")) - build.setTypeSignature(ownerClass, ClassInfoType(List(ObjectTpe), newScope, ownerClass)) + build.setInfo(ownerClass, ClassInfoType(List(ObjectTpe), newScope, ownerClass)) val owner = ownerClass.newLocalDummy(expr2.pos) val currentTyper = analyzer.newTyper(analyzer.rootContext(NoCompilationUnit, EmptyTree).make(expr2, owner)) val withImplicitFlag = if (!withImplicitViewsDisabled) (currentTyper.context.withImplicitsEnabled[Tree] _) else (currentTyper.context.withImplicitsDisabled[Tree] _) @@ -163,11 +164,11 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => }) } - def typecheck(expr: Tree, pt: Type, silent: Boolean, withImplicitViewsDisabled: Boolean, withMacrosDisabled: Boolean): Tree = - transformDuringTyper(expr, withImplicitViewsDisabled = withImplicitViewsDisabled, withMacrosDisabled = withMacrosDisabled)( + def typecheck(expr: Tree, pt: Type, mode: scala.reflect.internal.Mode, silent: Boolean, withImplicitViewsDisabled: Boolean, withMacrosDisabled: Boolean): Tree = + transformDuringTyper(expr, mode, withImplicitViewsDisabled = withImplicitViewsDisabled, withMacrosDisabled = withMacrosDisabled)( (currentTyper, expr) => { trace("typing (implicit views = %s, macros = %s): ".format(!withImplicitViewsDisabled, !withMacrosDisabled))(showAttributed(expr, true, true, settings.Yshowsymowners.value, settings.Yshowsymkinds.value)) - currentTyper.silent(_.typed(expr, pt), reportAmbiguousErrors = false) match { + currentTyper.silent(_.typed(expr, mode, pt), reportAmbiguousErrors = false) match { case analyzer.SilentResultValue(result) => trace("success: ")(showAttributed(result, true, true, settings.Yshowsymkinds.value)) result @@ -179,7 +180,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => }) def inferImplicit(tree: Tree, pt: Type, isView: Boolean, silent: Boolean, withMacrosDisabled: Boolean, pos: Position): Tree = - transformDuringTyper(tree, withImplicitViewsDisabled = false, withMacrosDisabled = withMacrosDisabled)( + transformDuringTyper(tree, TERMmode, withImplicitViewsDisabled = false, withMacrosDisabled = withMacrosDisabled)( (currentTyper, tree) => { trace("inferring implicit %s (macros = %s): ".format(if (isView) "view" else "value", !withMacrosDisabled))(showAttributed(pt, true, true, settings.Yshowsymowners.value, settings.Yshowsymkinds.value)) analyzer.inferImplicit(tree, pt, isView, currentTyper.context, silent, withMacrosDisabled, pos, (pos, msg) => throw ToolBoxError(msg)) @@ -209,7 +210,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => val (expr, freeTerms) = extractFreeTerms(expr0, wrapFreeTermRefs = true) val (obj, _) = rootMirror.EmptyPackageClass.newModuleAndClassSymbol( - nextWrapperModuleName()) + nextWrapperModuleName(), NoPosition, NoFlags) val minfo = ClassInfoType(List(ObjectTpe), newScope, obj.moduleClass) obj.moduleClass setInfo minfo @@ -356,7 +357,13 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => } } - def typecheck(tree: u.Tree, expectedType: u.Type, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree = withCompilerApi { compilerApi => + type TypecheckMode = scala.reflect.internal.Mode + val TypecheckMode = scala.reflect.internal.Mode + val TERMmode = TypecheckMode.EXPRmode + val TYPEmode = TypecheckMode.TYPEmode | TypecheckMode.FUNmode + val PATTERNmode = TypecheckMode.PATTERNmode + + def typecheck(tree: u.Tree, mode: TypecheckMode = TERMmode, expectedType: u.Type, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree = withCompilerApi { compilerApi => import compilerApi._ if (compiler.settings.verbose) println("importing "+tree+", expectedType = "+expectedType) @@ -364,7 +371,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => val cexpectedType: compiler.Type = importer.importType(expectedType) if (compiler.settings.verbose) println("typing "+ctree+", expectedType = "+expectedType) - val ttree: compiler.Tree = compiler.typecheck(ctree, cexpectedType, silent = silent, withImplicitViewsDisabled = withImplicitViewsDisabled, withMacrosDisabled = withMacrosDisabled) + val ttree: compiler.Tree = compiler.typecheck(ctree, cexpectedType, mode, silent = silent, withImplicitViewsDisabled = withImplicitViewsDisabled, withMacrosDisabled = withMacrosDisabled) val uttree = exporter.importTree(ttree) uttree } diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala b/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala index 2027d43264..8376fca4ad 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala @@ -5,17 +5,17 @@ import scala.collection.{immutable, mutable} import scala.reflect.internal.Flags._ import scala.reflect.macros.TypecheckException -class Cardinality private[Cardinality](val value: Int) extends AnyVal { - def pred = { assert(value - 1 >= 0); new Cardinality(value - 1) } - def succ = new Cardinality(value + 1) +class Rank private[Rank](val value: Int) extends AnyVal { + def pred = { assert(value - 1 >= 0); new Rank(value - 1) } + def succ = new Rank(value + 1) override def toString = if (value == 0) "no dots" else "." * (value + 1) } -object Cardinality { - val NoDot = new Cardinality(0) - val DotDot = new Cardinality(1) - val DotDotDot = new Cardinality(2) - object Dot { def unapply(card: Cardinality) = card != NoDot } +object Rank { + val NoDot = new Rank(0) + val DotDot = new Rank(1) + val DotDotDot = new Rank(2) + object Dot { def unapply(rank: Rank) = rank != NoDot } def parseDots(part: String) = { if (part.endsWith("...")) (part.stripSuffix("..."), DotDotDot) else if (part.endsWith("..")) (part.stripSuffix(".."), DotDot) @@ -27,7 +27,7 @@ object Cardinality { */ trait Holes { self: Quasiquotes => import global._ - import Cardinality._ + import Rank._ import definitions._ import universeTypes._ @@ -43,43 +43,43 @@ trait Holes { self: Quasiquotes => tpe <:< NothingClass.tpe || tpe <:< NullClass.tpe private def extractIterableTParam(tpe: Type) = IterableTParam.asSeenFrom(tpe, IterableClass) - private def stripIterable(tpe: Type, limit: Option[Cardinality] = None): (Cardinality, Type) = + private def stripIterable(tpe: Type, limit: Option[Rank] = None): (Rank, Type) = if (limit.map { _ == NoDot }.getOrElse { false }) (NoDot, tpe) else if (tpe != null && !isIterableType(tpe)) (NoDot, tpe) else if (isBottomType(tpe)) (NoDot, tpe) else { val targ = extractIterableTParam(tpe) - val (card, innerTpe) = stripIterable(targ, limit.map { _.pred }) - (card.succ, innerTpe) + val (rank, innerTpe) = stripIterable(targ, limit.map { _.pred }) + (rank.succ, innerTpe) } - private def iterableTypeFromCard(n: Cardinality, tpe: Type): Type = { + private def iterableTypeFromRank(n: Rank, tpe: Type): Type = { if (n == NoDot) tpe - else appliedType(IterableClass.toType, List(iterableTypeFromCard(n.pred, tpe))) + else appliedType(IterableClass.toType, List(iterableTypeFromRank(n.pred, tpe))) } - /** Hole encapsulates information about splices in quasiquotes. - * It packs together a cardinality of a splice, pre-reified tree - * representation (possibly preprocessed) and position. + /** Hole encapsulates information about unquotees in quasiquotes. + * It packs together a rank, pre-reified tree representation + * (possibly preprocessed) and position. */ abstract class Hole { val tree: Tree val pos: Position - val cardinality: Cardinality + val rank: Rank } object Hole { - def apply(card: Cardinality, tree: Tree): Hole = - if (method != nme.unapply) new ApplyHole(card, tree) - else new UnapplyHole(card, tree) - def unapply(hole: Hole): Some[(Tree, Cardinality)] = Some((hole.tree, hole.cardinality)) + def apply(rank: Rank, tree: Tree): Hole = + if (method != nme.unapply) new ApplyHole(rank, tree) + else new UnapplyHole(rank, tree) + def unapply(hole: Hole): Some[(Tree, Rank)] = Some((hole.tree, hole.rank)) } - class ApplyHole(card: Cardinality, splicee: Tree) extends Hole { + class ApplyHole(annotatedRank: Rank, unquotee: Tree) extends Hole { val (strippedTpe, tpe): (Type, Type) = { - val (strippedCard, strippedTpe) = stripIterable(splicee.tpe, limit = Some(card)) + val (strippedRank, strippedTpe) = stripIterable(unquotee.tpe, limit = Some(annotatedRank)) if (isBottomType(strippedTpe)) cantSplice() - else if (isNativeType(strippedTpe)) (strippedTpe, iterableTypeFromCard(card, strippedTpe)) - else if (isLiftableType(strippedTpe)) (strippedTpe, iterableTypeFromCard(card, treeType)) + else if (isNativeType(strippedTpe)) (strippedTpe, iterableTypeFromRank(annotatedRank, strippedTpe)) + else if (isLiftableType(strippedTpe)) (strippedTpe, iterableTypeFromRank(annotatedRank, treeType)) else cantSplice() } @@ -88,28 +88,28 @@ trait Holes { self: Quasiquotes => if (isNativeType(itpe)) tree else if (isLiftableType(itpe)) lifted(itpe)(tree) else global.abort("unreachable") - if (card == NoDot) inner(strippedTpe)(splicee) - else iterated(card, splicee, splicee.tpe) + if (annotatedRank == NoDot) inner(strippedTpe)(unquotee) + else iterated(annotatedRank, unquotee, unquotee.tpe) } - val pos = splicee.pos + val pos = unquotee.pos - val cardinality = stripIterable(tpe)._1 + val rank = stripIterable(tpe)._1 private def cantSplice(): Nothing = { - val (iterableCard, iterableType) = stripIterable(splicee.tpe) - val holeCardMsg = if (card != NoDot) s" with $card" else "" - val action = "splice " + splicee.tpe + holeCardMsg - val suggestCard = card != iterableCard || card != NoDot - val spliceeCardMsg = if (card != iterableCard && iterableCard != NoDot) s"using $iterableCard" else "omitting the dots" - val cardSuggestion = if (suggestCard) spliceeCardMsg else "" - val suggestLifting = (card == NoDot || iterableCard != NoDot) && !(iterableType <:< treeType) && !isLiftableType(iterableType) - val liftedTpe = if (card != NoDot) iterableType else splicee.tpe + val (iterableRank, iterableType) = stripIterable(unquotee.tpe) + val holeRankMsg = if (annotatedRank != NoDot) s" with $annotatedRank" else "" + val action = "unquote " + unquotee.tpe + holeRankMsg + val suggestRank = annotatedRank != iterableRank || annotatedRank != NoDot + val unquoteeRankMsg = if (annotatedRank != iterableRank && iterableRank != NoDot) s"using $iterableRank" else "omitting the dots" + val rankSuggestion = if (suggestRank) unquoteeRankMsg else "" + val suggestLifting = (annotatedRank == NoDot || iterableRank != NoDot) && !(iterableType <:< treeType) && !isLiftableType(iterableType) + val liftedTpe = if (annotatedRank != NoDot) iterableType else unquotee.tpe val liftSuggestion = if (suggestLifting) s"providing an implicit instance of Liftable[$liftedTpe]" else "" val advice = if (isBottomType(iterableType)) "bottom type values often indicate programmer mistake" - else "consider " + List(cardSuggestion, liftSuggestion).filter(_ != "").mkString(" or ") - c.abort(splicee.pos, s"Can't $action, $advice") + else "consider " + List(rankSuggestion, liftSuggestion).filter(_ != "").mkString(" or ") + c.abort(unquotee.pos, s"Can't $action, $advice") } private def lifted(tpe: Type)(tree: Tree): Tree = { @@ -120,8 +120,8 @@ trait Holes { self: Quasiquotes => } private def toStats(tree: Tree): Tree = - // q"$u.build.toStats($tree)" - Apply(Select(Select(u, nme.build), nme.toStats), tree :: Nil) + // q"$u.internal.reificationSupport.toStats($tree)" + Apply(Select(Select(Select(u, nme.internal), nme.reificationSupport), nme.toStats), tree :: Nil) private def toList(tree: Tree, tpe: Type): Tree = if (isListType(tpe)) tree @@ -149,7 +149,7 @@ trait Holes { self: Quasiquotes => else None } - /** Map high-cardinality splice onto an expression that eveluates as a list of given cardinality. + /** Map high-rank unquotee onto an expression that eveluates as a list of given rank. * * All possible combinations of representations are given in the table below: * @@ -166,7 +166,7 @@ trait Holes { self: Quasiquotes => * x is not just an Iterable[T] but a List[T]. Similarly no mapping is performed if mapping function is * known to be an identity. */ - private def iterated(card: Cardinality, tree: Tree, tpe: Type): Tree = (card, tpe) match { + private def iterated(rank: Rank, tree: Tree, tpe: Type): Tree = (rank, tpe) match { case (DotDot, tpe @ IterableType(LiftedType(lift))) => mapF(toList(tree, tpe), lift) case (DotDot, LiftedType(lift)) => toStats(lift(tree)) case (DotDotDot, tpe @ IterableType(inner)) => mapF(toList(tree, tpe), t => iterated(DotDot, t, inner)) @@ -175,7 +175,7 @@ trait Holes { self: Quasiquotes => } } - class UnapplyHole(val cardinality: Cardinality, pat: Tree) extends Hole { + class UnapplyHole(val rank: Rank, pat: Tree) extends Hole { val (placeholderName, pos, tptopt) = pat match { case Bind(pname, inner @ Bind(_, Typed(Ident(nme.WILDCARD), tpt))) => (pname, inner.pos, Some(tpt)) case Bind(pname, inner @ Typed(Ident(nme.WILDCARD), tpt)) => (pname, inner.pos, Some(tpt)) @@ -188,13 +188,13 @@ trait Holes { self: Quasiquotes => try c.typeCheck(TypeDef(NoMods, TypeName("T"), Nil, tpt)) catch { case TypecheckException(pos, msg) => c.abort(pos.asInstanceOf[c.Position], msg) } val tpe = typedTpt.tpe - val (iterableCard, _) = stripIterable(tpe) - if (iterableCard.value < cardinality.value) - c.abort(pat.pos, s"Can't extract $tpe with $cardinality, consider using $iterableCard") - val (_, strippedTpe) = stripIterable(tpe, limit = Some(cardinality)) + val (iterableRank, _) = stripIterable(tpe) + if (iterableRank.value < rank.value) + c.abort(pat.pos, s"Can't extract $tpe with $rank, consider using $iterableRank") + val (_, strippedTpe) = stripIterable(tpe, limit = Some(rank)) if (strippedTpe <:< treeType) treeNoUnlift else - unlifters.spawn(strippedTpe, cardinality).map { + unlifters.spawn(strippedTpe, rank).map { Apply(_, treeNoUnlift :: Nil) }.getOrElse { c.abort(pat.pos, s"Can't find $unliftableType[$strippedTpe], consider providing it") @@ -203,7 +203,7 @@ trait Holes { self: Quasiquotes => } /** Full support for unliftable implies that it's possible to interleave - * deconstruction with higher cardinality and unlifting of the values. + * deconstruction with higher rank and unlifting of the values. * In particular extraction of List[Tree] as List[T: Unliftable] requires * helper extractors that would do the job: UnliftListElementwise[T]. Similarly * List[List[Tree]] needs UnliftListOfListsElementwise[T]. @@ -211,33 +211,33 @@ trait Holes { self: Quasiquotes => * See also "unlift list" tests in UnapplyProps.scala */ object unlifters { - private var records = List.empty[(Type, Cardinality)] + private var records = List.empty[(Type, Rank)] // Materialize unlift helper that does elementwise - // unlifting for corresponding cardinality and type. - def spawn(tpe: Type, card: Cardinality): Option[Tree] = { + // unlifting for corresponding rank and type. + def spawn(tpe: Type, rank: Rank): Option[Tree] = { val unlifter = inferUnliftable(tpe) if (unlifter == EmptyTree) None - else if (card == NoDot) Some(unlifter) + else if (rank == NoDot) Some(unlifter) else { - val idx = records.indexWhere { p => p._1 =:= tpe && p._2 == card } - val resIdx = if (idx != -1) idx else { records +:= (tpe, card); records.length - 1} + val idx = records.indexWhere { p => p._1 =:= tpe && p._2 == rank } + val resIdx = if (idx != -1) idx else { records +:= (tpe, rank); records.length - 1} Some(Ident(TermName(nme.QUASIQUOTE_UNLIFT_HELPER + resIdx))) } } // Returns a list of vals that will defined required unlifters def preamble(): List[Tree] = - records.zipWithIndex.map { case ((tpe, card), idx) => + records.zipWithIndex.map { case ((tpe, rank), idx) => val name = TermName(nme.QUASIQUOTE_UNLIFT_HELPER + idx) - val helperName = card match { + val helperName = rank match { case DotDot => nme.UnliftListElementwise case DotDotDot => nme.UnliftListOfListsElementwise } val lifter = inferUnliftable(tpe) assert(helperName.isTermName) - // q"val $name: $u.build.${helperName.toTypeName} = $u.build.$helperName($lifter)" + // q"val $name: $u.internal.reificationSupport.${helperName.toTypeName} = $u.internal.reificationSupport.$helperName($lifter)" ValDef(NoMods, name, - AppliedTypeTree(Select(Select(u, nme.build), helperName.toTypeName), List(TypeTree(tpe))), - Apply(Select(Select(u, nme.build), helperName), lifter :: Nil)) + AppliedTypeTree(Select(Select(Select(u, nme.internal), nme.reificationSupport), helperName.toTypeName), List(TypeTree(tpe))), + Apply(Select(Select(Select(u, nme.internal), nme.reificationSupport), helperName), lifter :: Nil)) } } } diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala index 301e7051df..3b93a8933d 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala @@ -123,7 +123,7 @@ trait Parsers { self: Quasiquotes => override def isStatSep(token: Int) = token == EOF || super.isStatSep(token) override def expectedMsg(token: Int): String = - if (isHole) expectedMsgTemplate(token2string(token), "splicee") + if (isHole) expectedMsgTemplate(token2string(token), "unquotee") else super.expectedMsg(token) // $mods def foo diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala b/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala index 130a01332b..5986758c2b 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala @@ -12,7 +12,7 @@ import scala.collection.{immutable, mutable} */ trait Placeholders { self: Quasiquotes => import global._ - import Cardinality._ + import Rank._ import universeTypes._ // Step 1: Transform Scala source with holes into vanilla Scala source @@ -29,27 +29,27 @@ trait Placeholders { self: Quasiquotes => posMap += pos -> ((start, end)) } - def appendHole(tree: Tree, cardinality: Cardinality) = { + def appendHole(tree: Tree, rank: Rank) = { val placeholderName = c.freshName(TermName(nme.QUASIQUOTE_PREFIX + sessionSuffix)) sb.append(placeholderName) val holeTree = if (method != nme.unapply) tree else Bind(placeholderName, tree) - holeMap(placeholderName) = Hole(cardinality, holeTree) + holeMap(placeholderName) = Hole(rank, holeTree) } val iargs = method match { case nme.apply => args case nme.unapply => val (dummy @ Ident(nme.SELECTOR_DUMMY)) :: Nil = args - dummy.attachments.get[SubpatternsAttachment].get.patterns + internal.subpatterns(dummy).get case _ => global.abort("unreachable") } foreach2(iargs, parts.init) { case (tree, (p, pos)) => - val (part, cardinality) = parseDots(p) + val (part, rank) = parseDots(p) appendPart(part, pos) - appendHole(tree, cardinality) + appendHole(tree, rank) } val (p, pos) = parts.last appendPart(p, pos) diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala index 70580adbce..61fb22bc73 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala @@ -7,10 +7,10 @@ import scala.reflect.internal.Flags._ trait Reifiers { self: Quasiquotes => import global._ - import global.build.{Select => _, Ident => _, TypeTree => _, _} + import global.build._ import global.treeInfo._ import global.definitions._ - import Cardinality._ + import Rank._ import universeTypes._ abstract class Reifier(val isReifyingExpressions: Boolean) extends { @@ -23,7 +23,7 @@ trait Reifiers { self: Quasiquotes => lazy val typer = throw new UnsupportedOperationException def isReifyingPatterns: Boolean = !isReifyingExpressions - def action = if (isReifyingExpressions) "splice" else "extract" + def action = if (isReifyingExpressions) "unquote" else "extract" def holesHaveTypes = isReifyingExpressions /** Map that stores freshly generated names linked to the corresponding names in the reified tree. @@ -64,9 +64,9 @@ trait Reifiers { self: Quasiquotes => val FreshName(prefix) = origname val nameTypeName = if (origname.isTermName) tpnme.TermName else tpnme.TypeName val freshName = if (origname.isTermName) nme.freshTermName else nme.freshTypeName - // q"val ${names.head}: $u.$nameTypeName = $u.build.$freshName($prefix)" + // q"val ${names.head}: $u.$nameTypeName = $u.internal.reificationSupport.$freshName($prefix)" ValDef(NoMods, names.head, Select(u, nameTypeName), - Apply(Select(Select(u, nme.build), freshName), Literal(Constant(prefix)) :: Nil)) + Apply(Select(Select(Select(u, nme.internal), nme.reificationSupport), freshName), Literal(Constant(prefix)) :: Nil)) }.toList // q"..$freshdefs; $tree" SyntacticBlock(freshdefs :+ tree) @@ -129,7 +129,7 @@ trait Reifiers { self: Quasiquotes => def reifyTreePlaceholder(tree: Tree): Tree = tree match { case Placeholder(hole: ApplyHole) if hole.tpe <:< treeType => hole.tree case Placeholder(Hole(tree, NoDot)) if isReifyingPatterns => tree - case Placeholder(hole @ Hole(_, card @ Dot())) => c.abort(hole.pos, s"Can't $action with $card here") + case Placeholder(hole @ Hole(_, rank @ Dot())) => c.abort(hole.pos, s"Can't $action with $rank here") case TuplePlaceholder(args) => reifyTuple(args) case TupleTypePlaceholder(args) => reifyTupleType(args) case FunctionTypePlaceholder(argtpes, restpe) => reifyFunctionType(argtpes, restpe) @@ -146,7 +146,7 @@ trait Reifiers { self: Quasiquotes => override def reifyTreeSyntactically(tree: Tree) = tree match { case RefTree(qual, SymbolPlaceholder(Hole(tree, _))) if isReifyingExpressions => - mirrorBuildCall(nme.RefTree, reify(qual), tree) + mirrorBuildCall(nme.mkRefTree, reify(qual), tree) case This(SymbolPlaceholder(Hole(tree, _))) if isReifyingExpressions => mirrorCall(nme.This, tree) case SyntacticTraitDef(mods, name, tparams, earlyDefs, parents, selfdef, body) => @@ -236,7 +236,7 @@ trait Reifiers { self: Quasiquotes => case List(hole @ Placeholder(Hole(_, NoDot))) => reify(hole) case List(Placeholder(_)) => reifyBuildCall(nme.SyntacticTuple, args) // in a case we only have one element tuple without - // any cardinality annotations this means that this is + // any rank annotations this means that this is // just an expression wrapped in parentheses case List(other) => reify(other) case _ => reifyBuildCall(nme.SyntacticTuple, args) @@ -295,8 +295,8 @@ trait Reifiers { self: Quasiquotes => * * Example: * - * reifyMultiCardinalityList(lst) { - * // first we define patterns that extract high-cardinality holeMap (currently ..) + * reifyHighRankList(lst) { + * // first we define patterns that extract high-rank holeMap (currently ..) * case Placeholder(IterableType(_, _)) => tree * } { * // in the end we define how single elements are reified, typically with default reify call @@ -306,10 +306,10 @@ trait Reifiers { self: Quasiquotes => * Sample execution of previous concrete list reifier: * * > val lst = List(foo, bar, qq$f3948f9s$1) - * > reifyMultiCardinalityList(lst) { ... } { ... } + * > reifyHighRankList(lst) { ... } { ... } * q"List($foo, $bar) ++ ${holeMap(qq$f3948f9s$1).tree}" */ - def reifyMultiCardinalityList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree + def reifyHighRankList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree val fillListHole: PartialFunction[Any, Tree] = { case Placeholder(Hole(tree, DotDot)) => tree @@ -331,16 +331,16 @@ trait Reifiers { self: Quasiquotes => } /** Reifies arbitrary list filling ..$x and ...$y holeMap when they are put - * in the correct position. Fallbacks to regular reification for non-high cardinality + * in the correct position. Fallbacks to regular reification for zero rank * elements. */ - override def reifyList(xs: List[Any]): Tree = reifyMultiCardinalityList(xs)(fillListHole.orElse(fillListOfListsHole))(reify) + override def reifyList(xs: List[Any]): Tree = reifyHighRankList(xs)(fillListHole.orElse(fillListOfListsHole))(reify) - def reifyAnnotList(annots: List[Tree]): Tree = reifyMultiCardinalityList(annots) { + def reifyAnnotList(annots: List[Tree]): Tree = reifyHighRankList(annots) { case AnnotPlaceholder(h @ Hole(_, DotDot)) => reifyAnnotation(h) } { case AnnotPlaceholder(h: ApplyHole) if h.tpe <:< treeType => reifyAnnotation(h) - case AnnotPlaceholder(h: UnapplyHole) if h.cardinality == NoDot => reifyAnnotation(h) + case AnnotPlaceholder(h: UnapplyHole) if h.rank == NoDot => reifyAnnotation(h) case other => reify(other) } @@ -365,14 +365,14 @@ trait Reifiers { self: Quasiquotes => Apply(Select(universe, name), args.toList) override def mirrorBuildCall(name: TermName, args: Tree*): Tree = - Apply(Select(Select(universe, nme.build), name), args.toList) + Apply(Select(Select(Select(universe, nme.internal), nme.reificationSupport), name), args.toList) override def scalaFactoryCall(name: String, args: Tree*): Tree = call("scala." + name, args: _*) } class ApplyReifier extends Reifier(isReifyingExpressions = true) { - def reifyMultiCardinalityList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree = + def reifyHighRankList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree = if (xs.isEmpty) mkList(Nil) else { def reifyGroup(group: List[Any]): Tree = group match { @@ -399,12 +399,12 @@ trait Reifiers { self: Quasiquotes => } mods match { case hole :: Nil => - if (flags.nonEmpty) c.abort(flags(0).pos, "Can't splice flags together with modifiers, consider merging flags into modifiers") - if (annots.nonEmpty) c.abort(hole.pos, "Can't splice modifiers together with annotations, consider merging annotations into modifiers") + if (flags.nonEmpty) c.abort(flags(0).pos, "Can't unquote flags together with modifiers, consider merging flags into modifiers") + if (annots.nonEmpty) c.abort(hole.pos, "Can't unquote modifiers together with annotations, consider merging annotations into modifiers") ensureNoExplicitFlags(m, hole.pos) hole.tree case _ :: hole :: Nil => - c.abort(hole.pos, "Can't splice multiple modifiers, consider merging them into a single modifiers instance") + c.abort(hole.pos, "Can't unquote multiple modifiers, consider merging them into a single modifiers instance") case _ => val baseFlags = reifyFlags(m.flags) val reifiedFlags = flags.foldLeft[Tree](baseFlags) { case (flag, hole) => Apply(Select(flag, nme.OR), List(hole.tree)) } @@ -423,7 +423,7 @@ trait Reifiers { self: Quasiquotes => // pq"$lhs :: $rhs" private def cons(lhs: Tree, rhs: Tree) = Apply(collectionCons, lhs :: rhs :: Nil) - def reifyMultiCardinalityList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree = { + def reifyHighRankList(xs: List[Any])(fill: PartialFunction[Any, Tree])(fallback: Any => Tree): Tree = { val grouped = group(xs) { (a, b) => !fill.isDefinedAt(a) && !fill.isDefinedAt(b) } def appended(lst: List[Any], init: Tree) = lst.foldLeft(init) { (l, r) => append(l, fallback(r)) } def prepended(lst: List[Any], init: Tree) = lst.foldRight(init) { (l, r) => cons(fallback(l), r) } |