summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/reflect/macros/contexts/Typers.scala6
-rw-r--r--src/compiler/scala/reflect/reify/Reifier.scala14
-rw-r--r--src/compiler/scala/reflect/reify/codegen/GenTrees.scala2
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala55
-rw-r--r--src/compiler/scala/tools/nsc/transform/PostErasure.scala12
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala14
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Unapplies.scala4
-rw-r--r--src/compiler/scala/tools/nsc/util/package.scala13
-rw-r--r--src/compiler/scala/tools/reflect/ReflectGlobal.scala7
-rw-r--r--src/compiler/scala/tools/reflect/ToolBox.scala15
-rw-r--r--src/compiler/scala/tools/reflect/ToolBoxFactory.scala59
-rw-r--r--src/library/scala/collection/mutable/AnyRefMap.scala27
-rw-r--r--src/library/scala/util/matching/Regex.scala7
-rw-r--r--src/reflect/scala/reflect/api/Importers.scala2
-rw-r--r--src/reflect/scala/reflect/api/Trees.scala2
-rw-r--r--src/reflect/scala/reflect/api/TypeTags.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Required.scala3
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala75
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala8
-rw-r--r--src/reflect/scala/reflect/internal/transform/PostErasure.scala19
-rw-r--r--src/reflect/scala/reflect/internal/transform/Transforms.scala11
-rw-r--r--src/reflect/scala/reflect/macros/Evals.scala6
-rw-r--r--src/reflect/scala/reflect/macros/Typers.scala6
-rw-r--r--src/reflect/scala/reflect/macros/Universe.scala5
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala240
-rw-r--r--src/reflect/scala/reflect/runtime/JavaUniverse.scala2
-rw-r--r--src/reflect/scala/reflect/runtime/ReflectionUtils.scala2
-rw-r--r--src/repl/scala/tools/nsc/interpreter/IMain.scala27
-rw-r--r--test/disabled/run/t7843-jsr223-service.scala18
-rw-r--r--test/files/neg/names-defaults-neg.check2
-rw-r--r--test/files/neg/t8207.check7
-rw-r--r--test/files/neg/t8207.scala3
-rw-r--r--test/files/neg/t8237-default.check13
-rw-r--r--test/files/neg/t8237-default.scala29
-rw-r--r--test/files/pos/annotated-original/M_1.scala2
-rw-r--r--test/files/pos/annotated-treecopy/Impls_Macros_1.scala2
-rw-r--r--test/files/pos/t6169/Exist.java4
-rw-r--r--test/files/pos/t6169/ExistF.java4
-rw-r--r--test/files/pos/t6169/ExistIndir.java4
-rw-r--r--test/files/pos/t6169/OP.java1
-rw-r--r--test/files/pos/t6169/Skin.java1
-rw-r--r--test/files/pos/t6169/Skinnable.java3
-rw-r--r--test/files/pos/t6169/skinnable.scala14
-rw-r--r--test/files/pos/t6169/t6169.scala7
-rw-r--r--test/files/pos/t7377/Macro_1.scala2
-rw-r--r--test/files/pos/t7516/A_1.scala2
-rw-r--r--test/files/pos/t8064/Macro_1.scala2
-rw-r--r--test/files/pos/t8207.scala6
-rw-r--r--test/files/pos/t8237.scala29
-rw-r--r--test/files/pos/t8237b.scala10
-rw-r--r--test/files/run/macro-reify-splice-outside-reify/Impls_Macros_1.scala2
-rw-r--r--test/files/run/reflection-magicsymbols-invoke.check2
-rw-r--r--test/files/run/t6411a.check96
-rw-r--r--test/files/run/t6411a.scala81
-rw-r--r--test/files/run/t6411b.check1
-rw-r--r--test/files/run/t6411b.scala12
-rw-r--r--test/files/run/t7240/Macros_1.scala2
-rw-r--r--test/files/run/t7319.check2
-rw-r--r--test/files/run/t7328.check4
-rw-r--r--test/files/run/t7328.scala18
-rw-r--r--test/files/run/t7570a.check1
-rw-r--r--test/files/run/t7570a.scala11
-rw-r--r--test/files/run/t7570b.check1
-rw-r--r--test/files/run/t7570b.scala17
-rw-r--r--test/files/run/t7570c.check2
-rw-r--r--test/files/run/t7570c.scala13
-rw-r--r--test/files/run/t7843-jsr223-service.check (renamed from test/disabled/run/t7843-jsr223-service.check)0
-rw-r--r--test/files/run/t7843-jsr223-service.scala8
-rw-r--r--test/files/run/t7933.check2
-rw-r--r--test/files/run/t7933.scala11
-rw-r--r--test/files/run/t8245.scala14
-rw-r--r--test/junit/scala/collection/SetMapConsistencyTest.scala21
-rw-r--r--test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala1
-rw-r--r--test/pending/run/idempotency-partial-functions.scala2
79 files changed, 878 insertions, 279 deletions
diff --git a/src/compiler/scala/reflect/macros/contexts/Typers.scala b/src/compiler/scala/reflect/macros/contexts/Typers.scala
index cd3db74016..c1ab17027f 100644
--- a/src/compiler/scala/reflect/macros/contexts/Typers.scala
+++ b/src/compiler/scala/reflect/macros/contexts/Typers.scala
@@ -46,9 +46,7 @@ trait Typers {
universe.analyzer.inferImplicit(tree, viewTpe, true, callsiteTyper.context, silent, withMacrosDisabled, pos, (pos, msg) => throw TypecheckException(pos, msg))
}
- def resetAllAttrs(tree: Tree): Tree = universe.resetAllAttrs(universe.duplicateAndKeepPositions(tree))
+ def resetLocalAttrs(tree: Tree): Tree = universe.resetAttrs(universe.duplicateAndKeepPositions(tree))
- def resetLocalAttrs(tree: Tree): Tree = universe.resetLocalAttrs(universe.duplicateAndKeepPositions(tree))
-
- def untypecheck(tree: Tree): Tree = universe.resetLocalAttrs(universe.duplicateAndKeepPositions(tree))
+ def untypecheck(tree: Tree): Tree = resetLocalAttrs(tree)
}
diff --git a/src/compiler/scala/reflect/reify/Reifier.scala b/src/compiler/scala/reflect/reify/Reifier.scala
index ad0632f93e..6b0a0ee8d7 100644
--- a/src/compiler/scala/reflect/reify/Reifier.scala
+++ b/src/compiler/scala/reflect/reify/Reifier.scala
@@ -86,7 +86,7 @@ abstract class Reifier extends States
throw new Error("reifee %s of type %s is not supported".format(reifee, if (reifee == null) "null" else reifee.getClass.toString))
}
- // todo. why do we resetAllAttrs?
+ // todo. why do we reset attrs?
//
// typically we do some preprocessing before reification and
// the code emitted/moved around during preprocessing is very hard to typecheck, so we leave it as it is
@@ -109,19 +109,11 @@ 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
- // maybe try `resetLocalAttrs` once the dust settles
- 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 = resetAllAttrs(result, leaveAlone = {
+ // upd. a new hope: https://groups.google.com/forum/#!topic/scala-internals/TtCTPlj_qcQ
+ val untyped = resetAttrs(result, leaveAlone = {
case ValDef(_, u, _, _) if u == nme.UNIVERSE_SHORT => true
case ValDef(_, m, _, _) if m == nme.MIRROR_SHORT => true
case tree if symtab.syms contains tree.symbol => true
- case tree if isImportantSymbol(tree.symbol) => true
case _ => false
})
diff --git a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala
index f6b3c42ca9..b082796757 100644
--- a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala
+++ b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala
@@ -140,7 +140,7 @@ trait GenTrees {
if (sym == NoSymbol) {
// this sometimes happens, e.g. for binds that don't have a body
// or for untyped code generated during previous phases
- // (see a comment in Reifiers about the latter, starting with "why do we resetAllAttrs?")
+ // (see a comment in Reifiers about the latter, starting with "why do we reset attrs?")
mirrorCall(nme.Ident, reify(name))
}
else if (!sym.isLocalToReifee) {
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 5492e563dd..1617db7517 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -81,6 +81,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
def picklerPhase: Phase = if (currentRun.isDefined) currentRun.picklerPhase else NoPhase
+ def erasurePhase: Phase = if (currentRun.isDefined) currentRun.erasurePhase else NoPhase
+
// platform specific elements
protected class GlobalPlatform extends {
@@ -527,7 +529,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
} with Erasure
// phaseName = "posterasure"
- object postErasure extends {
+ override object postErasure extends {
val global: Global.this.type = Global.this
val runsAfter = List("erasure")
val runsRightAfter = Some("erasure")
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 24bce0636d..7a7d4ac0b2 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -176,13 +176,24 @@ trait Trees extends scala.reflect.internal.Trees { self: Global =>
}
}
- /** resets symbol and tpe fields in a tree, @see ResetAttrs
- */
-// def resetAllAttrs[A<:Tree](x:A): A = { new ResetAttrsTraverser().traverse(x); x }
-// def resetLocalAttrs[A<:Tree](x:A): A = { new ResetLocalAttrsTraverser().traverse(x); x }
-
- def resetAllAttrs(x: Tree, leaveAlone: Tree => Boolean = null): Tree = new ResetAttrs(false, leaveAlone).transform(x)
- def resetLocalAttrs(x: Tree, leaveAlone: Tree => Boolean = null): Tree = new ResetAttrs(true, leaveAlone).transform(x)
+ // Finally, noone resetAllAttrs it anymore, so I'm removing it from the compiler.
+ // Even though it's with great pleasure I'm doing that, I'll leave its body here to warn future generations about what happened in the past.
+ //
+ // So what actually happened in the past is that we used to have two flavors of resetAttrs: resetAllAttrs and resetLocalAttrs.
+ // resetAllAttrs destroyed all symbols and types in the tree in order to reset its state to something suitable for retypechecking
+ // and/or embedding into bigger trees / different lexical scopes. (Btw here's some background on why people would want to use
+ // reset attrs in the first place: https://groups.google.com/forum/#!topic/scala-internals/TtCTPlj_qcQ).
+ //
+ // However resetAllAttrs was more of a poison than of a treatment, because along with locally defined symbols that are the cause
+ // for almost every or maybe even every case of tree corruption, it erased external bindings that sometimes could not be restored.
+ // This is how we came up with resetLocalAttrs that left external bindings alone, and that was a big step forward.
+ // Then slowly but steadily we've evicted all usages of resetAllAttrs from our codebase in favor of resetLocalAttrs
+ // and have been living happily ever after.
+ //
+ // def resetAllAttrs(x: Tree, leaveAlone: Tree => Boolean = null): Tree = new ResetAttrs(localOnly = false, leaveAlone).transform(x)
+
+ /** @see ResetAttrs */
+ def resetAttrs(x: Tree, leaveAlone: Tree => Boolean = null): Tree = new ResetAttrs(leaveAlone).transform(x)
/** A transformer which resets symbol and tpe fields of all nodes in a given tree,
* with special treatment of:
@@ -193,7 +204,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(localOnly: Boolean, leaveAlone: Tree => Boolean = null, keepLabels: Boolean = false) {
+ private class ResetAttrs(leaveAlone: Tree => Boolean = null) {
// 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
@@ -277,29 +288,18 @@ trait Trees extends scala.reflect.internal.Trees { self: Global =>
// vetoXXX local variables declared below describe the conditions under which we cannot erase symbols.
//
// The first reason to not erase symbols is the threat of non-idempotency (SI-5464).
- // Here we take care of labels (SI-5562) and references to package classes (SI-5705).
+ // Here we take care of references to package classes (SI-5705).
// There are other non-idempotencies, but they are not worked around yet.
//
- // The second reason has to do with the fact that resetAttrs itself has limited usefulness.
- //
- // First of all, why do we need resetAttrs? Gor one, it's absolutely required to move trees around.
- // One cannot just take a typed tree from one lexical context and transplant it somewhere else.
- // Most likely symbols defined by those trees will become borked and the compiler will blow up (SI-5797).
- // To work around we just erase all symbols and types and then hope that we'll be able to correctly retypecheck.
- // For ones who're not affected by scalac Stockholm syndrome, this might seem to be an extremely naive fix, but well...
- //
- // Of course, sometimes erasing everything won't work, because if a given identifier got resolved to something
- // in one lexical scope, it can get resolved to something else.
- //
- // What do we do in these cases? Enter the workaround for the workaround: resetLocalAttrs, which only destroys
- // locally defined symbols, but doesn't touch references to stuff declared outside of a given tree.
- // That's what localOnly and vetoScope are for.
+ // The second reason has to do with the fact that resetAttrs needs to be less destructive.
+ // Erasing locally-defined symbols is useful to prevent tree corruption, but erasing external bindings is not,
+ // therefore we want to retain those bindings, especially given that restoring them can be impossible
+ // if we move these trees into lexical contexts different from their original locations.
if (dupl.hasSymbol) {
val sym = dupl.symbol
- val vetoScope = localOnly && !(locals contains sym)
- val vetoLabel = keepLabels && sym.isLabel
+ val vetoScope = !(locals contains sym)
val vetoThis = dupl.isInstanceOf[This] && sym.isPackageClass
- if (!(vetoScope || vetoLabel || vetoThis)) dupl.symbol = NoSymbol
+ if (!(vetoScope || vetoThis)) dupl.symbol = NoSymbol
}
dupl.clearType()
}
@@ -308,10 +308,9 @@ trait Trees extends scala.reflect.internal.Trees { self: Global =>
}
def transform(x: Tree): Tree = {
- if (localOnly)
new MarkLocals().traverse(x)
- if (localOnly && debug) {
+ if (debug) {
assert(locals.size == orderedLocals.size)
val msg = orderedLocals.toList filter {_ != NoSymbol} map {" " + _} mkString EOL
trace("locals (%d total): %n".format(orderedLocals.size))(msg)
diff --git a/src/compiler/scala/tools/nsc/transform/PostErasure.scala b/src/compiler/scala/tools/nsc/transform/PostErasure.scala
index cc78e27282..32987fed8c 100644
--- a/src/compiler/scala/tools/nsc/transform/PostErasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/PostErasure.scala
@@ -8,7 +8,7 @@ package transform
/** This phase maps ErasedValueTypes to the underlying unboxed representation and
* performs peephole optimizations.
*/
-trait PostErasure extends InfoTransform with TypingTransformers {
+trait PostErasure extends InfoTransform with TypingTransformers with scala.reflect.internal.transform.PostErasure {
val global: Global
import global._
@@ -19,16 +19,6 @@ trait PostErasure extends InfoTransform with TypingTransformers {
def newTransformer(unit: CompilationUnit): Transformer = new PostErasureTransformer(unit)
override def changesBaseClasses = false
- object elimErasedValueType extends TypeMap {
- def apply(tp: Type) = tp match {
- case ConstantType(Constant(tp: Type)) => ConstantType(Constant(apply(tp)))
- case ErasedValueType(_, underlying) => underlying
- case _ => mapOver(tp)
- }
- }
-
- def transformInfo(sym: Symbol, tp: Type) = elimErasedValueType(tp)
-
class PostErasureTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {
override def transform(tree: Tree) = {
def finish(res: Tree) = logResult(s"Posterasure reduction\n Old: $tree\n New")(res)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index e5907e1a0f..5b7956a757 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -457,7 +457,9 @@ trait Contexts { self: Analyzer =>
c.prefix = prefixInChild
c.enclClass = if (isTemplateOrPackage) c else enclClass
c(ConstructorSuffix) = !isTemplateOrPackage && c(ConstructorSuffix)
- c.enclMethod = if (isDefDef) c else enclMethod
+
+ // SI-8245 `isLazy` need to skip lazy getters to ensure `return` binds to the right place
+ c.enclMethod = if (isDefDef && !owner.isLazy) c else enclMethod
registerContext(c.asInstanceOf[analyzer.Context])
debuglog("[context] ++ " + c.unit + " / " + tree.summaryString)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 645f267a21..886dbed6d6 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -1205,7 +1205,7 @@ trait Namers extends MethodSynthesis {
* flag.
*/
private def addDefaultGetters(meth: Symbol, ddef: DefDef, vparamss: List[List[ValDef]], tparams: List[TypeDef], overriddenSymbol: => Symbol) {
- val DefDef(_, _, rtparams0, rvparamss0, _, _) = resetLocalAttrs(ddef.duplicate)
+ val DefDef(_, _, rtparams0, rvparamss0, _, _) = resetAttrs(ddef.duplicate)
// having defs here is important to make sure that there's no sneaky tree sharing
// in methods with multiple default parameters
def rtparams = rtparams0.map(_.duplicate)
@@ -1292,7 +1292,7 @@ trait Namers extends MethodSynthesis {
return // fix #3649 (prevent crash in erroneous source code)
}
}
- val ClassDef(_, _, rtparams, _) = resetLocalAttrs(cdef.duplicate)
+ val ClassDef(_, _, rtparams, _) = resetAttrs(cdef.duplicate)
defTparams = rtparams.map(rt => copyTypeDef(rt)(mods = rt.mods &~ (COVARIANT | CONTRAVARIANT)))
nmr
}
@@ -1408,8 +1408,14 @@ trait Namers extends MethodSynthesis {
if (expr1.isErrorTyped)
ErrorType
else {
- if (!treeInfo.isStableIdentifierPattern(expr1))
- typer.TyperErrorGen.UnstableTreeError(expr1)
+ expr1 match {
+ case This(_) =>
+ // SI-8207 okay, typedIdent expands Ident(self) to C.this which doesn't satisfy the next case
+ // TODO should we change `typedIdent` not to expand to the `Ident` to a `This`?
+ case _ if treeInfo.isStableIdentifierPattern(expr1) =>
+ case _ =>
+ typer.TyperErrorGen.UnstableTreeError(expr1)
+ }
val newImport = treeCopy.Import(imp, expr1, selectors).asInstanceOf[Import]
checkSelectors(newImport)
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index 46ff98875f..6a4df415ae 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -173,7 +173,7 @@ trait NamesDefaults { self: Analyzer =>
// setSymbol below is important because the 'selected' function might be overloaded. by
// assigning the correct method symbol, typedSelect will just assign the type. the reason
// to still call 'typed' is to correctly infer singleton types, SI-5259.
- val selectPos =
+ val selectPos =
if(qual.pos.isRange && baseFun.pos.isRange) qual.pos.union(baseFun.pos).withStart(Math.min(qual.pos.end, baseFun.pos.end))
else baseFun.pos
val f = blockTyper.typedOperator(Select(newQual, selected).setSymbol(baseFun1.symbol).setPos(selectPos))
@@ -287,7 +287,7 @@ trait NamesDefaults { self: Analyzer =>
}
else {
// TODO In 83c9c764b, we tried to a stable type here to fix SI-7234. But the resulting TypeTree over a
- // singleton type without an original TypeTree fails to retypecheck after a resetLocalAttrs (SI-7516),
+ // singleton type without an original TypeTree fails to retypecheck after a resetAttrs (SI-7516),
// which is important for (at least) macros.
arg.tpe
}
@@ -310,7 +310,7 @@ trait NamesDefaults { self: Analyzer =>
new ChangeOwnerTraverser(context.owner, sym) traverse arg // fixes #4502
if (repeated) arg match {
case WildcardStarArg(expr) => expr
- case _ => blockTyper typed gen.mkSeqApply(resetLocalAttrs(arg))
+ case _ => blockTyper typed gen.mkSeqApply(resetAttrs(arg))
} else arg
}
Some(atPos(body.pos)(ValDef(sym, body).setType(NoType)))
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index f7684b93af..2125e281f0 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -1414,7 +1414,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
case TypeRef(pre, sym, args) =>
tree match {
case tt: TypeTree if tt.original == null => // SI-7783 don't warn about inferred types
- // FIXME: reconcile this check with one in resetAllAttrs
+ // FIXME: reconcile this check with one in resetAttrs
case _ => checkUndesiredProperties(sym, tree.pos)
}
if(sym.isJavaDefined)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 101e1526fe..10fe530445 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -832,7 +832,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
else tpr.typed(withImplicitArgs, mode, pt)
}
orElse { _ =>
- val resetTree = resetLocalAttrs(original)
+ val resetTree = resetAttrs(original)
debuglog(s"fallback on implicits: ${tree}/$resetTree")
val tree1 = typed(resetTree, mode)
// Q: `typed` already calls `pluginsTyped` and `adapt`. the only difference here is that
@@ -2307,7 +2307,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
context.scope.unlink(ldef.symbol)
val sym2 = namer.enterInScope(
context.owner.newLabel(ldef.name, ldef.pos) setInfo MethodType(List(), restpe))
- val rhs2 = typed(resetAllAttrs(ldef.rhs), restpe)
+ val LabelDef(_, _, rhs1) = resetAttrs(ldef)
+ val rhs2 = typed(rhs1, restpe)
ldef.params foreach (param => param setType param.symbol.tpe)
deriveLabelDef(ldef)(_ => rhs2) setSymbol sym2 setType restpe
}
@@ -2589,7 +2590,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
//
// Well behaved trees satisfy the property:
//
- // typed(tree) == typed(resetLocalAttrs(typed(tree))
+ // typed(tree) == typed(resetAttrs(typed(tree))
//
// Trees constructed without low-level symbol manipulation get this for free;
// references to local symbols are cleared by `ResetAttrs`, but bind to the
diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
index ffac29b4b8..cc2d9141ce 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
@@ -52,13 +52,13 @@ trait Unapplies extends ast.TreeDSL {
}
private def constrParamss(cdef: ClassDef): List[List[ValDef]] = {
- val ClassDef(_, _, _, Template(_, _, body)) = resetLocalAttrs(cdef.duplicate)
+ val ClassDef(_, _, _, Template(_, _, body)) = resetAttrs(cdef.duplicate)
val DefDef(_, _, _, vparamss, _, _) = treeInfo firstConstructor body
vparamss
}
private def constrTparamsInvariant(cdef: ClassDef): List[TypeDef] = {
- val ClassDef(_, _, tparams, _) = resetLocalAttrs(cdef.duplicate)
+ val ClassDef(_, _, tparams, _) = resetAttrs(cdef.duplicate)
val tparamsInvariant = tparams.map(tparam => copyTypeDef(tparam)(mods = tparam.mods &~ (COVARIANT | CONTRAVARIANT)))
tparamsInvariant
}
diff --git a/src/compiler/scala/tools/nsc/util/package.scala b/src/compiler/scala/tools/nsc/util/package.scala
index 4237f36ade..bd95fdbb50 100644
--- a/src/compiler/scala/tools/nsc/util/package.scala
+++ b/src/compiler/scala/tools/nsc/util/package.scala
@@ -7,7 +7,7 @@ package scala
package tools
package nsc
-import java.io.{ OutputStream, PrintStream, ByteArrayOutputStream, PrintWriter, StringWriter }
+import java.io.{ OutputStream, PrintStream, ByteArrayOutputStream, PrintWriter, StringWriter, Reader }
package object util {
// forwarder for old code that builds against 2.9 and 2.10
@@ -46,6 +46,17 @@ package object util {
(result, ts2 filterNot (ts1 contains _))
}
+ def stringFromReader(reader: Reader) = {
+ val writer = new StringWriter()
+ var c = reader.read()
+ while(c != -1) {
+ writer.write(c)
+ c = reader.read()
+ }
+ reader.close()
+ writer.toString()
+ }
+
/** Generate a string using a routine that wants to write on a stream. */
def stringFromWriter(writer: PrintWriter => Unit): String = {
val stringWriter = new StringWriter()
diff --git a/src/compiler/scala/tools/reflect/ReflectGlobal.scala b/src/compiler/scala/tools/reflect/ReflectGlobal.scala
index f8ded56ec6..6f369212ad 100644
--- a/src/compiler/scala/tools/reflect/ReflectGlobal.scala
+++ b/src/compiler/scala/tools/reflect/ReflectGlobal.scala
@@ -12,9 +12,10 @@ class ReflectGlobal(currentSettings: Settings, reporter: Reporter, override val
extends Global(currentSettings, reporter) with scala.tools.reflect.ReflectSetup with scala.reflect.runtime.SymbolTable {
override def transformedType(sym: Symbol) =
- erasure.transformInfo(sym,
- uncurry.transformInfo(sym,
- refChecks.transformInfo(sym, sym.info)))
+ postErasure.transformInfo(sym,
+ erasure.transformInfo(sym,
+ uncurry.transformInfo(sym,
+ refChecks.transformInfo(sym, sym.info))))
override def isCompilerUniverse = true
diff --git a/src/compiler/scala/tools/reflect/ToolBox.scala b/src/compiler/scala/tools/reflect/ToolBox.scala
index 4c1bc794bc..4a3db09909 100644
--- a/src/compiler/scala/tools/reflect/ToolBox.scala
+++ b/src/compiler/scala/tools/reflect/ToolBox.scala
@@ -71,12 +71,6 @@ trait ToolBox[U <: scala.reflect.api.Universe] {
*/
def inferImplicitView(tree: u.Tree, from: u.Type, to: u.Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: u.Position = u.NoPosition): u.Tree
- /** Recursively resets symbols and types in a given tree.
- * WARNING: Don't use this API, go for [[untypecheck]] instead.
- */
- @deprecated("Use `tb.untypecheck` instead", "2.11.0")
- def resetAllAttrs(tree: u.Tree): u.Tree
-
/** Recursively resets locally defined symbols and types in a given tree.
* WARNING: Don't use this API, go for [[untypecheck]] instead.
*/
@@ -102,6 +96,15 @@ trait ToolBox[U <: scala.reflect.api.Universe] {
*/
def compile(tree: u.Tree): () => Any
+ /** Defines a top-level class, trait or module in this ToolBox,
+ * putting it into a uniquely-named package and returning a symbol that references the defined entity.
+ * For a ClassDef, a ClassSymbol is returned, and for a ModuleDef, a ModuleSymbol is returned (not a module class, but a module itself).
+ *
+ * This method can be used to generate definitions that will later be re-used by subsequent calls to
+ * `compile`, `define` or `eval`. To refer to the generated definition in a tree, use q"$sym".
+ */
+ def define(tree: u.ImplDef): u.Symbol
+
/** Compiles and runs a tree using this ToolBox.
* Is equivalent to `compile(tree)()`.
*/
diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
index 4a8c91bd1b..7bae3203c2 100644
--- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
+++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
@@ -193,6 +193,19 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
analyzer.inferImplicit(tree, pt, isView, currentTyper.context, silent, withMacrosDisabled, pos, (pos, msg) => throw ToolBoxError(msg))
})
+ private def wrapInPackageAndCompile(packageName: TermName, tree: ImplDef): Symbol = {
+ val pdef = PackageDef(Ident(packageName), List(tree))
+ val unit = new CompilationUnit(NoSourceFile)
+ unit.body = pdef
+
+ val run = new Run
+ reporter.reset()
+ run.compileUnits(List(unit), run.namerPhase)
+ throwIfErrors()
+
+ tree.symbol
+ }
+
def compile(expr0: Tree): () => Any = {
val expr = wrapIntoTerm(expr0)
@@ -200,7 +213,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
val thunks = freeTerms map (fte => () => fte.value) // need to be lazy in order not to distort evaluation order
verify(expr)
- def wrap(expr0: Tree): ModuleDef = {
+ def wrapInModule(expr0: Tree): ModuleDef = {
val (expr, freeTerms) = extractFreeTerms(expr0, wrapFreeTermRefs = true)
val (obj, _) = rootMirror.EmptyPackageClass.newModuleAndClassSymbol(
@@ -236,22 +249,15 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
NoPosition))
trace("wrapped: ")(showAttributed(moduledef, true, true, settings.Yshowsymkinds.value))
- val cleanedUp = resetLocalAttrs(moduledef)
+ val cleanedUp = resetAttrs(moduledef)
trace("cleaned up: ")(showAttributed(cleanedUp, true, true, settings.Yshowsymkinds.value))
cleanedUp.asInstanceOf[ModuleDef]
}
- val mdef = wrap(expr)
- val pdef = PackageDef(Ident(mdef.name), List(mdef))
- val unit = new CompilationUnit(NoSourceFile)
- unit.body = pdef
+ val mdef = wrapInModule(expr)
+ val msym = wrapInPackageAndCompile(mdef.name, mdef)
- val run = new Run
- reporter.reset()
- run.compileUnits(List(unit), run.namerPhase)
- throwIfErrors()
-
- val className = mdef.symbol.fullName
+ val className = msym.fullName
if (settings.debug) println("generated: "+className)
def moduleFileName(className: String) = className + "$"
val jclazz = jClass.forName(moduleFileName(className), true, classLoader)
@@ -278,6 +284,13 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
}
}
+ def define(tree: ImplDef): Symbol = {
+ val freeTerms = tree.freeTerms
+ if (freeTerms.nonEmpty) throw ToolBoxError(s"reflective toolbox has failed: cannot have free terms in a top-level definition")
+ verify(tree)
+ wrapInPackageAndCompile(nextWrapperModuleName(), tree)
+ }
+
def parse(code: String): Tree = {
reporter.reset()
val tree = gen.mkTreeOrBlock(newUnitParser(code, "<toolbox>").parseStatsOrPackages())
@@ -385,18 +398,10 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
uitree
}
- def resetAllAttrs(tree: u.Tree): u.Tree = withCompilerApi { compilerApi =>
- import compilerApi._
- val ctree: compiler.Tree = importer.importTree(tree)
- val ttree: compiler.Tree = compiler.resetAllAttrs(ctree)
- val uttree = exporter.importTree(ttree)
- uttree
- }
-
def resetLocalAttrs(tree: u.Tree): u.Tree = withCompilerApi { compilerApi =>
import compilerApi._
val ctree: compiler.Tree = importer.importTree(tree)
- val ttree: compiler.Tree = compiler.resetLocalAttrs(ctree)
+ val ttree: compiler.Tree = compiler.resetAttrs(ctree)
val uttree = exporter.importTree(ttree)
uttree
}
@@ -421,6 +426,18 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
compiler.compile(ctree)
}
+ def define(tree: u.ImplDef): u.Symbol = withCompilerApi { compilerApi =>
+ import compilerApi._
+
+ if (compiler.settings.verbose) println("importing "+tree)
+ val ctree: compiler.ImplDef = importer.importTree(tree).asInstanceOf[compiler.ImplDef]
+
+ if (compiler.settings.verbose) println("defining "+ctree)
+ val csym: compiler.Symbol = compiler.define(ctree)
+ val usym = exporter.importSymbol(csym)
+ usym
+ }
+
def eval(tree: u.Tree): Any = compile(tree)()
}
}
diff --git a/src/library/scala/collection/mutable/AnyRefMap.scala b/src/library/scala/collection/mutable/AnyRefMap.scala
index 29c92a111c..47fb66744e 100644
--- a/src/library/scala/collection/mutable/AnyRefMap.scala
+++ b/src/library/scala/collection/mutable/AnyRefMap.scala
@@ -22,9 +22,9 @@ import generic.CanBuildFrom
* on a map that will no longer have elements removed but will be
* used heavily may save both time and storage space.
*
- * This map is not indended to contain more than 2^29 entries (approximately
- * 500 million). The maximum capacity is 2^30, but performance will degrade
- * rapidly as 2^30 is approached.
+ * This map is not intended to contain more than 2^29^ entries (approximately
+ * 500 million). The maximum capacity is 2^30^, but performance will degrade
+ * rapidly as 2^30^ is approached.
*
*/
final class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K => V, initialBufferSize: Int, initBlank: Boolean)
@@ -291,24 +291,21 @@ extends AbstractMap[K, V]
private[this] val vz = _values
private[this] var index = 0
- private[this] var found = false
- def hasNext = found || (index<hz.length && {
+ def hasNext: Boolean = index<hz.length && {
var h = hz(index)
- if (h+h != 0) found = true
- else {
+ while (h+h == 0) {
index += 1
- while (index < hz.length && { h = hz(index); h+h == 0 }) index += 1
- found = (index < hz.length)
+ if (index >= hz.length) return false
+ h = hz(index)
}
- found
- })
+ true
+ }
- def next = {
- if (found || hasNext) {
- val ans = (_keys(index).asInstanceOf[K], _values(index).asInstanceOf[V])
+ def next: (K, V) = {
+ if (hasNext) {
+ val ans = (kz(index).asInstanceOf[K], vz(index).asInstanceOf[V])
index += 1
- found = false
ans
}
else throw new NoSuchElementException("next")
diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala
index b70426a145..6743b9e42a 100644
--- a/src/library/scala/util/matching/Regex.scala
+++ b/src/library/scala/util/matching/Regex.scala
@@ -647,9 +647,10 @@ object Regex {
/** A class to step through a sequence of regex matches.
*
* All methods inherited from [[scala.util.matching.Regex.MatchData]] will throw
- * an [[java.lang.IllegalStateException]] until the matcher is initialized by
- * calling `hasNext` or `next()` or causing these methods to be called, such as
- * by invoking `toString` or iterating through the iterator's elements.
+ * a [[java.lang.IllegalStateException]] until the matcher is initialized. The
+ * matcher can be initialized by calling `hasNext` or `next()` or causing these
+ * methods to be called, such as by invoking `toString` or iterating through
+ * the iterator's elements.
*
* @see [[java.util.regex.Matcher]]
*/
diff --git a/src/reflect/scala/reflect/api/Importers.scala b/src/reflect/scala/reflect/api/Importers.scala
index 5667d93e29..6539137cee 100644
--- a/src/reflect/scala/reflect/api/Importers.scala
+++ b/src/reflect/scala/reflect/api/Importers.scala
@@ -52,7 +52,7 @@ package api
* val imported = importer.importTree(tree)
*
* // after the tree is imported, it can be evaluated as usual
- * val tree = toolBox.resetAllAttrs(imported.duplicate)
+ * val tree = toolBox.untypecheck(imported.duplicate)
* val valueOfX = toolBox.eval(imported).asInstanceOf[T]
* ...
* }
diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala
index 83da5141b9..60e00ca5fd 100644
--- a/src/reflect/scala/reflect/api/Trees.scala
+++ b/src/reflect/scala/reflect/api/Trees.scala
@@ -1066,7 +1066,7 @@ trait Trees { self: Universe =>
* UnApply(
* // a dummy node that carries the type of unapplication to patmat
* // the <unapply-selector> here doesn't have an underlying symbol
- * // it only has a type assigned, therefore after `resetAllAttrs` this tree is no longer typeable
+ * // it only has a type assigned, therefore after `untypecheck` this tree is no longer typeable
* Apply(Select(Ident(Foo), newTermName("unapply")), List(Ident(newTermName("<unapply-selector>")))),
* // arguments of the unapply => nothing synthetic here
* List(Bind(newTermName("x"), Ident(nme.WILDCARD)))),
diff --git a/src/reflect/scala/reflect/api/TypeTags.scala b/src/reflect/scala/reflect/api/TypeTags.scala
index 7457910226..be76758224 100644
--- a/src/reflect/scala/reflect/api/TypeTags.scala
+++ b/src/reflect/scala/reflect/api/TypeTags.scala
@@ -134,7 +134,7 @@ import scala.language.implicitConversions
* reflection APIs provided by Java (for classes) and Scala (for types).</li>
*
* <li>'''Certain manifest operations(i.e., <:<, >:> and typeArguments) are not
- * supported.''' <br/>Instead, one culd use the reflection APIs provided by Java (for
+ * supported.''' <br/>Instead, one could use the reflection APIs provided by Java (for
* classes) and Scala (for types).</li>
*</ul>
*
diff --git a/src/reflect/scala/reflect/internal/Required.scala b/src/reflect/scala/reflect/internal/Required.scala
index 14db252a16..009bc39d4c 100644
--- a/src/reflect/scala/reflect/internal/Required.scala
+++ b/src/reflect/scala/reflect/internal/Required.scala
@@ -6,6 +6,9 @@ import settings.MutableSettings
trait Required { self: SymbolTable =>
def picklerPhase: Phase
+
+ def erasurePhase: Phase
+
def settings: MutableSettings
@deprecated("Interactive is implemented with a custom Global; this flag is ignored", "2.11.0") def forInteractive = false
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 74b2208278..4fbac235f4 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -899,7 +899,7 @@ trait Types
-1
}
- /** If this is a poly- or methodtype, a copy with cloned type / value parameters
+ /** If this is a ExistentialType, PolyType or MethodType, a copy with cloned type / value parameters
* owned by `owner`. Identity for all other types.
*/
def cloneInfo(owner: Symbol) = this
@@ -2683,8 +2683,55 @@ trait Types
override def baseTypeSeq = underlying.baseTypeSeq map maybeRewrap
override def isHigherKinded = false
- override def skolemizeExistential(owner: Symbol, origin: AnyRef) =
+ /** [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
+ *
+ * (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.)
+ */
+ 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)
+ }
+ }
+ }
+
+ _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
+
deriveType(quantified, tparam => (owner orElse tparam.owner).newExistentialSkolem(tparam, origin))(underlying)
+ }
private def wildcardArgsString(qset: Set[Symbol], args: List[Type]): List[String] = args map {
case TypeRef(_, sym, _) if (qset contains sym) =>
@@ -2905,6 +2952,8 @@ trait Types
override def params: List[Symbol] = zippedArgs map (_._1)
override def typeArgs: List[Type] = zippedArgs map (_._2)
+
+ override def safeToString: String = super.safeToString + typeArgs.map(_.safeToString).mkString("[", ", ", "]")
}
trait UntouchableTypeVar extends TypeVar {
@@ -3025,15 +3074,19 @@ trait Types
def addLoBound(tp: Type, isNumericBound: Boolean = false) {
assert(tp != this, tp) // implies there is a cycle somewhere (?)
//println("addLoBound: "+(safeToString, debugString(tp))) //DEBUG
- undoLog record this
- constr.addLoBound(tp, isNumericBound)
+ if (!sharesConstraints(tp)) {
+ undoLog record this
+ constr.addLoBound(tp, isNumericBound)
+ }
}
def addHiBound(tp: Type, isNumericBound: Boolean = false) {
// assert(tp != this)
//println("addHiBound: "+(safeToString, debugString(tp))) //DEBUG
- undoLog record this
- constr.addHiBound(tp, isNumericBound)
+ if (!sharesConstraints(tp)) {
+ undoLog record this
+ constr.addHiBound(tp, isNumericBound)
+ }
}
// </region>
@@ -3045,6 +3098,16 @@ trait Types
case ConstantTrue => true
case tv: TypeVar => tv.suspended
}
+
+ /** `AppliedTypeVar`s share the same `TypeConstraint` with the `HKTypeVar` that it was spawned from.
+ * A type inference session can also have more than one ATV.
+ * If we don't detect that, we end up with "cyclic constraint" when we try to instantiate type parameters
+ * after solving in, pos/t8237
+ */
+ protected final def sharesConstraints(other: Type): Boolean = other match {
+ case other: TypeVar => constr == other.constr // SI-8237 avoid cycles. Details in pos/t8237.scala
+ case _ => false
+ }
private[Types] def suspended_=(b: Boolean): Unit = _suspended = if (b) ConstantTrue else ConstantFalse
// SI-7785 Link the suspended attribute of a TypeVar created in, say, a TypeMap (e.g. AsSeenFrom) to its originator
private[Types] def linkSuspended(origin: TypeVar): Unit = _suspended = origin
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala b/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
index e2159d30f5..564cbb1ce3 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
@@ -257,6 +257,12 @@ private[internal] trait TypeConstraints {
// println("solving "+tvars+"/"+tparams+"/"+(tparams map (_.info)))
foreach3(tvars, tparams, variances)(solveOne)
- tvars forall (tv => tv.instWithinBounds || util.andFalse(log(s"Inferred type for ${tv.originString} does not conform to bounds: ${tv.constr}")))
+
+ def logBounds(tv: TypeVar) = log {
+ val what = if (!tv.instValid) "is invalid" else s"does not conform to bounds: ${tv.constr}"
+ s"Inferred type for ${tv.originString} (${tv.inst}) $what"
+ }
+
+ tvars forall (tv => tv.instWithinBounds || util.andFalse(logBounds(tv)))
}
}
diff --git a/src/reflect/scala/reflect/internal/transform/PostErasure.scala b/src/reflect/scala/reflect/internal/transform/PostErasure.scala
new file mode 100644
index 0000000000..f0c7d0f050
--- /dev/null
+++ b/src/reflect/scala/reflect/internal/transform/PostErasure.scala
@@ -0,0 +1,19 @@
+package scala.reflect
+package internal
+package transform
+
+trait PostErasure {
+ val global: SymbolTable
+ import global._
+ import definitions._
+
+ object elimErasedValueType extends TypeMap {
+ def apply(tp: Type) = tp match {
+ case ConstantType(Constant(tp: Type)) => ConstantType(Constant(apply(tp)))
+ case ErasedValueType(_, underlying) => underlying
+ case _ => mapOver(tp)
+ }
+ }
+
+ def transformInfo(sym: Symbol, tp: Type) = elimErasedValueType(tp)
+}
diff --git a/src/reflect/scala/reflect/internal/transform/Transforms.scala b/src/reflect/scala/reflect/internal/transform/Transforms.scala
index fa185db22f..296ccde443 100644
--- a/src/reflect/scala/reflect/internal/transform/Transforms.scala
+++ b/src/reflect/scala/reflect/internal/transform/Transforms.scala
@@ -26,17 +26,20 @@ trait Transforms { self: SymbolTable =>
private val refChecksLazy = new Lazy(new { val global: Transforms.this.type = self } with RefChecks)
private val uncurryLazy = new Lazy(new { val global: Transforms.this.type = self } with UnCurry)
private val erasureLazy = new Lazy(new { val global: Transforms.this.type = self } with Erasure)
+ private val postErasureLazy = new Lazy(new { val global: Transforms.this.type = self } with PostErasure)
def refChecks = refChecksLazy.force
def uncurry = uncurryLazy.force
def erasure = erasureLazy.force
+ def postErasure = postErasureLazy.force
def transformedType(sym: Symbol) =
- erasure.transformInfo(sym,
- uncurry.transformInfo(sym,
- refChecks.transformInfo(sym, sym.info)))
+ postErasure.transformInfo(sym,
+ erasure.transformInfo(sym,
+ uncurry.transformInfo(sym,
+ refChecks.transformInfo(sym, sym.info))))
def transformedType(tpe: Type) =
- erasure.scalaErasure(uncurry.uncurry(tpe))
+ postErasure.elimErasedValueType(erasure.scalaErasure(uncurry.uncurry(tpe)))
}
diff --git a/src/reflect/scala/reflect/macros/Evals.scala b/src/reflect/scala/reflect/macros/Evals.scala
index 222ae43d79..68e07dd319 100644
--- a/src/reflect/scala/reflect/macros/Evals.scala
+++ b/src/reflect/scala/reflect/macros/Evals.scala
@@ -17,13 +17,13 @@ trait Evals {
* permitted by the shape of the arguments.
*
* Known issues: because of [[https://issues.scala-lang.org/browse/SI-5748 https://issues.scala-lang.org/browse/SI-5748]]
- * trees being evaluated first need to undergo `resetAllAttrs`. Resetting symbols and types
+ * trees being evaluated first need to undergo `untypecheck`. Resetting symbols and types
* mutates the tree in place, therefore the conventional approach is to `duplicate` the tree first.
*
* {{{
* scala> def impl(c: Context)(x: c.Expr[String]) = {
- * | val x1 = c.Expr[String](c.resetAllAttrs(x.tree.duplicate))
- * | println(s"compile-time value is: \${c.eval(x1)}")
+ * | val x1 = c.Expr[String](c.untypecheck(x.tree.duplicate))
+ * | println(s"compile-time value is: ${c.eval(x1)}")
* | x
* | }
* impl: (c: Context)(x: c.Expr[String])c.Expr[String]
diff --git a/src/reflect/scala/reflect/macros/Typers.scala b/src/reflect/scala/reflect/macros/Typers.scala
index 87de442921..6c077de1d2 100644
--- a/src/reflect/scala/reflect/macros/Typers.scala
+++ b/src/reflect/scala/reflect/macros/Typers.scala
@@ -68,12 +68,6 @@ trait Typers {
*/
def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: Position = enclosingPosition): Tree
- /** Recursively resets symbols and types in a given tree.
- * WARNING: Don't use this API, go for [[untypecheck]] instead.
- */
- @deprecated("Use `c.untypecheck` instead", "2.11.0")
- def resetAllAttrs(tree: Tree): Tree
-
/** Recursively resets locally defined symbols and types in a given tree.
* WARNING: Don't use this API, go for [[untypecheck]] instead.
*/
diff --git a/src/reflect/scala/reflect/macros/Universe.scala b/src/reflect/scala/reflect/macros/Universe.scala
index d84e6aa737..bc5c8b2840 100644
--- a/src/reflect/scala/reflect/macros/Universe.scala
+++ b/src/reflect/scala/reflect/macros/Universe.scala
@@ -122,7 +122,7 @@ abstract class Universe extends scala.reflect.api.Universe {
def setType(tp: Type): Tree
/** Like `setType`, but if this is a previously empty TypeTree that
- * fact is remembered so that resetAllAttrs will snap back.
+ * fact is remembered so that `untypecheck` will snap back.
*
* \@PP: Attempting to elaborate on the above, I find: If defineType
* is called on a TypeTree whose type field is null or NoType,
@@ -130,7 +130,8 @@ abstract class Universe extends scala.reflect.api.Universe {
* ResetAttrsTraverser, which nulls out the type field of TypeTrees
* for which wasEmpty is true, leaving the others alone.
*
- * resetAllAttrs is used in situations where some speculative
+ * `untypecheck` (or `resetAttrs` in compiler parlance) is used
+ * in situations where some speculative
* typing of a tree takes place, fails, and the tree needs to be
* returned to its former state to try again. So according to me:
* using `defineType` instead of `setType` is how you communicate
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index 68c67bb1f8..bc95b839b7 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -16,7 +16,7 @@ import java.io.IOException
import scala.reflect.internal.{ MissingRequirementError, JavaAccFlags, JMethodOrConstructor }
import internal.pickling.ByteCodecs
import internal.pickling.UnPickler
-import scala.collection.mutable.{ HashMap, ListBuffer }
+import scala.collection.mutable.{ HashMap, ListBuffer, ArrayBuffer }
import internal.Flags._
import ReflectionUtils._
import scala.language.existentials
@@ -118,15 +118,16 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
private def abort(msg: String) = throw new ScalaReflectionException(msg)
- private def ErrorInnerClass(sym: Symbol) = abort(s"$sym is an inner class, use reflectClass on an InstanceMirror to obtain its ClassMirror")
- private def ErrorInnerModule(sym: Symbol) = abort(s"$sym is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror")
- private def ErrorStaticClass(sym: Symbol) = abort(s"$sym is a static class, use reflectClass on a RuntimeMirror to obtain its ClassMirror")
- private def ErrorStaticModule(sym: Symbol) = abort(s"$sym is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror")
- private def ErrorNotMember(sym: Symbol, owner: Symbol) = abort(s"expected a member of $owner, you provided ${sym.kindString} ${sym.fullName}")
- private def ErrorNotField(sym: Symbol) = abort(s"expected a field or an accessor method symbol, you provided $sym")
- private def ErrorNotConstructor(sym: Symbol, owner: Symbol) = abort(s"expected a constructor of $owner, you provided $sym")
- private def ErrorFree(member: Symbol, freeType: Symbol) = abort(s"cannot reflect ${member.kindString} ${member.name}, because it's a member of a weak type ${freeType.name}")
- private def ErrorNonExistentField(sym: Symbol) = abort(
+ private def ErrorInnerClass(sym: Symbol) = abort(s"$sym is an inner class, use reflectClass on an InstanceMirror to obtain its ClassMirror")
+ private def ErrorInnerModule(sym: Symbol) = abort(s"$sym is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror")
+ private def ErrorStaticClass(sym: Symbol) = abort(s"$sym is a static class, use reflectClass on a RuntimeMirror to obtain its ClassMirror")
+ private def ErrorStaticModule(sym: Symbol) = abort(s"$sym is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror")
+ private def ErrorNotMember(sym: Symbol, owner: Symbol) = abort(s"expected a member of $owner, you provided ${sym.kindString} ${sym.fullName}")
+ private def ErrorNotField(sym: Symbol) = abort(s"expected a field or an accessor method symbol, you provided $sym")
+ private def ErrorNotConstructor(sym: Symbol, owner: Symbol) = abort(s"expected a constructor of $owner, you provided $sym")
+ private def ErrorArrayConstructor(sym: Symbol, owner: Symbol) = abort(s"Cannot instantiate arrays with mirrors. Consider using `scala.reflect.ClassTag(<class of element>).newArray(<length>)` instead")
+ private def ErrorFree(member: Symbol, freeType: Symbol) = abort(s"cannot reflect ${member.kindString} ${member.name}, because it's a member of a weak type ${freeType.name}")
+ private def ErrorNonExistentField(sym: Symbol) = abort(
sm"""Scala field ${sym.name} isn't represented as a Java field, neither it has a Java accessor method
|note that private parameters of class constructors don't get mapped onto fields and/or accessors,
|unless they are used outside of their declaring constructors.""")
@@ -221,6 +222,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
private def checkConstructorOf(sym: Symbol, owner: ClassSymbol) {
if (!sym.isClassConstructor) ErrorNotConstructor(sym, owner)
+ if (owner == ArrayClass) ErrorArrayConstructor(sym, owner)
ensuringNotFree(sym) {
if (!owner.info.decls.toList.contains(sym)) ErrorNotConstructor(sym, owner)
}
@@ -247,7 +249,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
}
def reflectMethod(method: MethodSymbol): MethodMirror = {
checkMemberOf(method, symbol)
- mkJavaMethodMirror(instance, method)
+ mkMethodMirror(instance, method)
}
def reflectClass(cls: ClassSymbol): ClassMirror = {
if (cls.isStatic) ErrorStaticClass(cls)
@@ -262,16 +264,35 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
override def toString = s"instance mirror for $instance"
}
- private class JavaFieldMirror(val receiver: Any, val symbol: TermSymbol)
+ // caches value class metadata, so that we minimize the work that needs to be done during Mirror.apply
+ private class DerivedValueClassMetadata(info: Type) {
+ val symbol = info.typeSymbol
+ val isDerivedValueClass = symbol.isDerivedValueClass
+ lazy val boxer = runtimeClass(symbol.toType).getDeclaredConstructors().head
+ lazy val unboxer = {
+ val fields @ (field :: _) = symbol.toType.declarations.collect{ case ts: TermSymbol if ts.isParamAccessor && ts.isMethod => ts }.toList
+ assert(fields.length == 1, s"$symbol: $fields")
+ runtimeClass(symbol.asClass).getDeclaredMethod(field.name.toString)
+ }
+ }
+
+ private class JavaFieldMirror(val receiver: Any, val symbol: TermSymbol, metadata: DerivedValueClassMetadata)
extends FieldMirror {
+ def this(receiver: Any, symbol: TermSymbol) = this(receiver, symbol, new DerivedValueClassMetadata(symbol.info))
+ def bind(newReceiver: Any) = new JavaFieldMirror(newReceiver, symbol, metadata)
+ import metadata._
+
lazy val jfield = ensureAccessible(fieldToJava(symbol))
- def get = jfield get receiver
+ def get = {
+ val value = jfield get receiver
+ if (isDerivedValueClass) boxer.newInstance(value) else value
+ }
def set(value: Any) = {
// it appears useful to be able to set values of vals, therefore I'm disabling this check
// if (!symbol.isMutable) ErrorSetImmutableField(symbol)
- jfield.set(receiver, value)
+ jfield.set(receiver, if (isDerivedValueClass) unboxer.invoke(value) else value)
}
- def bind(newReceiver: Any) = new JavaFieldMirror(newReceiver, symbol)
+
override def toString = s"field mirror for ${symbol.fullName} (bound to $receiver)"
}
@@ -312,13 +333,17 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
bytecodelessMethodOwners(meth.owner) && !bytecodefulObjectMethods(meth)
}
+ private def isByNameParam(p: Type) = isByNameParamType(p)
+ private def isValueClassParam(p: Type) = p.typeSymbol.isDerivedValueClass
+
// unlike other mirrors, method mirrors are created by a factory
// that's because we want to have decent performance
// therefore we move special cases into separate subclasses
// rather than have them on a hot path them in a unified implementation of the `apply` method
- private def mkJavaMethodMirror[T: ClassTag](receiver: T, symbol: MethodSymbol): JavaMethodMirror = {
- if (isBytecodelessMethod(symbol)) new JavaBytecodelessMethodMirror(receiver, symbol)
- else if (symbol.paramss.flatten exists (p => isByNameParamType(p.info))) new JavaByNameMethodMirror(receiver, symbol)
+ private def mkMethodMirror[T: ClassTag](receiver: T, symbol: MethodSymbol): MethodMirror = {
+ def existsParam(pred: Type => Boolean) = symbol.paramss.flatten.map(_.info).exists(pred)
+ if (isBytecodelessMethod(symbol)) new BytecodelessMethodMirror(receiver, symbol)
+ else if (existsParam(isByNameParam) || existsParam(isValueClassParam)) new JavaTransformingMethodMirror(receiver, symbol)
else {
symbol.paramss.flatten.length match {
case 0 => new JavaVanillaMethodMirror0(receiver, symbol)
@@ -330,68 +355,123 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
}
}
}
- private abstract class JavaMethodMirror(val symbol: MethodSymbol) extends MethodMirror {
+
+ private abstract class JavaMethodMirror(val symbol: MethodSymbol, protected val ret: DerivedValueClassMetadata) extends MethodMirror {
lazy val jmeth = ensureAccessible(methodToJava(symbol))
- def jinvokeraw(jmeth: jMethod, receiver: Any, args: Seq[Any]) = jmeth.invoke(receiver, args.asInstanceOf[Seq[AnyRef]]: _*)
+ lazy val jconstr = ensureAccessible(constructorToJava(symbol))
- def jinvoke(jmeth: jMethod, receiver: Any, args: Seq[Any]): Any = {
- val result = jinvokeraw(jmeth, receiver, args)
- if (jmeth.getReturnType == java.lang.Void.TYPE) ()
+ def jinvokeraw(args: Seq[Any]) =
+ if (!symbol.isConstructor) jmeth.invoke(receiver, args.asInstanceOf[Seq[AnyRef]]: _*)
+ else if (receiver == null) jconstr.newInstance(args.asInstanceOf[Seq[AnyRef]]: _*)
+ else jconstr.newInstance((receiver +: args).asInstanceOf[Seq[AnyRef]]: _*)
+ def jinvoke(args: Seq[Any]): Any = {
+ val result = jinvokeraw(args)
+ if (!symbol.isConstructor && jmeth.getReturnType == java.lang.Void.TYPE) ()
+ else if (!symbol.isConstructor && ret.isDerivedValueClass) ret.boxer.newInstance(result.asInstanceOf[AnyRef])
else result
}
- override def toString = s"method mirror for ${showMethodSig(symbol)} (bound to $receiver)"
- }
-
- private class JavaVanillaMethodMirror(val receiver: Any, symbol: MethodSymbol)
- extends JavaMethodMirror(symbol) {
- def bind(newReceiver: Any) = new JavaVanillaMethodMirror(newReceiver, symbol)
- def apply(args: Any*): Any = jinvoke(jmeth, receiver, args)
- }
-
- private class JavaVanillaMethodMirror0(receiver: Any, symbol: MethodSymbol)
- extends JavaVanillaMethodMirror(receiver, symbol) {
- override def bind(newReceiver: Any) = new JavaVanillaMethodMirror0(newReceiver, symbol)
- override def jinvokeraw(jmeth: jMethod, receiver: Any, args: Seq[Any]) = jmeth.invoke(receiver)
- }
-
- private class JavaVanillaMethodMirror1(receiver: Any, symbol: MethodSymbol)
- extends JavaVanillaMethodMirror(receiver, symbol) {
- override def bind(newReceiver: Any) = new JavaVanillaMethodMirror1(newReceiver, symbol)
- override def jinvokeraw(jmeth: jMethod, receiver: Any, args: Seq[Any]) = jmeth.invoke(receiver, args(0).asInstanceOf[AnyRef])
- }
-
- private class JavaVanillaMethodMirror2(receiver: Any, symbol: MethodSymbol)
- extends JavaVanillaMethodMirror(receiver, symbol) {
- override def bind(newReceiver: Any) = new JavaVanillaMethodMirror2(newReceiver, symbol)
- override def jinvokeraw(jmeth: jMethod, receiver: Any, args: Seq[Any]) = jmeth.invoke(receiver, args(0).asInstanceOf[AnyRef], args(1).asInstanceOf[AnyRef])
- }
-
- private class JavaVanillaMethodMirror3(receiver: Any, symbol: MethodSymbol)
- extends JavaVanillaMethodMirror(receiver, symbol) {
- override def bind(newReceiver: Any) = new JavaVanillaMethodMirror3(newReceiver, symbol)
- override def jinvokeraw(jmeth: jMethod, receiver: Any, args: Seq[Any]) = jmeth.invoke(receiver, args(0).asInstanceOf[AnyRef], args(1).asInstanceOf[AnyRef], args(2).asInstanceOf[AnyRef])
+ override def toString = {
+ val what = if (symbol.isConstructor) "constructor mirror" else "method mirror"
+ s"$what for ${showMethodSig(symbol)} (bound to $receiver)"
+ }
}
- private class JavaVanillaMethodMirror4(receiver: Any, symbol: MethodSymbol)
- extends JavaVanillaMethodMirror(receiver, symbol) {
- override def bind(newReceiver: Any) = new JavaVanillaMethodMirror4(newReceiver, symbol)
- override def jinvokeraw(jmeth: jMethod, receiver: Any, args: Seq[Any]) = jmeth.invoke(receiver, args(0).asInstanceOf[AnyRef], args(1).asInstanceOf[AnyRef], args(2).asInstanceOf[AnyRef], args(3).asInstanceOf[AnyRef])
- }
+ private class JavaVanillaMethodMirror(val receiver: Any, symbol: MethodSymbol, ret: DerivedValueClassMetadata)
+ extends JavaMethodMirror(symbol, ret) {
+ def this(receiver: Any, symbol: MethodSymbol) = this(receiver, symbol, new DerivedValueClassMetadata(symbol.returnType))
+ def bind(newReceiver: Any) = new JavaVanillaMethodMirror(newReceiver, symbol, ret)
+ def apply(args: Any*): Any = jinvoke(args)
+ }
+
+ private class JavaVanillaMethodMirror0(receiver: Any, symbol: MethodSymbol, ret: DerivedValueClassMetadata)
+ extends JavaVanillaMethodMirror(receiver, symbol, ret) {
+ def this(receiver: Any, symbol: MethodSymbol) = this(receiver, symbol, new DerivedValueClassMetadata(symbol.returnType))
+ override def bind(newReceiver: Any) = new JavaVanillaMethodMirror0(newReceiver, symbol, ret)
+ override def jinvokeraw(args: Seq[Any]) =
+ if (!symbol.isConstructor) jmeth.invoke(receiver)
+ else if (receiver == null) jconstr.newInstance()
+ else jconstr.newInstance(receiver.asInstanceOf[AnyRef])
+ }
+
+ private class JavaVanillaMethodMirror1(receiver: Any, symbol: MethodSymbol, ret: DerivedValueClassMetadata)
+ extends JavaVanillaMethodMirror(receiver, symbol, ret) {
+ def this(receiver: Any, symbol: MethodSymbol) = this(receiver, symbol, new DerivedValueClassMetadata(symbol.returnType))
+ override def bind(newReceiver: Any) = new JavaVanillaMethodMirror1(newReceiver, symbol, ret)
+ override def jinvokeraw(args: Seq[Any]) =
+ if (!symbol.isConstructor) jmeth.invoke(receiver, args(0).asInstanceOf[AnyRef])
+ else if (receiver == null) jconstr.newInstance(args(0).asInstanceOf[AnyRef])
+ else jconstr.newInstance(receiver.asInstanceOf[AnyRef], args(0).asInstanceOf[AnyRef])
+ }
+
+ private class JavaVanillaMethodMirror2(receiver: Any, symbol: MethodSymbol, ret: DerivedValueClassMetadata)
+ extends JavaVanillaMethodMirror(receiver, symbol, ret) {
+ def this(receiver: Any, symbol: MethodSymbol) = this(receiver, symbol, new DerivedValueClassMetadata(symbol.returnType))
+ override def bind(newReceiver: Any) = new JavaVanillaMethodMirror2(newReceiver, symbol, ret)
+ override def jinvokeraw(args: Seq[Any]) =
+ if (!symbol.isConstructor) jmeth.invoke(receiver, args(0).asInstanceOf[AnyRef], args(1).asInstanceOf[AnyRef])
+ else if (receiver == null) jconstr.newInstance(args(0).asInstanceOf[AnyRef], args(1).asInstanceOf[AnyRef])
+ else jconstr.newInstance(receiver.asInstanceOf[AnyRef], args(0).asInstanceOf[AnyRef], args(1).asInstanceOf[AnyRef])
+ }
+
+ private class JavaVanillaMethodMirror3(receiver: Any, symbol: MethodSymbol, ret: DerivedValueClassMetadata)
+ extends JavaVanillaMethodMirror(receiver, symbol, ret) {
+ def this(receiver: Any, symbol: MethodSymbol) = this(receiver, symbol, new DerivedValueClassMetadata(symbol.returnType))
+ override def bind(newReceiver: Any) = new JavaVanillaMethodMirror3(newReceiver, symbol, ret)
+ override def jinvokeraw(args: Seq[Any]) =
+ if (!symbol.isConstructor) jmeth.invoke(receiver, args(0).asInstanceOf[AnyRef], args(1).asInstanceOf[AnyRef], args(2).asInstanceOf[AnyRef])
+ else if (receiver == null) jconstr.newInstance(args(0).asInstanceOf[AnyRef], args(1).asInstanceOf[AnyRef], args(2).asInstanceOf[AnyRef])
+ else jconstr.newInstance(receiver.asInstanceOf[AnyRef], args(0).asInstanceOf[AnyRef], args(1).asInstanceOf[AnyRef], args(2).asInstanceOf[AnyRef])
+ }
+
+ private class JavaVanillaMethodMirror4(receiver: Any, symbol: MethodSymbol, ret: DerivedValueClassMetadata)
+ extends JavaVanillaMethodMirror(receiver, symbol, ret) {
+ def this(receiver: Any, symbol: MethodSymbol) = this(receiver, symbol, new DerivedValueClassMetadata(symbol.returnType))
+ override def bind(newReceiver: Any) = new JavaVanillaMethodMirror4(newReceiver, symbol, ret)
+ override def jinvokeraw(args: Seq[Any]) =
+ if (!symbol.isConstructor) jmeth.invoke(receiver, args(0).asInstanceOf[AnyRef], args(1).asInstanceOf[AnyRef], args(2).asInstanceOf[AnyRef], args(3).asInstanceOf[AnyRef])
+ else if (receiver == null) jconstr.newInstance(args(0).asInstanceOf[AnyRef], args(1).asInstanceOf[AnyRef], args(2).asInstanceOf[AnyRef], args(3).asInstanceOf[AnyRef])
+ else jconstr.newInstance(receiver.asInstanceOf[AnyRef], args(0).asInstanceOf[AnyRef], args(1).asInstanceOf[AnyRef], args(2).asInstanceOf[AnyRef], args(3).asInstanceOf[AnyRef])
+ }
+
+ // caches MethodSymbol metadata, so that we minimize the work that needs to be done during Mirror.apply
+ // TODO: vararg is only supported in the last parameter list (SI-6182), so we don't need to worry about the rest for now
+ private class MethodMetadata(symbol: MethodSymbol) {
+ private val params = symbol.paramss.flatten.toArray
+ private val vcMetadata = params.map(p => new DerivedValueClassMetadata(p.info))
+ val isByName = params.map(p => isByNameParam(p.info))
+ def isDerivedValueClass(i: Int) = vcMetadata(i).isDerivedValueClass
+ def paramUnboxers(i: Int) = vcMetadata(i).unboxer
+ val paramCount = params.length
+ val ret = new DerivedValueClassMetadata(symbol.returnType)
+ }
+
+ private class JavaTransformingMethodMirror(val receiver: Any, symbol: MethodSymbol, metadata: MethodMetadata)
+ extends JavaMethodMirror(symbol, metadata.ret) {
+ def this(receiver: Any, symbol: MethodSymbol) = this(receiver, symbol, new MethodMetadata(symbol))
+ override def bind(newReceiver: Any) = new JavaTransformingMethodMirror(newReceiver, symbol, metadata)
+ import metadata._
- private class JavaByNameMethodMirror(val receiver: Any, symbol: MethodSymbol)
- extends JavaMethodMirror(symbol) {
- def bind(newReceiver: Any) = new JavaByNameMethodMirror(newReceiver, symbol)
def apply(args: Any*): Any = {
- val transformed = map2(args.toList, symbol.paramss.flatten)((arg, param) => if (isByNameParamType(param.info)) () => arg else arg)
- jinvoke(jmeth, receiver, transformed)
+ val args1 = new Array[Any](args.length)
+ var i = 0
+ while (i < args1.length) {
+ val arg = args(i)
+ if (i >= paramCount) args1(i) = arg // don't transform varargs
+ else if (isByName(i)) args1(i) = () => arg // don't transform by-name value class params
+ else if (isDerivedValueClass(i)) args1(i) = paramUnboxers(i).invoke(arg)
+ i += 1
+ }
+ jinvoke(args1)
}
}
- private class JavaBytecodelessMethodMirror[T: ClassTag](val receiver: T, symbol: MethodSymbol)
- extends JavaMethodMirror(symbol) {
- def bind(newReceiver: Any) = new JavaBytecodelessMethodMirror(newReceiver.asInstanceOf[T], symbol)
- def apply(args: Any*): Any = {
+ private class BytecodelessMethodMirror[T: ClassTag](val receiver: T, val symbol: MethodSymbol)
+ extends MethodMirror {
+ def bind(newReceiver: Any) = new BytecodelessMethodMirror(newReceiver.asInstanceOf[T], symbol)
+ override def toString = s"bytecodeless method mirror for ${showMethodSig(symbol)} (bound to $receiver)"
+
+ def apply(args: Any*): Any = {
// checking type conformance is too much of a hassle, so we don't do it here
// actually it's not even necessary, because we manually dispatch arguments below
val params = symbol.paramss.flatten
@@ -414,7 +494,10 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
def invokePrimitiveMethod = {
val jmeths = classOf[BoxesRunTime].getDeclaredMethods.filter(_.getName == nme.primitiveMethodName(symbol.name).toString)
assert(jmeths.length == 1, jmeths.toList)
- jinvoke(jmeths.head, null, objReceiver +: objArgs)
+ val jmeth = jmeths.head
+ val result = jmeth.invoke(null, (objReceiver +: objArgs).asInstanceOf[Seq[AnyRef]]: _*)
+ if (jmeth.getReturnType == java.lang.Void.TYPE) ()
+ else result
}
symbol match {
@@ -445,23 +528,6 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
}
}
- private class JavaConstructorMirror(val outer: AnyRef, val symbol: MethodSymbol)
- extends MethodMirror {
- def bind(newReceiver: Any) = new JavaConstructorMirror(newReceiver.asInstanceOf[AnyRef], symbol)
- override val receiver = outer
- lazy val jconstr = ensureAccessible(constructorToJava(symbol))
- def apply(args: Any*): Any = {
- if (symbol.owner == ArrayClass)
- abort("Cannot instantiate arrays with mirrors. Consider using `scala.reflect.ClassTag(<class of element>).newArray(<length>)` instead")
-
- val effectiveArgs =
- if (outer == null) args.asInstanceOf[Seq[AnyRef]]
- else outer +: args.asInstanceOf[Seq[AnyRef]]
- jconstr.newInstance(effectiveArgs: _*)
- }
- override def toString = s"constructor mirror for ${showMethodSig(symbol)} (bound to $outer)"
- }
-
private abstract class JavaTemplateMirror
extends TemplateMirror {
def outer: AnyRef
@@ -474,7 +540,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
def isStatic = false
def reflectConstructor(constructor: MethodSymbol) = {
checkConstructorOf(constructor, symbol)
- new JavaConstructorMirror(outer, constructor)
+ mkMethodMirror(outer, constructor)
}
override def toString = s"class mirror for ${symbol.fullName} (bound to $outer)"
}
diff --git a/src/reflect/scala/reflect/runtime/JavaUniverse.scala b/src/reflect/scala/reflect/runtime/JavaUniverse.scala
index cfd66744ff..f6556a442d 100644
--- a/src/reflect/scala/reflect/runtime/JavaUniverse.scala
+++ b/src/reflect/scala/reflect/runtime/JavaUniverse.scala
@@ -12,6 +12,8 @@ class JavaUniverse extends internal.SymbolTable with JavaUniverseForce with Refl
override def inform(msg: String): Unit = log(msg)
def picklerPhase = internal.SomePhase
+ def erasurePhase = internal.SomePhase
+
lazy val settings = new Settings
private val isLogging = sys.props contains "scala.debug.reflect"
diff --git a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala
index 813c0e1386..d642b25127 100644
--- a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala
+++ b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala
@@ -12,7 +12,7 @@ import scala.reflect.internal.util.AbstractFileClassLoader
/** A few java-reflection oriented utility functions useful during reflection bootstrapping.
*/
-private[scala] object ReflectionUtils {
+object ReflectionUtils {
// Unwraps some chained exceptions which arise during reflective calls.
def unwrapThrowable(x: Throwable): Throwable = x match {
case _: InvocationTargetException | // thrown by reflectively invoked method or constructor
diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala
index 8fba1e538e..d261fc5be9 100644
--- a/src/repl/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala
@@ -18,7 +18,7 @@ import scala.reflect.internal.util.{ BatchSourceFile, SourceFile }
import scala.tools.util.PathResolver
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.typechecker.{ TypeStrings, StructuredTypeStrings }
-import scala.tools.nsc.util.{ ScalaClassLoader, stringFromWriter, StackTraceOps }
+import scala.tools.nsc.util.{ ScalaClassLoader, stringFromReader, stringFromWriter, StackTraceOps }
import scala.tools.nsc.util.Exceptional.unwrap
import javax.script.{AbstractScriptEngine, Bindings, ScriptContext, ScriptEngine, ScriptEngineFactory, ScriptException, CompiledScript, Compilable}
@@ -534,8 +534,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
var code = ""
var bound = false
- @throws[ScriptException]
- def compile(script: String): CompiledScript = {
+ def compiled(script: String): CompiledScript = {
if (!bound) {
quietBind("engine" -> this.asInstanceOf[ScriptEngine])
bound = true
@@ -562,18 +561,6 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
}
}
- @throws[ScriptException]
- def compile(reader: java.io.Reader): CompiledScript = {
- val writer = new java.io.StringWriter()
- var c = reader.read()
- while(c != -1) {
- writer.write(c)
- c = reader.read()
- }
- reader.close()
- compile(writer.toString())
- }
-
private class WrappedRequest(val req: Request) extends CompiledScript {
var recorded = false
@@ -1014,10 +1001,16 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
}
@throws[ScriptException]
- def eval(script: String, context: ScriptContext): Object = compile(script).eval(context)
+ def compile(script: String): CompiledScript = eval("new javax.script.CompiledScript { def eval(context: javax.script.ScriptContext): Object = { " + script + " }.asInstanceOf[Object]; def getEngine: javax.script.ScriptEngine = engine }").asInstanceOf[CompiledScript]
+
+ @throws[ScriptException]
+ def compile(reader: java.io.Reader): CompiledScript = compile(stringFromReader(reader))
+
+ @throws[ScriptException]
+ def eval(script: String, context: ScriptContext): Object = compiled(script).eval(context)
@throws[ScriptException]
- def eval(reader: java.io.Reader, context: ScriptContext): Object = compile(reader).eval(context)
+ def eval(reader: java.io.Reader, context: ScriptContext): Object = eval(stringFromReader(reader), context)
override def finalize = close
diff --git a/test/disabled/run/t7843-jsr223-service.scala b/test/disabled/run/t7843-jsr223-service.scala
deleted file mode 100644
index e2ea850698..0000000000
--- a/test/disabled/run/t7843-jsr223-service.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-/*DISABLED:
- For Paul, it steals focus when it runs.
-
- For me, it fails with some platform specific extra output:
-
- -ScriptEngineManager providers.next(): javax.script.ScriptEngineFactory: Provider apple.applescript.AppleScriptEngin
- n: Object = 10
- 12345678910
-*/
-import javax.script._
-import scala.tools.nsc.interpreter.IMain
-
-object Test extends App {
- val engine = new ScriptEngineManager getEngineByName "scala"
- engine.asInstanceOf[IMain].settings.usejavacp.value = true
- engine put ("n", 10)
- engine eval "1 to n.asInstanceOf[Int] foreach print"
-}
diff --git a/test/files/neg/names-defaults-neg.check b/test/files/neg/names-defaults-neg.check
index 880ddc4327..20ddd55f1f 100644
--- a/test/files/neg/names-defaults-neg.check
+++ b/test/files/neg/names-defaults-neg.check
@@ -88,7 +88,7 @@ names-defaults-neg.scala:76: error: no type parameters for method test4: (x: T[T
--- because ---
argument expression's type is not compatible with formal parameter type;
found : List[Int]
- required: ?T
+ required: ?T[?T[List[?T[X forSome { type X }]]]]
Error occurred in an application involving default arguments.
test4()
^
diff --git a/test/files/neg/t8207.check b/test/files/neg/t8207.check
new file mode 100644
index 0000000000..59facd897a
--- /dev/null
+++ b/test/files/neg/t8207.check
@@ -0,0 +1,7 @@
+t8207.scala:1: error: '.' expected but '}' found.
+class C { import C.this.toString }
+ ^
+t8207.scala:3: error: '.' expected but '}' found.
+class D { import D.this.toString }
+ ^
+two errors found
diff --git a/test/files/neg/t8207.scala b/test/files/neg/t8207.scala
new file mode 100644
index 0000000000..738ce381f4
--- /dev/null
+++ b/test/files/neg/t8207.scala
@@ -0,0 +1,3 @@
+class C { import C.this.toString }
+
+class D { import D.this.toString }
diff --git a/test/files/neg/t8237-default.check b/test/files/neg/t8237-default.check
new file mode 100644
index 0000000000..59fe21ed03
--- /dev/null
+++ b/test/files/neg/t8237-default.check
@@ -0,0 +1,13 @@
+t8237-default.scala:5: error: no type parameters for method test4: (x: T[T[List[T[X forSome { type X }]]]])Nothing exist so that it can be applied to arguments (List[Int])
+ --- because ---
+argument expression's type is not compatible with formal parameter type;
+ found : List[Int]
+ required: ?T[?T[List[?T[X forSome { type X }]]]]
+ test4(test4$default$1)
+ ^
+t8237-default.scala:5: error: type mismatch;
+ found : List[Int]
+ required: T[T[List[T[X forSome { type X }]]]]
+ test4(test4$default$1)
+ ^
+two errors found
diff --git a/test/files/neg/t8237-default.scala b/test/files/neg/t8237-default.scala
new file mode 100644
index 0000000000..f695aa523f
--- /dev/null
+++ b/test/files/neg/t8237-default.scala
@@ -0,0 +1,29 @@
+// This test case was extracte from `names-defaults-neg.scala`
+// It pinpoints an improvement an error message that results from
+// a type inference failure
+object Test extends App {
+ test4(test4$default$1)
+
+ def test4[T[P]](x: T[T[List[T[X forSome { type X }]]]]) = ???
+ def test4$default$1[T[P]]: List[Int] = ???
+}
+
+/*
+OLD:
+ no type parameters for method test4: (x: T[T[List[T[X forSome { type X }]]]])Nothing exist so that it can be applied to arguments (List[Int])
+ --- because ---
+argument expression's type is not compatible with formal parameter type;
+ found : List[Int]
+ required: ?T
+ test4(test4$default$1)
+ ^
+
+NEW:
+
+no type parameters for method test4: (x: T[T[List[T[X forSome { type X }]]]])Nothing exist so that it can be applied to arguments (List[Int])
+ --- because ---
+argument expression's type is not compatible with formal parameter type;
+ found : List[Int]
+ required: ?T[?T[List[?T[X forSome { type X }]]]
+ test4(test4$default$1)
+*/
diff --git a/test/files/pos/annotated-original/M_1.scala b/test/files/pos/annotated-original/M_1.scala
index e312f9abbf..84a01bcce5 100644
--- a/test/files/pos/annotated-original/M_1.scala
+++ b/test/files/pos/annotated-original/M_1.scala
@@ -2,6 +2,6 @@ import language.experimental.macros
import scala.reflect.macros.blackbox.Context
object M {
- def impl(c: Context)(a: c.Expr[Any]) = c.Expr[Any](c.resetLocalAttrs(a.tree))
+ def impl(c: Context)(a: c.Expr[Any]) = c.Expr[Any](c.untypecheck(a.tree))
def m(a: Any) = macro impl
}
diff --git a/test/files/pos/annotated-treecopy/Impls_Macros_1.scala b/test/files/pos/annotated-treecopy/Impls_Macros_1.scala
index b02864b994..fdf9c72c31 100644
--- a/test/files/pos/annotated-treecopy/Impls_Macros_1.scala
+++ b/test/files/pos/annotated-treecopy/Impls_Macros_1.scala
@@ -44,7 +44,7 @@ object Macros {
val typeOut = c.Expr[String](q"${ttag.tpe.toString}").splice
def apply(_arg: T): U = c.Expr[U](b1)(ttag.asInstanceOf[c.WeakTypeTag[U]]).splice
})
- val untyped = c.resetLocalAttrs(template.tree)
+ val untyped = c.untypecheck(template.tree)
c.Expr[T => U](untyped)
case _ => sys.error("Bad function type")
diff --git a/test/files/pos/t6169/Exist.java b/test/files/pos/t6169/Exist.java
new file mode 100644
index 0000000000..dfc6b36b33
--- /dev/null
+++ b/test/files/pos/t6169/Exist.java
@@ -0,0 +1,4 @@
+public class Exist<T extends String> {
+ // java helpfully re-interprets Exist<?> as Exist<? extends String>
+ public Exist<?> foo() { throw new RuntimeException(); }
+} \ No newline at end of file
diff --git a/test/files/pos/t6169/ExistF.java b/test/files/pos/t6169/ExistF.java
new file mode 100644
index 0000000000..70fabd74cf
--- /dev/null
+++ b/test/files/pos/t6169/ExistF.java
@@ -0,0 +1,4 @@
+public class ExistF<T extends ExistF<T>> {
+ // java helpfully re-interprets ExistF<?> as ExistF<?0 extends ExistF<?0>>
+ public ExistF<?> foo() { throw new RuntimeException(); }
+} \ No newline at end of file
diff --git a/test/files/pos/t6169/ExistIndir.java b/test/files/pos/t6169/ExistIndir.java
new file mode 100644
index 0000000000..e66d1698c4
--- /dev/null
+++ b/test/files/pos/t6169/ExistIndir.java
@@ -0,0 +1,4 @@
+public class ExistIndir<T extends String, U extends T> {
+ // java helpfully re-interprets ExistIndir<?> as ExistIndir<? extends String>
+ public ExistIndir<?, ?> foo() { throw new RuntimeException(); }
+}
diff --git a/test/files/pos/t6169/OP.java b/test/files/pos/t6169/OP.java
new file mode 100644
index 0000000000..15e4c5640f
--- /dev/null
+++ b/test/files/pos/t6169/OP.java
@@ -0,0 +1 @@
+public abstract class OP<T> { }
diff --git a/test/files/pos/t6169/Skin.java b/test/files/pos/t6169/Skin.java
new file mode 100644
index 0000000000..780de1ee09
--- /dev/null
+++ b/test/files/pos/t6169/Skin.java
@@ -0,0 +1 @@
+public interface Skin<C extends Skinnable> { }
diff --git a/test/files/pos/t6169/Skinnable.java b/test/files/pos/t6169/Skinnable.java
new file mode 100644
index 0000000000..f91eaa30d8
--- /dev/null
+++ b/test/files/pos/t6169/Skinnable.java
@@ -0,0 +1,3 @@
+public interface Skinnable {
+ OP<Skin<?>> skinProperty();
+}
diff --git a/test/files/pos/t6169/skinnable.scala b/test/files/pos/t6169/skinnable.scala
new file mode 100644
index 0000000000..3ba2734526
--- /dev/null
+++ b/test/files/pos/t6169/skinnable.scala
@@ -0,0 +1,14 @@
+object ObjectProperty {
+ implicit def jfxObjectProperty2sfx[T](p: OP[T]) = new ObjectProperty[T](p)
+}
+
+class ObjectProperty[T](val delegate: OP[T])
+
+trait TestWildcardBoundInference {
+ def delegate: Skinnable
+ def skin: ObjectProperty[Skin[_ /* inferred: <: Skinnable */]] = ObjectProperty.jfxObjectProperty2sfx(delegate.skinProperty)
+ skin: ObjectProperty[Skin[_ <: Skinnable]]
+
+ def skinCheckInference = delegate.skinProperty
+ skinCheckInference: ObjectProperty[Skin[_ <: Skinnable]]
+} \ No newline at end of file
diff --git a/test/files/pos/t6169/t6169.scala b/test/files/pos/t6169/t6169.scala
new file mode 100644
index 0000000000..37f42619ca
--- /dev/null
+++ b/test/files/pos/t6169/t6169.scala
@@ -0,0 +1,7 @@
+class Test {
+ class MyExist extends ExistF[MyExist]
+ // SI-8197, SI-6169: java infers the bounds of existentials, so we have to as well now that SI-1786 is fixed...
+ def stringy: Exist[_ <: String] = (new Exist[String]).foo
+ def fbounded: (ExistF[t] forSome {type t <: ExistF[t] }) = (new MyExist).foo
+ def indir: ExistIndir[_ <: String, _ <: String] = (new ExistIndir[String, String]).foo
+} \ No newline at end of file
diff --git a/test/files/pos/t7377/Macro_1.scala b/test/files/pos/t7377/Macro_1.scala
index 9f51248095..b38687c8b3 100644
--- a/test/files/pos/t7377/Macro_1.scala
+++ b/test/files/pos/t7377/Macro_1.scala
@@ -2,6 +2,6 @@ import language.experimental._
import scala.reflect.macros.blackbox.Context
object M {
- def noopImpl[A](c: Context)(expr: c.Expr[A]): c.Expr[A] = c.Expr(c.typecheck(c.resetLocalAttrs(expr.tree)))
+ def noopImpl[A](c: Context)(expr: c.Expr[A]): c.Expr[A] = c.Expr(c.typecheck(c.untypecheck(expr.tree)))
def noop[A](expr: A): A = macro noopImpl[A]
}
diff --git a/test/files/pos/t7516/A_1.scala b/test/files/pos/t7516/A_1.scala
index 3bba19966d..3bd477dcda 100644
--- a/test/files/pos/t7516/A_1.scala
+++ b/test/files/pos/t7516/A_1.scala
@@ -3,7 +3,7 @@ import scala.reflect._,macros._, scala.language.experimental.macros
object A {
def impl[T: c.WeakTypeTag](c: Context)(t: c.Expr[T]): c.Expr[List[T]] = {
val r = c.universe.reify { List(t.splice) }
- c.Expr[List[T]]( c.resetLocalAttrs(r.tree) )
+ c.Expr[List[T]]( c.untypecheck(r.tree) )
}
def demo[T](t: T): List[T] = macro impl[T]
}
diff --git a/test/files/pos/t8064/Macro_1.scala b/test/files/pos/t8064/Macro_1.scala
index dd42950b34..9f1e6955b4 100644
--- a/test/files/pos/t8064/Macro_1.scala
+++ b/test/files/pos/t8064/Macro_1.scala
@@ -5,6 +5,6 @@ object Macro {
def apply(a: Any): Any = macro impl
def impl(c: Context)(a: c.Tree): c.Tree = {
- c.resetLocalAttrs(a)
+ c.untypecheck(a)
}
}
diff --git a/test/files/pos/t8207.scala b/test/files/pos/t8207.scala
new file mode 100644
index 0000000000..680b40f379
--- /dev/null
+++ b/test/files/pos/t8207.scala
@@ -0,0 +1,6 @@
+class C { me =>
+ import me.{toString => ts}
+ locally(this: me.type)
+ trait T
+ type X = me.T
+}
diff --git a/test/files/pos/t8237.scala b/test/files/pos/t8237.scala
new file mode 100644
index 0000000000..005089079e
--- /dev/null
+++ b/test/files/pos/t8237.scala
@@ -0,0 +1,29 @@
+import scala.language.higherKinds
+
+object TestExplicit {
+ trait TC[A]
+ def fTt[A,E[X] <: List[X]](a: A)(implicit tt: TC[E[A]]) = a
+ implicit def tc[T]: TC[T] = ???
+
+ // Typechecking results in SOE in TypeVar.isGround
+ fTt(1)(tc)
+ // fun = TestExplicit.this.fTt[Int, E](1)
+ // args = TestExplicit.this.tc[E[Int]]
+ // argTpes.head.instantiateTypeParams = TC[?E#1[Int]]
+ // formals.head.instantiateTypeParams = TC[?E#2[Int]]
+ // (where ?E#1 and ?E#2 as distinct AppliedTypeVars that resulted
+ // from separate applications of type args to the same HKTypeVar, ?E)
+ //
+ // As we check if the argument conforms to the formal, we would have
+ // AppliedTypeVars sharing the same TypeConstraints on the LHS and RHS,
+ // which leads to a cyclic constraint.
+}
+
+object TestImplicit {
+ trait TC[A]
+ def fTt[A,E[X] <: List[X]](a: A)(implicit tt: TC[E[A]]) = a
+ implicit def tc[T]: TC[T] = ???
+
+ // Oddly enough, this one works.
+ fTt(1)
+}
diff --git a/test/files/pos/t8237b.scala b/test/files/pos/t8237b.scala
new file mode 100644
index 0000000000..52bb310e8b
--- /dev/null
+++ b/test/files/pos/t8237b.scala
@@ -0,0 +1,10 @@
+import scala.language.higherKinds
+import scala.reflect.runtime.universe._
+object Test {
+
+ def fTt[A,E[X]<:List[X]](a: A)(implicit tt: TypeTag[E[A]]) = a
+
+ trait TC[A]
+ implicit def TCListInt[A]: TC[A] = ???
+ fTt(1)
+}
diff --git a/test/files/run/macro-reify-splice-outside-reify/Impls_Macros_1.scala b/test/files/run/macro-reify-splice-outside-reify/Impls_Macros_1.scala
index 624479480d..f038d8714f 100644
--- a/test/files/run/macro-reify-splice-outside-reify/Impls_Macros_1.scala
+++ b/test/files/run/macro-reify-splice-outside-reify/Impls_Macros_1.scala
@@ -3,7 +3,7 @@ import scala.reflect.macros.blackbox.Context
object Impls {
def foo(c: Context)(x: c.Expr[Int]) = {
import c.universe._
- val x1 = c.Expr[Int](c.resetAllAttrs(x.tree))
+ val x1 = c.Expr[Int](c.untypecheck(x.tree))
c.Expr[Int](Literal(Constant(c.eval(x1))))
}
}
diff --git a/test/files/run/reflection-magicsymbols-invoke.check b/test/files/run/reflection-magicsymbols-invoke.check
index 352aefaf25..43116858de 100644
--- a/test/files/run/reflection-magicsymbols-invoke.check
+++ b/test/files/run/reflection-magicsymbols-invoke.check
@@ -28,7 +28,7 @@ it's important to print the list of AnyVal's members
if some of them change (possibly, adding and/or removing magic symbols), we must update this test
constructor AnyVal: ()AnyVal
method getClass: ()Class[_ <: AnyVal]
-testing AnyVal.<init>: class java.lang.InstantiationException: null
+testing AnyVal.<init>: class scala.ScalaReflectionException: unsupported symbol constructor AnyVal when invoking bytecodeless method mirror for scala.AnyVal.<init>(): AnyVal (bound to null)
testing AnyVal.getClass: class scala.ScalaReflectionException: expected a member of class Integer, you provided method scala.AnyVal.getClass
============
AnyRef
diff --git a/test/files/run/t6411a.check b/test/files/run/t6411a.check
new file mode 100644
index 0000000000..9226146195
--- /dev/null
+++ b/test/files/run/t6411a.check
@@ -0,0 +1,96 @@
+meth = method yg_1
+as seen by Scala reflection: def yg_1[T](y: Y[T]): T
+as seen by Java reflection: public java.lang.Object a$.yg_1(java.lang.Object)
+result = 1
+meth = method yg_1
+as seen by Scala reflection: def yg_1[T](y: Y[T]): T
+as seen by Java reflection: public java.lang.Object a$.yg_1(java.lang.Object)
+result = 1
+meth = method yi_2
+as seen by Scala reflection: def yi_2(y: Y[Int]): Int
+as seen by Java reflection: public int a$.yi_2(java.lang.Integer)
+result = 2
+meth = method yi_2
+as seen by Scala reflection: def yi_2(y: Y[Int]): Int
+as seen by Java reflection: public int a$.yi_2(java.lang.Integer)
+result = class java.lang.IllegalArgumentException: argument type mismatch
+meth = method ys_3
+as seen by Scala reflection: def ys_3(y: Y[String]): String
+as seen by Java reflection: public java.lang.String a$.ys_3(java.lang.String)
+result = class java.lang.IllegalArgumentException: argument type mismatch
+meth = method ys_3
+as seen by Scala reflection: def ys_3(y: Y[String]): String
+as seen by Java reflection: public java.lang.String a$.ys_3(java.lang.String)
+result = 3
+meth = method ya_4
+as seen by Scala reflection: def ya_4(ys: Array[Y[String]]): List[String]
+as seen by Java reflection: public scala.collection.immutable.List a$.ya_4(Y[])
+result = class java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
+meth = method ya_4
+as seen by Scala reflection: def ya_4(ys: Array[Y[String]]): List[String]
+as seen by Java reflection: public scala.collection.immutable.List a$.ya_4(Y[])
+result = List(4)
+meth = method yl_5
+as seen by Scala reflection: def yl_5(ys: List[Y[String]]): List[String]
+as seen by Java reflection: public scala.collection.immutable.List a$.yl_5(scala.collection.immutable.List)
+result = class java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
+meth = method yl_5
+as seen by Scala reflection: def yl_5(ys: List[Y[String]]): List[String]
+as seen by Java reflection: public scala.collection.immutable.List a$.yl_5(scala.collection.immutable.List)
+result = List(5)
+meth = method yni_7
+as seen by Scala reflection: def yni_7(y: => Y[Int]): Int
+as seen by Java reflection: public int a$.yni_7(scala.Function0)
+result = 7
+meth = method yns_8
+as seen by Scala reflection: def yns_8(y: => Y[String]): String
+as seen by Java reflection: public java.lang.String a$.yns_8(scala.Function0)
+result = 8
+meth = method zg_1
+as seen by Scala reflection: def zg_1[T](z: Z[T]): T
+as seen by Java reflection: public java.lang.Object a$.zg_1(Z)
+result = 1
+meth = method zg_1
+as seen by Scala reflection: def zg_1[T](z: Z[T]): T
+as seen by Java reflection: public java.lang.Object a$.zg_1(Z)
+result = 1
+meth = method zi_2
+as seen by Scala reflection: def zi_2(z: Z[Int]): Int
+as seen by Java reflection: public int a$.zi_2(Z)
+result = 2
+meth = method zi_2
+as seen by Scala reflection: def zi_2(z: Z[Int]): Int
+as seen by Java reflection: public int a$.zi_2(Z)
+result = class java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
+meth = method zs_3
+as seen by Scala reflection: def zs_3(z: Z[String]): String
+as seen by Java reflection: public java.lang.String a$.zs_3(Z)
+result = class java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
+meth = method zs_3
+as seen by Scala reflection: def zs_3(z: Z[String]): String
+as seen by Java reflection: public java.lang.String a$.zs_3(Z)
+result = 3
+meth = method za_4
+as seen by Scala reflection: def za_4(zs: Array[Z[String]]): List[String]
+as seen by Java reflection: public scala.collection.immutable.List a$.za_4(Z[])
+result = class java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
+meth = method za_4
+as seen by Scala reflection: def za_4(zs: Array[Z[String]]): List[String]
+as seen by Java reflection: public scala.collection.immutable.List a$.za_4(Z[])
+result = List(4)
+meth = method zl_5
+as seen by Scala reflection: def zl_5(zs: List[Z[String]]): List[String]
+as seen by Java reflection: public scala.collection.immutable.List a$.zl_5(scala.collection.immutable.List)
+result = class java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
+meth = method zl_5
+as seen by Scala reflection: def zl_5(zs: List[Z[String]]): List[String]
+as seen by Java reflection: public scala.collection.immutable.List a$.zl_5(scala.collection.immutable.List)
+result = List(5)
+meth = method zni_7
+as seen by Scala reflection: def zni_7(z: => Z[Int]): Int
+as seen by Java reflection: public int a$.zni_7(scala.Function0)
+result = 7
+meth = method zns_8
+as seen by Scala reflection: def zns_8(z: => Z[String]): String
+as seen by Java reflection: public java.lang.String a$.zns_8(scala.Function0)
+result = 8
diff --git a/test/files/run/t6411a.scala b/test/files/run/t6411a.scala
new file mode 100644
index 0000000000..3bfeac2890
--- /dev/null
+++ b/test/files/run/t6411a.scala
@@ -0,0 +1,81 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.language.reflectiveCalls
+
+class Y[T](val i: T) extends AnyVal {
+ override def toString = s"Y($i)"
+}
+class Z[T](val i: T) extends AnyRef {
+ override def toString = s"Z($i)"
+}
+
+object a {
+ def yg_1[T](y: Y[T]) = y.i
+ def yi_2(y: Y[Int]) = y.i
+ def ys_3(y: Y[String]) = y.i
+ def ya_4(ys: Array[Y[String]]) = ys.toList.map(_.i)
+ def yl_5(ys: List[Y[String]]) = ys.map(_.i)
+ def yv_6(ys: Y[String]*) = ys.toList.map(_.i)
+ def yni_7(y: => Y[Int]) = y.i
+ def yns_8(y: => Y[String]) = y.i
+
+ def zg_1[T](z: Z[T]) = z.i
+ def zi_2(z: Z[Int]) = z.i
+ def zs_3(z: Z[String]) = z.i
+ def za_4(zs: Array[Z[String]]) = zs.toList.map(_.i)
+ def zl_5(zs: List[Z[String]]) = zs.map(_.i)
+ def zv_6(zs: Z[String]*) = zs.toList.map(_.i)
+ def zni_7(z: => Z[Int]) = z.i
+ def zns_8(z: => Z[String]) = z.i
+}
+
+object Test extends App {
+ def test(methName: String, arg: Any) = {
+ val moduleA = cm.reflect(a)
+ val msym = moduleA.symbol.typeSignature.declaration(TermName(methName)).asMethod
+ println(s"meth = $msym")
+ val mmirror = moduleA.reflectMethod(msym)
+ val mresult =
+ try { mmirror(arg) }
+ catch {
+ case ex: Exception =>
+ val ex1 = scala.reflect.runtime.ReflectionUtils.unwrapThrowable(ex)
+ s"${ex1.getClass}: ${ex1.getMessage}"
+ }
+ println(s"as seen by Scala reflection: ${msym.asInstanceOf[scala.reflect.internal.Symbols#Symbol].defString}")
+ println(s"as seen by Java reflection: ${mmirror.asInstanceOf[{val jmeth: java.lang.reflect.Method}].jmeth}")
+ println(s"result = $mresult")
+ }
+
+ test("yg_1", new Y(1))
+ test("yg_1", new Y("1"))
+ test("yi_2", new Y(2))
+ test("yi_2", new Y("2"))
+ test("ys_3", new Y(3))
+ test("ys_3", new Y("3"))
+ test("ya_4", Array(new Y(4)))
+ test("ya_4", Array(new Y("4")))
+ test("yl_5", List(new Y(5)))
+ test("yl_5", List(new Y("5")))
+ // FIXME: disabled because of SI-7056
+ // test("yv_6", new Y(6))
+ // test("yv_6", new Y("6"))
+ test("yni_7", new Y(7))
+ test("yns_8", new Y("8"))
+
+ test("zg_1", new Z(1))
+ test("zg_1", new Z("1"))
+ test("zi_2", new Z(2))
+ test("zi_2", new Z("2"))
+ test("zs_3", new Z(3))
+ test("zs_3", new Z("3"))
+ test("za_4", Array(new Z(4)))
+ test("za_4", Array(new Z("4")))
+ test("zl_5", List(new Z(5)))
+ test("zl_5", List(new Z("5")))
+ // FIXME: disabled because of SI-7056
+ // test("zv_6", new Z(6))
+ // test("zv_6", new Z("6"))
+ test("zni_7", new Z(7))
+ test("zns_8", new Z("8"))
+} \ No newline at end of file
diff --git a/test/files/run/t6411b.check b/test/files/run/t6411b.check
new file mode 100644
index 0000000000..e20bed6d8d
--- /dev/null
+++ b/test/files/run/t6411b.check
@@ -0,0 +1 @@
+Bar(Foo(3))
diff --git a/test/files/run/t6411b.scala b/test/files/run/t6411b.scala
new file mode 100644
index 0000000000..af30108826
--- /dev/null
+++ b/test/files/run/t6411b.scala
@@ -0,0 +1,12 @@
+import scala.reflect.runtime.universe._
+
+case class Foo(n: Int) extends AnyVal
+case class Bar(foo: Foo)
+
+object Test extends App {
+ val mirror = runtimeMirror(getClass.getClassLoader)
+ val cm = mirror.reflectClass(typeOf[Bar].typeSymbol.asClass)
+ val ctor = typeOf[Bar].declaration(nme.CONSTRUCTOR).asMethod
+ val ctorm = cm.reflectConstructor(ctor)
+ println(ctorm(Foo(3)))
+} \ No newline at end of file
diff --git a/test/files/run/t7240/Macros_1.scala b/test/files/run/t7240/Macros_1.scala
index 019ddf7cd6..c6e976038d 100644
--- a/test/files/run/t7240/Macros_1.scala
+++ b/test/files/run/t7240/Macros_1.scala
@@ -41,7 +41,7 @@ object Bakery {
def constructor = Apply(Select(New(Ident(newTypeName("eval"))), nme.CONSTRUCTOR), List())
c.eval(c.Expr[Any](
- c.resetAllAttrs(Block(composeDSL(Literal(Constant(1))), constructor))))
+ c.untypecheck(Block(composeDSL(Literal(Constant(1))), constructor))))
c.Expr[Any](Literal(Constant(1)))
}
diff --git a/test/files/run/t7319.check b/test/files/run/t7319.check
index d03ee3a6cf..b7443aa0c4 100644
--- a/test/files/run/t7319.check
+++ b/test/files/run/t7319.check
@@ -21,7 +21,7 @@ scala> convert(Some[Int](0))
--- because ---
argument expression's type is not compatible with formal parameter type;
found : Some[Int]
- required: ?F forSome { type _$1 <: ?F forSome { type _$2 } }
+ required: ?F[_$1] forSome { type _$1 <: ?F[_$2] forSome { type _$2 } }
convert(Some[Int](0))
^
<console>:12: error: type mismatch;
diff --git a/test/files/run/t7328.check b/test/files/run/t7328.check
new file mode 100644
index 0000000000..e386fe70d9
--- /dev/null
+++ b/test/files/run/t7328.check
@@ -0,0 +1,4 @@
+Foo
+Foo(3)
+Foo(3)
+Foo(5)
diff --git a/test/files/run/t7328.scala b/test/files/run/t7328.scala
new file mode 100644
index 0000000000..8816fa2347
--- /dev/null
+++ b/test/files/run/t7328.scala
@@ -0,0 +1,18 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+
+case class Foo(x: Int) extends AnyVal
+case class Bar(foo: Foo)
+
+object Test extends App {
+ val foo = typeOf[Bar].declaration(TermName("foo")).asMethod
+ println(foo.returnType) // Foo
+
+ val bar = Bar(Foo(3))
+ println(bar.foo) // Foo(3)
+
+ val im = cm.reflect(bar)
+ println(im.reflectField(foo).get) // incorrectly gives java.lang.Integer(3) not Foo(3)
+ im.reflectField(foo).set(Foo(5)) // java.lang.IllegalArgumentException: Can not set int field Bar.foo to Foo
+ println(im.reflectMethod(foo)()) // incorrectly gives java.lang.Integer(3) not Foo(3)
+} \ No newline at end of file
diff --git a/test/files/run/t7570a.check b/test/files/run/t7570a.check
new file mode 100644
index 0000000000..3cc58df837
--- /dev/null
+++ b/test/files/run/t7570a.check
@@ -0,0 +1 @@
+C
diff --git a/test/files/run/t7570a.scala b/test/files/run/t7570a.scala
new file mode 100644
index 0000000000..b8b4ddeaf2
--- /dev/null
+++ b/test/files/run/t7570a.scala
@@ -0,0 +1,11 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.tools.reflect.ToolBox
+import definitions._
+import Flag._
+
+object Test extends App {
+ val tb = cm.mkToolBox()
+ val csym = tb.define(q"""class C { override def toString = "C" }""")
+ println(tb.eval(q"new $csym"))
+} \ No newline at end of file
diff --git a/test/files/run/t7570b.check b/test/files/run/t7570b.check
new file mode 100644
index 0000000000..0c28247025
--- /dev/null
+++ b/test/files/run/t7570b.check
@@ -0,0 +1 @@
+compilation failed: reflective toolbox has failed: cannot have free terms in a top-level definition
diff --git a/test/files/run/t7570b.scala b/test/files/run/t7570b.scala
new file mode 100644
index 0000000000..f1db193186
--- /dev/null
+++ b/test/files/run/t7570b.scala
@@ -0,0 +1,17 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.tools.reflect.{ToolBox, ToolBoxError}
+import definitions._
+import Flag._
+
+object Test extends App {
+ val tb = cm.mkToolBox()
+ val msg = build.newFreeTerm("msg", "C")
+ build.setTypeSignature(msg, typeOf[String])
+ try {
+ val csym = tb.define(q"""class C { override def toString = $msg }""")
+ println(tb.eval(q"new $csym"))
+ } catch {
+ case ToolBoxError(message, _) => println(s"compilation failed: $message")
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t7570c.check b/test/files/run/t7570c.check
new file mode 100644
index 0000000000..61e659d9e0
--- /dev/null
+++ b/test/files/run/t7570c.check
@@ -0,0 +1,2 @@
+(class C,true,false,false)
+(object D,false,true,false)
diff --git a/test/files/run/t7570c.scala b/test/files/run/t7570c.scala
new file mode 100644
index 0000000000..a5bdbffe18
--- /dev/null
+++ b/test/files/run/t7570c.scala
@@ -0,0 +1,13 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.tools.reflect.{ToolBox, ToolBoxError}
+import definitions._
+import Flag._
+
+object Test extends App {
+ val tb = cm.mkToolBox()
+ val csym = tb.define(q"""class C { override def toString = "C" }""")
+ println((csym, csym.isClass, csym.isModule, csym.isModuleClass))
+ val dsym = tb.define(q"""object D { override def toString = "D" }""".asInstanceOf[ModuleDef])
+ println((dsym, dsym.isClass, dsym.isModule, dsym.isModuleClass))
+} \ No newline at end of file
diff --git a/test/disabled/run/t7843-jsr223-service.check b/test/files/run/t7843-jsr223-service.check
index a668df3567..a668df3567 100644
--- a/test/disabled/run/t7843-jsr223-service.check
+++ b/test/files/run/t7843-jsr223-service.check
diff --git a/test/files/run/t7843-jsr223-service.scala b/test/files/run/t7843-jsr223-service.scala
new file mode 100644
index 0000000000..31112212ea
--- /dev/null
+++ b/test/files/run/t7843-jsr223-service.scala
@@ -0,0 +1,8 @@
+import scala.tools.nsc.interpreter.IMain
+
+object Test extends App {
+ val engine = new IMain.Factory getScriptEngine()
+ engine.asInstanceOf[IMain].settings.usejavacp.value = true
+ engine put ("n", 10)
+ engine eval "1 to n.asInstanceOf[Int] foreach print"
+}
diff --git a/test/files/run/t7933.check b/test/files/run/t7933.check
new file mode 100644
index 0000000000..317e9677c3
--- /dev/null
+++ b/test/files/run/t7933.check
@@ -0,0 +1,2 @@
+hello
+hello
diff --git a/test/files/run/t7933.scala b/test/files/run/t7933.scala
new file mode 100644
index 0000000000..b06dffcd80
--- /dev/null
+++ b/test/files/run/t7933.scala
@@ -0,0 +1,11 @@
+import scala.tools.nsc.interpreter.IMain
+
+object Test extends App {
+ val engine = new IMain.Factory getScriptEngine()
+ engine.asInstanceOf[IMain].settings.usejavacp.value = true
+ val res2 = engine.asInstanceOf[javax.script.Compilable]
+ res2 compile "8" eval()
+ val res5 = res2 compile """println("hello") ; 8"""
+ res5 eval()
+ res5 eval()
+}
diff --git a/test/files/run/t8245.scala b/test/files/run/t8245.scala
new file mode 100644
index 0000000000..d44defbb9e
--- /dev/null
+++ b/test/files/run/t8245.scala
@@ -0,0 +1,14 @@
+object Test {
+ def foo(o: Option[Int]): Int = {
+ lazy val i: Int = {
+ def local: Int = {if ("".isEmpty) return 42; -42}
+ assert(local == 42)
+ o.getOrElse(return -1)
+ }
+ i + 1
+ }
+
+ def main(args: Array[String]) {
+ assert(foo(None) == -1)
+ }
+}
diff --git a/test/junit/scala/collection/SetMapConsistencyTest.scala b/test/junit/scala/collection/SetMapConsistencyTest.scala
index 7bb8ca958b..0d6f43db06 100644
--- a/test/junit/scala/collection/SetMapConsistencyTest.scala
+++ b/test/junit/scala/collection/SetMapConsistencyTest.scala
@@ -478,7 +478,7 @@ class SetMapConsistencyTest {
}
@Test
- def si8213() {
+ def testSI8213() {
val am = new scala.collection.mutable.AnyRefMap[String, Int]
for (i <- 0 until 1024) am += i.toString -> i
am.getOrElseUpdate("1024", { am.clear; -1 })
@@ -488,4 +488,23 @@ class SetMapConsistencyTest {
lm.getOrElseUpdate(1024, { lm.clear; -1 })
assert(lm == scala.collection.mutable.LongMap(1024L -> -1))
}
+
+ // Mutating when an iterator is in the wild shouldn't produce random junk in the iterator
+ // Todo: test all sets/maps this way
+ @Test
+ def testSI8154() {
+ def f() = {
+ val xs = scala.collection.mutable.AnyRefMap[String, Int]("a" -> 1)
+ val it = xs.iterator
+ it.hasNext
+ xs.clear()
+
+ if (it.hasNext) Some(it.next)
+ else None
+ }
+ assert(f() match {
+ case Some((a,b)) if (a==null || b==null) => false
+ case _ => true
+ })
+ }
}
diff --git a/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala b/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala
index a3699a4eeb..b42e9a07cb 100644
--- a/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala
+++ b/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala
@@ -69,6 +69,7 @@ class SymbolTableForUnitTesting extends SymbolTable {
// Members declared in scala.reflect.internal.Required
def picklerPhase: scala.reflect.internal.Phase = SomePhase
+ def erasurePhase: scala.reflect.internal.Phase = SomePhase
// Members declared in scala.reflect.internal.SymbolTable
def currentRunId: Int = 1
diff --git a/test/pending/run/idempotency-partial-functions.scala b/test/pending/run/idempotency-partial-functions.scala
index e673da5a29..b26c442599 100644
--- a/test/pending/run/idempotency-partial-functions.scala
+++ b/test/pending/run/idempotency-partial-functions.scala
@@ -22,7 +22,7 @@ object Test extends App {
val tb = cm.mkToolBox()
val tpartials = tb.typecheck(partials.tree)
println(tpartials)
- val rtpartials = tb.resetAllAttrs(tpartials)
+ val rtpartials = tb.untypecheck(tpartials)
println(tb.eval(rtpartials))
}
Test.main(null) \ No newline at end of file