diff options
68 files changed, 906 insertions, 341 deletions
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/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index d33ea5bb5c..9ca06427e8 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -194,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: @@ -206,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 @@ -299,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/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala index 2a3c631a66..dc4969be43 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala @@ -261,7 +261,8 @@ trait MatchApproximation extends TreeAndTypeAnalysis with ScalaLogic with MatchT } def nonNullTest(testedBinder: Symbol) = uniqueNonNullProp(binderToUniqueTree(testedBinder)) def equalsTest(pat: Tree, testedBinder: Symbol) = uniqueEqualityProp(binderToUniqueTree(testedBinder), unique(pat)) - def eqTest(pat: Tree, testedBinder: Symbol) = uniqueEqualityProp(binderToUniqueTree(testedBinder), unique(pat)) // TODO: eq, not == + // rewrite eq test to type test against the singleton type `pat.tpe`; unrelated to == (uniqueEqualityProp), could be null + def eqTest(pat: Tree, testedBinder: Symbol) = uniqueTypeProp(binderToUniqueTree(testedBinder), uniqueTp(pat.tpe)) def tru = True } ttm.renderCondition(condStrategy) diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala index a80f158949..5d8a9fecef 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala @@ -447,8 +447,7 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging { // - Scala's arrays are invariant (so we don't drop type tests unsoundly) if (extractorArgTypeTest) mkDefault else expectedTp match { - // TODO: [SPEC] the spec requires `eq` instead of `==` for singleton types - this implies sym.isStable - case SingleType(_, sym) => and(mkEqualsTest(gen.mkAttributedQualifier(expectedTp)), mkTypeTest) + case SingleType(_, sym) => mkEqTest(gen.mkAttributedQualifier(expectedTp)) // SI-4577, SI-4897 case ThisType(sym) if sym.isModule => and(mkEqualsTest(CODE.REF(sym)), mkTypeTest) // must use == to support e.g. List() == Nil case ConstantType(Constant(null)) if isAnyRef => mkEqTest(expTp(CODE.NULL)) case ConstantType(const) => mkEqualsTest(expTp(Literal(const))) 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/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 2bb874a8aa..c8ac3622e2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -807,7 +807,7 @@ trait Implicits { private def isIneligible(info: ImplicitInfo) = ( info.isCyclicOrErroneous - || isView && (info.sym eq Predef_conforms) + || isView && (info.sym eq Predef_conforms) // as an implicit conversion, Predef.$conforms is a no-op, so exclude it || (!context.macrosEnabled && info.sym.isTermMacro) ) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 8721450dc9..fa96d98bcc 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -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 } diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala b/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala index c2f1bf430d..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 = { @@ -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,24 +211,24 @@ 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 } 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 e7730f878f..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,13 +29,13 @@ 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 { @@ -47,9 +47,9 @@ trait Placeholders { self: Quasiquotes => } 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 339937adc3..61fb22bc73 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala @@ -10,7 +10,7 @@ trait Reifiers { self: Quasiquotes => 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. @@ -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) @@ -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) } @@ -372,7 +372,7 @@ trait Reifiers { self: Quasiquotes => } 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) } diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index 50577e710e..faeb1dcbe2 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -264,8 +264,16 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { @inline def formatted(fmtstr: String): String = fmtstr format self } - implicit final class StringAdd[A](private val self: A) extends AnyVal { - def +(other: String) = String.valueOf(self) + other + // TODO: remove, only needed for binary compatibility of 2.11.0-RC1 with 2.11.0-M8 + // note that `private[scala]` becomes `public` in bytecode + private[scala] final class StringAdd[A](private val self: A) extends AnyVal { + def +(other: String): String = String.valueOf(self) + other + } + private[scala] def StringAdd(x: Any): Any = new StringAdd(x) + + // SI-8229 retaining the pre 2.11 name for source compatibility in shadowing this implicit + implicit final class any2stringadd[A](private val self: A) extends AnyVal { + def +(other: String): String = String.valueOf(self) + other } implicit final class RichException(private val self: Throwable) extends AnyVal { @@ -374,9 +382,13 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef { @implicitNotFound(msg = "Cannot prove that ${From} <:< ${To}.") sealed abstract class <:<[-From, +To] extends (From => To) with Serializable private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x } - // not in the <:< companion object because it is also - // intended to subsume identity (which is no longer implicit) - implicit def conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A] + // The dollar prefix is to dodge accidental shadowing of this method + // by a user-defined method of the same name (SI-7788). + // The collections rely on this method. + implicit def $conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A] + + @deprecated("Use `implicitly[T <:< U]` or `identity` instead.", "2.11.0") + def conforms[A]: A <:< A = $conforms[A] /** An instance of `A =:= B` witnesses that the types `A` and `B` are equal. * @@ -410,7 +422,6 @@ private[scala] trait DeprecatedPredef { @deprecated("Use `ArrowAssoc`", "2.11.0") def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x) @deprecated("Use `Ensuring`", "2.11.0") def any2Ensuring[A](x: A): Ensuring[A] = new Ensuring(x) @deprecated("Use `StringFormat`", "2.11.0") def any2stringfmt(x: Any): StringFormat[Any] = new StringFormat(x) - @deprecated("Use String interpolation", "2.11.0") def any2stringadd(x: Any): StringAdd[Any] = new StringAdd(x) @deprecated("Use `Throwable` directly", "2.11.0") def exceptionWrapper(exc: Throwable) = new RichException(exc) @deprecated("Use `SeqCharSequence`", "2.11.0") def seqToCharSequence(xs: scala.collection.IndexedSeq[Char]): CharSequence = new SeqCharSequence(xs) @deprecated("Use `ArrayCharSequence`", "2.11.0") def arrayToCharSequence(xs: Array[Char]): CharSequence = new ArrayCharSequence(xs) diff --git a/src/reflect/scala/reflect/api/Printers.scala b/src/reflect/scala/reflect/api/Printers.scala index b262fdce68..92ae6d8b44 100644 --- a/src/reflect/scala/reflect/api/Printers.scala +++ b/src/reflect/scala/reflect/api/Printers.scala @@ -209,20 +209,22 @@ trait Printers { self: Universe => * Renders the code of the passed tree, so that: * 1) it can be later compiled by scalac retaining the same meaning, * 2) it looks pretty. - * At the moment we have handled #1 for unattributed trees and - * later on plan to account for typical idiosyncrasies of the typechecker. + * #1 is available for unattributed trees and attributed trees * #2 is more or less okay indentation-wise, but at the moment there's a lot of desugaring - * left in place, and that's what we also plan to improve in the future. + * left in place, and that's what we plan to improve in the future. + * printTypes, printIds, printPositions options have the same meaning as for TreePrinter + * printRootPkg option is available only for attributed trees. * * @group Printers */ - def showCode(tree: Tree) = render(tree, newCodePrinter) + def showCode(tree: Tree, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printOwners: BooleanFlag = None, printPositions: BooleanFlag = None, printRootPkg: Boolean = false) = + render(tree, newCodePrinter(_, tree, printRootPkg), printTypes, printIds, printOwners, printKinds = None, printMirrors = None, printPositions) /** * Hook to define what `showCode(...)` means. * @group Printers */ - protected def newCodePrinter(out: PrintWriter): TreePrinter + protected def newCodePrinter(out: PrintWriter, tree: Tree, printRootPkg: Boolean): TreePrinter /** Renders internal structure of a reflection artifact as the * visualization of a Scala syntax tree. diff --git a/src/reflect/scala/reflect/api/Quasiquotes.scala b/src/reflect/scala/reflect/api/Quasiquotes.scala index fcf8edcec7..c939eee164 100644 --- a/src/reflect/scala/reflect/api/Quasiquotes.scala +++ b/src/reflect/scala/reflect/api/Quasiquotes.scala @@ -7,7 +7,7 @@ trait Quasiquotes { self: Universe => // using the mechanism implemented in `scala.tools.reflect.FastTrack` implicit class Quasiquote(ctx: StringContext) { protected trait api { - def apply[T](args: T*): Any = macro ??? + def apply[T](args: T*): Tree = macro ??? def unapply(scrutinee: Any): Any = macro ??? } object q extends api diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 2567abe51d..e1d760a87a 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -1432,7 +1432,8 @@ trait Definitions extends api.StandardDefinitions { TypeTagClass -> materializeTypeTag ) lazy val TagSymbols = TagMaterializers.keySet - lazy val Predef_conforms = getMemberMethod(PredefModule, nme.conforms) + lazy val Predef_conforms = (getMemberIfDefined(PredefModule, nme.conforms) + orElse getMemberMethod(PredefModule, "conforms": TermName)) // TODO: predicate on -Xsource:2.10 (for now, needed for transition from M8 -> RC1) lazy val Predef_classOf = getMemberMethod(PredefModule, nme.classOf) lazy val Predef_implicitly = getMemberMethod(PredefModule, nme.implicitly) lazy val Predef_wrapRefArray = getMemberMethod(PredefModule, nme.wrapRefArray) diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala index b1d76b6056..680c19e426 100644 --- a/src/reflect/scala/reflect/internal/Printers.scala +++ b/src/reflect/scala/reflect/internal/Printers.scala @@ -73,7 +73,14 @@ trait Printers extends api.Printers { self: SymbolTable => def indent() = indentMargin += indentStep def undent() = indentMargin -= indentStep - def printPosition(tree: Tree) = if (printPositions) print(tree.pos.show) + def printPosition(tree: Tree) = + if (printPositions) comment(print(tree.pos.show)) + + protected def printTypesInfo(tree: Tree) = + if (printTypes && tree.isTerm && tree.canHaveAttrs) + comment{ + print("{", if (tree.tpe eq null) "<null>" else tree.tpe.toString, "}") + } def println() = { out.println() @@ -124,12 +131,17 @@ trait Printers extends api.Printers { self: SymbolTable => print(symName(p, p.name)); printOpt(": ", TypeTree() setType p.tpe) } - protected def parenthesize(condition: Boolean = true)(body: => Unit) = { - if (condition) print("(") + protected def parenthesize(condition: Boolean = true, open: String = "(", close: String = ")")(body: => Unit) = { + if (condition) print(open) body - if (condition) print(")") + if (condition) print(close) } + protected val commentsRequired = false + + protected def comment(body: => Unit) = + parenthesize(commentsRequired, "/*", "*/")(body) + protected def printImplicitInParamsList(vds: List[ValDef]) = if (vds.nonEmpty) printFlags(vds.head.mods.flags & IMPLICIT, "") @@ -275,13 +287,20 @@ trait Printers extends api.Printers { self: SymbolTable => print("("); printValueParams print(" => ", body, ")") - if (printIds && tree.symbol != null) print("#" + tree.symbol.id) - if (printOwners && tree.symbol != null) print("@" + tree.symbol.owner.id) + if (printIds && tree.symbol != null) + comment{ + print("#" + tree.symbol.id) + } + + if (printOwners && tree.symbol != null) + comment{ + print("@" + tree.symbol.owner.id) + } } - protected def printSuper(tree: Super, resultName: => String) = { + protected def printSuper(tree: Super, resultName: => String, checkSymbol: Boolean = true) = { val Super(This(qual), mix) = tree - if (qual.nonEmpty || tree.symbol != NoSymbol) print(resultName + ".") + if (qual.nonEmpty || (checkSymbol && tree.symbol != NoSymbol)) print(resultName + ".") print("super") if (mix.nonEmpty) print(s"[$mix]") } @@ -292,6 +311,9 @@ trait Printers extends api.Printers { self: SymbolTable => print("this") } + protected def printBlock(stats: List[Tree], expr: Tree) = + printColumn(stats ::: List(expr), "{", ";", "}") + def printTree(tree: Tree) = { tree match { case EmptyTree => @@ -351,7 +373,7 @@ trait Printers extends api.Printers { self: SymbolTable => currentOwner = currentOwner1 case Block(stats, expr) => - printColumn(stats ::: List(expr), "{", ";", "}") + printBlock(stats, expr) case Match(selector, cases) => val selectorType1 = selectorType @@ -498,9 +520,7 @@ trait Printers extends api.Printers { self: SymbolTable => case tree => xprintTree(this, tree) } - if (printTypes && tree.isTerm && tree.canHaveAttrs) { - print("{", if (tree.tpe eq null) "<null>" else tree.tpe.toString, "}") - } + printTypesInfo(tree) } def print(args: Any*): Unit = args foreach { @@ -514,21 +534,8 @@ trait Printers extends api.Printers { self: SymbolTable => } } - // it's the printer for trees after parser and before typer phases - class ParsedTreePrinter(out: PrintWriter) extends TreePrinter(out) { - override def withTypes = this - override def withIds = this - override def withKinds = this - override def withMirrors = this - override def withPositions = this - - // TODO: add print parameters to typed trees printer - printTypes = false - printIds = false - printKinds = false - printMirrors = false - printPositions = false - + // it's the printer for AST-based code generation + class CodePrinter(out: PrintWriter, printRootPkg: Boolean) extends TreePrinter(out) { protected val parentsStack = scala.collection.mutable.Stack[Tree]() protected def currentTree = if (parentsStack.nonEmpty) Some(parentsStack.top) else None @@ -558,6 +565,8 @@ trait Printers extends api.Printers { self: SymbolTable => qualIsIntLit && name.isOperatorName } + override protected val commentsRequired = true + protected def needsParentheses(parent: Tree)(insideIf: Boolean = true, insideMatch: Boolean = true, insideTry: Boolean = true, insideAnnotated: Boolean = true, insideBlock: Boolean = true, insideLabelDef: Boolean = true) = { parent match { @@ -582,10 +591,21 @@ trait Printers extends api.Printers { self: SymbolTable => case Select(qual, name) if name.isTermName => s"${resolveSelect(qual)}.${printedName(name)}" case Select(qual, name) if name.isTypeName => s"${resolveSelect(qual)}#${blankForOperatorName(name)}%${printedName(name)}" case Ident(name) => printedName(name) - case _ => showCode(t) + case _ => render(t, new CodePrinter(_, printRootPkg)) } } + protected def emptyTree(tree: Tree) = tree match { + case EmptyTree | build.SyntacticEmptyTypeTree() => true + case _ => false + } + + protected def originalTypeTrees(trees: List[Tree]) = + trees.filter(!emptyTree(_)) map { + case tt: TypeTree => tt.original + case tree => tree + } + val defaultClasses = List(tpnme.AnyRef) val defaultTraitsForCase = List(tpnme.Product, tpnme.Serializable) protected def removeDefaultTypesFromList(trees: List[Tree])(classesToRemove: List[Name] = defaultClasses)(traitsToRemove: List[Name]) = { @@ -602,9 +622,24 @@ trait Printers extends api.Printers { self: SymbolTable => removeDefaultTraitsFromList(removeDefaultClassesFromList(trees, classesToRemove), traitsToRemove) } - protected def removeDefaultClassesFromList(trees: List[Tree], classesToRemove: List[Name] = defaultClasses) = trees filter { - case Select(Ident(sc), name) => !(classesToRemove.contains(name) && sc == nme.scala_) - case _ => true + protected def removeDefaultClassesFromList(trees: List[Tree], classesToRemove: List[Name] = defaultClasses) = + originalTypeTrees(trees) filter { + case Select(Ident(sc), name) => !(classesToRemove.contains(name) && sc == nme.scala_) + case _ => true + } + + protected def syntheticToRemove(tree: Tree) = + tree match { + case _: ValDef | _: TypeDef => false // don't remove ValDef and TypeDef + case md: MemberDef if md.mods.isSynthetic => true + case _ => false + } + + override def printOpt(prefix: String, tree: Tree) = + if (!emptyTree(tree)) super.printOpt(prefix, tree) + + override def printColumn(ts: List[Tree], start: String, sep: String, end: String) = { + super.printColumn(ts.filter(!syntheticToRemove(_)), start, sep, end) } def printFlags(mods: Modifiers, primaryCtorParam: Boolean = false): Unit = { @@ -635,6 +670,7 @@ trait Printers extends api.Printers { self: SymbolTable => def printParam(tree: Tree, primaryCtorParam: Boolean): Unit = tree match { case vd @ ValDef(mods, name, tp, rhs) => + printPosition(tree) printAnnotations(vd) val mutableOrOverride = mods.isOverride || mods.isMutable val hideCtorMods = mods.isParamAccessor && mods.isPrivateLocal && !mutableOrOverride @@ -648,6 +684,7 @@ trait Printers extends api.Printers { self: SymbolTable => printOpt(": ", tp); printOpt(" = ", rhs) case TypeDef(_, name, tparams, rhs) => + printPosition(tree) print(printedName(name)) printTypeParams(tparams); print(rhs) @@ -682,7 +719,17 @@ trait Printers extends api.Printers { self: SymbolTable => override def printTree(tree: Tree): Unit = { parentsStack.push(tree) + try { + processTreePrinting(tree); + printTypesInfo(tree) + } finally parentsStack.pop() + } + + def processTreePrinting(tree: Tree): Unit = { tree match { + // don't remove synthetic ValDef/TypeDef + case _ if syntheticToRemove(tree) => + case cl @ ClassDef(mods, name, tparams, impl) => if (mods.isJavaDefined) super.printTree(cl) printAnnotations(cl) @@ -733,12 +780,11 @@ trait Printers extends api.Printers { self: SymbolTable => printSeq(stats) { print(_) } { - print(";"); + println() println() }; case _ => - val separator = scala.util.Properties.lineSeparator - printPackageDef(pd, separator) + printPackageDef(pd, scala.util.Properties.lineSeparator) } case md @ ModuleDef(mods, name, impl) => @@ -786,7 +832,8 @@ trait Printers extends api.Printers { self: SymbolTable => case imp @ Import(expr, _) => printImport(imp, resolveSelect(expr)) - case Template(parents, self, body) => + case t @ Template(parents, self, tbody) => + val body = treeInfo.untypecheckedTemplBody(t) val printedParents = currentParent map { case _: CompoundTypeTree => parents @@ -840,7 +887,7 @@ trait Printers extends api.Printers { self: SymbolTable => case dd: DefDef => dd.name != nme.CONSTRUCTOR case _ => true } - val modBody = left ::: right.drop(1) + val modBody = (left ::: right.drop(1)) val showBody = !(modBody.isEmpty && (self == noSelfType || self.isEmpty)) if (showBody) { if (self.name != nme.WILDCARD) { @@ -855,7 +902,8 @@ trait Printers extends api.Printers { self: SymbolTable => printColumn(modBody, "", ";", "}") } - case Block(stats, expr) => super.printTree(tree) + case bl @ Block(stats, expr) => + printBlock(treeInfo.untypecheckedBlockBody(bl), expr) case Match(selector, cases) => /* Insert braces if match is inner @@ -900,12 +948,24 @@ trait Printers extends api.Printers { self: SymbolTable => printFunction(f)(printValueParams(vparams, inParentheses = printParentheses)) case Typed(expr, tp) => + def printTp = print("(", tp, ")") + tp match { + case EmptyTree | build.SyntacticEmptyTypeTree() => printTp + // case for untypechecked trees + case Annotated(annot, arg) if (expr ne null) && (arg ne null) && expr.equalsStructure(arg) => printTp // remove double arg - 5: 5: @unchecked + case tt: TypeTree if tt.original.isInstanceOf[Annotated] => printTp case Function(List(), EmptyTree) => print("(", expr, " _)") //func _ // parentheses required when (a match {}) : Type case _ => print("((", expr, "): ", tp, ")") } + // print only fun when targs are TypeTrees with empty original + case TypeApply(fun, targs) => + if (targs.exists(emptyTree(_))) { + print(fun) + } else super.printTree(tree) + case Apply(fun, vargs) => tree match { // processing methods ending on colons (x \: list) @@ -918,20 +978,48 @@ trait Printers extends api.Printers { self: SymbolTable => case _ => super.printTree(tree) } + case UnApply(fun, args) => + fun match { + case treeInfo.Unapplied(body) => + body match { + case Select(qual, name) if name == nme.unapply => print(qual) + case TypeApply(Select(qual, name), args) if name == nme.unapply || name == nme.unapplySeq => + print(TypeApply(qual, args)) + case _ => print(body) + } + case _ => print(fun) + } + printRow(args, "(", ", ", ")") + case st @ Super(This(qual), mix) => - printSuper(st, printedName(qual)) + printSuper(st, printedName(qual), checkSymbol = false) case th @ This(qual) => - printThis(th, printedName(qual)) + if (tree.hasExistingSymbol && tree.symbol.isPackage) print(tree.symbol.fullName) + else printThis(th, printedName(qual)) + + // remove this prefix from constructor invocation in typechecked trees: this.this -> this + case Select(This(_), name @ nme.CONSTRUCTOR) => print(printedName(name)) case Select(qual: New, name) => print(qual) - case Select(qualifier, name) => { - val printParentheses = needsParentheses(qualifier)(insideAnnotated = false) || isIntLitWithDecodedOp(qualifier, name) - if (printParentheses) print("(", resolveSelect(qualifier), ").", printedName(name)) - else print(resolveSelect(qualifier), ".", printedName(name)) - } + case Select(qual, name) => + def checkRootPackage(tr: Tree): Boolean = + (currentParent match { //check that Select is not for package def name + case Some(_: PackageDef) => false + case _ => true + }) && (tr match { // check that Select contains package + case Select(q, _) => checkRootPackage(q) + case _: Ident | _: This => val sym = tr.symbol + tr.hasExistingSymbol && sym.isPackage && sym.name != nme.ROOTPKG + case _ => false + }) + + if (printRootPkg && checkRootPackage(tree)) print(s"${printedName(nme.ROOTPKG)}.") + val printParentheses = needsParentheses(qual)(insideAnnotated = false) || isIntLitWithDecodedOp(qual, name) + if (printParentheses) print("(", resolveSelect(qual), ").", printedName(name)) + else print(resolveSelect(qual), ".", printedName(name)) case id @ Ident(name) => if (name.nonEmpty) { @@ -971,6 +1059,9 @@ trait Printers extends api.Printers { self: SymbolTable => case SelectFromTypeTree(qualifier, selector) => print("(", qualifier, ")#", blankForOperatorName(selector), printedName(selector)) + case tt: TypeTree => + if (!emptyTree(tt)) print(tt.original) + case AppliedTypeTree(tp, args) => // it's possible to have (=> String) => String type but Function1[=> String, String] is not correct val containsByNameTypeParam = args exists treeInfo.isByNameParamType @@ -996,7 +1087,6 @@ trait Printers extends api.Printers { self: SymbolTable => case tree => super.printTree(tree) } - parentsStack.pop() } } @@ -1004,7 +1094,9 @@ trait Printers extends api.Printers { self: SymbolTable => def xprintTree(treePrinter: TreePrinter, tree: Tree) = treePrinter.print(tree.productPrefix+tree.productIterator.mkString("(", ", ", ")")) - def newCodePrinter(writer: PrintWriter): TreePrinter = new ParsedTreePrinter(writer) + def newCodePrinter(writer: PrintWriter, tree: Tree, printRootPkg: Boolean): TreePrinter = + new CodePrinter(writer, printRootPkg) + def newTreePrinter(writer: PrintWriter): TreePrinter = new TreePrinter(writer) def newTreePrinter(stream: OutputStream): TreePrinter = newTreePrinter(new PrintWriter(stream)) def newTreePrinter(): TreePrinter = newTreePrinter(new PrintWriter(ConsoleWriter)) diff --git a/src/reflect/scala/reflect/internal/ReificationSupport.scala b/src/reflect/scala/reflect/internal/ReificationSupport.scala index 087d4186be..ea230a215b 100644 --- a/src/reflect/scala/reflect/internal/ReificationSupport.scala +++ b/src/reflect/scala/reflect/internal/ReificationSupport.scala @@ -237,7 +237,9 @@ trait ReificationSupport { self: SymbolTable => // undo gen.mkTemplate protected object UnMkTemplate { def unapply(templ: Template): Option[(List[Tree], ValDef, Modifiers, List[List[ValDef]], List[Tree], List[Tree])] = { - val Template(parents, selfType, tbody) = templ + val Template(parents, selfType, _) = templ + val tbody = treeInfo.untypecheckedTemplBody(templ) + def result(ctorMods: Modifiers, vparamss: List[List[ValDef]], edefs: List[Tree], body: List[Tree]) = Some((parents, selfType, ctorMods, vparamss, edefs, body)) def indexOfCtor(trees: List[Tree]) = @@ -463,8 +465,8 @@ trait ReificationSupport { self: SymbolTable => else gen.mkBlock(stats) def unapply(tree: Tree): Option[List[Tree]] = tree match { - case self.Block(stats, SyntheticUnit()) => Some(stats) - case self.Block(stats, expr) => Some(stats :+ expr) + case bl @ self.Block(stats, SyntheticUnit()) => Some(treeInfo.untypecheckedBlockBody(bl)) + case bl @ self.Block(stats, expr) => Some(treeInfo.untypecheckedBlockBody(bl) :+ expr) case EmptyTree => Some(Nil) case _ if tree.isTerm => Some(tree :: Nil) case _ => None diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 0c28c4fba4..f3467ff9f4 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -671,7 +671,7 @@ trait StdNames { val classOf: NameType = "classOf" val clone_ : NameType = "clone" val collection: NameType = "collection" - val conforms: NameType = "conforms" + val conforms: NameType = "$conforms" // dollar prefix to avoid accidental shadowing val copy: NameType = "copy" val create: NameType = "create" val currentMirror: NameType = "currentMirror" diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala index b7df2e82cb..7cf749c048 100644 --- a/src/reflect/scala/reflect/internal/TreeInfo.scala +++ b/src/reflect/scala/reflect/internal/TreeInfo.scala @@ -405,6 +405,67 @@ abstract class TreeInfo { case _ => false } + /** Does the tree have a structure similar to typechecked trees? */ + private[internal] def detectTypecheckedTree(tree: Tree) = + tree.hasExistingSymbol || tree.exists { + case dd: DefDef => dd.mods.hasAccessorFlag || dd.mods.isSynthetic // for untypechecked trees + case md: MemberDef => md.hasExistingSymbol + case _ => false + } + + /** Recover template body to parsed state */ + private[internal] def untypecheckedTemplBody(templ: Template) = + untypecheckedTreeBody(templ, templ.body) + + /** Recover block body to parsed state */ + private[internal] def untypecheckedBlockBody(block: Block) = + untypecheckedTreeBody(block, block.stats) + + /** Recover tree body to parsed state */ + private[internal] def untypecheckedTreeBody(tree: Tree, tbody: List[Tree]) = { + def filterBody(body: List[Tree]) = body filter { + case _: ValDef | _: TypeDef => true + // keep valdef or getter for val/var + case dd: DefDef if dd.mods.hasAccessorFlag => !nme.isSetterName(dd.name) && !tbody.exists { + case vd: ValDef => dd.name == vd.name.dropLocal + case _ => false + } + case md: MemberDef => !md.mods.isSynthetic + case tree => true + } + + def lazyValDefRhs(body: Tree) = + body match { + case Block(List(Assign(_, rhs)), _) => rhs + case _ => body + } + + def recoverBody(body: List[Tree]) = body map { + case vd @ ValDef(vmods, vname, _, vrhs) if nme.isLocalName(vname) => + tbody find { + case dd: DefDef => dd.name == vname.dropLocal + case _ => false + } map { dd => + val DefDef(dmods, dname, _, _, _, drhs) = dd + // get access flags from DefDef + val vdMods = (vmods &~ Flags.AccessFlags) | (dmods & Flags.AccessFlags).flags + // for most cases lazy body should be taken from accessor DefDef + val vdRhs = if (vmods.isLazy) lazyValDefRhs(drhs) else vrhs + copyValDef(vd)(mods = vdMods, name = dname, rhs = vdRhs) + } getOrElse (vd) + // for abstract and some lazy val/vars + case dd @ DefDef(mods, name, _, _, tpt, rhs) if mods.hasAccessorFlag => + // transform getter mods to field + val vdMods = (if (!mods.hasStableFlag) mods | Flags.MUTABLE else mods &~ Flags.STABLE) &~ Flags.ACCESSOR + ValDef(vdMods, name, tpt, rhs) + case tr => tr + } + + if (detectTypecheckedTree(tree)) { + recoverBody(filterBody(tbody)) + } else tbody + } + /** The first constructor definitions in `stats` */ def firstConstructor(stats: List[Tree]): Tree = stats find { case x: DefDef => nme.isConstructorName(x.name) diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index 7a6862a770..9dc4baee32 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -1685,10 +1685,12 @@ trait Trees extends api.Trees { // this is necessary to avoid crashes like https://github.com/scalamacros/paradise/issues/1 // when someone tries to c.typecheck a naked MemberDef - def wrappingIntoTerm(tree: Tree)(op: Tree => Tree): Tree = { - op(build.SyntacticBlock(tree :: Nil)) match { - case build.SyntacticBlock(tree :: Nil) => tree - case tree => tree + def wrappingIntoTerm(tree0: Tree)(op: Tree => Tree): Tree = { + val neededWrapping = !tree0.isTerm + val tree1 = build.SyntacticBlock(tree0 :: Nil) + op(tree1) match { + case Block(tree2 :: Nil, Literal(Constant(()))) if neededWrapping => tree2 + case tree2 => tree2 } } diff --git a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala index 048fe9ef37..a494c7f0d0 100644 --- a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala +++ b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala @@ -37,6 +37,7 @@ abstract class MutableSettings extends AbsSettings { def XfullLubs: BooleanSetting def XnoPatmatAnalysis: BooleanSetting def Xprintpos: BooleanSetting + def strictInference: BooleanSetting def Yposdebug: BooleanSetting def Yrangepos: BooleanSetting def Yshowsymowners: BooleanSetting diff --git a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala index 1c4d05ae32..876685e24a 100644 --- a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala +++ b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala @@ -14,11 +14,11 @@ private[internal] trait GlbLubs { import TypesStats._ private final val printLubs = scala.sys.props contains "scalac.debug.lub" + private final val strictInference = settings.strictInference /** In case anyone wants to turn off lub verification without reverting anything. */ private final val verifyLubs = true - private def printLubMatrix(btsMap: Map[Type, List[Type]], depth: Depth) { import util.TableDef import TableDef.Column @@ -63,6 +63,26 @@ private[internal] trait GlbLubs { } } + // only called when strictInference + private def willViolateRecursiveBounds(tp: Type, ts: List[Type], tsElimSub: List[Type]) = { + val typeSym = ts.head.typeSymbol // we're uniform, the `.head` is as good as any. + def fbounds = findRecursiveBounds(ts) map (_._2) + def isRecursive = typeSym.typeParams exists fbounds.contains + + isRecursive && (transposeSafe(tsElimSub map (_.normalize.typeArgs)) match { + case Some(arggsTransposed) => + val mergedTypeArgs = (tp match { case et: ExistentialType => et.underlying; case _ => tp}).typeArgs + exists3(typeSym.typeParams, mergedTypeArgs, arggsTransposed) { + (param, arg, lubbedArgs) => + val isExistential = arg.typeSymbol.isExistentiallyBound + val isInFBound = fbounds contains param + val wasLubbed = !lubbedArgs.exists(_ =:= arg) + (!isExistential && isInFBound && wasLubbed) + } + case None => false + }) + } + /** Given a matrix `tsBts` whose columns are basetype sequences (and the symbols `tsParams` that should be interpreted as type parameters in this matrix), * compute its least sorted upwards closed upper bound relative to the following ordering <= between lists of types: * @@ -88,7 +108,8 @@ private[internal] trait GlbLubs { case _ => tp } // pretypes is a tail-recursion-preserving accumulator. - @tailrec def loop(pretypes: List[Type], tsBts: List[List[Type]]): List[Type] = { + @tailrec + def loop(pretypes: List[Type], tsBts: List[List[Type]]): List[Type] = { lubListDepth = lubListDepth.incr if (tsBts.isEmpty || (tsBts exists typeListIsEmpty)) pretypes.reverse @@ -110,28 +131,19 @@ private[internal] trait GlbLubs { // merging, strip targs that refer to bound tparams (when we're computing the lub of type // constructors.) Also filter out all types that are a subtype of some other type. if (isUniformFrontier) { - val fbounds = findRecursiveBounds(ts0) map (_._2) - val tcLubList = typeConstructorLubList(ts0) - def isRecursive(tp: Type) = tp.typeSymbol.typeParams exists fbounds.contains - - val ts1 = ts0 map { t => - if (isRecursive(t)) { - tcLubList map (t baseType _.typeSymbol) find (t => !isRecursive(t)) match { - case Some(tp) => logResult(s"Breaking recursion in lublist, substituting weaker type.\n Was: $t\n Now")(tp) - case _ => t - } - } - else t - } val tails = tsBts map (_.tail) - mergePrefixAndArgs(elimSub(ts1, depth) map elimHigherOrderTypeParam, Covariant, depth) match { + val ts1 = elimSub(ts0, depth) map elimHigherOrderTypeParam + mergePrefixAndArgs(ts1, Covariant, depth) match { case NoType => loop(pretypes, tails) - case tp => loop(tp :: pretypes, tails) + case tp if strictInference && willViolateRecursiveBounds(tp, ts0, ts1) => + log(s"Breaking recursion in lublist, advancing frontier and discaring merged prefix/args from $tp") + loop(pretypes, tails) + case tp => + loop(tp :: pretypes, tails) } - } - else { + } else { // frontier is not uniform yet, move it beyond the current minimal symbol; - // lather, rinSe, repeat + // lather, rinse, repeat val sym = minSym(ts0) val newtps = tsBts map (ts => if (ts.head.typeSymbol == sym) ts.tail else ts) if (printLubs) { @@ -257,23 +269,6 @@ private[internal] trait GlbLubs { private val _glbResults = new mutable.HashMap[(Depth, List[Type]), Type] def glbResults = _glbResults - /** Given a list of types, finds all the base classes they have in - * common, then returns a list of type constructors derived directly - * from the symbols (so any more specific type information is ignored.) - * The list is filtered such that every type constructor in the list - * expects the same number of type arguments, which is chosen based - * on the deepest class among the common baseclasses. - */ - def typeConstructorLubList(ts: List[Type]): List[Type] = { - val bcs = ts.flatMap(_.baseClasses).distinct sortWith (_ isLess _) - val tcons = bcs filter (clazz => ts forall (_.typeSymbol isSubClass clazz)) - - tcons map (_.typeConstructor) match { - case Nil => Nil - case t :: ts => t :: ts.filter(_.typeParams.size == t.typeParams.size) - } - } - def lub(ts: List[Type]): Type = ts match { case Nil => NothingTpe case t :: Nil => t diff --git a/src/reflect/scala/reflect/runtime/Settings.scala b/src/reflect/scala/reflect/runtime/Settings.scala index d46846fc21..27d574b1de 100644 --- a/src/reflect/scala/reflect/runtime/Settings.scala +++ b/src/reflect/scala/reflect/runtime/Settings.scala @@ -33,6 +33,7 @@ private[reflect] class Settings extends MutableSettings { val Xexperimental = new BooleanSetting(false) val XfullLubs = new BooleanSetting(false) val XnoPatmatAnalysis = new BooleanSetting(false) + val strictInference = new BooleanSetting(false) val Xprintpos = new BooleanSetting(false) val Yposdebug = new BooleanSetting(false) val Yrangepos = new BooleanSetting(false) diff --git a/src/scaladoc/scala/tools/nsc/doc/Settings.scala b/src/scaladoc/scala/tools/nsc/doc/Settings.scala index 5ea1443a19..67529f4178 100644 --- a/src/scaladoc/scala/tools/nsc/doc/Settings.scala +++ b/src/scaladoc/scala/tools/nsc/doc/Settings.scala @@ -298,7 +298,7 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_)) /** Common conversion targets that affect any class in Scala */ val commonConversionTargets = Set( "scala.Predef.StringFormat", - "scala.Predef.StringAdd", + "scala.Predef.any2stringadd", "scala.Predef.ArrowAssoc", "scala.Predef.Ensuring", "scala.collection.TraversableOnce.alternateImplicit") diff --git a/test/files/neg/logImplicits.check b/test/files/neg/logImplicits.check index 2265614962..270882b71a 100644 --- a/test/files/neg/logImplicits.check +++ b/test/files/neg/logImplicits.check @@ -10,7 +10,7 @@ logImplicits.scala:15: inferred view from String("abc") to Int = C.this.convert: logImplicits.scala:19: applied implicit conversion from Int(1) to ?{def ->: ?} = implicit def ArrowAssoc[A](self: A): ArrowAssoc[A] def f = (1 -> 2) + "c" ^ -logImplicits.scala:19: applied implicit conversion from (Int, Int) to ?{def +: ?} = implicit def StringAdd[A](self: A): StringAdd[A] +logImplicits.scala:19: applied implicit conversion from (Int, Int) to ?{def +: ?} = implicit def any2stringadd[A](self: A): any2stringadd[A] def f = (1 -> 2) + "c" ^ logImplicits.scala:22: error: class Un needs to be abstract, since method unimplemented is not defined diff --git a/test/files/neg/predef-masking.scala b/test/files/neg/predef-masking.scala index 6f4f4859d0..67b69aa169 100644 --- a/test/files/neg/predef-masking.scala +++ b/test/files/neg/predef-masking.scala @@ -1,5 +1,5 @@ // Testing predef masking -import Predef.{ StringAdd => _, _ } +import Predef.{ any2stringadd => _, _ } object StringPlusConfusion { // Would love to do something about this error message, but by the diff --git a/test/files/neg/quasiquotes-syntax-error-position.check b/test/files/neg/quasiquotes-syntax-error-position.check index 14fef16e01..fd55bd25b5 100644 --- a/test/files/neg/quasiquotes-syntax-error-position.check +++ b/test/files/neg/quasiquotes-syntax-error-position.check @@ -7,7 +7,7 @@ quasiquotes-syntax-error-position.scala:6: error: illegal start of simple expres quasiquotes-syntax-error-position.scala:7: error: '}' expected but end of quote found. q"class $t { def foo = $a" ^ -quasiquotes-syntax-error-position.scala:8: error: '.' expected but splicee found. +quasiquotes-syntax-error-position.scala:8: error: '.' expected but unquotee found. q"import $t $t" ^ quasiquotes-syntax-error-position.scala:9: error: '{' expected but end of quote found. diff --git a/test/files/neg/t6675.flags b/test/files/neg/t6675.flags index e93641e931..2843ea9efc 100644 --- a/test/files/neg/t6675.flags +++ b/test/files/neg/t6675.flags @@ -1 +1 @@ --Xlint -Xfatal-warnings
\ No newline at end of file +-deprecation -Xlint -Xfatal-warnings
\ No newline at end of file diff --git a/test/files/neg/t6675b.flags b/test/files/neg/t6675b.flags index 1008b0a70c..2fcfa0cddb 100644 --- a/test/files/neg/t6675b.flags +++ b/test/files/neg/t6675b.flags @@ -1 +1 @@ --Xlint +-deprecation -Xlint diff --git a/test/files/neg/si7980.check b/test/files/neg/t7980.check index b085cabf1d..031c23dbeb 100644 --- a/test/files/neg/si7980.check +++ b/test/files/neg/t7980.check @@ -1,4 +1,4 @@ -si7980.scala:7: error: Can't splice Nothing, bottom type values often indicate programmer mistake +t7980.scala:7: error: Can't unquote Nothing, bottom type values often indicate programmer mistake println(q"class ${Name(X)} { }") ^ one error found diff --git a/test/files/neg/si7980.scala b/test/files/neg/t7980.scala index b21907de54..b21907de54 100644 --- a/test/files/neg/si7980.scala +++ b/test/files/neg/t7980.scala diff --git a/test/files/neg/t8229.check b/test/files/neg/t8229.check new file mode 100644 index 0000000000..cc504fa34e --- /dev/null +++ b/test/files/neg/t8229.check @@ -0,0 +1,4 @@ +t8229.scala:5: error: value + is not a member of Object + o + "" + ^ +one error found diff --git a/test/files/neg/t8229.scala b/test/files/neg/t8229.scala new file mode 100644 index 0000000000..91966311e2 --- /dev/null +++ b/test/files/neg/t8229.scala @@ -0,0 +1,6 @@ +import Predef.{any2stringadd => _, _} + +object Test { + val o = new Object() + o + "" +} diff --git a/test/files/pos/t6675.flags b/test/files/pos/t6675.flags index e8fb65d50c..d1b831ea87 100644 --- a/test/files/pos/t6675.flags +++ b/test/files/pos/t6675.flags @@ -1 +1 @@ --Xfatal-warnings
\ No newline at end of file +-deprecation -Xfatal-warnings
\ No newline at end of file diff --git a/test/files/pos/t7788.scala b/test/files/pos/t7788.scala new file mode 100644 index 0000000000..81eada962b --- /dev/null +++ b/test/files/pos/t7788.scala @@ -0,0 +1,8 @@ +class Test { + // Predef used to define a method `conforms` to produce the implicit evidence below + // all this does is ensure we don't rename Predef.$conforms back to conforms when $ goes out of fashion + // or that there is some other way of generating the implicit value that witnesses T => U for T <: U + def conforms(x: Int, y: Int) = x < y + def foo[A](implicit ev: Int => A) = ??? + foo[Int] +}
\ No newline at end of file diff --git a/test/files/pos/t8224.scala b/test/files/pos/t8224.scala new file mode 100644 index 0000000000..2fae925df3 --- /dev/null +++ b/test/files/pos/t8224.scala @@ -0,0 +1,12 @@ +import language.higherKinds + +trait P [N1, +E1[X <: N1]] +trait PIn[N2, +E2[X <: N2]] extends P[Int,Any] + +trait EI extends PIn[Int, Nothing] +trait NI extends PIn[Int, Nothing] + +object Test { + val lub = if (true) ??? : EI else ??? : NI + val pin: PIn[Int,Nothing] = lub +} diff --git a/test/files/run/macro-reify-nested-b/Impls_Macros_1.scala b/test/files/run/macro-reify-chained1/Impls_Macros_1.scala index 3bea04cead..7f877b2729 100644 --- a/test/files/run/macro-reify-nested-b/Impls_Macros_1.scala +++ b/test/files/run/macro-reify-chained1/Impls_Macros_1.scala @@ -1,6 +1,7 @@ import scala.reflect.runtime.universe._ import scala.reflect.runtime.{universe => ru} import scala.reflect.macros.blackbox.Context +import scala.language.experimental.macros case class Utils[C <: Context]( c:C ) { import c.universe._ @@ -34,7 +35,7 @@ object QueryableMacros{ c.universe.reify{ Queryable.factory[S]( foo.splice )} } def map[T:c.WeakTypeTag, S:c.WeakTypeTag] - (c: scala.reflect.macros.blackbox.Context) + (c: Context) (projection: c.Expr[T => S]): c.Expr[Queryable[S]] = _helper[c.type,S]( c )( "_map", projection ) } class Queryable[T]{ diff --git a/test/files/run/macro-reify-chained1/Test_2.scala b/test/files/run/macro-reify-chained1/Test_2.scala new file mode 100644 index 0000000000..2adb07b035 --- /dev/null +++ b/test/files/run/macro-reify-chained1/Test_2.scala @@ -0,0 +1,9 @@ +object Test extends App{ + val q : Queryable[Any] = new Queryable[Any] + q.map(x => x).map(x => x) + + locally { + val q : Queryable[Any] = new Queryable[Any] + q.map(x => x).map(x => x) + } +}
\ No newline at end of file diff --git a/test/files/run/macro-reify-chained2/Impls_Macros_1.scala b/test/files/run/macro-reify-chained2/Impls_Macros_1.scala new file mode 100644 index 0000000000..965b191044 --- /dev/null +++ b/test/files/run/macro-reify-chained2/Impls_Macros_1.scala @@ -0,0 +1,47 @@ +import scala.reflect.runtime.universe._ +import scala.reflect.runtime.{universe => ru} +import scala.reflect.macros.whitebox.Context +import scala.language.experimental.macros + +case class Utils[C <: Context]( c:C ) { + import c.universe._ + import c.{Tree=>_} + object removeDoubleReify extends c.universe.Transformer { + def apply( tree:Tree ) = transform(tree) + override def transform(tree: Tree): Tree = { + super.transform { + tree match { + case Apply(TypeApply(Select(_this, termname), _), reification::Nil ) + if termname.toString == "factory" => c.unreifyTree(reification) + case Apply(Select(_this, termname), reification::Nil ) + if termname.toString == "factory" => c.unreifyTree(reification) + case _ => tree + } + } + } + } +} +object QueryableMacros{ + def _helper[C <: Context,S:c.WeakTypeTag]( c:C )( name:String, projection:c.Expr[_] ) = { + import c.universe._ + import internal._ + val element_type = implicitly[c.WeakTypeTag[S]].tpe + val foo = c.Expr[ru.Expr[Queryable[S]]]( + c.reifyTree( gen.mkRuntimeUniverseRef, EmptyTree, c.typecheck( + Utils[c.type](c).removeDoubleReify( + Apply(Select(c.prefix.tree, TermName( name )), List( projection.tree )) + ).asInstanceOf[Tree] + ))) + c.universe.reify{ Queryable.factory[S]( foo.splice )} + } + def map[T:c.WeakTypeTag, S:c.WeakTypeTag] + (c: Context) + (projection: c.Expr[T => S]): c.Expr[Queryable[S]] = _helper[c.type,S]( c )( "_map", projection ) +} +class Queryable[T]{ + def _map[S]( projection: T => S ) : Queryable[S] = ??? + def map[S]( projection: T => S ) : Queryable[S] = macro QueryableMacros.map[T,S] +} +object Queryable{ + def factory[S]( projection:ru.Expr[Queryable[S]] ) : Queryable[S] = null +}
\ No newline at end of file diff --git a/test/files/run/macro-reify-chained2/Test_2.scala b/test/files/run/macro-reify-chained2/Test_2.scala new file mode 100644 index 0000000000..2adb07b035 --- /dev/null +++ b/test/files/run/macro-reify-chained2/Test_2.scala @@ -0,0 +1,9 @@ +object Test extends App{ + val q : Queryable[Any] = new Queryable[Any] + q.map(x => x).map(x => x) + + locally { + val q : Queryable[Any] = new Queryable[Any] + q.map(x => x).map(x => x) + } +}
\ No newline at end of file diff --git a/test/files/run/macro-reify-nested-a.flags b/test/files/run/macro-reify-nested-a.flags deleted file mode 100644 index cd66464f2f..0000000000 --- a/test/files/run/macro-reify-nested-a.flags +++ /dev/null @@ -1 +0,0 @@ --language:experimental.macros
\ No newline at end of file diff --git a/test/files/run/macro-reify-nested-a/Impls_Macros_1.scala b/test/files/run/macro-reify-nested-a1/Impls_Macros_1.scala index 3bea04cead..7f877b2729 100644 --- a/test/files/run/macro-reify-nested-a/Impls_Macros_1.scala +++ b/test/files/run/macro-reify-nested-a1/Impls_Macros_1.scala @@ -1,6 +1,7 @@ import scala.reflect.runtime.universe._ import scala.reflect.runtime.{universe => ru} import scala.reflect.macros.blackbox.Context +import scala.language.experimental.macros case class Utils[C <: Context]( c:C ) { import c.universe._ @@ -34,7 +35,7 @@ object QueryableMacros{ c.universe.reify{ Queryable.factory[S]( foo.splice )} } def map[T:c.WeakTypeTag, S:c.WeakTypeTag] - (c: scala.reflect.macros.blackbox.Context) + (c: Context) (projection: c.Expr[T => S]): c.Expr[Queryable[S]] = _helper[c.type,S]( c )( "_map", projection ) } class Queryable[T]{ diff --git a/test/files/run/macro-reify-nested-a/Test_2.scala b/test/files/run/macro-reify-nested-a1/Test_2.scala index fa0eb378af..b99c4c55e4 100644 --- a/test/files/run/macro-reify-nested-a/Test_2.scala +++ b/test/files/run/macro-reify-nested-a1/Test_2.scala @@ -1,4 +1,9 @@ object Test extends App{ val q : Queryable[Any] = new Queryable[Any] q.map(e1 => q.map(e2=>e1)) + + locally { + val q : Queryable[Any] = new Queryable[Any] + q.map(e1 => q.map(e2=>e1)) + } }
\ No newline at end of file diff --git a/test/files/run/macro-reify-nested-a2/Impls_Macros_1.scala b/test/files/run/macro-reify-nested-a2/Impls_Macros_1.scala new file mode 100644 index 0000000000..965b191044 --- /dev/null +++ b/test/files/run/macro-reify-nested-a2/Impls_Macros_1.scala @@ -0,0 +1,47 @@ +import scala.reflect.runtime.universe._ +import scala.reflect.runtime.{universe => ru} +import scala.reflect.macros.whitebox.Context +import scala.language.experimental.macros + +case class Utils[C <: Context]( c:C ) { + import c.universe._ + import c.{Tree=>_} + object removeDoubleReify extends c.universe.Transformer { + def apply( tree:Tree ) = transform(tree) + override def transform(tree: Tree): Tree = { + super.transform { + tree match { + case Apply(TypeApply(Select(_this, termname), _), reification::Nil ) + if termname.toString == "factory" => c.unreifyTree(reification) + case Apply(Select(_this, termname), reification::Nil ) + if termname.toString == "factory" => c.unreifyTree(reification) + case _ => tree + } + } + } + } +} +object QueryableMacros{ + def _helper[C <: Context,S:c.WeakTypeTag]( c:C )( name:String, projection:c.Expr[_] ) = { + import c.universe._ + import internal._ + val element_type = implicitly[c.WeakTypeTag[S]].tpe + val foo = c.Expr[ru.Expr[Queryable[S]]]( + c.reifyTree( gen.mkRuntimeUniverseRef, EmptyTree, c.typecheck( + Utils[c.type](c).removeDoubleReify( + Apply(Select(c.prefix.tree, TermName( name )), List( projection.tree )) + ).asInstanceOf[Tree] + ))) + c.universe.reify{ Queryable.factory[S]( foo.splice )} + } + def map[T:c.WeakTypeTag, S:c.WeakTypeTag] + (c: Context) + (projection: c.Expr[T => S]): c.Expr[Queryable[S]] = _helper[c.type,S]( c )( "_map", projection ) +} +class Queryable[T]{ + def _map[S]( projection: T => S ) : Queryable[S] = ??? + def map[S]( projection: T => S ) : Queryable[S] = macro QueryableMacros.map[T,S] +} +object Queryable{ + def factory[S]( projection:ru.Expr[Queryable[S]] ) : Queryable[S] = null +}
\ No newline at end of file diff --git a/test/files/run/macro-reify-nested-a2/Test_2.scala b/test/files/run/macro-reify-nested-a2/Test_2.scala new file mode 100644 index 0000000000..b99c4c55e4 --- /dev/null +++ b/test/files/run/macro-reify-nested-a2/Test_2.scala @@ -0,0 +1,9 @@ +object Test extends App{ + val q : Queryable[Any] = new Queryable[Any] + q.map(e1 => q.map(e2=>e1)) + + locally { + val q : Queryable[Any] = new Queryable[Any] + q.map(e1 => q.map(e2=>e1)) + } +}
\ No newline at end of file diff --git a/test/files/run/macro-reify-nested-b.flags b/test/files/run/macro-reify-nested-b.flags deleted file mode 100644 index cd66464f2f..0000000000 --- a/test/files/run/macro-reify-nested-b.flags +++ /dev/null @@ -1 +0,0 @@ --language:experimental.macros
\ No newline at end of file diff --git a/test/files/run/macro-reify-nested-b1/Impls_Macros_1.scala b/test/files/run/macro-reify-nested-b1/Impls_Macros_1.scala new file mode 100644 index 0000000000..7f877b2729 --- /dev/null +++ b/test/files/run/macro-reify-nested-b1/Impls_Macros_1.scala @@ -0,0 +1,47 @@ +import scala.reflect.runtime.universe._ +import scala.reflect.runtime.{universe => ru} +import scala.reflect.macros.blackbox.Context +import scala.language.experimental.macros + +case class Utils[C <: Context]( c:C ) { + import c.universe._ + import c.{Tree=>_} + object removeDoubleReify extends c.universe.Transformer { + def apply( tree:Tree ) = transform(tree) + override def transform(tree: Tree): Tree = { + super.transform { + tree match { + case Apply(TypeApply(Select(_this, termname), _), reification::Nil ) + if termname.toString == "factory" => c.unreifyTree(reification) + case Apply(Select(_this, termname), reification::Nil ) + if termname.toString == "factory" => c.unreifyTree(reification) + case _ => tree + } + } + } + } +} +object QueryableMacros{ + def _helper[C <: Context,S:c.WeakTypeTag]( c:C )( name:String, projection:c.Expr[_] ) = { + import c.universe._ + import internal._ + val element_type = implicitly[c.WeakTypeTag[S]].tpe + val foo = c.Expr[ru.Expr[Queryable[S]]]( + c.reifyTree( gen.mkRuntimeUniverseRef, EmptyTree, c.typecheck( + Utils[c.type](c).removeDoubleReify( + Apply(Select(c.prefix.tree, TermName( name )), List( projection.tree )) + ).asInstanceOf[Tree] + ))) + c.universe.reify{ Queryable.factory[S]( foo.splice )} + } + def map[T:c.WeakTypeTag, S:c.WeakTypeTag] + (c: Context) + (projection: c.Expr[T => S]): c.Expr[Queryable[S]] = _helper[c.type,S]( c )( "_map", projection ) +} +class Queryable[T]{ + def _map[S]( projection: T => S ) : Queryable[S] = ??? + def map[S]( projection: T => S ) : Queryable[S] = macro QueryableMacros.map[T,S] +} +object Queryable{ + def factory[S]( projection:ru.Expr[Queryable[S]] ) : Queryable[S] = null +}
\ No newline at end of file diff --git a/test/files/run/macro-reify-nested-b/Test_2.scala b/test/files/run/macro-reify-nested-b1/Test_2.scala index fa13f57ffb..b199036349 100644 --- a/test/files/run/macro-reify-nested-b/Test_2.scala +++ b/test/files/run/macro-reify-nested-b1/Test_2.scala @@ -1,4 +1,9 @@ object Test extends App{ val q : Queryable[Any] = new Queryable[Any] q.map(e1 => q.map(e2=>e1).map(e2=>e1)) + + locally { + val q : Queryable[Any] = new Queryable[Any] + q.map(e1 => q.map(e2=>e1).map(e2=>e1)) + } }
\ No newline at end of file diff --git a/test/files/run/macro-reify-nested-b2/Impls_Macros_1.scala b/test/files/run/macro-reify-nested-b2/Impls_Macros_1.scala new file mode 100644 index 0000000000..965b191044 --- /dev/null +++ b/test/files/run/macro-reify-nested-b2/Impls_Macros_1.scala @@ -0,0 +1,47 @@ +import scala.reflect.runtime.universe._ +import scala.reflect.runtime.{universe => ru} +import scala.reflect.macros.whitebox.Context +import scala.language.experimental.macros + +case class Utils[C <: Context]( c:C ) { + import c.universe._ + import c.{Tree=>_} + object removeDoubleReify extends c.universe.Transformer { + def apply( tree:Tree ) = transform(tree) + override def transform(tree: Tree): Tree = { + super.transform { + tree match { + case Apply(TypeApply(Select(_this, termname), _), reification::Nil ) + if termname.toString == "factory" => c.unreifyTree(reification) + case Apply(Select(_this, termname), reification::Nil ) + if termname.toString == "factory" => c.unreifyTree(reification) + case _ => tree + } + } + } + } +} +object QueryableMacros{ + def _helper[C <: Context,S:c.WeakTypeTag]( c:C )( name:String, projection:c.Expr[_] ) = { + import c.universe._ + import internal._ + val element_type = implicitly[c.WeakTypeTag[S]].tpe + val foo = c.Expr[ru.Expr[Queryable[S]]]( + c.reifyTree( gen.mkRuntimeUniverseRef, EmptyTree, c.typecheck( + Utils[c.type](c).removeDoubleReify( + Apply(Select(c.prefix.tree, TermName( name )), List( projection.tree )) + ).asInstanceOf[Tree] + ))) + c.universe.reify{ Queryable.factory[S]( foo.splice )} + } + def map[T:c.WeakTypeTag, S:c.WeakTypeTag] + (c: Context) + (projection: c.Expr[T => S]): c.Expr[Queryable[S]] = _helper[c.type,S]( c )( "_map", projection ) +} +class Queryable[T]{ + def _map[S]( projection: T => S ) : Queryable[S] = ??? + def map[S]( projection: T => S ) : Queryable[S] = macro QueryableMacros.map[T,S] +} +object Queryable{ + def factory[S]( projection:ru.Expr[Queryable[S]] ) : Queryable[S] = null +}
\ No newline at end of file diff --git a/test/files/run/macro-reify-nested-b2/Test_2.scala b/test/files/run/macro-reify-nested-b2/Test_2.scala new file mode 100644 index 0000000000..b199036349 --- /dev/null +++ b/test/files/run/macro-reify-nested-b2/Test_2.scala @@ -0,0 +1,9 @@ +object Test extends App{ + val q : Queryable[Any] = new Queryable[Any] + q.map(e1 => q.map(e2=>e1).map(e2=>e1)) + + locally { + val q : Queryable[Any] = new Queryable[Any] + q.map(e1 => q.map(e2=>e1).map(e2=>e1)) + } +}
\ No newline at end of file diff --git a/test/files/run/t2251.flags b/test/files/run/t2251.flags new file mode 100644 index 0000000000..19243266d1 --- /dev/null +++ b/test/files/run/t2251.flags @@ -0,0 +1 @@ +-Xstrict-inference
\ No newline at end of file diff --git a/test/files/run/t2251b.flags b/test/files/run/t2251b.flags new file mode 100644 index 0000000000..19243266d1 --- /dev/null +++ b/test/files/run/t2251b.flags @@ -0,0 +1 @@ +-Xstrict-inference
\ No newline at end of file diff --git a/test/files/run/t4577.scala b/test/files/run/t4577.scala new file mode 100644 index 0000000000..b08100d3ea --- /dev/null +++ b/test/files/run/t4577.scala @@ -0,0 +1,38 @@ +object Test { + val bippy = new Symbol("bippy") + val imposter = new Symbol("bippy") + val notBippy = new Symbol("not-bippy") + val syms = List(bippy, imposter, notBippy) + + // the equals method should only be used for case `bippy`, + // for the singleton type pattern, case _: bippy.type, the spec mandates `bippy eq _` as the test + class Symbol(val name: String) { + override def equals(other: Any) = other match { + case x: Symbol => name == x.name + case _ => false + } + override def toString = name + } + + // TODO: test bytecode equality for f and fDirect (and g and gDirect), + // for now the optimizer doesn't quite get from `f` to `fDirect` + def f(s: Symbol) = s match { + case _: bippy.type => true + case _ => false + } + def fDirect(s: Symbol) = bippy eq s + + def g(s: Symbol) = s match { + case _: bippy.type => 1 + case `bippy` => 2 + case _ => 3 + } + def gDirect(s: Symbol) = if (bippy eq s) 1 else if (bippy == s) 2 else 3 + + def main(args: Array[String]): Unit = { + // `syms map f` should be: true false false + assert(syms forall (s => f(s) == fDirect(s))) + // `syms map g` should be: 1 2 3 + assert(syms forall (s => g(s) == gDirect(s))) + } +}
\ No newline at end of file diff --git a/test/files/run/t6111.check b/test/files/run/t6111.check index 7fd2e33526..1f23a87f73 100644 --- a/test/files/run/t6111.check +++ b/test/files/run/t6111.check @@ -1,2 +1,3 @@ +warning: there were 2 deprecation warning(s); re-run with -deprecation for details (8,8) (x,x) diff --git a/test/files/run/t6111.scala b/test/files/run/t6111.scala index 7cceea1d09..c0bcf17a07 100644 --- a/test/files/run/t6111.scala +++ b/test/files/run/t6111.scala @@ -1,3 +1,5 @@ +// SI-6675 DEPRECATED AUTO-TUPLING BECAUSE BAD IDEA -- MEAMAXIMACULPA +// TODO: remove this test case in 2.12, when the deprecation will go into effect and this will no longer compile // slightly overkill, but a good test case for implicit resolution in extractor calls, // along with the real fix: an extractor pattern with 1 sub-pattern should type check for all extractors // that return Option[T], whatever T (even if it's a tuple) diff --git a/test/files/run/t7185.check b/test/files/run/t7185.check index 2b4adf36b4..ebf85b731f 100644 --- a/test/files/run/t7185.check +++ b/test/files/run/t7185.check @@ -24,7 +24,9 @@ tree: reflect.runtime.universe.Apply = scala> {val tb = reflect.runtime.currentMirror.mkToolBox(); tb.typecheck(tree): Any} res0: Any = { - $read.O.apply() + { + $read.O.apply() + } } scala> diff --git a/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala b/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala index 7e846bfb24..fdb0d83277 100644 --- a/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala @@ -50,24 +50,24 @@ trait ClassConstruction { self: QuasiquoteProperties => assertEqAst(q"class Foo extends ..$parents", "class Foo") } - property("splice term name into class") = forAll { (rname: TypeName) => + property("unquote term name into class") = forAll { (rname: TypeName) => // add prefix to avoid failure in case rname is keyword val name = TypeName("prefix$" + rname) eqAst(q"class $name", "class " + name.toString) } - property("splice method into class") = forAll { (name: TypeName, method: DefDef) => + property("unquote method into class") = forAll { (name: TypeName, method: DefDef) => q"class $name { $method }" ≈ classWith(name, body = List(method)) } - property("splice members into class") = forAll { (name: TypeName, defs: List[DefDef], extra: DefDef) => + property("unquote members into class") = forAll { (name: TypeName, defs: List[DefDef], extra: DefDef) => q"""class $name { ..$defs $extra }""" ≈ classWith(name, body = defs :+ extra) } - property("splice type name into class parents") = forAll { (name: TypeName, parent: TypeName) => + property("unquote type name into class parents") = forAll { (name: TypeName, parent: TypeName) => q"class $name extends $parent" ≈ classWith(name, parents = List(Ident(parent))) } @@ -84,27 +84,27 @@ trait ClassConstruction { self: QuasiquoteProperties => } trait TraitConstruction { self: QuasiquoteProperties => - property("splice name into trait def") = test { + property("unquote name into trait def") = test { val Foo = TypeName("Foo") assert(q"trait $Foo" ≈ q"trait Foo") } - property("splice type params into trait def") = test { + property("unquote type params into trait def") = test { val tparams = q"type A" :: q"type B" :: Nil assert(q"trait Foo[..$tparams]" ≈ q"trait Foo[A, B]") } - property("splice defs into trait body") = test { + property("unquote defs into trait body") = test { val body = q"def foo" :: q"val bar: Baz" :: Nil assert(q"trait Foo { ..$body }" ≈ q"trait Foo { def foo; val bar: Baz }") } - property("splice parents into trait") = test { + property("unquote parents into trait") = test { val parents = tq"A" :: tq"B" :: Nil assert(q"trait Foo extends ..$parents" ≈ q"trait Foo extends A with B") } - property("splice early valdef into trait") = test { + property("unquote early valdef into trait") = test { val x = q"val x: Int = 1" assertEqAst(q"trait T extends { $x } with Any", "trait T extends { val x: Int = 1} with Any") } @@ -113,7 +113,7 @@ trait TraitConstruction { self: QuasiquoteProperties => assertEqAst(q"trait T extends { val x: Int = 1 } with Any", "trait T extends { val x: Int = 1 } with Any") } - property("splice defs into early block") = test { + property("unquote defs into early block") = test { val defs = q"val x: Int = 0" :: q"type Foo = Bar" :: Nil assert(q"trait T extends { ..$defs } with Bippy" ≈ q"trait T extends { val x: Int = 0; type Foo = Bar} with Bippy") @@ -126,37 +126,37 @@ trait TraitConstruction { self: QuasiquoteProperties => } trait TypeDefConstruction { self: QuasiquoteProperties => - property("splice type name into typedef") = forAll { (name1: TypeName, name2: TypeName) => + property("unquote type name into typedef") = forAll { (name1: TypeName, name2: TypeName) => q"type $name1 = $name2" ≈ TypeDef(Modifiers(), name1, List(), Ident(name2)) } - property("splice type names into type bounds") = forAll { (T1: TypeName, T2: TypeName, T3: TypeName) => + property("unquote type names into type bounds") = forAll { (T1: TypeName, T2: TypeName, T3: TypeName) => q"type $T1 >: $T2 <: $T3" ≈ TypeDef( Modifiers(DEFERRED), T1, List(), TypeBoundsTree(Ident(T2), Ident(T3))) } - property("splice trees names into type bounds") = forAll { (T: TypeName, t1: Tree, t2: Tree) => + property("unquote trees names into type bounds") = forAll { (T: TypeName, t1: Tree, t2: Tree) => q"type $T >: $t1 <: $t2" ≈ TypeDef( Modifiers(DEFERRED), T, List(), TypeBoundsTree(t1, t2)) } - property("splice tparams into typedef (1)") = forAll { (T: TypeName, targs: List[TypeDef], t: Tree) => + property("unquote tparams into typedef (1)") = forAll { (T: TypeName, targs: List[TypeDef], t: Tree) => q"type $T[..$targs] = $t" ≈ TypeDef(Modifiers(), T, targs, t) } - property("splice tparams into typedef (2)") = forAll { (T: TypeName, targs1: List[TypeDef], targs2: List[TypeDef], t: Tree) => + property("unquote tparams into typedef (2)") = forAll { (T: TypeName, targs1: List[TypeDef], targs2: List[TypeDef], t: Tree) => q"type $T[..$targs1, ..$targs2] = $t" ≈ TypeDef(Modifiers(), T, targs1 ++ targs2, t) } - property("splice tparams into typedef (3)") = forAll { (T: TypeName, targ: TypeDef, targs: List[TypeDef], t: Tree) => + property("unquote tparams into typedef (3)") = forAll { (T: TypeName, targ: TypeDef, targs: List[TypeDef], t: Tree) => q"type $T[$targ, ..$targs] = $t" ≈ TypeDef(Modifiers(), T, targ :: targs, t) } - property("splice typename into typedef with default bounds") = forAll { (T1: TypeName, T2: TypeName, t: Tree) => + property("unquote typename into typedef with default bounds") = forAll { (T1: TypeName, T2: TypeName, t: Tree) => q"type $T1[$T2 >: Any <: Nothing] = $t" ≈ TypeDef( Modifiers(), T1, @@ -169,7 +169,7 @@ trait TypeDefConstruction { self: QuasiquoteProperties => t) } - property("splice type names into compound type tree") = forAll { (T: TypeName, A: TypeName, B: TypeName) => + property("unquote type names into compound type tree") = forAll { (T: TypeName, A: TypeName, B: TypeName) => q"type $T = $A with $B" ≈ TypeDef( Modifiers(), T, List(), @@ -177,7 +177,7 @@ trait TypeDefConstruction { self: QuasiquoteProperties => Template(List(Ident(A), Ident(B)), ValDef(Modifiers(PRIVATE), termNames.WILDCARD, TypeTree(), EmptyTree), List()))) } - property("splice trees into existential type tree") = forAll { + property("unquote trees into existential type tree") = forAll { (T1: TypeName, T2: TypeName, X: TypeName, Lo: TypeName, Hi: TypeName) => q"type $T1 = $T2[$X] forSome { type $X >: $Lo <: $Hi }" ≈ @@ -189,11 +189,11 @@ trait TypeDefConstruction { self: QuasiquoteProperties => TypeDef(Modifiers(DEFERRED), X, List(), TypeBoundsTree(Ident(Lo), Ident(Hi)))))) } - property("splice tree into singleton type tree") = forAll { (name: TypeName, t: Tree) => + property("unquote tree into singleton type tree") = forAll { (name: TypeName, t: Tree) => q"type $name = $t.type" ≈ q"type $name = ${SingletonTypeTree(t)}" } - property("splice into applied type tree") = forAll { (T1: TypeName, T2: TypeName, args: List[Tree]) => + property("unquote into applied type tree") = forAll { (T1: TypeName, T2: TypeName, args: List[Tree]) => q"type $T1 = $T2[..$args]" ≈ TypeDef(Modifiers(), T1, List(), if(args.nonEmpty) AppliedTypeTree(Ident(T2), args) else Ident(T2)) @@ -201,11 +201,11 @@ trait TypeDefConstruction { self: QuasiquoteProperties => } trait ValDefConstruction { self: QuasiquoteProperties => - property("splice into val") = forAll { (name: TermName, tpt: Tree, rhs: Tree) => + property("unquote into val") = forAll { (name: TermName, tpt: Tree, rhs: Tree) => q"val $name: $tpt = $rhs" ≈ ValDef(Modifiers(), name, tpt, rhs) } - property("splice into var") = forAll { (name: TermName, tpt: Tree, rhs: Tree) => + property("unquote into var") = forAll { (name: TermName, tpt: Tree, rhs: Tree) => q"var $name: $tpt = $rhs" ≈ ValDef(Modifiers(MUTABLE), name, tpt, rhs) } @@ -216,28 +216,28 @@ trait ValDefConstruction { self: QuasiquoteProperties => } trait PatDefConstruction { self: QuasiquoteProperties => - property("splice pattern into pat def") = test { + property("unquote pattern into pat def") = test { val pat = pq"(a, b)" assertEqAst(q"val $pat = (1, 2)", "val (a, b) = (1, 2)") val tpt = tq"(Int, Int)" assertEqAst(q"val $pat: $tpt = (1, 2)", "val (a, b): (Int, Int) = (1, 2)") } - property("splice pattern into pat def within other pattern (1)") = test { + property("unquote pattern into pat def within other pattern (1)") = test { val pat = pq"(a, b)" assertEqAst(q"val Foo($pat) = Foo((1, 2))", "val Foo((a, b)) = Foo((1, 2))") val tpt = tq"Foo" assertEqAst(q"val Foo($pat): $tpt = Foo((1, 2))", "val Foo((a, b)): Foo = Foo((1, 2))") } - property("splice patterns into pat def within other pattern (2)") = test { + property("unquote patterns into pat def within other pattern (2)") = test { val pat1 = pq"(a, b)"; val pat2 = pq"(c, d)" assertEqAst(q"val ($pat1, $pat2) = ((1, 2), (3, 4))", "val ((a, b), (c, d)) = ((1, 2), (3, 4))") val tpt = tq"((Int, Int), (Int, Int))" assertEqAst(q"val ($pat1, $pat2): $tpt = ((1, 2), (3, 4))", "val ((a, b), (c, d)): ((Int, Int), (Int, Int)) = ((1, 2), (3, 4))") } - property("splice pattern without free vars into pat def") = test { + property("unquote pattern without free vars into pat def") = test { val pat = pq"((1, 2), 3)" assertEqAst(q"val $pat = ((1, 2), 3)", "{ val ((1, 2), 3) = ((1, 2), 3) }") val tpt = tq"((Int, Int), Int)" @@ -245,19 +245,19 @@ trait PatDefConstruction { self: QuasiquoteProperties => } // won't result into pattern match due to SI-8211 - property("splice typed pat into pat def") = test { + property("unquote typed pat into pat def") = test { val pat = pq"x: Int" assertEqAst(q"val $pat = 2", "{ val x: Int = 2 }") } } trait MethodConstruction { self: QuasiquoteProperties => - property("splice paramss into defdef") = test { + property("unquote paramss into defdef") = test { val paramss = List(q"val x: Int") :: List(q"val y: Int = 1") :: Nil assert(q"def foo(...$paramss)" ≈ parse("def foo(x: Int)(y: Int = 1)")) } - property("splice tparams into defdef") = test { + property("unquote tparams into defdef") = test { val tparams = q"type A" :: q"type B <: Bippy" :: Nil assert(q"def foo[..$tparams]" ≈ parse("def foo[A, B <: Bippy]")) } @@ -270,84 +270,84 @@ trait MethodConstruction { self: QuasiquoteProperties => assert(tree1.mods.annotations ≈ tree2.mods.annotations, s"${tree1.mods.annotations} =/= ${tree2.mods.annotations}") - property("splice type name into annotation") = test { + property("unquote type name into annotation") = test { val name = TypeName("annot") assertSameAnnots(q"@$name def foo", List(q"new $name")) } - property("splice ident into annotation") = test { + property("unquote ident into annotation") = test { val name = TypeName("annot") val ident = Ident(name) assertSameAnnots(q"@$ident def foo", List(q"new $name")) } - property("splice idents into annotation") = test { + property("unquote idents into annotation") = test { val idents = List(Ident(TypeName("annot1")), Ident(TypeName("annot2"))) assertSameAnnots(q"@..$idents def foo", idents.map { ident => Apply(Select(New(ident), termNames.CONSTRUCTOR), List()) }) } - property("splice constructor calls into annotation") = test { + property("unquote constructor calls into annotation") = test { val ctorcalls = List(q"new a1", q"new a2") assertSameAnnots(q"@..$ctorcalls def foo", ctorcalls) } - property("splice multiple annotations (1)") = test { + property("unquote multiple annotations (1)") = test { val annot1 = q"new a1" val annot2 = q"new a2" val res = q"@$annot1 @$annot2 def foo" assertSameAnnots(res, List(annot1, annot2)) } - property("splice multiple annotations (2)") = test { + property("unquote multiple annotations (2)") = test { val annot1 = q"new a1" val annots = List(q"new a2", q"new a3") val res = q"@$annot1 @..$annots def foo" assertSameAnnots(res, annot1 :: annots) } - property("splice annotations with arguments (1)") = test { + property("unquote annotations with arguments (1)") = test { val a = q"new a(x)" assertSameAnnots(q"@$a def foo", q"@a(x) def foo") } - property("splice annotations with arguments (2)") = test { + property("unquote annotations with arguments (2)") = test { val a = TypeName("a") assertSameAnnots(q"@$a(x) def foo", q"@a(x) def foo") } - property("splice annotations with arguments (3") = test { + property("unquote annotations with arguments (3") = test { val a = Ident(TypeName("a")) assertSameAnnots(q"@$a(x) def foo", q"@a(x) def foo") } - property("splice improper tree into annot") = test { + property("unquote improper tree into annot") = test { val t = tq"Foo[Baz]" assertThrows[IllegalArgumentException] { q"@$t def foo" } } - property("can't splice annotations with arguments specificed twice") = test { + property("can't unquote annotations with arguments specificed twice") = test { val a = q"new a(x)" assertThrows[IllegalArgumentException] { q"@$a(y) def foo" } } - property("splice annotation with targs") = test { + property("unquote annotation with targs") = test { val a = q"new Foo[A, B]" assertEqAst(q"@$a def foo", "@Foo[A,B] def foo") } - property("splice annotation with multiple argument lists") = test { + property("unquote annotation with multiple argument lists") = test { val a = q"new Foo(a)(b)" assertEqAst(q"@$a def foo", "@Foo(a)(b) def foo") } } trait PackageConstruction { self: QuasiquoteProperties => - property("splice select into package name") = test { + property("unquote select into package name") = test { val name = q"foo.bar" assertEqAst(q"package $name { }", "package foo.bar { }") } @@ -357,12 +357,12 @@ trait PackageConstruction { self: QuasiquoteProperties => assertEqAst(q"package $name { }", "package bippy { }") } - property("splice members into package body") = test { + property("unquote members into package body") = test { val members = q"class C" :: q"object O" :: Nil assertEqAst(q"package foo { ..$members }", "package foo { class C; object O }") } - property("splice illegal members into package body") = test { + property("unquote illegal members into package body") = test { val f = q"def f" assertThrows[IllegalArgumentException] { q"package foo { $f }" } val v = q"val v = 0" @@ -371,24 +371,24 @@ trait PackageConstruction { self: QuasiquoteProperties => assertThrows[IllegalArgumentException] { q"package foo { $expr }" } } - property("splice name into package object") = test { + property("unquote name into package object") = test { val foo = TermName("foo") assertEqAst(q"package object $foo", "package object foo") } - property("splice parents into package object") = test { + property("unquote parents into package object") = test { val parents = tq"a" :: tq"b" :: Nil assertEqAst(q"package object foo extends ..$parents", "package object foo extends a with b") } - property("splice members into package object") = test { + property("unquote members into package object") = test { val members = q"def foo" :: q"val x = 1" :: Nil assertEqAst(q"package object foo { ..$members }", "package object foo { def foo; val x = 1 }") } - property("splice early def into package object") = test { + property("unquote early def into package object") = test { val edefs = q"val x = 1" :: q"type I = Int" :: Nil assertEqAst(q"package object foo extends { ..$edefs } with Any", "package object foo extends { val x = 1; type I = Int } with Any") diff --git a/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala index 512b81c0e6..996ac65b36 100644 --- a/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala @@ -259,7 +259,7 @@ trait ImportDeconstruction { self: QuasiquoteProperties => val pq"_" = right } - property("splice names into import selector") = forAll { + property("unquote names into import selector") = forAll { (expr: Tree, plain: TermName, oldname: TermName, newname: TermName, discard: TermName) => val Import(expr1, List( diff --git a/test/files/scalacheck/quasiquotes/ErrorProps.scala b/test/files/scalacheck/quasiquotes/ErrorProps.scala index 1ba9bba381..d61119d98f 100644 --- a/test/files/scalacheck/quasiquotes/ErrorProps.scala +++ b/test/files/scalacheck/quasiquotes/ErrorProps.scala @@ -1,21 +1,21 @@ import org.scalacheck._, Prop._, Gen._, Arbitrary._ object ErrorProps extends QuasiquoteProperties("errors") { - property("can't extract two .. cardinalities in a row") = fails( + property("can't extract two .. rankinalities in a row") = fails( "Can't extract with .. here", """ val xs = List(q"x1", q"x2") val q"f(..$xs1, ..$xs2)" = xs """) - property("can't splice with given cardinality") = fails( - "Can't splice List[reflect.runtime.universe.Ident], consider using ..", + property("can't unquote with given rank") = fails( + "Can't unquote List[reflect.runtime.universe.Ident], consider using ..", """ val xs = List(q"x", q"x") q"$xs" """) - property("splice typename into typedef with default bounds") = fails( + property("unquote typename into typedef with default bounds") = fails( "reflect.runtime.universe.Name expected but reflect.runtime.universe.TypeDef found", """ val T1 = TypeName("T1") @@ -25,8 +25,8 @@ object ErrorProps extends QuasiquoteProperties("errors") { TypeDef(Modifiers(), T1, List(T2), t) """) - property("can't splice annotations with ... cardinality") = fails( - "Can't splice with ... here", + property("can't unquote annotations with ... rank") = fails( + "Can't unquote with ... here", """ val annots = List(List(q"Foo")) q"@...$annots def foo" @@ -39,15 +39,15 @@ object ErrorProps extends QuasiquoteProperties("errors") { StringContext(s).q() """) - property("don't know how to splice inside of strings") = fails( - "Don't know how to splice here", + property("don't know how to unquote inside of strings") = fails( + "Don't know how to unquote here", """ val x: Tree = EmptyTree StringContext("\"", "\"").q(x) """) property("non-liftable type ..") = fails( - "Can't splice List[StringBuilder] with .., consider omitting the dots or providing an implicit instance of Liftable[StringBuilder]", + "Can't unquote List[StringBuilder] with .., consider omitting the dots or providing an implicit instance of Liftable[StringBuilder]", """ import java.lang.StringBuilder val bazs = List(new StringBuilder) @@ -55,38 +55,38 @@ object ErrorProps extends QuasiquoteProperties("errors") { """) property("non-liftable type ...") = fails( - "Can't splice List[List[StringBuilder]] with .., consider using ... or providing an implicit instance of Liftable[StringBuilder]", + "Can't unquote List[List[StringBuilder]] with .., consider using ... or providing an implicit instance of Liftable[StringBuilder]", """ import java.lang.StringBuilder val bazs = List(List(new StringBuilder)) q"f(..$bazs)" """) - property("use .. card or provide liftable") = fails( - "Can't splice List[StringBuilder], consider using .. or providing an implicit instance of Liftable[List[StringBuilder]]", + property("use .. rank or provide liftable") = fails( + "Can't unquote List[StringBuilder], consider using .. or providing an implicit instance of Liftable[List[StringBuilder]]", """ import java.lang.StringBuilder val lst: List[StringBuilder] = Nil q"f($lst)" """) - property("use ... card or provide liftable") = fails( - "Can't splice List[List[reflect.runtime.universe.Ident]], consider using ...", + property("use ... rank or provide liftable") = fails( + "Can't unquote List[List[reflect.runtime.universe.Ident]], consider using ...", """ val xs = List(List(q"x", q"x")) q"$xs" """) property("not liftable or natively supported") = fails( - "Can't splice StringBuilder, consider providing an implicit instance of Liftable[StringBuilder]", + "Can't unquote StringBuilder, consider providing an implicit instance of Liftable[StringBuilder]", """ import java.lang.StringBuilder val sb = new StringBuilder q"f($sb)" """) - property("can't splice with ... card here") = fails( - "Can't splice with ... here", + property("can't unquote with ... rank here") = fails( + "Can't unquote with ... here", """ val lst: List[List[Tree]] = Nil; val t = EmptyTree q"f(...$lst, $t)" @@ -106,29 +106,29 @@ object ErrorProps extends QuasiquoteProperties("errors") { q"$t def foo" """) - property("cant splice flags together with mods") = fails( - "Can't splice flags together with modifiers, consider merging flags into modifiers", + property("cant unquote flags together with mods") = fails( + "Can't unquote flags together with modifiers, consider merging flags into modifiers", """ val f = Flag.IMPLICIT; val m = NoMods q"$f $m def foo" """) - property("can't splice mods with annots") = fails( - "Can't splice modifiers together with annotations, consider merging annotations into modifiers", + property("can't unquote mods with annots") = fails( + "Can't unquote modifiers together with annotations, consider merging annotations into modifiers", """ val m = NoMods q"@annot $m def foo" """) - property("can't splice modifiers with inline flags") = fails( - "Can't splice modifiers together with flags, consider merging flags into modifiers", + property("can't unquote modifiers with inline flags") = fails( + "Can't unquote modifiers together with flags, consider merging flags into modifiers", """ val m = NoMods q"$m implicit def foo" """) - property("can't splice multiple mods") = fails( - "Can't splice multiple modifiers, consider merging them into a single modifiers instance", + property("can't unquote multiple mods") = fails( + "Can't unquote multiple modifiers, consider merging them into a single modifiers instance", """ val m1 = NoMods; val m2 = NoMods q"$m1 $m2 def foo" @@ -146,15 +146,15 @@ object ErrorProps extends QuasiquoteProperties("errors") { val q"$m1 $m2 def foo" = EmptyTree """) - property("can't splice values of Null") = fails( - "Can't splice Null, bottom type values often indicate programmer mistake", + property("can't unquote values of Null") = fails( + "Can't unquote Null, bottom type values often indicate programmer mistake", """ val n = null q"$n" """) - property("can't splice values of Nothing") = fails( - "Can't splice Nothing, bottom type values often indicate programmer mistake", + property("can't unquote values of Nothing") = fails( + "Can't unquote Nothing, bottom type values often indicate programmer mistake", """ def n = ??? q"$n" diff --git a/test/files/scalacheck/quasiquotes/LiftableProps.scala b/test/files/scalacheck/quasiquotes/LiftableProps.scala index 20cfcbe139..5d0eeb53c6 100644 --- a/test/files/scalacheck/quasiquotes/LiftableProps.scala +++ b/test/files/scalacheck/quasiquotes/LiftableProps.scala @@ -2,62 +2,62 @@ import org.scalacheck._, Prop._, Gen._, Arbitrary._ import scala.reflect.runtime.universe._, Flag._ object LiftableProps extends QuasiquoteProperties("liftable") { - property("splice byte") = test { + property("unquote byte") = test { val c: Byte = 0 assert(q"$c" ≈ Literal(Constant(c))) assert(q"${0: Byte}" ≈ Literal(Constant(c))) } - property("splice short") = test { + property("unquote short") = test { val c: Short = 0 assert(q"$c" ≈ Literal(Constant(c))) assert(q"${0: Short}" ≈ Literal(Constant(c))) } - property("splice char") = test { + property("unquote char") = test { val c: Char = 'c' assert(q"$c" ≈ Literal(Constant(c))) assert(q"${'c'}" ≈ Literal(Constant(c))) } - property("splice int") = test { + property("unquote int") = test { val c: Int = 0 assert(q"$c" ≈ Literal(Constant(c))) assert(q"${0: Int}" ≈ Literal(Constant(c))) } - property("splice long") = test { + property("unquote long") = test { val c: Long = 0 assert(q"$c" ≈ Literal(Constant(c))) assert(q"${0: Long}" ≈ Literal(Constant(c))) } - property("splice float") = test { + property("unquote 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 { + property("unquote 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 { + property("unquote 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 { + property("unquote string") = test { val c: String = "s" assert(q"$c" ≈ Literal(Constant(c))) assert(q"${"s"}" ≈ Literal(Constant(c))) } - property("splice unit") = test { + property("unquote unit") = test { val c: Unit = () assert(q"$c" ≈ Literal(Constant(c))) assert(q"${()}" ≈ Literal(Constant(c))) diff --git a/test/files/scalacheck/quasiquotes/PatternConstructionProps.scala b/test/files/scalacheck/quasiquotes/PatternConstructionProps.scala index fffaf1b363..7ed95fa984 100644 --- a/test/files/scalacheck/quasiquotes/PatternConstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/PatternConstructionProps.scala @@ -2,35 +2,35 @@ import org.scalacheck._, Prop._, Gen._, Arbitrary._ import scala.reflect.runtime.universe._, Flag._ object PatternConstructionProps extends QuasiquoteProperties("pattern construction") { - property("splice bind") = forAll { (bind: Bind) => + property("unquote bind") = forAll { (bind: Bind) => pq"$bind" ≈ bind } - property("splice name into bind") = forAll { (name: TermName) => + property("unquote name into bind") = forAll { (name: TermName) => pq"$name" ≈ Bind(name, Ident(termNames.WILDCARD)) } - property("splice name and tree into bind") = forAll { (name: TermName, tree: Tree) => + property("unquote name and tree into bind") = forAll { (name: TermName, tree: Tree) => pq"$name @ $tree" ≈ Bind(name, tree) } - property("splice type name into typed") = forAll { (name: TypeName) => + property("unquote type name into typed") = forAll { (name: TypeName) => pq"_ : $name" ≈ Typed(Ident(termNames.WILDCARD), Ident(name)) } - property("splice tree into typed") = forAll { (typ: Tree) => + property("unquote tree into typed") = forAll { (typ: Tree) => pq"_ : $typ" ≈ Typed(Ident(termNames.WILDCARD), typ) } - property("splice into apply") = forAll { (pat: Tree, subpat: Tree) => + property("unquote into apply") = forAll { (pat: Tree, subpat: Tree) => pq"$pat($subpat)" ≈ Apply(pat, List(subpat)) } - property("splice into casedef") = forAll { (pat: Tree, cond: Tree, body: Tree) => + property("unquote into casedef") = forAll { (pat: Tree, cond: Tree, body: Tree) => cq"$pat if $cond => $body" ≈ CaseDef(pat, cond, body) } - property("splice into alternative") = forAll { (first: Tree, rest: List[Tree]) => + property("unquote into alternative") = forAll { (first: Tree, rest: List[Tree]) => pq"$first | ..$rest" ≈ Alternative(first :: rest) } } diff --git a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala index 4dbf746cfe..10ce1604b1 100644 --- a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala @@ -2,41 +2,41 @@ import org.scalacheck._, Prop._, Gen._, Arbitrary._ import scala.reflect.runtime.universe._, Flag._ object TermConstructionProps extends QuasiquoteProperties("term construction") { - property("splice single tree return tree itself") = forAll { (t: Tree) => + property("unquote single tree return tree itself") = forAll { (t: Tree) => q"$t" ≈ t } - property("splice trees into if expression") = forAll { (t1: Tree, t2: Tree, t3: Tree) => + property("unquote trees into if expression") = forAll { (t1: Tree, t2: Tree, t3: Tree) => q"if($t1) $t2 else $t3" ≈ If(t1, t2, t3) } - property("splice trees into ascriptiopn") = forAll { (t1: Tree, t2: Tree) => + property("unquote trees into ascriptiopn") = forAll { (t1: Tree, t2: Tree) => q"$t1 : $t2" ≈ Typed(t1, t2) } - property("splice trees into apply") = forAll { (t1: Tree, t2: Tree, t3: Tree) => + property("unquote trees into apply") = forAll { (t1: Tree, t2: Tree, t3: Tree) => q"$t1($t2, $t3)" ≈ Apply(t1, List(t2, t3)) } - property("splice trees with .. cardinality into apply") = forAll { (ts: List[Tree]) => + property("unquote trees with .. rank into apply") = forAll { (ts: List[Tree]) => q"f(..$ts)" ≈ Apply(q"f", ts) } - property("splice iterable into apply") = forAll { (trees: List[Tree]) => + property("unquote iterable into apply") = forAll { (trees: List[Tree]) => val itrees: Iterable[Tree] = trees q"f(..$itrees)" ≈ Apply(q"f", trees) } - property("splice trees with ... cardinality into apply") = forAll { (ts1: List[Tree], ts2: List[Tree]) => + property("unquote trees with ... rank into apply") = forAll { (ts1: List[Tree], ts2: List[Tree]) => val argss = List(ts1, ts2) q"f(...$argss)" ≈ Apply(Apply(q"f", ts1), ts2) } - property("splice term name into assign") = forAll { (name: TermName, t: Tree) => + property("unquote term name into assign") = forAll { (name: TermName, t: Tree) => q"$name = $t" ≈ Assign(Ident(name), t) } - property("splice trees into block") = forAll { (t1: Tree, t2: Tree, t3: Tree) => + property("unquote trees into block") = forAll { (t1: Tree, t2: Tree, t3: Tree) => blockInvariant(q"""{ $t1 $t2 @@ -45,25 +45,25 @@ object TermConstructionProps extends QuasiquoteProperties("term construction") { } - property("splice tree into new") = forAll { (tree: Tree) => + property("unquote tree into new") = forAll { (tree: Tree) => q"new $tree" ≈ Apply(Select(New(tree), termNames.CONSTRUCTOR), List()) } - property("splice tree into return") = forAll { (tree: Tree) => + property("unquote tree into return") = forAll { (tree: Tree) => q"return $tree" ≈ Return(tree) } - property("splice a list of arguments") = forAll { (fun: Tree, args: List[Tree]) => + property("unquote a list of arguments") = forAll { (fun: Tree, args: List[Tree]) => q"$fun(..$args)" ≈ Apply(fun, args) } - property("splice list and non-list fun arguments") = forAll { (fun: Tree, arg1: Tree, arg2: Tree, args: List[Tree]) => + property("unquote list and non-list fun arguments") = forAll { (fun: Tree, arg1: Tree, arg2: Tree, args: List[Tree]) => q"$fun(..$args, $arg1, $arg2)" ≈ Apply(fun, args ++ List(arg1) ++ List(arg2)) && q"$fun($arg1, ..$args, $arg2)" ≈ Apply(fun, List(arg1) ++ args ++ List(arg2)) && q"$fun($arg1, $arg2, ..$args)" ≈ Apply(fun, List(arg1) ++ List(arg2) ++ args) } - property("splice into new") = forAll { (name: TypeName, body: List[Tree]) => + property("unquote into new") = forAll { (name: TypeName, body: List[Tree]) => q"new $name { ..$body }" ≈ q"""{ final class $$anon extends $name { @@ -73,29 +73,29 @@ object TermConstructionProps extends QuasiquoteProperties("term construction") { }""" } - property("splice type name into this") = forAll { (T: TypeName) => + property("unquote type name into this") = forAll { (T: TypeName) => q"$T.this" ≈ This(T) } - property("splice tree into throw") = forAll { (t: Tree) => + property("unquote tree into throw") = forAll { (t: Tree) => q"throw $t" ≈ Throw(t) } - property("splice trees into type apply") = forAll { (fun: TreeIsTerm, types: List[Tree]) => + property("unquote trees into type apply") = forAll { (fun: TreeIsTerm, types: List[Tree]) => q"$fun[..$types]" ≈ (if (types.nonEmpty) TypeApply(fun, types) else fun) } - property("splice trees into while loop") = forAll { (cond: Tree, body: Tree) => + property("unquote trees into while loop") = forAll { (cond: Tree, body: Tree) => val LabelDef(_, List(), If(cond1, Block(List(body1), Apply(_, List())), Literal(Constant(())))) = q"while($cond) $body" body1 ≈ body && cond1 ≈ cond } - property("splice trees into do while loop") = forAll { (cond: Tree, body: Tree) => + property("unquote trees into do while loop") = forAll { (cond: Tree, body: Tree) => val LabelDef(_, List(), Block(List(body1), If(cond1, Apply(_, List()), Literal(Constant(()))))) = q"do $body while($cond)" body1 ≈ body && cond1 ≈ cond } - property("splice trees into alternative") = forAll { (c: Tree, A: Tree, B: Tree) => + property("unquote trees into alternative") = forAll { (c: Tree, A: Tree, B: Tree) => q"$c match { case $A | $B => }" ≈ Match(c, List( CaseDef(Alternative(List(A, B)), EmptyTree, Literal(Constant(()))))) @@ -109,24 +109,24 @@ object TermConstructionProps extends QuasiquoteProperties("term construction") { case init :+ last => Block(init, last) }) - property("splice list of trees into block (1)") = forAll { (trees: List[Tree]) => + property("unquote list of trees into block (1)") = forAll { (trees: List[Tree]) => blockInvariant(q"{ ..$trees }", trees) } - property("splice list of trees into block (2)") = forAll { (trees1: List[Tree], trees2: List[Tree]) => + property("unquote list of trees into block (2)") = forAll { (trees1: List[Tree], trees2: List[Tree]) => blockInvariant(q"{ ..$trees1 ; ..$trees2 }", trees1 ++ trees2) } - property("splice list of trees into block (3)") = forAll { (trees: List[Tree], tree: Tree) => + property("unquote list of trees into block (3)") = forAll { (trees: List[Tree], tree: Tree) => blockInvariant(q"{ ..$trees; $tree }", trees :+ tree) } - property("splice term into brackets") = test { + property("unquote term into brackets") = test { val a = q"a" assert(q"($a)" ≈ a) } - property("splice terms into tuple") = test { + property("unquote terms into tuple") = test { val a1 = q"a1" val a2 = q"a2" val as = List(a1, a2) @@ -134,12 +134,12 @@ object TermConstructionProps extends QuasiquoteProperties("term construction") { assert(q"(a0, ..$as)" ≈ q"scala.Tuple3(a0, $a1, $a2)") } - property("splice empty list into tuple") = test { + property("unquote empty list into tuple") = test { val empty = List[Tree]() assert(q"(..$empty)" ≈ q"()") } - property("splice single element list into tuple") = test { + property("unquote single element list into tuple") = test { val xs = q"x" :: Nil assert(q"(..$xs)" ≈ xs.head) } @@ -196,7 +196,7 @@ object TermConstructionProps extends QuasiquoteProperties("term construction") { assert(q"f(${if (true) q"a" else q"b"})" ≈ q"f(a)") } - property("splice iterable of non-parametric type") = test { + property("unquote iterable of non-parametric type") = test { object O extends Iterable[Tree] { def iterator = List(q"foo").iterator } q"f(..$O)" } diff --git a/test/files/scalacheck/quasiquotes/TypeConstructionProps.scala b/test/files/scalacheck/quasiquotes/TypeConstructionProps.scala index 07875af326..27ad4c50e9 100644 --- a/test/files/scalacheck/quasiquotes/TypeConstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/TypeConstructionProps.scala @@ -6,7 +6,7 @@ object TypeConstructionProps extends QuasiquoteProperties("type construction") tq"x" ≈ Ident(TypeName("x")) } - property("splice type names into AppliedTypeTree") = forAll { (name1: TypeName, name2: TypeName) => + property("unquote type names into AppliedTypeTree") = forAll { (name1: TypeName, name2: TypeName) => tq"$name1[$name2]" ≈ AppliedTypeTree(Ident(name1), List(Ident(name2))) } diff --git a/test/files/scalacheck/quasiquotes/TypecheckedProps.scala b/test/files/scalacheck/quasiquotes/TypecheckedProps.scala index 8b1cb6cc49..432c0959c9 100644 --- a/test/files/scalacheck/quasiquotes/TypecheckedProps.scala +++ b/test/files/scalacheck/quasiquotes/TypecheckedProps.scala @@ -65,7 +65,7 @@ object TypecheckedProps extends QuasiquoteProperties("typechecked") { } property("extract UnApply (2)") = test { - val q"object $_ { $_; $_; $m }" = typecheck(q""" + val q"object $_ { $_; $m }" = typecheck(q""" object Test { case class Cell(val x: Int) new Cell(0) match { case Cell(v) => v } @@ -82,4 +82,74 @@ object TypecheckedProps extends QuasiquoteProperties("typechecked") { val q"val x: ${tq""} = 42" = typechecked val q"val x: ${t: Type} = 42" = typechecked } + + property("class with param (1)") = test { + val paramName = TermName("x") + val q"class $_($param)" = typecheck(q"class Test(val $paramName: Int)") + + assert(param.name == paramName) + } + + property("class with param (2)") = test { + val paramName = TermName("y") + val q"{class $_($param)}" = typecheck(q"class Test(val $paramName: Int = 3)") + + assert(param.name == paramName) + assert(param.rhs ≈ q"3") + } + + property("class with params") = test { + val pName1 = TermName("x1") + val pName2 = TermName("x2") + val q"{class $_($param1)(..$params2)}" = typecheck(q"class Test(val x0: Float)(val $pName1: Int = 3, $pName2: String)") + + val List(p1, p2, _*) = params2 + + assert(p1.name == pName1) + assert(p2.name == pName2) + assert(params2.size == 2) + } + + property("implicit class") = test { + val clName = TypeName("Test") + val paramName = TermName("x") + val q"{implicit class $name($param)}" = typecheck(q"implicit class $clName(val $paramName: String)") + + assert(name == clName) + assert(param.name == paramName) + } + + property("block with lazy") = test { + val lazyName = TermName("x") + val lazyRhsVal = 42 + val lazyRhs = Literal(Constant(lazyRhsVal)) + val q"{lazy val $pname = $rhs}" = typecheck(q"{lazy val $lazyName = $lazyRhsVal}") + + assert(pname == lazyName) + assert(rhs ≈ lazyRhs) + } + + property("class with lazy") = test { + val clName = TypeName("Test") + val paramName = TermName("x") + val q"class $name{lazy val $pname = $_}" = typecheck(q"class $clName {lazy val $paramName = 42}") + + assert(name == clName) + assert(pname == paramName) + } + + property("case class with object") = test { + val defName = TermName("z") + val defRhsVal = 42 + val defRhs = Literal(Constant(defRhsVal)) + val q"object $_{ $_; object $_ extends ..$_ {def $name = $rhs} }" = + typecheck(q""" + object Test{ + case class C(x: Int) { def y = x }; + object C { def $defName = $defRhsVal } + }""") + + assert(name == defName) + assert(rhs ≈ defRhs) + } } diff --git a/test/files/scalacheck/quasiquotes/UnliftableProps.scala b/test/files/scalacheck/quasiquotes/UnliftableProps.scala index 4e996c90d7..1d7629aa29 100644 --- a/test/files/scalacheck/quasiquotes/UnliftableProps.scala +++ b/test/files/scalacheck/quasiquotes/UnliftableProps.scala @@ -99,13 +99,13 @@ object UnliftableProps extends QuasiquoteProperties("unliftable") { assert(l5 == orig2) } - property("don't unlift non-tree splicee (1)") = test { + property("don't unlift non-tree unquotee (1)") = test { val q"${a: TermName}.${b: TermName}" = q"a.b" assert(a == TermName("a")) assert(b == TermName("b")) } - property("don't unlift non-tree splicee (2)") = test { + property("don't unlift non-tree unquotee (2)") = test { val q"${mods: Modifiers} def foo" = q"def foo" assert(mods == Modifiers(DEFERRED)) } diff --git a/test/junit/scala/reflect/internal/PrintersTest.scala b/test/junit/scala/reflect/internal/PrintersTest.scala index 9fec112c99..62cb401aa9 100644 --- a/test/junit/scala/reflect/internal/PrintersTest.scala +++ b/test/junit/scala/reflect/internal/PrintersTest.scala @@ -821,4 +821,4 @@ // |case class X(x: Int, s: String) { // | def y = "test" // |}""", q"""case class X(x: Int, s: String){ def y = "test" }""") -// } +// }
\ No newline at end of file diff --git a/test/scaladoc/run/diagrams-base.scala b/test/scaladoc/run/diagrams-base.scala index b7aeed51d2..1e83a78b38 100644 --- a/test/scaladoc/run/diagrams-base.scala +++ b/test/scaladoc/run/diagrams-base.scala @@ -46,7 +46,7 @@ object Test extends ScaladocModelTest { val (incoming, outgoing) = diag.edges.partition(!_._1.isThisNode) assert(incoming.length == 5) - assert(outgoing.head._2.length == 4) + assert(outgoing.head._2.length == 4, s"${outgoing.head._2} has length ${outgoing.head._2.length}, expecting 4") val (outgoingSuperclass, outgoingImplicit) = outgoing.head._2.partition(_.isNormalNode) assert(outgoingSuperclass.length == 3) diff --git a/test/scaladoc/run/diagrams-filtering.scala b/test/scaladoc/run/diagrams-filtering.scala index 54e3e9ac63..12b5f4caba 100644 --- a/test/scaladoc/run/diagrams-filtering.scala +++ b/test/scaladoc/run/diagrams-filtering.scala @@ -57,7 +57,7 @@ object Test extends ScaladocModelTest { // Assert we have just 3 nodes and 2 edges val A = base._trait("A") val ADiag = A.inheritanceDiagram.get - assert(ADiag.nodes.length == 3) + assert(ADiag.nodes.length == 3, s"${ADiag.nodes} has length ${ADiag.nodes.length}, expected 3") assert(ADiag.edges.map(_._2.length).sum == 2) // trait C |