summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2014-02-16 16:58:28 +0100
committerEugene Burmako <xeno.by@gmail.com>2014-02-16 19:25:38 +0100
commit862f7709cdabd82327ca0f37a480884c88f96be7 (patch)
tree688717816eeee19ddb391f1009c82d9b6f09f224 /src/reflect
parent2fc0164a5e777a0495c1801d8d38d60158ec2a77 (diff)
parent6ef6c96eff2f0d2f505d45a1436d73a960193076 (diff)
downloadscala-862f7709cdabd82327ca0f37a480884c88f96be7.tar.gz
scala-862f7709cdabd82327ca0f37a480884c88f96be7.tar.bz2
scala-862f7709cdabd82327ca0f37a480884c88f96be7.zip
Merge remote-tracking branch 'origin/master' into topic/palladium0
Conflicts: src/compiler/scala/reflect/macros/compiler/Resolvers.scala src/compiler/scala/reflect/macros/contexts/Typers.scala src/compiler/scala/tools/reflect/ToolBoxFactory.scala src/reflect/scala/reflect/api/BuildUtils.scala
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/scala/reflect/api/Internals.scala6
-rw-r--r--src/reflect/scala/reflect/api/Printers.scala14
-rw-r--r--src/reflect/scala/reflect/api/StandardLiftables.scala6
-rw-r--r--src/reflect/scala/reflect/internal/Printers.scala11
-rw-r--r--src/reflect/scala/reflect/internal/ReificationSupport.scala92
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala21
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala54
-rw-r--r--src/reflect/scala/reflect/internal/TreeGen.scala4
-rw-r--r--src/reflect/scala/reflect/internal/TreeInfo.scala15
-rw-r--r--src/reflect/scala/reflect/internal/Trees.scala9
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala79
-rw-r--r--src/reflect/scala/reflect/internal/settings/MutableSettings.scala1
-rw-r--r--src/reflect/scala/reflect/runtime/Settings.scala1
13 files changed, 210 insertions, 103 deletions
diff --git a/src/reflect/scala/reflect/api/Internals.scala b/src/reflect/scala/reflect/api/Internals.scala
index 2fd52d5cd8..37406385c8 100644
--- a/src/reflect/scala/reflect/api/Internals.scala
+++ b/src/reflect/scala/reflect/api/Internals.scala
@@ -698,6 +698,12 @@ trait Internals { self: Universe =>
def unapply(tree: Tree): Option[(Modifiers, TermName, Tree, Tree)]
}
+ val SyntacticPatDef: SyntacticPatDefExtractor
+
+ trait SyntacticPatDefExtractor {
+ def apply(mods: Modifiers, pat: Tree, tpt: Tree, rhs: Tree): List[ValDef]
+ }
+
val SyntacticAssign: SyntacticAssignExtractor
trait SyntacticAssignExtractor {
diff --git a/src/reflect/scala/reflect/api/Printers.scala b/src/reflect/scala/reflect/api/Printers.scala
index 6f634c55fe..b262fdce68 100644
--- a/src/reflect/scala/reflect/api/Printers.scala
+++ b/src/reflect/scala/reflect/api/Printers.scala
@@ -142,6 +142,7 @@ trait Printers { self: Universe =>
def print(args: Any*)
protected var printTypes = false
protected var printIds = false
+ protected var printOwners = false
protected var printKinds = false
protected var printMirrors = false
protected var printPositions = false
@@ -149,6 +150,8 @@ trait Printers { self: Universe =>
def withoutTypes: this.type = { printTypes = false; this }
def withIds: this.type = { printIds = true; this }
def withoutIds: this.type = { printIds = false; this }
+ def withOwners: this.type = { printOwners = true; this }
+ def withoutOwners: this.type = { printOwners = false; this }
def withKinds: this.type = { printKinds = true; this }
def withoutKinds: this.type = { printKinds = false; this }
def withMirrors: this.type = { printMirrors = true; this }
@@ -169,12 +172,13 @@ trait Printers { self: Universe =>
}
/** @group Printers */
- protected def render(what: Any, mkPrinter: PrintWriter => TreePrinter, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None, printPositions: BooleanFlag = None): String = {
+ protected def render(what: Any, mkPrinter: PrintWriter => TreePrinter, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printOwners: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None, printPositions: BooleanFlag = None): String = {
val buffer = new StringWriter()
val writer = new PrintWriter(buffer)
val printer = mkPrinter(writer)
printTypes.value.map(printTypes => if (printTypes) printer.withTypes else printer.withoutTypes)
printIds.value.map(printIds => if (printIds) printer.withIds else printer.withoutIds)
+ printOwners.value.map(printOwners => if (printOwners) printer.withOwners else printer.withoutOwners)
printKinds.value.map(printKinds => if (printKinds) printer.withKinds else printer.withoutKinds)
printMirrors.value.map(printMirrors => if (printMirrors) printer.withMirrors else printer.withoutMirrors)
printPositions.value.map(printPositions => if (printPositions) printer.withPositions else printer.withoutPositions)
@@ -193,8 +197,8 @@ trait Printers { self: Universe =>
*
* @group Printers
*/
- def show(any: Any, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None, printPositions: BooleanFlag = None): String =
- render(any, newTreePrinter(_), printTypes, printIds, printKinds, printMirrors, printPositions)
+ def show(any: Any, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printOwners: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None, printPositions: BooleanFlag = None): String =
+ render(any, newTreePrinter(_), printTypes, printIds, printOwners, printKinds, printMirrors, printPositions)
/** Hook to define what `show(...)` means.
* @group Printers
@@ -225,8 +229,8 @@ trait Printers { self: Universe =>
*
* @group Printers
*/
- def showRaw(any: Any, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None, printPositions: BooleanFlag = None): String =
- render(any, newRawTreePrinter(_), printTypes, printIds, printKinds, printMirrors, printPositions)
+ def showRaw(any: Any, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printOwners: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None, printPositions: BooleanFlag = None): String =
+ render(any, newRawTreePrinter(_), printTypes, printIds, printOwners, printKinds, printMirrors, printPositions)
/** Hook to define what `showRaw(...)` means.
* @group Printers
diff --git a/src/reflect/scala/reflect/api/StandardLiftables.scala b/src/reflect/scala/reflect/api/StandardLiftables.scala
index 6fc00de3e5..af11de46ce 100644
--- a/src/reflect/scala/reflect/api/StandardLiftables.scala
+++ b/src/reflect/scala/reflect/api/StandardLiftables.scala
@@ -54,9 +54,6 @@ trait StandardLiftables { self: Universe =>
case right: Right[L, R] => lift(right)
}
- implicit def liftTuple1[T1](implicit liftT1: Liftable[T1]): Liftable[Tuple1[T1]] = Liftable { t =>
- SyntacticTuple(liftT1(t._1) :: Nil)
- }
implicit def liftTuple2[T1, T2](implicit liftT1: Liftable[T1], liftT2: Liftable[T2]): Liftable[Tuple2[T1, T2]] = Liftable { t =>
SyntacticTuple(liftT1(t._1) :: liftT2(t._2) :: Nil)
}
@@ -148,9 +145,6 @@ trait StandardLiftables { self: Universe =>
implicit def unliftType: Unliftable[Type] = Unliftable[Type] { case tt: TypeTree if tt.tpe != null => tt.tpe }
implicit def unliftConstant: Unliftable[Constant] = Unliftable[Constant] { case Literal(const) => const }
- implicit def unliftTuple1[T1](implicit UnliftT1: Unliftable[T1]): Unliftable[Tuple1[T1]] = Unliftable {
- case SyntacticTuple(UnliftT1(v1) :: Nil) => Tuple1(v1)
- }
implicit def unliftTuple2[T1, T2](implicit UnliftT1: Unliftable[T1], UnliftT2: Unliftable[T2]): Unliftable[Tuple2[T1, T2]] = Unliftable {
case SyntacticTuple(UnliftT1(v1) :: UnliftT2(v2) :: Nil) => Tuple2(v1, v2)
}
diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala
index 8ec4c98cd9..b1d76b6056 100644
--- a/src/reflect/scala/reflect/internal/Printers.scala
+++ b/src/reflect/scala/reflect/internal/Printers.scala
@@ -33,10 +33,10 @@ trait Printers extends api.Printers { self: SymbolTable =>
def qowner = quotedName(sym.owner.name.dropLocal, decoded)
def qsymbol = quotedName(sym.nameString)
- if (sym.name.toTermName == nme.ERROR)
- s"<$qname: error>"
- else if (sym == null || sym == NoSymbol)
+ if (sym == null || sym == NoSymbol)
qname
+ else if (sym.isErroneous)
+ s"<$qname: error>"
else if (sym.isMixinConstructor)
s"/*$qowner*/$qsymbol"
else
@@ -65,6 +65,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
printTypes = settings.printtypes.value
printIds = settings.uniqid.value
+ printOwners = settings.Yshowsymowners.value
printKinds = settings.Yshowsymkinds.value
printMirrors = false // typically there's no point to print mirrors inside the compiler, as there is only one mirror there
printPositions = settings.Xprintpos.value
@@ -275,6 +276,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
printValueParams
print(" => ", body, ")")
if (printIds && tree.symbol != null) print("#" + tree.symbol.id)
+ if (printOwners && tree.symbol != null) print("@" + tree.symbol.owner.id)
}
protected def printSuper(tree: Super, resultName: => String) = {
@@ -1093,7 +1095,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
case self.pendingSuperCall =>
print("pendingSuperCall")
case tree: Tree =>
- val hasSymbolField = tree.hasSymbolField && tree.symbol != NoSymbol
+ def hasSymbolField = tree.hasSymbolField && tree.symbol != NoSymbol
val isError = hasSymbolField && (tree.symbol.name string_== nme.ERROR)
printProduct(
tree,
@@ -1139,6 +1141,7 @@ trait Printers extends api.Printers { self: SymbolTable =>
else if (sym.isStatic && (sym.isClass || sym.isModule)) print(sym.fullName)
else print(sym.name)
if (printIds) print("#", sym.id)
+ if (printOwners) print("@", sym.owner.id)
if (printKinds) print("#", sym.abbreviatedKindString)
if (printMirrors) print("%M", footnotes.put[scala.reflect.api.Mirror[_]](mirrorThatLoaded(sym)))
case tag: TypeTag[_] =>
diff --git a/src/reflect/scala/reflect/internal/ReificationSupport.scala b/src/reflect/scala/reflect/internal/ReificationSupport.scala
index 6a91109faf..087d4186be 100644
--- a/src/reflect/scala/reflect/internal/ReificationSupport.scala
+++ b/src/reflect/scala/reflect/internal/ReificationSupport.scala
@@ -226,9 +226,9 @@ trait ReificationSupport { self: SymbolTable =>
// recover constructor contents generated by gen.mkTemplate
protected object UnCtor {
def unapply(tree: Tree): Option[(Modifiers, List[List[ValDef]], List[Tree])] = tree match {
- case DefDef(mods, nme.MIXIN_CONSTRUCTOR, _, _, _, Block(lvdefs, _)) =>
+ case DefDef(mods, nme.MIXIN_CONSTRUCTOR, _, _, _, SyntacticBlock(lvdefs :+ _)) =>
Some((mods | Flag.TRAIT, Nil, lvdefs))
- case DefDef(mods, nme.CONSTRUCTOR, Nil, vparamss, _, Block(lvdefs :+ _, _)) =>
+ case DefDef(mods, nme.CONSTRUCTOR, Nil, vparamss, _, SyntacticBlock(lvdefs :+ _ :+ _)) =>
Some((mods, vparamss, lvdefs))
case _ => None
}
@@ -383,7 +383,7 @@ trait ReificationSupport { self: SymbolTable =>
object SyntacticTuple extends SyntacticTupleExtractor {
def apply(args: List[Tree]): Tree = {
require(args.isEmpty || TupleClass(args.length).exists, s"Tuples with ${args.length} arity aren't supported")
- gen.mkTuple(args, flattenUnary = false)
+ gen.mkTuple(args)
}
def unapply(tree: Tree): Option[List[Tree]] = tree match {
@@ -393,6 +393,8 @@ trait ReificationSupport { self: SymbolTable =>
if sym == TupleClass(args.length).companionModule
&& (targs.isEmpty || targs.length == args.length) =>
Some(args)
+ case _ if tree.isTerm =>
+ Some(tree :: Nil)
case _ =>
None
}
@@ -401,7 +403,7 @@ trait ReificationSupport { self: SymbolTable =>
object SyntacticTupleType extends SyntacticTupleExtractor {
def apply(args: List[Tree]): Tree = {
require(args.isEmpty || TupleClass(args.length).exists, s"Tuples with ${args.length} arity aren't supported")
- gen.mkTupleType(args, flattenUnary = false)
+ gen.mkTupleType(args)
}
def unapply(tree: Tree): Option[List[Tree]] = tree match {
@@ -410,6 +412,8 @@ trait ReificationSupport { self: SymbolTable =>
case MaybeTypeTreeOriginal(AppliedTypeTree(TupleClassRef(sym), args))
if sym == TupleClass(args.length) =>
Some(args)
+ case _ if tree.isType =>
+ Some(tree :: Nil)
case _ =>
None
}
@@ -507,10 +511,9 @@ trait ReificationSupport { self: SymbolTable =>
}
protected class SyntacticValDefBase(isMutable: Boolean) extends SyntacticValDefExtractor {
- def apply(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree) = {
- val mods1 = if (isMutable) mods | MUTABLE else mods
- ValDef(mods1, name, tpt, rhs)
- }
+ def modifiers(mods: Modifiers): Modifiers = if (isMutable) mods | MUTABLE else mods
+
+ def apply(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree): ValDef = ValDef(modifiers(mods), name, tpt, rhs)
def unapply(tree: Tree): Option[(Modifiers, TermName, Tree, Tree)] = tree match {
case ValDef(mods, name, tpt, rhs) if mods.hasFlag(MUTABLE) == isMutable =>
@@ -580,25 +583,57 @@ trait ReificationSupport { self: SymbolTable =>
// match a sequence of desugared `val $pat = $value`
protected object UnPatSeq {
- def unapply(trees: List[Tree]): Option[List[(Tree, Tree)]] = trees match {
- case Nil => Some(Nil)
- // case q"$mods val ${_}: ${_} = ${MaybeUnchecked(value)} match { case $pat => (..$ids) }" :: tail
- case ValDef(mods, _, _, Match(MaybeUnchecked(value), CaseDef(pat, EmptyTree, SyntacticTuple(ids)) :: Nil)) :: tail
+ def unapply(trees: List[Tree]): Option[List[(Tree, Tree)]] = {
+ val imploded = implodePatDefs(trees)
+ val patvalues = imploded.flatMap {
+ case SyntacticPatDef(_, pat, EmptyTree, rhs) => Some((pat, rhs))
+ case ValDef(_, name, SyntacticEmptyTypeTree(), rhs) => Some((Bind(name, self.Ident(nme.WILDCARD)), rhs))
+ case ValDef(_, name, tpt, rhs) => Some((Bind(name, Typed(self.Ident(nme.WILDCARD), tpt)), rhs))
+ case _ => None
+ }
+ if (patvalues.length == imploded.length) Some(patvalues) else None
+ }
+ }
+
+ // implode multiple-statement desugaring of pattern definitions
+ // into single-statement valdefs with nme.QUASIQUOTE_PAT_DEF name
+ object implodePatDefs extends Transformer {
+ override def transform(tree: Tree) = tree match {
+ case templ: Template => deriveTemplate(templ)(transformStats)
+ case block: Block =>
+ val Block(init, last) = block
+ Block(transformStats(init), transform(last)).copyAttrs(block)
+ case ValDef(mods, name1, SyntacticEmptyTypeTree(), Match(MaybeTyped(MaybeUnchecked(value), tpt), CaseDef(pat, EmptyTree, Ident(name2)) :: Nil))
+ if name1 == name2 =>
+ ValDef(mods, nme.QUASIQUOTE_PAT_DEF, Typed(pat, tpt), transform(value))
+ case _ =>
+ super.transform(tree)
+ }
+ def transformStats(trees: List[Tree]): List[Tree] = trees match {
+ case Nil => Nil
+ case ValDef(mods, _, SyntacticEmptyTypeTree(), Match(MaybeTyped(MaybeUnchecked(value), tpt), CaseDef(pat, EmptyTree, SyntacticTuple(ids)) :: Nil)) :: tail
if mods.hasFlag(SYNTHETIC) && mods.hasFlag(ARTIFACT) =>
- tail.drop(ids.length) match {
- case UnPatSeq(rest) => Some((pat, value) :: rest)
- case _ => None
+ ids match {
+ case Nil =>
+ ValDef(NoMods, nme.QUASIQUOTE_PAT_DEF, Typed(pat, tpt), transform(value)) :: transformStats(tail)
+ case _ =>
+ val mods = tail.take(1).head.asInstanceOf[ValDef].mods
+ ValDef(mods, nme.QUASIQUOTE_PAT_DEF, Typed(pat, tpt), transform(value)) :: transformStats(tail.drop(ids.length))
}
- // case q"${_} val $name1: ${_} = ${MaybeUnchecked(value)} match { case $pat => ${Ident(name2)} }" :: UnPatSeq(rest)
- case ValDef(_, name1, _, Match(MaybeUnchecked(value), CaseDef(pat, EmptyTree, Ident(name2)) :: Nil)) :: UnPatSeq(rest)
- if name1 == name2 =>
- Some((pat, value) :: rest)
- // case q"${_} val $name: ${SyntacticEmptyTypeTree()} = $value" :: UnPatSeq(rest) =>
- case ValDef(_, name, SyntacticEmptyTypeTree(), value) :: UnPatSeq(rest) =>
- Some((Bind(name, self.Ident(nme.WILDCARD)), value) :: rest)
- // case q"${_} val $name: $tpt = $value" :: UnPatSeq(rest) =>
- case ValDef(_, name, tpt, value) :: UnPatSeq(rest) =>
- Some((Bind(name, Typed(self.Ident(nme.WILDCARD), tpt)), value) :: rest)
+ case other :: tail =>
+ transform(other) :: transformStats(tail)
+ }
+ def apply(tree: Tree) = transform(tree)
+ def apply(trees: List[Tree]) = transformStats(trees)
+ }
+
+ object SyntacticPatDef extends SyntacticPatDefExtractor {
+ def apply(mods: Modifiers, pat: Tree, tpt: Tree, rhs: Tree): List[ValDef] = tpt match {
+ case SyntacticEmptyTypeTree() => gen.mkPatDef(mods, pat, rhs)
+ case _ => gen.mkPatDef(mods, Typed(pat, tpt), rhs)
+ }
+ def unapply(tree: Tree): Option[(Modifiers, Tree, Tree, Tree)] = tree match {
+ case ValDef(mods, nme.QUASIQUOTE_PAT_DEF, Typed(pat, tpt), rhs) => Some((mods, pat, tpt, rhs))
case _ => None
}
}
@@ -779,6 +814,13 @@ trait ReificationSupport { self: SymbolTable =>
}
}
+ protected object MaybeTyped {
+ def unapply(tree: Tree): Some[(Tree, Tree)] = tree match {
+ case Typed(v, tpt) => Some((v, tpt))
+ case v => Some((v, SyntacticEmptyTypeTree()))
+ }
+ }
+
protected def mkCases(cases: List[Tree]): List[CaseDef] = cases.map {
case c: CaseDef => c
case tree => throw new IllegalArgumentException("$tree is not valid representation of pattern match case")
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index 1e133eced9..b95c83d6cb 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -253,12 +253,8 @@ trait StdNames {
final val Quasiquote: NameType = "Quasiquote"
// quasiquote-specific names
- final val QUASIQUOTE_EARLY_DEF: NameType = "$quasiquote$early$def$"
final val QUASIQUOTE_FUNCTION: NameType = "$quasiquote$function$"
final val QUASIQUOTE_MODS: NameType = "$quasiquote$mods$"
- final val QUASIQUOTE_PACKAGE_STAT: NameType = "$quasiquote$package$stat$"
- final val QUASIQUOTE_PARAM: NameType = "$quasiquote$param$"
- final val QUASIQUOTE_REFINE_STAT: NameType = "$quasiquote$refine$stat$"
final val QUASIQUOTE_TUPLE: NameType = "$quasiquote$tuple$"
// Annotation simple names, used in Namer
@@ -312,6 +308,8 @@ trait StdNames {
val WHILE_PREFIX = "while$"
val FRESH_PREFIX = "fresh"
val FRESH_SUFFIX = "macro$" // uses a keyword to avoid collisions with mangled names
+ val QUAL_PREFIX = "qual$"
+ val NAMEDARG_PREFIX = "x$"
// Compiler internal names
val ANYname: NameType = "<anyname>"
@@ -331,12 +329,17 @@ trait StdNames {
val REIFY_FREE_THIS_SUFFIX: NameType = "$this"
val REIFY_FREE_VALUE_SUFFIX: NameType = "$value"
val REIFY_SYMDEF_PREFIX: NameType = "symdef$"
- val QUASIQUOTE_PREFIX: String = "qq$"
- val QUASIQUOTE_NAME_PREFIX: String = "nn$"
- val QUASIQUOTE_FILE: String = "<quasiquote>"
- val QUASIQUOTE_TUPLE: NameType = "$quasiquote$tuple$"
val QUASIQUOTE_CASE: NameType = "$quasiquote$case$"
+ val QUASIQUOTE_EARLY_DEF: NameType = "$quasiquote$early$def$"
+ val QUASIQUOTE_FILE: String = "<quasiquote>"
val QUASIQUOTE_FOR_ENUM: NameType = "$quasiquote$for$enum$"
+ val QUASIQUOTE_NAME_PREFIX: String = "nn$"
+ val QUASIQUOTE_PACKAGE_STAT: NameType = "$quasiquote$package$stat$"
+ val QUASIQUOTE_PARAM: NameType = "$quasiquote$param$"
+ val QUASIQUOTE_PAT_DEF: NameType = "$quasiquote$pat$def$"
+ val QUASIQUOTE_PREFIX: String = "qq$"
+ val QUASIQUOTE_REFINE_STAT: NameType = "$quasiquote$refine$stat$"
+ val QUASIQUOTE_TUPLE: NameType = "$quasiquote$tuple$"
val QUASIQUOTE_UNLIFT_HELPER: String = "$quasiquote$unlift$helper$"
val MIXIN_CONSTRUCTOR: NameType = "$init$"
val MODULE_INSTANCE_FIELD: NameType = NameTransformer.MODULE_INSTANCE_NAME // "MODULE$"
@@ -625,6 +628,7 @@ trait StdNames {
val SyntacticNew: NameType = "SyntacticNew"
val SyntacticObjectDef: NameType = "SyntacticObjectDef"
val SyntacticPackageObjectDef: NameType = "SyntacticPackageObjectDef"
+ val SyntacticPatDef: NameType = "SyntacticPatDef"
val SyntacticTraitDef: NameType = "SyntacticTraitDef"
val SyntacticTry: NameType = "SyntacticTry"
val SyntacticTuple: NameType = "SyntacticTuple"
@@ -651,7 +655,6 @@ trait StdNames {
val applyDynamicNamed: NameType = "applyDynamicNamed"
val applyOrElse: NameType = "applyOrElse"
val args : NameType = "args"
- val argv : NameType = "argv"
val arrayClass: NameType = "arrayClass"
val array_apply : NameType = "array_apply"
val array_clone : NameType = "array_clone"
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 5e81badfad..5fa4772d60 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -405,9 +405,14 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Create a new existential type skolem with this symbol its owner,
* based on the given symbol and origin.
*/
- def newExistentialSkolem(basis: Symbol, origin: AnyRef): TypeSkolem = {
- val skolem = newTypeSkolemSymbol(basis.name.toTypeName, origin, basis.pos, (basis.flags | EXISTENTIAL) & ~PARAM)
- skolem setInfo (basis.info cloneInfo skolem)
+ def newExistentialSkolem(basis: Symbol, origin: AnyRef): TypeSkolem =
+ newExistentialSkolem(basis.name.toTypeName, basis.info, basis.flags, basis.pos, origin)
+
+ /** Create a new existential type skolem with this symbol its owner, and the given other properties.
+ */
+ def newExistentialSkolem(name: TypeName, info: Type, flags: Long, pos: Position, origin: AnyRef): TypeSkolem = {
+ val skolem = newTypeSkolemSymbol(name.toTypeName, origin, pos, (flags | EXISTENTIAL) & ~PARAM)
+ skolem setInfo (info cloneInfo skolem)
}
// don't test directly -- use isGADTSkolem
@@ -577,6 +582,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def isConstructor = false
def isEarlyInitialized = false
def isGetter = false
+ def isDefaultGetter = false
def isLocalDummy = false
def isMixinConstructor = false
def isOverloaded = false
@@ -2502,14 +2508,14 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* If !settings.debug translates expansions of operators back to operator symbol.
* E.g. $eq => =.
* If settings.uniqid, adds id.
+ * If settings.Yshowsymowners, adds owner's id
* If settings.Yshowsymkinds, adds abbreviated symbol kind.
*/
def nameString: String = {
val name_s = if (settings.debug.value) "" + unexpandedName else unexpandedName.dropLocal.decode
- val id_s = if (settings.uniqid.value) "#" + id else ""
val kind_s = if (settings.Yshowsymkinds.value) "#" + abbreviatedKindString else ""
- name_s + id_s + kind_s
+ name_s + idString + kind_s
}
def fullNameString: String = {
@@ -2523,7 +2529,11 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
/** If settings.uniqid is set, the symbol's id, else "" */
- final def idString = if (settings.uniqid.value) "#"+id else ""
+ final def idString = {
+ val id_s = if (settings.uniqid.value) "#"+id else ""
+ val owner_s = if (settings.Yshowsymowners.value) "@"+owner.id else ""
+ id_s + owner_s
+ }
/** String representation, including symbol's kind e.g., "class Foo", "method Bar".
* If hasMeaninglessName is true, uses the owner's name to disambiguate identity.
@@ -2675,6 +2685,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
override def isSetterParameter = isValueParameter && owner.isSetter
override def isAccessor = this hasFlag ACCESSOR
override def isGetter = isAccessor && !isSetter
+ override def isDefaultGetter = name containsName nme.DEFAULT_GETTER_STRING
override def isSetter = isAccessor && nme.isSetterName(name) // todo: make independent of name, as this can be forged.
override def isLocalDummy = nme.isLocalDummyName(name)
override def isClassConstructor = name == nme.CONSTRUCTOR
@@ -3459,6 +3470,21 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
mapList(syms1)(_ substInfo (syms, syms1))
}
+ /** Derives a new list of symbols from the given list by mapping the given
+ * list of `syms` and `as` across the given function.
+ * Then fixes the info of all the new symbols
+ * by substituting the new symbols for the original symbols.
+ *
+ * @param syms the prototypical symbols
+ * @param as arguments to be passed to symFn together with symbols from syms (must be same length)
+ * @param symFn the function to create new symbols
+ * @return the new list of info-adjusted symbols
+ */
+ def deriveSymbols2[A](syms: List[Symbol], as: List[A], symFn: (Symbol, A) => Symbol): List[Symbol] = {
+ val syms1 = map2(syms, as)(symFn)
+ mapList(syms1)(_ substInfo (syms, syms1))
+ }
+
/** Derives a new Type by first deriving new symbols as in deriveSymbols,
* then performing the same oldSyms => newSyms substitution on `tpe` as is
* performed on the symbol infos in deriveSymbols.
@@ -3472,6 +3498,22 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
val syms1 = deriveSymbols(syms, symFn)
tpe.substSym(syms, syms1)
}
+
+ /** Derives a new Type by first deriving new symbols as in deriveSymbols2,
+ * then performing the same oldSyms => newSyms substitution on `tpe` as is
+ * performed on the symbol infos in deriveSymbols.
+ *
+ * @param syms the prototypical symbols
+ * @param as arguments to be passed to symFn together with symbols from syms (must be same length)
+ * @param symFn the function to create new symbols based on `as`
+ * @param tpe the prototypical type
+ * @return the new symbol-subsituted type
+ */
+ def deriveType2[A](syms: List[Symbol], as: List[A], symFn: (Symbol, A) => Symbol)(tpe: Type): Type = {
+ val syms1 = deriveSymbols2(syms, as, symFn)
+ tpe.substSym(syms, syms1)
+ }
+
/** Derives a new Type by instantiating the given list of symbols as
* WildcardTypes.
*
diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala
index 7ed808a7fb..6011289baf 100644
--- a/src/reflect/scala/reflect/internal/TreeGen.scala
+++ b/src/reflect/scala/reflect/internal/TreeGen.scala
@@ -691,11 +691,11 @@ abstract class TreeGen {
}
/** Create tree for pattern definition <val pat0 = rhs> */
- def mkPatDef(pat: Tree, rhs: Tree)(implicit fresh: FreshNameCreator): List[Tree] =
+ def mkPatDef(pat: Tree, rhs: Tree)(implicit fresh: FreshNameCreator): List[ValDef] =
mkPatDef(Modifiers(0), pat, rhs)
/** Create tree for pattern definition <mods val pat0 = rhs> */
- def mkPatDef(mods: Modifiers, pat: Tree, rhs: Tree)(implicit fresh: FreshNameCreator): List[Tree] = matchVarPattern(pat) match {
+ def mkPatDef(mods: Modifiers, pat: Tree, rhs: Tree)(implicit fresh: FreshNameCreator): List[ValDef] = matchVarPattern(pat) match {
case Some((name, tpt)) =>
List(atPos(pat.pos union rhs.pos) {
ValDef(mods, name.toTermName, tpt, rhs)
diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala
index 8cad2497c1..0b42a8f9ac 100644
--- a/src/reflect/scala/reflect/internal/TreeInfo.scala
+++ b/src/reflect/scala/reflect/internal/TreeInfo.scala
@@ -281,6 +281,10 @@ abstract class TreeInfo {
}
}
+ def isDefaultGetter(tree: Tree) = {
+ tree.symbol != null && tree.symbol.isDefaultGetter
+ }
+
/** Is tree a self constructor call this(...)? I.e. a call to a constructor of the
* same object?
*/
@@ -864,13 +868,8 @@ abstract class TreeInfo {
case _ => false
})
- def isMacroApplication(tree: Tree): Boolean = !tree.isDef && {
- val sym = tree.symbol
- sym != null && sym.isTermMacro && !sym.isErroneous
- }
-
- def isMacroApplicationOrBlock(tree: Tree): Boolean = tree match {
- case Block(_, expr) => isMacroApplicationOrBlock(expr)
- case tree => isMacroApplication(tree)
+ def isMacroApplication(tree: Tree): Boolean = tree match {
+ case Block(_, expr) => isMacroApplication(expr)
+ case tree => !tree.isDef && tree.symbol != null && tree.symbol.isTermMacro && !tree.symbol.isErroneous
}
}
diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala
index 5b4b7fd2a4..7a6862a770 100644
--- a/src/reflect/scala/reflect/internal/Trees.scala
+++ b/src/reflect/scala/reflect/internal/Trees.scala
@@ -1683,6 +1683,15 @@ trait Trees extends api.Trees {
def duplicateAndKeepPositions(tree: Tree) = new Duplicator(focusPositions = false) transform tree
+ // 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
+ }
+ }
+
// ------ copiers -------------------------------------------
def copyDefDef(tree: Tree)(
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 089684413d..3ede21d5e3 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -93,10 +93,11 @@ trait Types
private final val traceTypeVars = sys.props contains "scalac.debug.tvar"
private final val breakCycles = settings.breakCycles.value
- /** In case anyone wants to turn off type parameter bounds being used
+ /** In case anyone wants to turn on type parameter bounds being used
* to seed type constraints.
*/
private final val propagateParameterBoundsToTypeVars = sys.props contains "scalac.debug.prop-constraints"
+ private final val sharperSkolems = sys.props contains "scalac.experimental.sharper-skolems"
protected val enableTypeVarExperimentals = settings.Xexperimental.value
@@ -2574,56 +2575,58 @@ trait Types
override def baseTypeSeq = underlying.baseTypeSeq map maybeRewrap
override def isHigherKinded = false
+ // TODO: check invariant that all quantifiers have the same (existing) owner
+ private def quantifierOwner = quantified collectFirst { case q if q.owner.exists => q.owner } getOrElse NoSymbol
+
+ // Is this existential of the form: T[Q1, ..., QN] forSome { type Q1 >: L1 <: U1, ..., QN >: LN <: UN}
+ private def isStraightApplication = (quantified corresponds underlying.typeArgs){ (q, a) => q.tpe =:= a }
+
/** [SI-6169, SI-8197 -- companion to SI-1786]
*
- * Approximation to improve the bounds of a Java-defined existential type,
- * based on the bounds of the type parameters of the quantified type
- * In Scala syntax, given a java-defined class C[T <: String], the existential type C[_]
- * is improved to C[_ <: String] before skolemization, which captures (get it?) what Java does:
- * enter the type paramers' bounds into the context when checking subtyping/type equality of existential types
+ * Approximation to improve the bounds of a Java-defined existential type,
+ * based on the bounds of the type parameters of the quantified type
+ * In Scala syntax, given a java-defined class C[T <: String], the existential type C[_]
+ * is improved to C[_ <: String] before skolemization, which captures (get it?) what Java does:
+ * enter the type paramers' bounds into the context when checking subtyping/type equality of existential types
*
- * (Also tried doing this once during class file parsing or when creating the existential type,
- * but that causes cyclic errors because it happens too early.)
+ * Also tried doing this once during class file parsing or when creating the existential type,
+ * but that causes cyclic errors because it happens too early.
+ *
+ * NOTE: we're only modifying the skolems to avoid leaking the sharper bounds to `quantified` (SI-8283)
*
* TODO: figure out how to do this earlier without running into cycles, so this can subsume the fix for SI-1786
*/
- private def sharpenQuantifierBounds(): Unit = {
- /* Check that we're looking at rawToExistential's handiwork
- * (`existentialAbstraction(eparams, typeRef(apply(pre), sym, eparams map (_.tpe)))`).
- * We can't do this sharpening there because we'll run into cycles.
- */
- def rawToExistentialCreatedMe = (quantified corresponds underlying.typeArgs){ (q, a) => q.tpe =:= a }
-
- if (underlying.typeSymbol.isJavaDefined && rawToExistentialCreatedMe) {
- val tpars = underlying.typeSymbol.initialize.typeParams // TODO: is initialize needed?
- debuglog(s"sharpen bounds: $this | ${underlying.typeArgs.map(_.typeSymbol)} <-- ${tpars.map(_.info)}")
-
- foreach2(quantified, tpars) { (quant, tparam) =>
- // TODO: check `tparam.info.substSym(tpars, quantified) <:< quant.info` instead (for some weird reason not working for test/t6169/ExistF)
- // for now, crude approximation for the common case
- if (quant.info.bounds.isEmptyBounds && !tparam.info.bounds.isEmptyBounds) {
- // avoid creating cycles [pos/t2940] that consist of an existential quantifier's
- // bounded by an existential type that unhygienically has that quantifier as its own quantifier
- // (TODO: clone latter existential with fresh quantifiers -- not covering this case for now)
- if ((existentialsInType(tparam.info) intersect quantified).isEmpty)
- quant setInfo tparam.info.substSym(tpars, quantified)
- }
- }
- }
+ override def skolemizeExistential(owner0: Symbol, origin: AnyRef) = {
+ val owner = owner0 orElse quantifierOwner
- _sharpenQuantifierBounds = false
- }
- private[this] var _sharpenQuantifierBounds = true
-
- override def skolemizeExistential(owner: Symbol, origin: AnyRef) = {
// do this here because it's quite close to what Java does:
// when checking subtyping/type equality, enter constraints
// derived from the existentially quantified type into the typing environment
// (aka \Gamma, which tracks types for variables and constraints/kinds for types)
// as a nice bonus, delaying this until we need it avoids cyclic errors
- if (_sharpenQuantifierBounds) sharpenQuantifierBounds
+ def tpars = underlying.typeSymbol.initialize.typeParams
+
+ def newSkolem(quant: Symbol) = owner.newExistentialSkolem(quant, origin)
+ def newSharpenedSkolem(quant: Symbol, tparam: Symbol): Symbol = {
+ def emptyBounds(sym: Symbol) = sym.info.bounds.isEmptyBounds
+
+ // avoid creating cycles [pos/t2940] that consist of an existential quantifier's
+ // bounded by an existential type that unhygienically has that quantifier as its own quantifier
+ // (TODO: clone latter existential with fresh quantifiers -- not covering this case for now)
+ val canSharpen = (
+ emptyBounds(quant) && !emptyBounds(tparam)
+ && (existentialsInType(tparam.info) intersect quantified).isEmpty
+ )
+
+ val skolemInfo = if (!canSharpen) quant.info else tparam.info.substSym(tpars, quantified)
+
+ owner.newExistentialSkolem(quant.name.toTypeName, skolemInfo, quant.flags, quant.pos, origin)
+ }
+
+ val canSharpenBounds = (underlying.typeSymbol.isJavaDefined || sharperSkolems) && isStraightApplication
- deriveType(quantified, tparam => (owner orElse tparam.owner).newExistentialSkolem(tparam, origin))(underlying)
+ if (canSharpenBounds) deriveType2(quantified, tpars, newSharpenedSkolem)(underlying)
+ else deriveType(quantified, newSkolem)(underlying)
}
private def wildcardArgsString(qset: Set[Symbol], args: List[Type]): List[String] = args map {
diff --git a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala
index 816916787e..048fe9ef37 100644
--- a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala
+++ b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala
@@ -39,6 +39,7 @@ abstract class MutableSettings extends AbsSettings {
def Xprintpos: BooleanSetting
def Yposdebug: BooleanSetting
def Yrangepos: BooleanSetting
+ def Yshowsymowners: BooleanSetting
def Yshowsymkinds: BooleanSetting
def breakCycles: BooleanSetting
def debug: BooleanSetting
diff --git a/src/reflect/scala/reflect/runtime/Settings.scala b/src/reflect/scala/reflect/runtime/Settings.scala
index de5ba99900..d46846fc21 100644
--- a/src/reflect/scala/reflect/runtime/Settings.scala
+++ b/src/reflect/scala/reflect/runtime/Settings.scala
@@ -36,6 +36,7 @@ private[reflect] class Settings extends MutableSettings {
val Xprintpos = new BooleanSetting(false)
val Yposdebug = new BooleanSetting(false)
val Yrangepos = new BooleanSetting(false)
+ val Yshowsymowners = new BooleanSetting(false)
val Yshowsymkinds = new BooleanSetting(false)
val breakCycles = new BooleanSetting(false)
val debug = new BooleanSetting(false)