summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala5
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala24
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala4
-rw-r--r--src/interactive/scala/tools/nsc/interactive/Global.scala15
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala6
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala20
-rw-r--r--test/files/neg/t7636.check2
-rw-r--r--test/files/pos/t3439.scala26
-rw-r--r--test/files/pos/t5454.scala10
-rw-r--r--test/files/pos/t8934a/A_1.scala18
-rw-r--r--test/files/pos/t8934a/Test_2.flags1
-rw-r--r--test/files/pos/t8934a/Test_2.scala12
-rw-r--r--test/files/presentation/quasiquotes.flags0
-rw-r--r--test/files/presentation/t8934.check2
-rw-r--r--test/files/presentation/t8934/Runner.scala27
-rw-r--r--test/files/presentation/t8934/src/Source.scala10
-rw-r--r--test/files/presentation/t8941.check7
-rw-r--r--test/files/presentation/t8941/Runner.scala11
-rw-r--r--test/files/presentation/t8941/src/Source.scala8
-rw-r--r--test/files/presentation/t8941b/IdempotencyTest.scala73
-rw-r--r--test/files/presentation/t8941b/Test.scala53
-rw-r--r--test/files/res/t6613.check5
-rw-r--r--test/files/res/t6613.res3
-rw-r--r--test/files/res/t6613/Broken.scala1
-rw-r--r--test/files/res/t6613/Enummy.java1
-rw-r--r--test/files/res/t8871.check5
-rw-r--r--test/files/res/t8871.res4
-rw-r--r--test/files/res/t8871/tag.scala3
-rw-r--r--test/files/res/t8871/usetag.scala6
-rw-r--r--test/pending/pos/t3439.scala2
33 files changed, 339 insertions, 49 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 452081cff1..76d8b7e5ef 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -1232,13 +1232,12 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
/** does this run compile given class, module, or case factory? */
// NOTE: Early initialized members temporarily typechecked before the enclosing class, see typedPrimaryConstrBody!
- // Here we work around that wrinkle by claiming that a top-level, early-initialized member is compiled in
+ // Here we work around that wrinkle by claiming that a early-initialized member is compiled in
// *every* run. This approximation works because this method is exclusively called with `this` == `currentRun`.
def compiles(sym: Symbol): Boolean =
if (sym == NoSymbol) false
else if (symSource.isDefinedAt(sym)) true
- else if (sym.isTopLevel && sym.isEarlyInitialized) true
- else if (!sym.isTopLevel) compiles(sym.enclosingTopLevelClass)
+ else if (!sym.isTopLevel) compiles(sym.enclosingTopLevelClassOrDummy)
else if (sym.isModuleClass) compiles(sym.sourceModule)
else false
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 908aa69310..9c81e31ad9 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -861,11 +861,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
debuglog("%s expands to %s in %s".format(sym, specMember.name.decode, pp(env)))
info(specMember) = NormalizedMember(sym)
newOverload(sym, specMember, env)
- // if this is a class, we insert the normalized member in scope,
- // if this is a method, there's no attached scope for it (EmptyScope)
- val decls = owner.info.decls
- if (decls != EmptyScope)
- decls.enter(specMember)
specMember
}
}
@@ -1504,20 +1499,13 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val residualTargs = symbol.info.typeParams zip baseTargs collect {
case (tvar, targ) if !env.contains(tvar) || !isPrimitiveValueClass(env(tvar).typeSymbol) => targ
}
- // See SI-5583. Don't know why it happens now if it didn't before.
- if (specMember.info.typeParams.isEmpty && residualTargs.nonEmpty) {
- devWarning("Type args to be applied, but symbol says no parameters: " + ((specMember.defString, residualTargs)))
- baseTree
- }
- else {
- ifDebug(assert(residualTargs.length == specMember.info.typeParams.length,
- "residual: %s, tparams: %s, env: %s".format(residualTargs, specMember.info.typeParams, env))
- )
+ ifDebug(assert(residualTargs.length == specMember.info.typeParams.length,
+ "residual: %s, tparams: %s, env: %s".format(residualTargs, specMember.info.typeParams, env))
+ )
- val tree1 = gen.mkTypeApply(specTree, residualTargs)
- debuglog("rewrote " + tree + " to " + tree1)
- localTyper.typedOperator(atPos(tree.pos)(tree1)) // being polymorphic, it must be a method
- }
+ val tree1 = gen.mkTypeApply(specTree, residualTargs)
+ debuglog("rewrote " + tree + " to " + tree1)
+ localTyper.typedOperator(atPos(tree.pos)(tree1)) // being polymorphic, it must be a method
}
curTree = tree
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala b/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala
index 79f5e3bee8..7fcfdf4868 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala
@@ -73,9 +73,7 @@ trait ScalacPatternExpanders {
* Unfortunately the MethodType does not carry the information of whether
* it was unapplySeq, so we have to funnel that information in separately.
*/
- def unapplyMethodTypes(method: Type, isSeq: Boolean): Extractor = {
- val whole = firstParamType(method)
- val result = method.finalResultType
+ def unapplyMethodTypes(whole: Type, result: Type, isSeq: Boolean): Extractor = {
val expanded = (
if (result =:= BooleanTpe) Nil
else typeOfMemberNamedGet(result) match {
@@ -126,9 +124,10 @@ trait ScalacPatternExpanders {
val patterns = newPatterns(args)
val isSeq = sel.symbol.name == nme.unapplySeq
val isUnapply = sel.symbol.name == nme.unapply
+
val extractor = sel.symbol.name match {
- case nme.unapply => unapplyMethodTypes(fn.tpe, isSeq = false)
- case nme.unapplySeq => unapplyMethodTypes(fn.tpe, isSeq = true)
+ case nme.unapply => unapplyMethodTypes(firstParamType(fn.tpe), sel.tpe, isSeq = false)
+ case nme.unapplySeq => unapplyMethodTypes(firstParamType(fn.tpe), sel.tpe, isSeq = true)
case _ => applyMethodTypes(fn.tpe)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
index ba183fe3e6..0aa62d771e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
@@ -212,7 +212,9 @@ trait MethodSynthesis {
List(cd, mdef)
case _ =>
// Shouldn't happen, but let's give ourselves a reasonable error when it does
- abort("No synthetics for " + meth + ": synthetics contains " + context.unit.synthetics.keys.mkString(", "))
+ context.error(cd.pos, s"Internal error: Symbol for synthetic factory method not found among ${context.unit.synthetics.keys.mkString(", ")}")
+ // Soldier on for the sake of the presentation compiler
+ List(cd)
}
case _ =>
stat :: Nil
@@ -355,8 +357,9 @@ trait MethodSynthesis {
def derivedSym: Symbol = {
// Only methods will do! Don't want to pick up any stray
// companion objects of the same name.
- val result = enclClass.info decl name suchThat (x => x.isMethod && x.isSynthetic)
- assert(result != NoSymbol, "not found: "+name+" in "+enclClass+" "+enclClass.info.decls)
+ val result = enclClass.info decl name filter (x => x.isMethod && x.isSynthetic)
+ if (result == NoSymbol || result.isOverloaded)
+ context.error(tree.pos, s"Internal error: Unable to find the synthetic factory method corresponding to implicit class $name in $enclClass / ${enclClass.info.decls}")
result
}
def derivedTree: DefDef =
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 95d4711c5f..a1de5e303b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -296,7 +296,7 @@ trait Namers extends MethodSynthesis {
}
tree.symbol match {
case NoSymbol => try dispatch() catch typeErrorHandler(tree, this.context)
- case sym => enterExistingSym(sym)
+ case sym => enterExistingSym(sym, tree)
}
}
@@ -737,7 +737,9 @@ trait Namers extends MethodSynthesis {
}
// Hooks which are overridden in the presentation compiler
- def enterExistingSym(sym: Symbol): Context = this.context
+ def enterExistingSym(sym: Symbol, tree: Tree): Context = {
+ this.context
+ }
def enterIfNotThere(sym: Symbol) { }
def enterSyntheticSym(tree: Tree): Symbol = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index aae2d24b32..70acb03584 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1516,7 +1516,9 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
val cbody1 = treeCopy.Block(cbody, preSuperStats, superCall1)
val clazz = context.owner
assert(clazz != NoSymbol, templ)
- val cscope = context.outer.makeNewScope(ctor, context.outer.owner)
+ val dummy = context.outer.owner.newLocalDummy(templ.pos)
+ val cscope = context.outer.makeNewScope(ctor, dummy)
+ if (dummy.isTopLevel) currentRun.symSource(dummy) = currentUnit.source.file
val cbody2 = { // called both during completion AND typing.
val typer1 = newTyper(cscope)
// XXX: see about using the class's symbol....
diff --git a/src/interactive/scala/tools/nsc/interactive/Global.scala b/src/interactive/scala/tools/nsc/interactive/Global.scala
index 174254d523..7df809b6ff 100644
--- a/src/interactive/scala/tools/nsc/interactive/Global.scala
+++ b/src/interactive/scala/tools/nsc/interactive/Global.scala
@@ -64,7 +64,9 @@ trait InteractiveAnalyzer extends Analyzer {
// that case the definitions that were already attributed as
// well as any default parameters of such methods need to be
// re-entered in the current scope.
- override def enterExistingSym(sym: Symbol): Context = {
+ //
+ // Tested in test/files/presentation/t8941b
+ override def enterExistingSym(sym: Symbol, tree: Tree): Context = {
if (sym != null && sym.owner.isTerm) {
enterIfNotThere(sym)
if (sym.isLazy)
@@ -72,8 +74,13 @@ trait InteractiveAnalyzer extends Analyzer {
for (defAtt <- sym.attachments.get[DefaultsOfLocalMethodAttachment])
defAtt.defaultGetters foreach enterIfNotThere
+ } else if (sym != null && sym.isClass && sym.isImplicit) {
+ val owningInfo = sym.owner.info
+ val existingDerivedSym = owningInfo.decl(sym.name.toTermName).filter(sym => sym.isSynthetic && sym.isMethod)
+ existingDerivedSym.alternatives foreach (owningInfo.decls.unlink)
+ enterImplicitWrapper(tree.asInstanceOf[ClassDef])
}
- super.enterExistingSym(sym)
+ super.enterExistingSym(sym, tree)
}
override def enterIfNotThere(sym: Symbol) {
val scope = context.scope
@@ -732,7 +739,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
}
}
- private def reloadSource(source: SourceFile) {
+ private[interactive] def reloadSource(source: SourceFile) {
val unit = new RichCompilationUnit(source)
unitOfFile(source.file) = unit
toBeRemoved -= source.file
@@ -781,7 +788,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
}
/** A fully attributed tree located at position `pos` */
- private def typedTreeAt(pos: Position): Tree = getUnit(pos.source) match {
+ private[interactive] def typedTreeAt(pos: Position): Tree = getUnit(pos.source) match {
case None =>
reloadSources(List(pos.source))
try typedTreeAt(pos)
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index 70375d974c..666a3a5e64 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -905,12 +905,14 @@ trait Definitions extends api.StandardDefinitions {
)
}
- def EnumType(sym: Symbol) =
+ def EnumType(sym: Symbol) = {
// given (in java): "class A { enum E { VAL1 } }"
// - sym: the symbol of the actual enumeration value (VAL1)
// - .owner: the ModuleClassSymbol of the enumeration (object E)
// - .linkedClassOfClass: the ClassSymbol of the enumeration (class E)
- sym.owner.linkedClassOfClass.tpe
+ // SI-6613 Subsequent runs of the resident compiler demand the phase discipline here.
+ enteringPhaseNotLaterThan(picklerPhase)(sym.owner.linkedClassOfClass).tpe
+ }
/** Given a class symbol C with type parameters T1, T2, ... Tn
* which have upper/lower bounds LB1/UB1, LB1/UB2, ..., LBn/UBn,
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 2c039ab5a7..51f06b1d6d 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -173,7 +173,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
with HasFlags
with Annotatable[Symbol]
with Attachable {
-
// makes sure that all symbols that runtime reflection deals with are synchronized
private def isSynchronized = this.isInstanceOf[scala.reflect.runtime.SynchronizedSymbols#SynchronizedSymbol]
private def isAprioriThreadsafe = isThreadsafe(AllOps)
@@ -1592,13 +1591,11 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
assert(isCompilerUniverse)
if (infos == null || runId(infos.validFrom) == currentRunId) {
infos
- } else if (isPackageClass) {
- // SI-7801 early phase package scopes are mutated in new runs (Namers#enterPackage), so we have to
- // discard transformed infos, rather than just marking them as from this run.
- val oldest = infos.oldest
- oldest.validFrom = validTo
- this.infos = oldest
- oldest
+ } else if (infos ne infos.oldest) {
+ // SI-8871 Discard all but the first element of type history. Specialization only works in the resident
+ // compiler / REPL if re-run its info transformer in this run to correctly populate its
+ // per-run caches, e.g. typeEnv
+ adaptInfos(infos.oldest)
} else {
val prev1 = adaptInfos(infos.prev)
if (prev1 ne infos.prev) prev1
@@ -2157,6 +2154,12 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
if (isClass) this else moduleClass
} else owner.enclosingTopLevelClass
+ /** The top-level class or local dummy symbol containing this symbol. */
+ def enclosingTopLevelClassOrDummy: Symbol =
+ if (isTopLevel) {
+ if (isClass) this else moduleClass.orElse(this)
+ } else owner.enclosingTopLevelClassOrDummy
+
/** Is this symbol defined in the same scope and compilation unit as `that` symbol? */
def isCoDefinedWith(that: Symbol) = (
!rawInfoIsNoType
@@ -3505,6 +3508,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
override def enclClassChain = Nil
override def enclClass: Symbol = this
override def enclosingTopLevelClass: Symbol = this
+ override def enclosingTopLevelClassOrDummy: Symbol = this
override def enclosingPackageClass: Symbol = this
override def enclMethod: Symbol = this
override def associatedFile = NoAbstractFile
diff --git a/test/files/neg/t7636.check b/test/files/neg/t7636.check
index f70d50bee3..12391cccc8 100644
--- a/test/files/neg/t7636.check
+++ b/test/files/neg/t7636.check
@@ -4,7 +4,7 @@ t7636.scala:3: error: illegal inheritance;
^
t7636.scala:3: error: type mismatch;
found : Either[_$2,_$3(in constructor C)] where type _$3(in constructor C), type _$2
- required: Either[_, _$3(in object Main)] where type _$3(in object Main)
+ required: Either[_, _$3(in value <local Main>)] where type _$3(in value <local Main>)
class C extends ResultTable(Left(5):Either[_,_])(5)
^
two errors found
diff --git a/test/files/pos/t3439.scala b/test/files/pos/t3439.scala
new file mode 100644
index 0000000000..ccc75cc4cf
--- /dev/null
+++ b/test/files/pos/t3439.scala
@@ -0,0 +1,26 @@
+class Base[M](i: Int)
+
+// was "implicit modifier not allowed on top level objects"
+class D1()(implicit i: Int) extends Base({println(i); 0})
+
+// what "no implicit value of type Int found"
+class D2()(implicit i: Int) extends Base(implicitly[Int])
+
+
+abstract class ParametricMessage[M: Manifest](msg: M) { def message = msg }
+case class ParametricMessage1[M: Manifest](msg: M, p1: Class[_]) extends ParametricMessage(msg)
+
+
+class Wrap {
+ class Base[M](i: Int)
+
+ // was "implicit modifier not allowed on top level objects"
+ class D1()(implicit i: Int) extends Base({println(i); 0})
+
+ // what "no implicit value of type Int found"
+ class D2()(implicit i: Int) extends Base(implicitly[Int])
+
+
+ abstract class ParametricMessage[M: Manifest](msg: M) { def message = msg }
+ case class ParametricMessage1[M: Manifest](msg: M, p1: Class[_]) extends ParametricMessage(msg)
+}
diff --git a/test/files/pos/t5454.scala b/test/files/pos/t5454.scala
new file mode 100644
index 0000000000..4045f3b57b
--- /dev/null
+++ b/test/files/pos/t5454.scala
@@ -0,0 +1,10 @@
+object IllegalInheritance {
+ trait A
+ implicit def a = new A {} // def => val
+ //val r = implicitly[A] // uncomment
+
+ class B[T](t : T)(implicit a : A) // remove implicit param block
+
+ class C extends B/*[Int]*/(23) // uncomment
+ val c = new C // comment
+}
diff --git a/test/files/pos/t8934a/A_1.scala b/test/files/pos/t8934a/A_1.scala
new file mode 100644
index 0000000000..6c1f29d030
--- /dev/null
+++ b/test/files/pos/t8934a/A_1.scala
@@ -0,0 +1,18 @@
+import language.experimental.macros
+import reflect.macros.whitebox.Context
+
+object Unapply {
+ def impl1(c: Context)(a: c.Tree): c.Tree = {
+ import c.universe._
+ q"(new { def unapply[T](a: String): Option[(Int, String)] = ??? }).unapply($a)"
+ }
+ def unapply(a: Any): Any = macro impl1
+}
+
+object UnapplySeq {
+ def impl1(c: Context)(a: c.Tree): c.Tree = {
+ import c.universe._
+ q"(new { def unapplySeq[T](a: String): Option[(Int, Seq[String])] = ??? }).unapplySeq($a)"
+ }
+ def unapplySeq(a: Any): Any = macro impl1
+}
diff --git a/test/files/pos/t8934a/Test_2.flags b/test/files/pos/t8934a/Test_2.flags
new file mode 100644
index 0000000000..618dfe2b75
--- /dev/null
+++ b/test/files/pos/t8934a/Test_2.flags
@@ -0,0 +1 @@
+-Ystop-after:typer -Ymacro-expand:discard -nowarn
diff --git a/test/files/pos/t8934a/Test_2.scala b/test/files/pos/t8934a/Test_2.scala
new file mode 100644
index 0000000000..e1792ed3c5
--- /dev/null
+++ b/test/files/pos/t8934a/Test_2.scala
@@ -0,0 +1,12 @@
+object Test {
+ "" match {
+ case Unapply(a, b) =>
+ a: Int
+ b: String
+ case UnapplySeq(a, b1, b2) =>
+ a: Int
+ b1: String
+ b2: String
+ }
+}
+// These used to fail `too many patterns` under -Ymacro-expand:discard
diff --git a/test/files/presentation/quasiquotes.flags b/test/files/presentation/quasiquotes.flags
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/presentation/quasiquotes.flags
diff --git a/test/files/presentation/t8934.check b/test/files/presentation/t8934.check
new file mode 100644
index 0000000000..0ece87f808
--- /dev/null
+++ b/test/files/presentation/t8934.check
@@ -0,0 +1,2 @@
+reload: Source.scala
+Test OK
diff --git a/test/files/presentation/t8934/Runner.scala b/test/files/presentation/t8934/Runner.scala
new file mode 100644
index 0000000000..944f458391
--- /dev/null
+++ b/test/files/presentation/t8934/Runner.scala
@@ -0,0 +1,27 @@
+import scala.tools.nsc.interactive.tests.InteractiveTest
+import scala.reflect.internal.util.SourceFile
+import scala.tools.nsc.interactive.Response
+
+object Test extends InteractiveTest {
+
+ override def execute(): Unit = {
+ val src = loadSourceAndWaitUntilTypechecked("Source.scala")
+ checkErrors(src)
+ }
+
+ private def loadSourceAndWaitUntilTypechecked(sourceName: String): SourceFile = {
+ val sourceFile = sourceFiles.find(_.file.name == sourceName).head
+ askReload(List(sourceFile)).get
+ askLoadedTyped(sourceFile).get
+ sourceFile
+ }
+
+ private def checkErrors(source: SourceFile): Unit = compiler.getUnitOf(source) match {
+ case Some(unit) =>
+ val problems = unit.problems.toList
+ if(problems.isEmpty) reporter.println("Test OK")
+ else problems.foreach(problem => reporter.println(problem.msg))
+
+ case None => reporter.println("No compilation unit found for " + source.file.name)
+ }
+}
diff --git a/test/files/presentation/t8934/src/Source.scala b/test/files/presentation/t8934/src/Source.scala
new file mode 100644
index 0000000000..769c8fd38b
--- /dev/null
+++ b/test/files/presentation/t8934/src/Source.scala
@@ -0,0 +1,10 @@
+class Quasi {
+ import reflect.runtime.universe._
+
+ def test: Unit = {
+ (null: Any) match {
+ case q"$foo($bar)" =>
+ }
+ ()
+ }
+}
diff --git a/test/files/presentation/t8941.check b/test/files/presentation/t8941.check
new file mode 100644
index 0000000000..341804903a
--- /dev/null
+++ b/test/files/presentation/t8941.check
@@ -0,0 +1,7 @@
+reload: Source.scala
+
+askType at Source.scala(6,7)
+================================================================================
+[response] askTypeAt (6,7)
+scala.this.Predef.???
+================================================================================
diff --git a/test/files/presentation/t8941/Runner.scala b/test/files/presentation/t8941/Runner.scala
new file mode 100644
index 0000000000..0a8923a583
--- /dev/null
+++ b/test/files/presentation/t8941/Runner.scala
@@ -0,0 +1,11 @@
+import scala.tools.nsc.interactive.tests.InteractiveTest
+
+object Test extends InteractiveTest {
+ override def runDefaultTests() {
+ // make sure typer is done.. the virtual pattern matcher might translate
+ // some trees and mess up positions. But we'll catch it red handed!
+ // sourceFiles foreach (src => askLoadedTyped(src).get)
+ super.runDefaultTests()
+ }
+
+}
diff --git a/test/files/presentation/t8941/src/Source.scala b/test/files/presentation/t8941/src/Source.scala
new file mode 100644
index 0000000000..7438cccb03
--- /dev/null
+++ b/test/files/presentation/t8941/src/Source.scala
@@ -0,0 +1,8 @@
+object Foo {
+ implicit class MatCreator(val ctx: StringContext) extends AnyVal {
+ def m(args: Any*): Unit = {
+ ctx.checkLengths(args)
+ }
+ ???/*?*/
+ }
+}
diff --git a/test/files/presentation/t8941b/IdempotencyTest.scala b/test/files/presentation/t8941b/IdempotencyTest.scala
new file mode 100644
index 0000000000..af01b36898
--- /dev/null
+++ b/test/files/presentation/t8941b/IdempotencyTest.scala
@@ -0,0 +1,73 @@
+package scala.tools.nsc
+package interactive
+package tests.core
+
+import reporters.{Reporter => CompilerReporter}
+import scala.tools.nsc.interactive.InteractiveReporter
+import scala.reflect.internal.util.SourceFile
+
+/** Determistically interrupts typechecking of `code` when a defintion named
+ * `MagicInterruptionMarker` is typechecked, and then performs a targetted
+ * typecheck of the tree at the specal comment marker marker
+ */
+abstract class IdempotencyTest { self =>
+ private val settings = new Settings
+ settings.usejavacp.value = true
+
+ private object Break extends scala.util.control.ControlThrowable
+
+ private val compilerReporter: CompilerReporter = new InteractiveReporter {
+ override def compiler = self.compiler
+ }
+
+ object compiler extends Global(settings, compilerReporter) {
+ override def checkForMoreWork(pos: Position) {
+ }
+ override def signalDone(context: Context, old: Tree, result: Tree) {
+ // println("signalDone: " + old.toString.take(50).replaceAll("\n", "\\n"))
+ if (!interrupted && analyzer.lockedCount == 0 && interruptsEnabled && shouldInterrupt(result)) {
+ interrupted = true
+ val typed = typedTreeAt(markerPosition)
+ checkTypedTree(typed)
+ throw Break
+ }
+ super.signalDone(context, old, result)
+ }
+
+ // we're driving manually using our own thread, disable the check here.
+ override def assertCorrectThread() {}
+ }
+
+ import compiler._
+
+ private var interrupted = false
+
+ // Extension points
+ protected def code: String
+ protected def shouldInterrupt(tree: Tree): Boolean = {
+ tree.symbol != null && tree.symbol.name.toString == "MagicInterruptionMarker"
+ }
+ protected def checkTypedTree(tree: Tree): Unit = {}
+
+
+ private val source: SourceFile = newSourceFile(code)
+ private def markerPosition: Position = source.position(code.indexOf("/*?*/"))
+
+ def assertNoProblems() {
+ val problems = getUnit(source).get.problems
+ assert(problems.isEmpty, problems.mkString("\n"))
+ }
+
+ def show() {
+ reloadSource(source)
+ try {
+ typedTree(source, true)
+ assert(false, "Expected to break out of typechecking.")
+ } catch {
+ case Break => // expected
+ }
+ assertNoProblems()
+ }
+
+ def main(args: Array[String]) { show() }
+}
diff --git a/test/files/presentation/t8941b/Test.scala b/test/files/presentation/t8941b/Test.scala
new file mode 100644
index 0000000000..7269a14286
--- /dev/null
+++ b/test/files/presentation/t8941b/Test.scala
@@ -0,0 +1,53 @@
+import scala.tools.nsc.interactive.tests.core.IdempotencyTest
+
+// At the time of writing this test, removing any part of `enterExistingSym`
+// leads to a failure.
+object Test {
+ def main(args: Array[String]) {
+ test("""
+ object Foo {
+ def term {
+ def foo(c: String = "") = c
+ class MagicInterruptionMarker
+ foo()/*?*/
+ }
+ }
+ """)
+
+ test("""
+ object Foo {
+ def term {
+ def foo = 42
+ class MagicInterruptionMarker
+ foo/*?*/
+ }
+ }
+ """)
+
+ test("""
+ object Foo {
+ def term {
+ lazy val foo = 42
+ class MagicInterruptionMarker
+ foo/*?*/
+ }
+ }
+ """)
+
+ test("""
+ object Foo {
+ implicit class C(val a: String) extends AnyVal
+ class MagicInterruptionMarker
+ ""/*?*/
+ }
+ """)
+ }
+
+ def test(code0: String) {
+ val t = new IdempotencyTest {
+ def code = code0
+ }
+ t.show()
+ }
+}
+
diff --git a/test/files/res/t6613.check b/test/files/res/t6613.check
new file mode 100644
index 0000000000..bbd9331b16
--- /dev/null
+++ b/test/files/res/t6613.check
@@ -0,0 +1,5 @@
+
+nsc>
+nsc>
+nsc>
+nsc>
diff --git a/test/files/res/t6613.res b/test/files/res/t6613.res
new file mode 100644
index 0000000000..e3fa000fdd
--- /dev/null
+++ b/test/files/res/t6613.res
@@ -0,0 +1,3 @@
+t6613/Enummy.java
+t6613/Broken.scala
+t6613/Broken.scala
diff --git a/test/files/res/t6613/Broken.scala b/test/files/res/t6613/Broken.scala
new file mode 100644
index 0000000000..9bcd12dbe1
--- /dev/null
+++ b/test/files/res/t6613/Broken.scala
@@ -0,0 +1 @@
+class Broken() { def broken() = Enummy.Broke.CHIP }
diff --git a/test/files/res/t6613/Enummy.java b/test/files/res/t6613/Enummy.java
new file mode 100644
index 0000000000..1863ef1297
--- /dev/null
+++ b/test/files/res/t6613/Enummy.java
@@ -0,0 +1 @@
+public class Enummy { public enum Broke { SHARD, CHIP } }
diff --git a/test/files/res/t8871.check b/test/files/res/t8871.check
new file mode 100644
index 0000000000..bbd9331b16
--- /dev/null
+++ b/test/files/res/t8871.check
@@ -0,0 +1,5 @@
+
+nsc>
+nsc>
+nsc>
+nsc>
diff --git a/test/files/res/t8871.res b/test/files/res/t8871.res
new file mode 100644
index 0000000000..9b1a5fb57f
--- /dev/null
+++ b/test/files/res/t8871.res
@@ -0,0 +1,4 @@
+t8871/tag.scala
+t8871/usetag.scala
+t8871/usetag.scala
+
diff --git a/test/files/res/t8871/tag.scala b/test/files/res/t8871/tag.scala
new file mode 100644
index 0000000000..1a1803b77d
--- /dev/null
+++ b/test/files/res/t8871/tag.scala
@@ -0,0 +1,3 @@
+class Tag {
+ @inline def apply[@specialized A, T](a: A): A = a
+}
diff --git a/test/files/res/t8871/usetag.scala b/test/files/res/t8871/usetag.scala
new file mode 100644
index 0000000000..139d768552
--- /dev/null
+++ b/test/files/res/t8871/usetag.scala
@@ -0,0 +1,6 @@
+trait Foo
+
+object Test {
+ val y = new Tag().apply[Double, Foo](3.3)
+ // under FSC, this gave t8871/usetag.scala:4: error: wrong number of type parameters for method apply$mDc$sp: [T](a: Double)Double
+}
diff --git a/test/pending/pos/t3439.scala b/test/pending/pos/t3439.scala
deleted file mode 100644
index 425f1aeeb5..0000000000
--- a/test/pending/pos/t3439.scala
+++ /dev/null
@@ -1,2 +0,0 @@
-abstract class ParametricMessage[M: Manifest](msg: M) { def message = msg }
-case class ParametricMessage1[M: Manifest](msg: M, p1: Class[_]) extends ParametricMessage(msg)