diff options
18 files changed, 189 insertions, 53 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index d122a1a207..38a6170637 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -133,7 +133,7 @@ self => val global: Global import global._ - case class OpInfo(lhs: Tree, operator: TermName, offset: Offset) { + case class OpInfo(lhs: Tree, operator: TermName, targs: List[Tree], offset: Offset) { def precedence = Precedence(operator.toString) } @@ -787,10 +787,13 @@ self => private def opHead = opstack.head private def headPrecedence = opHead.precedence private def popOpInfo(): OpInfo = try opHead finally opstack = opstack.tail - private def pushOpInfo(top: Tree) { - val opinfo = OpInfo(top, in.name, in.offset) - opstack ::= opinfo + private def pushOpInfo(top: Tree): Unit = { + val name = in.name + val offset = in.offset ident() + val targs = if (in.token == LBRACKET) exprTypeArgs() else Nil + val opinfo = OpInfo(top, name, targs, offset) + opstack ::= opinfo } def checkHeadAssoc(leftAssoc: Boolean) = checkAssoc(opHead.offset, opHead.operator, leftAssoc) @@ -800,6 +803,9 @@ self => ) def finishPostfixOp(start: Int, base: List[OpInfo], opinfo: OpInfo): Tree = { + if (opinfo.targs.nonEmpty) + syntaxError(opinfo.offset, "type application is not allowed for postfix operators") + val od = stripParens(reduceExprStack(base, opinfo.lhs)) makePostfixSelect(start, opinfo.offset, od, opinfo.operator) } @@ -809,7 +815,7 @@ self => val operatorPos: Position = Position.range(rhs.pos.source, offset, offset, offset + operator.length) val pos = lhs.pos union rhs.pos union operatorPos withPoint offset - atPos(pos)(makeBinop(isExpr, lhs, operator, rhs, operatorPos)) + atPos(pos)(makeBinop(isExpr, lhs, operator, rhs, operatorPos, opinfo.targs)) } def reduceExprStack(base: List[OpInfo], top: Tree): Tree = reduceStack(isExpr = true, base, top) @@ -1892,9 +1898,9 @@ self => def isDelimiter = in.token == RPAREN || in.token == RBRACE def isCommaOrDelimiter = isComma || isDelimiter val (isUnderscore, isStar) = opstack match { - case OpInfo(Ident(nme.WILDCARD), nme.STAR, _) :: _ => (true, true) - case OpInfo(_, nme.STAR, _) :: _ => (false, true) - case _ => (false, false) + case OpInfo(Ident(nme.WILDCARD), nme.STAR, _, _) :: _ => (true, true) + case OpInfo(_, nme.STAR, _, _) :: _ => (false, true) + case _ => (false, false) } def isSeqPatternClose = isUnderscore && isStar && isSequenceOK && isDelimiter val preamble = "bad simple pattern:" diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index d88470bd5e..cfee988efc 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -55,7 +55,13 @@ abstract class TreeBuilder { ValDef(Modifiers(PRIVATE), name, tpt, EmptyTree) /** Create tree representing (unencoded) binary operation expression or pattern. */ - def makeBinop(isExpr: Boolean, left: Tree, op: TermName, right: Tree, opPos: Position): Tree = { + def makeBinop(isExpr: Boolean, left: Tree, op: TermName, right: Tree, opPos: Position, targs: List[Tree] = Nil): Tree = { + require(isExpr || targs.isEmpty, s"Incompatible args to makeBinop: !isExpr but targs=$targs") + + def mkSelection(t: Tree) = { + def sel = atPos(opPos union t.pos)(Select(stripParens(t), op.encode)) + if (targs.isEmpty) sel else atPos(left.pos)(TypeApply(sel, targs)) + } def mkNamed(args: List[Tree]) = if (isExpr) args map treeInfo.assignmentToMaybeNamedArg else args val arguments = right match { case Parens(args) => mkNamed(args) @@ -63,12 +69,12 @@ abstract class TreeBuilder { } if (isExpr) { if (treeInfo.isLeftAssoc(op)) { - Apply(atPos(opPos union left.pos) { Select(stripParens(left), op.encode) }, arguments) + Apply(mkSelection(left), arguments) } else { val x = freshTermName() Block( List(ValDef(Modifiers(SYNTHETIC | ARTIFACT), x, TypeTree(), stripParens(left))), - Apply(atPos(opPos union right.pos) { Select(stripParens(right), op.encode) }, List(Ident(x)))) + Apply(mkSelection(right), List(Ident(x)))) } } else { Apply(Ident(op.encode), stripParens(left) :: arguments) diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 95f2620061..4ba8d56da0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -132,11 +132,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans defaultMethodNames.toList.distinct foreach { name => val methods = clazz.info.findMember(name, 0L, requiredFlags = METHOD, stableOnly = false).alternatives - def hasDefaultParam(tpe: Type): Boolean = tpe match { - case MethodType(params, restpe) => (params exists (_.hasDefault)) || hasDefaultParam(restpe) - case _ => false - } - val haveDefaults = methods filter (sym => hasDefaultParam(sym.info) && !nme.isProtectedAccessorName(sym.name)) + val haveDefaults = methods filter (sym => mexists(sym.info.paramss)(_.hasDefault) && !nme.isProtectedAccessorName(sym.name)) if (haveDefaults.lengthCompare(1) > 0) { val owners = haveDefaults map (_.owner) diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala b/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala index f5bcaf68e0..8a54519401 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala @@ -115,8 +115,7 @@ trait Holes { self: Quasiquotes => val lifter = inferLiftable(tpe) assert(lifter != EmptyTree, s"couldnt find a liftable for $tpe") val lifted = Apply(lifter, List(tree)) - val targetType = Select(u, tpnme.Tree) - atPos(tree.pos)(TypeApply(Select(lifted, nme.asInstanceOf_), List(targetType))) + atPos(tree.pos)(lifted) } protected def iterated(card: Cardinality, tpe: Type, elementTransform: Tree => Tree = identity)(tree: Tree): Tree = { @@ -167,16 +166,15 @@ trait Holes { self: Quasiquotes => /** Full support for unliftable implies that it's possible to interleave * deconstruction with higher cardinality and unlifting of the values. * In particular extraction of List[Tree] as List[T: Unliftable] requires - * helper extractors that would do the job: UnliftHelper1[T]. Similarly - * List[List[Tree]] needs UnliftHelper2[T]. + * helper extractors that would do the job: UnliftListElementwise[T]. Similarly + * List[List[Tree]] needs UnliftListOfListsElementwise[T]. * * See also "unlift list" tests in UnapplyProps.scala */ object unlifters { private var records = List.empty[(Type, Cardinality)] - // Request an UnliftHelperN[T] where n == card and T == tpe. - // If card == 0 then helper is not needed and plain instance - // of unliftable is returned. + // Materialize unlift helper that does elementwise + // unlifting for corresponding cardinality and type. def spawn(tpe: Type, card: Cardinality): Option[Tree] = { val unlifter = inferUnliftable(tpe) if (unlifter == EmptyTree) None @@ -191,7 +189,10 @@ trait Holes { self: Quasiquotes => def preamble(): List[Tree] = records.zipWithIndex.map { case ((tpe, card), idx) => val name = TermName(nme.QUASIQUOTE_UNLIFT_HELPER + idx) - val helperName = card match { case DotDot => nme.UnliftHelper1 case DotDotDot => nme.UnliftHelper2 } + val helperName = card 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)" diff --git a/src/reflect/scala/reflect/api/BuildUtils.scala b/src/reflect/scala/reflect/api/BuildUtils.scala index 6971175f88..10c2def72a 100644 --- a/src/reflect/scala/reflect/api/BuildUtils.scala +++ b/src/reflect/scala/reflect/api/BuildUtils.scala @@ -246,13 +246,13 @@ private[reflect] trait BuildUtils { self: Universe => def unapply(tree: Tree): Option[(List[Tree], Tree)] } - def UnliftHelper1[T](unliftable: Unliftable[T]): UnliftHelper1[T] - trait UnliftHelper1[T] { + def UnliftListElementwise[T](unliftable: Unliftable[T]): UnliftListElementwise[T] + trait UnliftListElementwise[T] { def unapply(lst: List[Tree]): Option[List[T]] } - def UnliftHelper2[T](unliftable: Unliftable[T]): UnliftHelper2[T] - trait UnliftHelper2[T] { + def UnliftListOfListsElementwise[T](unliftable: Unliftable[T]): UnliftListOfListsElementwise[T] + trait UnliftListOfListsElementwise[T] { def unapply(lst: List[List[Tree]]): Option[List[List[T]]] } diff --git a/src/reflect/scala/reflect/api/Mirrors.scala b/src/reflect/scala/reflect/api/Mirrors.scala index 0f0e2b81c9..f11b9a5c55 100644 --- a/src/reflect/scala/reflect/api/Mirrors.scala +++ b/src/reflect/scala/reflect/api/Mirrors.scala @@ -153,7 +153,7 @@ package api * * '''[[scala.reflect.api.Mirrors#ClassMirror]]'''. Used for creating invoker mirrors for constructors. * Entry points: for ''static classes'' `val cm1 = m.reflectClass(<class symbol>)`, - * for ''inner classes'' `val mm2 = im.reflectClass(<module symbol>)`. + * for ''inner classes'' `val mm2 = im.reflectClass(<class symbol>)`. * Example: * {{{ * scala> case class C(x: Int) diff --git a/src/reflect/scala/reflect/api/StandardLiftables.scala b/src/reflect/scala/reflect/api/StandardLiftables.scala index 6756d5e114..5a03996dd9 100644 --- a/src/reflect/scala/reflect/api/StandardLiftables.scala +++ b/src/reflect/scala/reflect/api/StandardLiftables.scala @@ -11,16 +11,16 @@ trait StandardLiftables { self: Universe => private def callCollection(name: Name)(args: List[Tree]) = callScala(nme.collection, nme.immutable, name)(args) private def liftAsLiteral[T]: Liftable[T] = Liftable { v => Literal(Constant(v)) } - implicit def liftByte[T <: Byte]: Liftable[T] = liftAsLiteral[T] - implicit def liftShort[T <: Short]: Liftable[T] = liftAsLiteral[T] - implicit def liftChar[T <: Char]: Liftable[T] = liftAsLiteral[T] - implicit def liftInt[T <: Int]: Liftable[T] = liftAsLiteral[T] - implicit def liftLong[T <: Long]: Liftable[T] = liftAsLiteral[T] - implicit def liftFloat[T <: Float]: Liftable[T] = liftAsLiteral[T] - implicit def liftDouble[T <: Double]: Liftable[T] = liftAsLiteral[T] - implicit def liftBoolean: Liftable[Boolean] = liftAsLiteral[Boolean] - implicit def liftUnit: Liftable[Unit] = liftAsLiteral[Unit] - implicit def liftString: Liftable[String] = liftAsLiteral[String] + implicit def liftByte[T <: Byte]: Liftable[T] = liftAsLiteral[T] + implicit def liftShort[T <: Short]: Liftable[T] = liftAsLiteral[T] + implicit def liftChar[T <: Char]: Liftable[T] = liftAsLiteral[T] + implicit def liftInt[T <: Int]: Liftable[T] = liftAsLiteral[T] + implicit def liftLong[T <: Long]: Liftable[T] = liftAsLiteral[T] + implicit def liftFloat[T <: Float]: Liftable[T] = liftAsLiteral[T] + implicit def liftDouble[T <: Double]: Liftable[T] = liftAsLiteral[T] + implicit def liftBoolean[T <: Boolean]: Liftable[T] = liftAsLiteral[T] + implicit def liftUnit: Liftable[Unit] = liftAsLiteral[Unit] + implicit def liftString[T <: String]: Liftable[T] = liftAsLiteral[T] implicit def liftScalaSymbol: Liftable[scala.Symbol] = Liftable { v => callScala(nme.Symbol)(Literal(Constant(v.name)) :: Nil) @@ -35,16 +35,22 @@ trait StandardLiftables { self: Universe => implicit def liftArray[T: Liftable]: Liftable[Array[T]] = Liftable { arr => callScala(nme.Array)(arr.map(lift(_)).toList) } implicit def liftVector[T: Liftable]: Liftable[Vector[T]] = Liftable { vect => callCollection(nme.Vector)(vect.map(lift(_)).toList) } implicit def liftList[T: Liftable]: Liftable[List[T]] = Liftable { lst => callCollection(nme.List)(lst.map(lift(_))) } + implicit def liftNil: Liftable[Nil.type] = Liftable { _ => selectScala(nme.collection, nme.immutable, nme.Nil) } implicit def liftMap[K: Liftable, V: Liftable]: Liftable[Map[K, V]] = Liftable { m => callCollection(nme.Map)(m.toList.map(lift(_))) } implicit def liftSet[T: Liftable]: Liftable[Set[T]] = Liftable { s => callCollection(nme.Set)(s.toList.map(lift(_))) } + implicit def liftSome[T: Liftable]: Liftable[Some[T]] = Liftable { case Some(v) => callScala(nme.Some)(lift(v) :: Nil) } + implicit def liftNone: Liftable[None.type] = Liftable { _ => selectScala(nme.None) } implicit def liftOption[T: Liftable]: Liftable[Option[T]] = Liftable { - case Some(v) => callScala(nme.Some)(lift(v) :: Nil) - case None => selectScala(nme.None) + case some: Some[T] => lift(some) + case none: None.type => lift(none) } + + implicit def liftLeft[L: Liftable, R]: Liftable[Left[L, R]] = Liftable { case Left(v) => callScala(nme.util, nme.Left)(lift(v) :: Nil) } + implicit def liftRight[L, R: Liftable]: Liftable[Right[L, R]] = Liftable { case Right(v) => callScala(nme.util, nme.Right)(lift(v) :: Nil) } implicit def liftEither[L: Liftable, R: Liftable]: Liftable[Either[L, R]] = Liftable { - case Left(l) => callScala(nme.util, nme.Left)(lift(l) :: Nil) - case Right(r) => callScala(nme.util, nme.Right)(lift(r) :: Nil) + case left: Left[L, R] => lift(left) + case right: Right[L, R] => lift(right) } implicit def liftTuple1[T1](implicit liftT1: Liftable[T1]): Liftable[Tuple1[T1]] = Liftable { t => @@ -220,6 +226,7 @@ trait StandardLiftables { self: Universe => val List = TermName("List") val Map = TermName("Map") val None = TermName("None") + val Nil = TermName("Nil") val Right = TermName("Right") val Set = TermName("Set") val Some = TermName("Some") diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala index 0a81bfa2a5..9b19dc11cb 100644 --- a/src/reflect/scala/reflect/internal/BuildUtils.scala +++ b/src/reflect/scala/reflect/internal/BuildUtils.scala @@ -455,14 +455,14 @@ trait BuildUtils { self: SymbolTable => } } - def UnliftHelper1[T](unliftable: Unliftable[T]) = new UnliftHelper1[T] { + def UnliftListElementwise[T](unliftable: Unliftable[T]) = new UnliftListElementwise[T] { def unapply(lst: List[Tree]): Option[List[T]] = { val unlifted = lst.flatMap { unliftable.unapply(_) } if (unlifted.length == lst.length) Some(unlifted) else None } } - def UnliftHelper2[T](unliftable: Unliftable[T]) = new UnliftHelper2[T] { + def UnliftListOfListsElementwise[T](unliftable: Unliftable[T]) = new UnliftListOfListsElementwise[T] { def unapply(lst: List[List[Tree]]): Option[List[List[T]]] = { val unlifted = lst.map { l => l.flatMap { unliftable.unapply(_) } } if (unlifted.flatten.length == lst.flatten.length) Some(unlifted) else None diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index a54aa1f6e8..ed3e7dbc4c 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -763,8 +763,8 @@ trait StdNames { val unapplySeq: NameType = "unapplySeq" val unbox: NameType = "unbox" val universe: NameType = "universe" - val UnliftHelper1: NameType = "UnliftHelper1" - val UnliftHelper2: NameType = "UnliftHelper2" + val UnliftListElementwise: NameType = "UnliftListElementwise" + val UnliftListOfListsElementwise: NameType = "UnliftListOfListsElementwise" val update: NameType = "update" val updateDynamic: NameType = "updateDynamic" val value: NameType = "value" diff --git a/src/reflect/scala/reflect/macros/Aliases.scala b/src/reflect/scala/reflect/macros/Aliases.scala index cc92cd10c7..d2b878d081 100644 --- a/src/reflect/scala/reflect/macros/Aliases.scala +++ b/src/reflect/scala/reflect/macros/Aliases.scala @@ -40,10 +40,16 @@ trait Aliases { /** The type of tree modifiers. */ type Modifiers = universe.Modifiers - /** The type of compilation runs. */ + /** The type of compilation runs. + * @see [[scala.reflect.macros.Enclosures]] + */ + @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") type Run = universe.Run - /** The type of compilation units. */ + /** The type of compilation units. + * @see [[scala.reflect.macros.Enclosures]] + */ + @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") type CompilationUnit = universe.CompilationUnit /** Expr wraps an abstract syntax tree and tags it with its type. */ diff --git a/src/reflect/scala/reflect/macros/Enclosures.scala b/src/reflect/scala/reflect/macros/Enclosures.scala index 5f248d25d3..1ced2e54c6 100644 --- a/src/reflect/scala/reflect/macros/Enclosures.scala +++ b/src/reflect/scala/reflect/macros/Enclosures.scala @@ -8,9 +8,21 @@ import scala.language.existentials // SI-6541 * <span class="badge badge-red" style="float: right;">EXPERIMENTAL</span> * * A slice of [[scala.reflect.macros.blackbox.Context the Scala macros context]] that exposes - * enclosing trees (method, class, compilation unit and currently compiled application), + * enclosing trees (method, class, compilation unit and currently compiled macro application), * the enclosing position of the macro expansion, as well as macros and implicits * that are currently in-flight. + * + * Starting from Scala 2.11.0, the APIs to get the trees enclosing by the current macro application are deprecated, + * and the reasons for that are two-fold. Firstly, we would like to move towards the philosophy of locally-expanded macros, + * as it has proven to be important for understanding of code. Secondly, within the current architecture of scalac, + * we are unable to have c.enclosingTree-style APIs working robustly. Required changes to the typechecker would greatly + * exceed the effort that we would like to expend on this feature given the existence of more pressing concerns at the moment. + * This is somewhat aligned with the overall evolution of macros during the 2.11 development cycle, where we played with + * `c.introduceTopLevel` and `c.introduceMember`, but at the end of the day decided to reject them. + * + * If you're relying on the now deprecated APIs, consider reformulating your macros in terms of completely local expansion + * and/or joining a discussion of a somewhat related potential language feature at [[https://groups.google.com/forum/#!topic/scala-debate/f4CLmYShX6Q]]. + * We also welcome questions and suggestions on our mailing lists, where we would be happy to further discuss this matter. */ trait Enclosures { self: blackbox.Context => @@ -40,46 +52,62 @@ trait Enclosures { def enclosingPosition: Position /** Tree that corresponds to the enclosing method, or EmptyTree if not applicable. + * @see [[scala.reflect.macros.Enclosures]] */ - @deprecated("Use enclosingDef instead, but be wary of changes in semantics", "2.10.1") + @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") def enclosingMethod: Tree /** Tree that corresponds to the enclosing class, or EmptyTree if not applicable. + * @see [[scala.reflect.macros.Enclosures]] */ - @deprecated("Use enclosingImpl instead, but be wary of changes in semantics", "2.10.1") + @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") def enclosingClass: Tree /** Tree that corresponds to the enclosing DefDef tree. * Throws `EnclosureException` if there's no such enclosing tree. + * @see [[scala.reflect.macros.Enclosures]] */ + @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") def enclosingDef: universe.DefDef /** Tree that corresponds to the enclosing Template tree. * Throws `EnclosureException` if there's no such enclosing tree. + * @see [[scala.reflect.macros.Enclosures]] */ + @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") def enclosingTemplate: universe.Template /** Tree that corresponds to the enclosing ImplDef tree (i.e. either ClassDef or ModuleDef). * Throws `EnclosureException` if there's no such enclosing tree. + * @see [[scala.reflect.macros.Enclosures]] */ + @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") def enclosingImpl: universe.ImplDef /** Tree that corresponds to the enclosing PackageDef tree. * Throws `EnclosureException` if there's no such enclosing tree. + * @see [[scala.reflect.macros.Enclosures]] */ + @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") def enclosingPackage: universe.PackageDef /** Compilation unit that contains this macro application. + * @see [[scala.reflect.macros.Enclosures]] */ + @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") def enclosingUnit: CompilationUnit /** Compilation run that contains this macro application. + * @see [[scala.reflect.macros.Enclosures]] */ + @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") def enclosingRun: Run /** Indicates than one of the enclosure methods failed to find a tree * of required type among enclosing trees. + * @see [[scala.reflect.macros.Enclosures]] */ + @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") case class EnclosureException(expected: Class[_], enclosingTrees: List[Tree]) extends Exception(s"Couldn't find a tree of type $expected among enclosing trees $enclosingTrees") } diff --git a/src/reflect/scala/reflect/macros/Universe.scala b/src/reflect/scala/reflect/macros/Universe.scala index 297bac2999..d84e6aa737 100644 --- a/src/reflect/scala/reflect/macros/Universe.scala +++ b/src/reflect/scala/reflect/macros/Universe.scala @@ -197,34 +197,44 @@ abstract class Universe extends scala.reflect.api.Universe { def capturedVariableType(vble: Symbol): Type /** The type of compilation runs. + * @see [[scala.reflect.macros.Enclosures]] * @template * @group Macros */ + @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") type Run <: RunContextApi /** Compilation run uniquely identifies current invocation of the compiler * (e.g. can be used to implement per-run caches for macros) and provides access to units of work * of the invocation (currently processed unit of work and the list of all units). + * @see [[scala.reflect.macros.Enclosures]] * @group API */ + @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") trait RunContextApi { /** Currently processed unit of work (a real or a virtual file). */ + @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") def currentUnit: CompilationUnit /** All units of work comprising this compilation run. */ + @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") def units: Iterator[CompilationUnit] } /** The type of compilation units. + * @see [[scala.reflect.macros.Enclosures]] * @template * @group Macros */ + @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") type CompilationUnit <: CompilationUnitContextApi /** Compilation unit describes a unit of work of the compilation run. * It provides such information as file name, textual representation of the unit and the underlying AST. + * @see [[scala.reflect.macros.Enclosures]] * @group API */ + @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") trait CompilationUnitContextApi { /** Source file corresponding to this compilation unit. * @@ -235,9 +245,11 @@ abstract class Universe extends scala.reflect.api.Universe { * It should not be used unless you know what you are doing. In subsequent releases, this API will be refined * and exposed as a part of scala.reflect.api. */ + @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") def source: scala.reflect.internal.util.SourceFile /** The AST that corresponds to this compilation unit. */ + @deprecated("c.enclosingTree-style APIs are now deprecated; consult the scaladoc for more information", "2.11.0") def body: Tree } } diff --git a/test/files/neg/dotless-targs.check b/test/files/neg/dotless-targs.check new file mode 100644 index 0000000000..4aab939f61 --- /dev/null +++ b/test/files/neg/dotless-targs.check @@ -0,0 +1,4 @@ +dotless-targs.scala:2: error: type application is not allowed for postfix operators + def f1 = "f1" isInstanceOf[String] // not ok + ^ +one error found diff --git a/test/files/neg/dotless-targs.scala b/test/files/neg/dotless-targs.scala new file mode 100644 index 0000000000..eff63cbec4 --- /dev/null +++ b/test/files/neg/dotless-targs.scala @@ -0,0 +1,5 @@ +class A { + def f1 = "f1" isInstanceOf[String] // not ok + def f2 = "f2".isInstanceOf[String] // ok + def f3 = "f3" toList // ok +} diff --git a/test/files/neg/t8157.check b/test/files/neg/t8157.check new file mode 100644 index 0000000000..9a21a49a07 --- /dev/null +++ b/test/files/neg/t8157.check @@ -0,0 +1,4 @@ +t8157.scala:1: error: in object Test, multiple overloaded alternatives of method foo define default arguments. +object Test { + ^ +one error found diff --git a/test/files/neg/t8157.scala b/test/files/neg/t8157.scala new file mode 100644 index 0000000000..462d4fa3f1 --- /dev/null +++ b/test/files/neg/t8157.scala @@ -0,0 +1,4 @@ +object Test { + def foo(printer: Any, question: => String, show: Boolean = false)(op: => Any): Any = ??? + def foo[T](question: => String, show: Boolean)(op: => Any = ()): Any = ??? +} diff --git a/test/files/pos/dotless-targs.scala b/test/files/pos/dotless-targs.scala new file mode 100644 index 0000000000..8c0e244e4e --- /dev/null +++ b/test/files/pos/dotless-targs.scala @@ -0,0 +1,9 @@ +class A { + def fn1 = List apply 1 + def fn2 = List apply[Int] 2 + + def g1: Char = "g1" toList 0 + def g2: Char = "g2" apply 1 + + def h1 = List apply[List[Int]] (List(1), List(2)) mapConserve[List[Any]] (x => x) +} diff --git a/test/files/scalacheck/quasiquotes/LiftableProps.scala b/test/files/scalacheck/quasiquotes/LiftableProps.scala index 539375d905..bd631b8734 100644 --- a/test/files/scalacheck/quasiquotes/LiftableProps.scala +++ b/test/files/scalacheck/quasiquotes/LiftableProps.scala @@ -5,51 +5,62 @@ object LiftableProps extends QuasiquoteProperties("liftable") { property("splice byte") = test { val c: Byte = 0 assert(q"$c" ≈ Literal(Constant(c))) + assert(q"${0: Byte}" ≈ Literal(Constant(c))) } property("splice short") = test { val c: Short = 0 assert(q"$c" ≈ Literal(Constant(c))) + assert(q"${0: Short}" ≈ Literal(Constant(c))) } property("splice char") = test { val c: Char = 'c' assert(q"$c" ≈ Literal(Constant(c))) + assert(q"${'c'}" ≈ Literal(Constant(c))) } property("splice int") = test { val c: Int = 0 assert(q"$c" ≈ Literal(Constant(c))) + assert(q"${0: Int}" ≈ Literal(Constant(c))) } property("splice long") = test { val c: Long = 0 assert(q"$c" ≈ Literal(Constant(c))) + assert(q"${0: Long}" ≈ Literal(Constant(c))) } property("splice float") = test { val c: Float = 0.0f assert(q"$c" ≈ Literal(Constant(c))) + assert(q"${0.0f: Float}" ≈ Literal(Constant(c))) } property("splice double") = test { val c: Double = 0.0 assert(q"$c" ≈ Literal(Constant(c))) + assert(q"${0.0: Double}" ≈ Literal(Constant(c))) } property("splice boolean") = test { val c: Boolean = false assert(q"$c" ≈ Literal(Constant(c))) + assert(q"${true}" ≈ Literal(Constant(true))) + assert(q"${false}" ≈ Literal(Constant(false))) } property("splice string") = test { val c: String = "s" assert(q"$c" ≈ Literal(Constant(c))) + assert(q"${"s"}" ≈ Literal(Constant(c))) } property("splice unit") = test { val c: Unit = () assert(q"$c" ≈ Literal(Constant(c))) + assert(q"${()}" ≈ Literal(Constant(c))) } property("lift symbol") = test { @@ -111,4 +122,41 @@ object LiftableProps extends QuasiquoteProperties("liftable") { assert(q"${(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21)}" ≈ q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21)") assert(q"${(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22)}" ≈ q"(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22)") } -}
\ No newline at end of file + + property("lift nil") = test { + val nil = Nil + assert(q"$nil" ≈ q"scala.collection.immutable.Nil") + } + + property("lift some") = test { + val some1 = Some(1) + assert(q"$some1" ≈ q"scala.Some(1)") + val some2: Option[Int] = Some(1) + assert(q"$some2" ≈ q"scala.Some(1)") + } + + property("lift none") = test { + val none1 = None + assert(q"$none1" ≈ q"scala.None") + val none2: Option[Int] = None + assert(q"$none2" ≈ q"scala.None") + } + + property("lift left") = test { + val left1 = Left(1) + assert(q"$left1" ≈ q"scala.util.Left(1)") + val left2: Left[Int, Int] = Left(1) + assert(q"$left2" ≈ q"scala.util.Left(1)") + val left3: Either[Int, Int] = Left(1) + assert(q"$left3" ≈ q"scala.util.Left(1)") + } + + property("lift right") = test { + val right1 = Right(1) + assert(q"$right1" ≈ q"scala.util.Right(1)") + val right2: Right[Int, Int] = Right(1) + assert(q"$right2" ≈ q"scala.util.Right(1)") + val right3: Either[Int, Int] = Right(1) + assert(q"$right3" ≈ q"scala.util.Right(1)") + } +} |