From 54d11fe5451a9f26207ce283f2df1114c89384dd Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 29 Mar 2013 19:05:13 +0100 Subject: SI-7312 @deprecatedInheritance now ignores same-file subclasses This allows us to deprecate external inheritances as a prelude to sealing a class, without enduring the warnings ourselved in interlude. --- src/compiler/scala/tools/nsc/typechecker/Typers.scala | 6 ++++-- src/library/scala/deprecatedInheritance.scala | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 5e31395215..6719411700 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1738,14 +1738,16 @@ trait Typers extends Adaptations with Tags { if (psym.isFinal) pending += ParentFinalInheritanceError(parent, psym) - if (psym.hasDeprecatedInheritanceAnnotation) { + val sameSourceFile = context.unit.source.file == psym.sourceFile + + if (psym.hasDeprecatedInheritanceAnnotation && !sameSourceFile) { val suffix = psym.deprecatedInheritanceMessage map (": " + _) getOrElse "" val msg = s"inheritance from ${psym.fullLocationString} is deprecated$suffix" unit.deprecationWarning(parent.pos, msg) } if (psym.isSealed && !phase.erasedTypes) - if (context.unit.source.file == psym.sourceFile) + if (sameSourceFile) psym addChild context.owner else pending += ParentSealedInheritanceError(parent, psym) diff --git a/src/library/scala/deprecatedInheritance.scala b/src/library/scala/deprecatedInheritance.scala index 70065560b1..7d20219d4d 100644 --- a/src/library/scala/deprecatedInheritance.scala +++ b/src/library/scala/deprecatedInheritance.scala @@ -11,7 +11,8 @@ package scala /** An annotation that designates that inheriting from a class is deprecated. * * This is usually done to warn about a non-final class being made final in a future version. - * Sub-classing such a class then generates a warning. + * Sub-classing such a class then generates a warning. No warnings are generated if the + * subclass is in the same compilation unit. * * @param message the message to print during compilation if the class was sub-classed * @param since a string identifying the first version in which inheritance was deprecated -- cgit v1.2.3 From 34a6fa9bb44ffd96dbb0ee59905fecf4e29879ba Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Wed, 3 Apr 2013 17:46:16 +0300 Subject: SI-6937 core type tags are no longer referentially unique Type tag factory used to evaluate the provided type creator in the context of the initial mirror in order to maintain referential equality of instances of standard tags. Unfortunately this evaluation might fail if the mirror provided doesn't contain the classes being referred to. Therefore I think we should avoid evaluating type creators there. Note that failure of evaluation doesn't mean that there's something bad going on. When one creates a type tag, the correct mirror / classloader to interpret that tag in might be unknown (like it happens here). This is okay, and this is exactly what the 2.10.0-M4 refactoring has addressed. Something like `res2.typeTag[A].in(currentMirror)` should be okay. --- src/reflect/scala/reflect/api/TypeTags.scala | 38 ++-------------------- test/files/run/macro-expand-nullary-generic.check | 10 +++--- test/files/run/macro-expand-tparams-explicit.check | 2 +- test/files/run/macro-expand-tparams-implicit.check | 2 +- test/files/run/macro-expand-tparams-prefix-a.check | 6 ++-- test/files/run/macro-expand-tparams-prefix-b.check | 4 +-- .../files/run/macro-expand-tparams-prefix-c1.check | 4 +-- .../files/run/macro-expand-tparams-prefix-c2.check | 4 +-- .../files/run/macro-expand-tparams-prefix-d1.check | 2 +- test/files/run/macro-undetparams-consfromsls.check | 6 ++-- test/files/run/macro-undetparams-macroitself.check | 2 +- test/files/run/t6937.check | 26 +++++++++++++++ test/files/run/t6937.scala | 12 +++++++ 13 files changed, 61 insertions(+), 57 deletions(-) create mode 100644 test/files/run/t6937.check create mode 100644 test/files/run/t6937.scala (limited to 'src') diff --git a/src/reflect/scala/reflect/api/TypeTags.scala b/src/reflect/scala/reflect/api/TypeTags.scala index e988971ace..7457910226 100644 --- a/src/reflect/scala/reflect/api/TypeTags.scala +++ b/src/reflect/scala/reflect/api/TypeTags.scala @@ -221,24 +221,7 @@ trait TypeTags { self: Universe => def apply[T](mirror1: scala.reflect.api.Mirror[self.type], tpec1: TypeCreator): WeakTypeTag[T] = - tpec1(mirror1) match { - case ByteTpe => WeakTypeTag.Byte.asInstanceOf[WeakTypeTag[T]] - case ShortTpe => WeakTypeTag.Short.asInstanceOf[WeakTypeTag[T]] - case CharTpe => WeakTypeTag.Char.asInstanceOf[WeakTypeTag[T]] - case IntTpe => WeakTypeTag.Int.asInstanceOf[WeakTypeTag[T]] - case LongTpe => WeakTypeTag.Long.asInstanceOf[WeakTypeTag[T]] - case FloatTpe => WeakTypeTag.Float.asInstanceOf[WeakTypeTag[T]] - case DoubleTpe => WeakTypeTag.Double.asInstanceOf[WeakTypeTag[T]] - case BooleanTpe => WeakTypeTag.Boolean.asInstanceOf[WeakTypeTag[T]] - case UnitTpe => WeakTypeTag.Unit.asInstanceOf[WeakTypeTag[T]] - case AnyTpe => WeakTypeTag.Any.asInstanceOf[WeakTypeTag[T]] - case AnyValTpe => WeakTypeTag.AnyVal.asInstanceOf[WeakTypeTag[T]] - case AnyRefTpe => WeakTypeTag.AnyRef.asInstanceOf[WeakTypeTag[T]] - case ObjectTpe => WeakTypeTag.Object.asInstanceOf[WeakTypeTag[T]] - case NothingTpe => WeakTypeTag.Nothing.asInstanceOf[WeakTypeTag[T]] - case NullTpe => WeakTypeTag.Null.asInstanceOf[WeakTypeTag[T]] - case _ => new WeakTypeTagImpl[T](mirror1.asInstanceOf[Mirror], tpec1) - } + new WeakTypeTagImpl[T](mirror1.asInstanceOf[Mirror], tpec1) def unapply[T](ttag: WeakTypeTag[T]): Option[Type] = Some(ttag.tpe) } @@ -299,24 +282,7 @@ trait TypeTags { self: Universe => val Null: TypeTag[scala.Null] = new PredefTypeTag[scala.Null] (NullTpe, _.TypeTag.Null) def apply[T](mirror1: scala.reflect.api.Mirror[self.type], tpec1: TypeCreator): TypeTag[T] = - tpec1(mirror1) match { - case ByteTpe => TypeTag.Byte.asInstanceOf[TypeTag[T]] - case ShortTpe => TypeTag.Short.asInstanceOf[TypeTag[T]] - case CharTpe => TypeTag.Char.asInstanceOf[TypeTag[T]] - case IntTpe => TypeTag.Int.asInstanceOf[TypeTag[T]] - case LongTpe => TypeTag.Long.asInstanceOf[TypeTag[T]] - case FloatTpe => TypeTag.Float.asInstanceOf[TypeTag[T]] - case DoubleTpe => TypeTag.Double.asInstanceOf[TypeTag[T]] - case BooleanTpe => TypeTag.Boolean.asInstanceOf[TypeTag[T]] - case UnitTpe => TypeTag.Unit.asInstanceOf[TypeTag[T]] - case AnyTpe => TypeTag.Any.asInstanceOf[TypeTag[T]] - case AnyValTpe => TypeTag.AnyVal.asInstanceOf[TypeTag[T]] - case AnyRefTpe => TypeTag.AnyRef.asInstanceOf[TypeTag[T]] - case ObjectTpe => TypeTag.Object.asInstanceOf[TypeTag[T]] - case NothingTpe => TypeTag.Nothing.asInstanceOf[TypeTag[T]] - case NullTpe => TypeTag.Null.asInstanceOf[TypeTag[T]] - case _ => new TypeTagImpl[T](mirror1.asInstanceOf[Mirror], tpec1) - } + new TypeTagImpl[T](mirror1.asInstanceOf[Mirror], tpec1) def unapply[T](ttag: TypeTag[T]): Option[Type] = Some(ttag.tpe) } diff --git a/test/files/run/macro-expand-nullary-generic.check b/test/files/run/macro-expand-nullary-generic.check index 133840c469..42976f4baf 100644 --- a/test/files/run/macro-expand-nullary-generic.check +++ b/test/files/run/macro-expand-nullary-generic.check @@ -1,6 +1,6 @@ -it works TypeTag[Int] -it works TypeTag[Int] -it works TypeTag[Int] -it works TypeTag[Int] -it works TypeTag[Int] +it works WeakTypeTag[Int] +it works WeakTypeTag[Int] +it works WeakTypeTag[Int] +it works WeakTypeTag[Int] +it works WeakTypeTag[Int] kkthxbai diff --git a/test/files/run/macro-expand-tparams-explicit.check b/test/files/run/macro-expand-tparams-explicit.check index e7e6718406..b6b4f6fa3a 100644 --- a/test/files/run/macro-expand-tparams-explicit.check +++ b/test/files/run/macro-expand-tparams-explicit.check @@ -1 +1 @@ -TypeTag[Int] +WeakTypeTag[Int] diff --git a/test/files/run/macro-expand-tparams-implicit.check b/test/files/run/macro-expand-tparams-implicit.check index fa6b335afb..a9bf55423e 100644 --- a/test/files/run/macro-expand-tparams-implicit.check +++ b/test/files/run/macro-expand-tparams-implicit.check @@ -1,2 +1,2 @@ -TypeTag[Int] +WeakTypeTag[Int] WeakTypeTag[String] diff --git a/test/files/run/macro-expand-tparams-prefix-a.check b/test/files/run/macro-expand-tparams-prefix-a.check index 0bf3c55bbe..ca44a4f652 100644 --- a/test/files/run/macro-expand-tparams-prefix-a.check +++ b/test/files/run/macro-expand-tparams-prefix-a.check @@ -1,4 +1,4 @@ -TypeTag[Int] -TypeTag[Int] +WeakTypeTag[Int] +WeakTypeTag[Int] WeakTypeTag[String] -TypeTag[Boolean] +WeakTypeTag[Boolean] diff --git a/test/files/run/macro-expand-tparams-prefix-b.check b/test/files/run/macro-expand-tparams-prefix-b.check index 77c2ee9051..2ff2ce435d 100644 --- a/test/files/run/macro-expand-tparams-prefix-b.check +++ b/test/files/run/macro-expand-tparams-prefix-b.check @@ -1,2 +1,2 @@ -TypeTag[Boolean] TypeTag[Int] -TypeTag[Boolean] WeakTypeTag[String] +WeakTypeTag[Boolean] WeakTypeTag[Int] +WeakTypeTag[Boolean] WeakTypeTag[String] diff --git a/test/files/run/macro-expand-tparams-prefix-c1.check b/test/files/run/macro-expand-tparams-prefix-c1.check index f0dd5b9cd8..0f24f74db1 100644 --- a/test/files/run/macro-expand-tparams-prefix-c1.check +++ b/test/files/run/macro-expand-tparams-prefix-c1.check @@ -1,3 +1,3 @@ -TypeTag[Int] +WeakTypeTag[Int] WeakTypeTag[String] -TypeTag[Boolean] +WeakTypeTag[Boolean] diff --git a/test/files/run/macro-expand-tparams-prefix-c2.check b/test/files/run/macro-expand-tparams-prefix-c2.check index f0dd5b9cd8..0f24f74db1 100644 --- a/test/files/run/macro-expand-tparams-prefix-c2.check +++ b/test/files/run/macro-expand-tparams-prefix-c2.check @@ -1,3 +1,3 @@ -TypeTag[Int] +WeakTypeTag[Int] WeakTypeTag[String] -TypeTag[Boolean] +WeakTypeTag[Boolean] diff --git a/test/files/run/macro-expand-tparams-prefix-d1.check b/test/files/run/macro-expand-tparams-prefix-d1.check index c5aaaf5a09..7832503256 100644 --- a/test/files/run/macro-expand-tparams-prefix-d1.check +++ b/test/files/run/macro-expand-tparams-prefix-d1.check @@ -1,3 +1,3 @@ WeakTypeTag[T] WeakTypeTag[U] -TypeTag[Boolean] +WeakTypeTag[Boolean] diff --git a/test/files/run/macro-undetparams-consfromsls.check b/test/files/run/macro-undetparams-consfromsls.check index b10a90043e..3fee58d9c1 100644 --- a/test/files/run/macro-undetparams-consfromsls.check +++ b/test/files/run/macro-undetparams-consfromsls.check @@ -1,5 +1,5 @@ -A = TypeTag[Int] -B = TypeTag[Nothing] +A = WeakTypeTag[Int] +B = WeakTypeTag[Nothing] List(1) -A = TypeTag[Any] +A = WeakTypeTag[Any] List(abc, 1) diff --git a/test/files/run/macro-undetparams-macroitself.check b/test/files/run/macro-undetparams-macroitself.check index fa6b335afb..a9bf55423e 100644 --- a/test/files/run/macro-undetparams-macroitself.check +++ b/test/files/run/macro-undetparams-macroitself.check @@ -1,2 +1,2 @@ -TypeTag[Int] +WeakTypeTag[Int] WeakTypeTag[String] diff --git a/test/files/run/t6937.check b/test/files/run/t6937.check new file mode 100644 index 0000000000..9a1fa4cfaf --- /dev/null +++ b/test/files/run/t6937.check @@ -0,0 +1,26 @@ +Type in expressions to have them evaluated. +Type :help for more information. + +scala> + +scala> import scala.reflect.runtime.{universe => ru} +import scala.reflect.runtime.{universe=>ru} + +scala> import scala.reflect.runtime.{currentMirror => cm} +import scala.reflect.runtime.{currentMirror=>cm} + +scala> import scala.reflect.api.{Universe => ApiUniverse} +import scala.reflect.api.{Universe=>ApiUniverse} + +scala> class A +defined class A + +scala> lazy val apiru = ru: ApiUniverse +apiru: scala.reflect.api.Universe = + +scala> apiru.typeTag[A].in(cm) +res0: reflect.runtime.universe.TypeTag[A] = TypeTag[A] + +scala> + +scala> diff --git a/test/files/run/t6937.scala b/test/files/run/t6937.scala new file mode 100644 index 0000000000..4b30894bf3 --- /dev/null +++ b/test/files/run/t6937.scala @@ -0,0 +1,12 @@ +import scala.tools.partest.ReplTest + +object Test extends ReplTest { + def code = """ + import scala.reflect.runtime.{universe => ru} + import scala.reflect.runtime.{currentMirror => cm} + import scala.reflect.api.{Universe => ApiUniverse} + class A + lazy val apiru = ru: ApiUniverse + apiru.typeTag[A].in(cm) + """ +} \ No newline at end of file -- cgit v1.2.3 From f93c4c906994d17cd62083d1431dca35f7da74bf Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 6 Apr 2013 16:44:39 +0200 Subject: SI-7337 Error out on missing -d directory. This check was removed without comment in 3a30af154, the addition of JSR-223 support for the interpreter. After this commit, I manually tested that JSR-223 support works. scala> import javax.script._, collection.JavaConverters._; val manager = new ScriptEngineManager; manager.getEngineByName("scala").eval("List(1)") import javax.script._ import collection.JavaConverters._ manager: javax.script.ScriptEngineManager = javax.script.ScriptEngineManager@4418f61b res1: Object = List(1) 3a30af154 did not include a test case, so I don't know whether I've broken some other aspect of it. I tried the above as a `run` test, but hit two problems, one of them seemingly our fault, and the other a MacOS JDK wrinkle. 1. scala.reflect.internal.MissingRequirementError: object scala.runtime in compiler mirror not found. 2. java.lang.UnsatisfiedLinkError: no AppleScriptEngine in java.library.path I can't find my way to fix these, so JSR-223 remains untested. I don't think that commit was really up to standard; it could handle additional review, documentation, and testing. It might even be modularized so as not to pollute the REPL itself. --- .../scala/tools/nsc/settings/MutableSettings.scala | 3 +-- test/files/run/t7337.check | 1 + test/files/run/t7337.scala | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 test/files/run/t7337.check create mode 100644 test/files/run/t7337.scala (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala index 4d086e787e..cd23ad74e4 100644 --- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala @@ -251,8 +251,7 @@ class MutableSettings(val errorFn: String => Unit) else if (allowJar && dir == null && Jar.isJarOrZip(name, examineFile = false)) new PlainFile(Path(name)) else -// throw new FatalError(name + " does not exist or is not a directory") - dir + throw new FatalError(name + " does not exist or is not a directory") ) /** Set the single output directory. From now on, all files will diff --git a/test/files/run/t7337.check b/test/files/run/t7337.check new file mode 100644 index 0000000000..dd2b31f23c --- /dev/null +++ b/test/files/run/t7337.check @@ -0,0 +1 @@ +doesnotexist does not exist or is not a directory diff --git a/test/files/run/t7337.scala b/test/files/run/t7337.scala new file mode 100644 index 0000000000..d878182ed0 --- /dev/null +++ b/test/files/run/t7337.scala @@ -0,0 +1,19 @@ +import scala.tools.partest._ +import scala.tools.nsc._ +import util.{CommandLineParser} + +object Test extends DirectTest { + override def code = "class C" + override def newCompiler(args: String*): Global = { + val settings = newSettings((CommandLineParser tokenize ("-d doesnotexist " + extraSettings)) ++ args.toList) + newCompiler(settings) + } + + override def show() { + try { + newCompiler() + } catch { + case fe: FatalError => println(fe.getMessage) + } + } +} -- cgit v1.2.3 From aa6723c500b5c226a68609418f98f94adab7a8bf Mon Sep 17 00:00:00 2001 From: Eugene Vigdorchik Date: Sun, 7 Apr 2013 14:07:05 +0400 Subject: SI-7329 duplicate default getters for specialized parameters. The default getter is generated with @specialized annotation if the type parameter corresponding to the type of the parameter is specialized. Consequently specialize pass tries to generate overloads. Rather than pruning overloads to exclude duplicates, let's notice that default getter specialization is not needed at all: - The dynamic scope of default getter doesn't include specialized method or class constructor. - generic default getter is called even when calling specialized method: object V { @specialized def foo[@specialized B](b: B = (??? : B)) = {} foo[Int]() } gives: invokevirtual Method V$.foo$default$1:()Ljava/lang/Object; invokestatic (unboxToInt) invokevirtual Method V$.foo$mIc$sp:(I)V --- src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala | 6 +++++- test/files/pos/t7329.scala | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 test/files/pos/t7329.scala (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index a71920f787..d91ea4707d 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -796,7 +796,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { private def normalizeMember(owner: Symbol, sym: Symbol, outerEnv: TypeEnv): List[Symbol] = { sym :: ( if (!sym.isMethod || beforeTyper(sym.typeParams.isEmpty)) Nil - else { + else if (sym.hasDefault) { + /* Specializing default getters is useless, also see SI-7329 . */ + sym.resetFlag(SPECIALIZED) + Nil + } else { // debuglog("normalizeMember: " + sym.fullNameAsName('.').decode) var specializingOn = specializedParams(sym) val unusedStvars = specializingOn filterNot specializedTypeVars(sym.info) diff --git a/test/files/pos/t7329.scala b/test/files/pos/t7329.scala new file mode 100644 index 0000000000..76bf1fb9f5 --- /dev/null +++ b/test/files/pos/t7329.scala @@ -0,0 +1 @@ +class TwoParamSpecializedWithDefault[@specialized A, @specialized B](a: A, b: B = (??? : B)) \ No newline at end of file -- cgit v1.2.3 From 2885eb0b2d49c33c707cecd2ee7b9588fe3f76ab Mon Sep 17 00:00:00 2001 From: Eugene Vigdorchik Date: Mon, 8 Apr 2013 14:12:26 +0400 Subject: Revert "SI-6387 Clones accessor before name expansion" This reverts commit 4e10b2c833fa846c68b81e94a08d867e7de656aa. Add 6387 test to pending and 7341 to up-to-date. --- src/reflect/scala/reflect/internal/Symbols.scala | 35 ++++++++---------------- test/files/run/t6387.check | 1 - test/files/run/t6387.scala | 16 ----------- test/files/run/t7341.check | 0 test/files/run/t7341.flags | 1 + test/files/run/t7341.scala | 15 ++++++++++ test/pending/run/t6387.check | 1 + test/pending/run/t6387.scala | 16 +++++++++++ 8 files changed, 44 insertions(+), 41 deletions(-) delete mode 100644 test/files/run/t6387.check delete mode 100644 test/files/run/t6387.scala create mode 100644 test/files/run/t7341.check create mode 100755 test/files/run/t7341.flags create mode 100755 test/files/run/t7341.scala create mode 100644 test/pending/run/t6387.check create mode 100644 test/pending/run/t6387.scala (limited to 'src') diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 7274eeafe0..45c16b7302 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -2538,32 +2538,20 @@ trait Symbols extends api.Symbols { self: SymbolTable => } /** change name by appending $$ - * Do the same for any accessed symbols or setters/getters. - * If the accessor to be renamed is overriding a base symbol, enter - * a cloned symbol with the original name but without ACCESSOR flag. + * Do the same for any accessed symbols or setters/getters */ override def expandName(base: Symbol) { - def expand(sym: Symbol) { - if ((sym eq NoSymbol) || (sym hasFlag EXPANDEDNAME)) () // skip - else sym setFlag EXPANDEDNAME setName nme.expandedName(sym.name.toTermName, base) - } - def cloneAndExpand(accessor: Symbol) { - val clone = accessor.cloneSymbol(accessor.owner, (accessor.flags | ARTIFACT) & ~ACCESSOR) - expand(accessor) - log(s"Expanded overriding accessor to $accessor, but cloned $clone to preserve override") - accessor.owner.info.decls enter clone - } - def expandAccessor(accessor: Symbol) { - if (accessor.isOverridingSymbol) cloneAndExpand(accessor) else expand(accessor) - } - if (hasAccessorFlag && !isDeferred) { - expand(accessed) - } - else if (hasGetter) { - expandAccessor(getter(owner)) - expandAccessor(setter(owner)) + if (!hasFlag(EXPANDEDNAME)) { + setFlag(EXPANDEDNAME) + if (hasAccessorFlag && !isDeferred) { + accessed.expandName(base) + } + else if (hasGetter) { + getter(owner).expandName(base) + setter(owner).expandName(base) + } + name = nme.expandedName(name.toTermName, base) } - expand(this) } protected def doCookJavaRawInfo() { @@ -3235,7 +3223,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def companionModule = NoSymbol override def companionSymbol = NoSymbol override def isSubClass(that: Symbol) = false - override def isOverridingSymbol = false override def filter(cond: Symbol => Boolean) = this override def defString: String = toString override def locationString: String = "" diff --git a/test/files/run/t6387.check b/test/files/run/t6387.check deleted file mode 100644 index 83b33d238d..0000000000 --- a/test/files/run/t6387.check +++ /dev/null @@ -1 +0,0 @@ -1000 diff --git a/test/files/run/t6387.scala b/test/files/run/t6387.scala deleted file mode 100644 index bbebb5f511..0000000000 --- a/test/files/run/t6387.scala +++ /dev/null @@ -1,16 +0,0 @@ -trait A { - def foo: Long -} - -object Test { - def a(): A = new A { - var foo: Long = 1000L - - val test = () => { - foo = 28 - } - } - def main(args: Array[String]) { - println(a().foo) - } -} diff --git a/test/files/run/t7341.check b/test/files/run/t7341.check new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/files/run/t7341.flags b/test/files/run/t7341.flags new file mode 100755 index 0000000000..ae08446055 --- /dev/null +++ b/test/files/run/t7341.flags @@ -0,0 +1 @@ +-Xcheckinit \ No newline at end of file diff --git a/test/files/run/t7341.scala b/test/files/run/t7341.scala new file mode 100755 index 0000000000..dc526c6c19 --- /dev/null +++ b/test/files/run/t7341.scala @@ -0,0 +1,15 @@ +object Obj { + private var cache: Any = () + def returning(f: () => Unit) = () + def foo { + returning(() => cache = ()) + } + + def apply(): Any = { + cache + } +} + +object Test extends App { + Obj() +} diff --git a/test/pending/run/t6387.check b/test/pending/run/t6387.check new file mode 100644 index 0000000000..83b33d238d --- /dev/null +++ b/test/pending/run/t6387.check @@ -0,0 +1 @@ +1000 diff --git a/test/pending/run/t6387.scala b/test/pending/run/t6387.scala new file mode 100644 index 0000000000..bbebb5f511 --- /dev/null +++ b/test/pending/run/t6387.scala @@ -0,0 +1,16 @@ +trait A { + def foo: Long +} + +object Test { + def a(): A = new A { + var foo: Long = 1000L + + val test = () => { + foo = 28 + } + } + def main(args: Array[String]) { + println(a().foo) + } +} -- cgit v1.2.3 From d43f5ce5aa10e39ad05a385c31fc7178eba997c1 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sun, 7 Apr 2013 14:08:14 +0200 Subject: SI-7335 Mandate that parents of Predef must be defined in Predef.scala This avoids thorny issues of cyclic references and/or missing symbol errors due to the way Predef is completed earlier than user classes, and due to the addition of `import Predef._` to LowPriorityImplicits.scala. More details in Lukas's comments in [2]. How did we bootstrap originally? Manually ordering source files, either in the Ant Build [1], or later in Global [2]. But neither mechanism remains in place (due, I suppose, to the difficulty in defending them with a test case.) The reordering in Global was removed in [3]. After the change, we can compile the standard library without the results of a prior compilation run on the classpath. rm -rf target/locker/library/classes/scala && export LIB=build/pack/lib; java -Xmx1G -cp $LIB/scala-library.jar:$LIB/scala-reflect.jar:$LIB/scala-compiler.jar:$LIB/forkjoin.jar scala.tools.nsc.Main @args.txt src/library/scala/SerialVersionUID.scala:15: warning: Implementation restriction: subclassing Classfile does not make your annotation visible at runtime. If that is what you want, you must write the annotation class in Java. class SerialVersionUID(value: Long) extends scala.annotation.ClassfileAnnotation ^ warning: there were 75 deprecation warning(s); re-run with -deprecation for details warning: there were 1 unchecked warning(s); re-run with -unchecked for details warning: there were 5 feature warning(s); re-run with -feature for details four warnings found Where @args.txt contains: -classpath lib/forkjoin.jar:target/locker/library/classes -sourcepath src/library -d target/locker/library/classes src/library/scala/Function3.scala src/library/scala/Console.scala This change will break scala-virtualized, which will need to move the contents of StandardEmbeddings.scala into Predef.scala. [1] https://github.com/scala/scala/commit/c5441dc [2] https://github.com/scala/scala/commit/e72f0c7 [3] https://github.com/scala/scala/pull/968 --- .../scala/tools/nsc/typechecker/Typers.scala | 9 ++ src/library/scala/LowPriorityImplicits.scala | 95 ---------------------- src/library/scala/Predef.scala | 86 ++++++++++++++++++++ 3 files changed, 95 insertions(+), 95 deletions(-) delete mode 100644 src/library/scala/LowPriorityImplicits.scala (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 0be7192471..be59b4e86b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1856,6 +1856,9 @@ trait Typers extends Adaptations with Tags { } val impl2 = finishMethodSynthesis(impl1, clazz, context) + if (mdef.symbol == PredefModule) + ensurePredefParentsAreInSameSourceFile(impl2) + // SI-5954. On second compile of a companion class contained in a package object we end up // with some confusion of names which leads to having two symbols with the same name in the // same owner. Until that can be straightened out we will warn on companion objects in package @@ -1884,6 +1887,12 @@ trait Typers extends Adaptations with Tags { treeCopy.ModuleDef(mdef, typedMods, mdef.name, impl2) setType NoType } + + private def ensurePredefParentsAreInSameSourceFile(template: Template) = { + val parentSyms = template.parents map (_.symbol) filterNot (_ == AnyRefClass) + if (parentSyms exists (_.associatedFile != PredefModule.associatedFile)) + unit.error(template.pos, s"All parents of Predef must be defined in ${PredefModule.associatedFile}.") + } /** In order to override this in the TreeCheckers Typer so synthetics aren't re-added * all the time, it is exposed here the module/class typing methods go through it. * ...but it turns out it's also the ideal spot for namer/typer coordination for diff --git a/src/library/scala/LowPriorityImplicits.scala b/src/library/scala/LowPriorityImplicits.scala deleted file mode 100644 index 535f1ac699..0000000000 --- a/src/library/scala/LowPriorityImplicits.scala +++ /dev/null @@ -1,95 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala - -import scala.collection.{ mutable, immutable, generic } -import mutable.WrappedArray -import immutable.WrappedString -import generic.CanBuildFrom -import scala.language.implicitConversions - -/** The `LowPriorityImplicits` class provides implicit values that - * are valid in all Scala compilation units without explicit qualification, - * but that are partially overridden by higher-priority conversions in object - * `Predef`. - * - * @author Martin Odersky - * @since 2.8 - */ -private[scala] abstract class LowPriorityImplicits { - /** We prefer the java.lang.* boxed types to these wrappers in - * any potential conflicts. Conflicts do exist because the wrappers - * need to implement ScalaNumber in order to have a symmetric equals - * method, but that implies implementing java.lang.Number as well. - * - * Note - these are inlined because they are value classes, but - * the call to xxxWrapper is not eliminated even though it does nothing. - * Even inlined, every call site does a no-op retrieval of Predef's MODULE$ - * because maybe loading Predef has side effects! - */ - @inline implicit def byteWrapper(x: Byte) = new runtime.RichByte(x) - @inline implicit def shortWrapper(x: Short) = new runtime.RichShort(x) - @inline implicit def intWrapper(x: Int) = new runtime.RichInt(x) - @inline implicit def charWrapper(c: Char) = new runtime.RichChar(c) - @inline implicit def longWrapper(x: Long) = new runtime.RichLong(x) - @inline implicit def floatWrapper(x: Float) = new runtime.RichFloat(x) - @inline implicit def doubleWrapper(x: Double) = new runtime.RichDouble(x) - @inline implicit def booleanWrapper(x: Boolean) = new runtime.RichBoolean(x) - - // These eight implicits exist solely to exclude Null from the domain of - // the boxed types, so that e.g. "var x: Int = null" is a compile time - // error rather than a delayed null pointer exception by way of the - // conversion from java.lang.Integer. If defined in the same file as - // Integer2int, they would have higher priority because Null is a subtype - // of Integer. We balance that out and create conflict by moving the - // definition into the superclass. - // - // Caution: do not adjust tightrope tension without safety goggles in place. - implicit def Byte2byteNullConflict(x: Null): Byte = sys.error("value error") - implicit def Short2shortNullConflict(x: Null): Short = sys.error("value error") - implicit def Character2charNullConflict(x: Null): Char = sys.error("value error") - implicit def Integer2intNullConflict(x: Null): Int = sys.error("value error") - implicit def Long2longNullConflict(x: Null): Long = sys.error("value error") - implicit def Float2floatNullConflict(x: Null): Float = sys.error("value error") - implicit def Double2doubleNullConflict(x: Null): Double = sys.error("value error") - implicit def Boolean2booleanNullConflict(x: Null): Boolean = sys.error("value error") - - implicit def genericWrapArray[T](xs: Array[T]): WrappedArray[T] = - if (xs eq null) null - else WrappedArray.make(xs) - - // Since the JVM thinks arrays are covariant, one 0-length Array[AnyRef] - // is as good as another for all T <: AnyRef. Instead of creating 100,000,000 - // unique ones by way of this implicit, let's share one. - implicit def wrapRefArray[T <: AnyRef](xs: Array[T]): WrappedArray[T] = { - if (xs eq null) null - else if (xs.length == 0) WrappedArray.empty[T] - else new WrappedArray.ofRef[T](xs) - } - - implicit def wrapIntArray(xs: Array[Int]): WrappedArray[Int] = if (xs ne null) new WrappedArray.ofInt(xs) else null - implicit def wrapDoubleArray(xs: Array[Double]): WrappedArray[Double] = if (xs ne null) new WrappedArray.ofDouble(xs) else null - implicit def wrapLongArray(xs: Array[Long]): WrappedArray[Long] = if (xs ne null) new WrappedArray.ofLong(xs) else null - implicit def wrapFloatArray(xs: Array[Float]): WrappedArray[Float] = if (xs ne null) new WrappedArray.ofFloat(xs) else null - implicit def wrapCharArray(xs: Array[Char]): WrappedArray[Char] = if (xs ne null) new WrappedArray.ofChar(xs) else null - implicit def wrapByteArray(xs: Array[Byte]): WrappedArray[Byte] = if (xs ne null) new WrappedArray.ofByte(xs) else null - implicit def wrapShortArray(xs: Array[Short]): WrappedArray[Short] = if (xs ne null) new WrappedArray.ofShort(xs) else null - implicit def wrapBooleanArray(xs: Array[Boolean]): WrappedArray[Boolean] = if (xs ne null) new WrappedArray.ofBoolean(xs) else null - implicit def wrapUnitArray(xs: Array[Unit]): WrappedArray[Unit] = if (xs ne null) new WrappedArray.ofUnit(xs) else null - - implicit def wrapString(s: String): WrappedString = if (s ne null) new WrappedString(s) else null - implicit def unwrapString(ws: WrappedString): String = if (ws ne null) ws.self else null - - implicit def fallbackStringCanBuildFrom[T]: CanBuildFrom[String, T, immutable.IndexedSeq[T]] = - new CanBuildFrom[String, T, immutable.IndexedSeq[T]] { - def apply(from: String) = immutable.IndexedSeq.newBuilder[T] - def apply() = immutable.IndexedSeq.newBuilder[T] - } -} - diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index 9a468489a2..511e5b842a 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -446,3 +446,89 @@ private[scala] trait DeprecatedPredef { @deprecated("Use the method in `scala.io.ReadStdin`", "2.11.0") def readf2(format: String) = ReadStdin.readf2(format) @deprecated("Use the method in `scala.io.ReadStdin`", "2.11.0") def readf3(format: String) = ReadStdin.readf3(format) } + +/** The `LowPriorityImplicits` class provides implicit values that +* are valid in all Scala compilation units without explicit qualification, +* but that are partially overridden by higher-priority conversions in object +* `Predef`. +* +* @author Martin Odersky +* @since 2.8 +*/ +// SI-7335 Parents of Predef are defined in the same compilation unit to avoid +// cyclic reference errors compiling the standard library *without* a previously +// compiled copy on the classpath. +private[scala] abstract class LowPriorityImplicits { + import mutable.WrappedArray + import immutable.WrappedString + + /** We prefer the java.lang.* boxed types to these wrappers in + * any potential conflicts. Conflicts do exist because the wrappers + * need to implement ScalaNumber in order to have a symmetric equals + * method, but that implies implementing java.lang.Number as well. + * + * Note - these are inlined because they are value classes, but + * the call to xxxWrapper is not eliminated even though it does nothing. + * Even inlined, every call site does a no-op retrieval of Predef's MODULE$ + * because maybe loading Predef has side effects! + */ + @inline implicit def byteWrapper(x: Byte) = new runtime.RichByte(x) + @inline implicit def shortWrapper(x: Short) = new runtime.RichShort(x) + @inline implicit def intWrapper(x: Int) = new runtime.RichInt(x) + @inline implicit def charWrapper(c: Char) = new runtime.RichChar(c) + @inline implicit def longWrapper(x: Long) = new runtime.RichLong(x) + @inline implicit def floatWrapper(x: Float) = new runtime.RichFloat(x) + @inline implicit def doubleWrapper(x: Double) = new runtime.RichDouble(x) + @inline implicit def booleanWrapper(x: Boolean) = new runtime.RichBoolean(x) + + // These eight implicits exist solely to exclude Null from the domain of + // the boxed types, so that e.g. "var x: Int = null" is a compile time + // error rather than a delayed null pointer exception by way of the + // conversion from java.lang.Integer. If defined in the same file as + // Integer2int, they would have higher priority because Null is a subtype + // of Integer. We balance that out and create conflict by moving the + // definition into the superclass. + // + // Caution: do not adjust tightrope tension without safety goggles in place. + implicit def Byte2byteNullConflict(x: Null): Byte = sys.error("value error") + implicit def Short2shortNullConflict(x: Null): Short = sys.error("value error") + implicit def Character2charNullConflict(x: Null): Char = sys.error("value error") + implicit def Integer2intNullConflict(x: Null): Int = sys.error("value error") + implicit def Long2longNullConflict(x: Null): Long = sys.error("value error") + implicit def Float2floatNullConflict(x: Null): Float = sys.error("value error") + implicit def Double2doubleNullConflict(x: Null): Double = sys.error("value error") + implicit def Boolean2booleanNullConflict(x: Null): Boolean = sys.error("value error") + + implicit def genericWrapArray[T](xs: Array[T]): WrappedArray[T] = + if (xs eq null) null + else WrappedArray.make(xs) + + // Since the JVM thinks arrays are covariant, one 0-length Array[AnyRef] + // is as good as another for all T <: AnyRef. Instead of creating 100,000,000 + // unique ones by way of this implicit, let's share one. + implicit def wrapRefArray[T <: AnyRef](xs: Array[T]): WrappedArray[T] = { + if (xs eq null) null + else if (xs.length == 0) WrappedArray.empty[T] + else new WrappedArray.ofRef[T](xs) + } + + implicit def wrapIntArray(xs: Array[Int]): WrappedArray[Int] = if (xs ne null) new WrappedArray.ofInt(xs) else null + implicit def wrapDoubleArray(xs: Array[Double]): WrappedArray[Double] = if (xs ne null) new WrappedArray.ofDouble(xs) else null + implicit def wrapLongArray(xs: Array[Long]): WrappedArray[Long] = if (xs ne null) new WrappedArray.ofLong(xs) else null + implicit def wrapFloatArray(xs: Array[Float]): WrappedArray[Float] = if (xs ne null) new WrappedArray.ofFloat(xs) else null + implicit def wrapCharArray(xs: Array[Char]): WrappedArray[Char] = if (xs ne null) new WrappedArray.ofChar(xs) else null + implicit def wrapByteArray(xs: Array[Byte]): WrappedArray[Byte] = if (xs ne null) new WrappedArray.ofByte(xs) else null + implicit def wrapShortArray(xs: Array[Short]): WrappedArray[Short] = if (xs ne null) new WrappedArray.ofShort(xs) else null + implicit def wrapBooleanArray(xs: Array[Boolean]): WrappedArray[Boolean] = if (xs ne null) new WrappedArray.ofBoolean(xs) else null + implicit def wrapUnitArray(xs: Array[Unit]): WrappedArray[Unit] = if (xs ne null) new WrappedArray.ofUnit(xs) else null + + implicit def wrapString(s: String): WrappedString = if (s ne null) new WrappedString(s) else null + implicit def unwrapString(ws: WrappedString): String = if (ws ne null) ws.self else null + + implicit def fallbackStringCanBuildFrom[T]: CanBuildFrom[String, T, immutable.IndexedSeq[T]] = + new CanBuildFrom[String, T, immutable.IndexedSeq[T]] { + def apply(from: String) = immutable.IndexedSeq.newBuilder[T] + def apply() = immutable.IndexedSeq.newBuilder[T] + } +} + -- cgit v1.2.3 From 9d7f81103b423a51b021ab80884cfbc57bfb75f6 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sun, 7 Apr 2013 14:52:07 +0200 Subject: SI-7335 Don't import Predef._ in Predef.scala The check for this was foiled by the introduction of DeprecatedPredef in c26a8db0. This didn't cause any harm, but in any case this commit restores the intended state of affairs. The change is visible only through logging; no test case is included. qbin/scalac -Ydebug -Ylog:all src/library/scala/Predef.scala -Ystop-after:typer 2>&1 | grep -i "Omitted import of Predef" [log namer] Omitted import of Predef._ for Predef.scala [log typer] Omitted import of Predef._ for Predef.scala A redundant override of `firstDefinesClassOrObject` is also removed. Maybe we can remove the special case altogether? --- src/compiler/scala/tools/nsc/ast/TreeInfo.scala | 8 -------- src/compiler/scala/tools/nsc/typechecker/Contexts.scala | 5 ++++- src/reflect/scala/reflect/internal/TreeInfo.scala | 13 ++++++------- 3 files changed, 10 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala index 6a0f4407fc..0731d78a9b 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala @@ -87,12 +87,4 @@ abstract class TreeInfo extends scala.reflect.internal.TreeInfo { case DocDef(_, definition) => isPureDef(definition) case _ => super.isPureDef(tree) } - - /** Does list of trees start with a definition of - * a class of module with given name (ignoring imports) - */ - override def firstDefinesClassOrObject(trees: List[Tree], name: Name): Boolean = trees match { - case ClassDef(_, `name`, _, _) :: Nil => true - case _ => super.firstDefinesClassOrObject(trees, name) - } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index e89a860e0f..f135f7f6ae 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -81,7 +81,10 @@ trait Contexts { self: Analyzer => if (settings.noimports) Nil else if (unit.isJava) RootImports.javaList - else if (settings.nopredef || treeInfo.noPredefImportForUnit(unit.body)) RootImports.javaAndScalaList + else if (settings.nopredef || treeInfo.noPredefImportForUnit(unit.body)) { + debuglog("Omitted import of Predef._ for " + unit) + RootImports.javaAndScalaList + } else RootImports.completeList } diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala index b1f58814c7..0ddcc9fd7b 100644 --- a/src/reflect/scala/reflect/internal/TreeInfo.scala +++ b/src/reflect/scala/reflect/internal/TreeInfo.scala @@ -667,13 +667,12 @@ abstract class TreeInfo { * a class of module with given name (ignoring imports) */ def firstDefinesClassOrObject(trees: List[Tree], name: Name): Boolean = trees match { - case Import(_, _) :: xs => firstDefinesClassOrObject(xs, name) - case Annotated(_, tree1) :: Nil => firstDefinesClassOrObject(List(tree1), name) - case ModuleDef(_, `name`, _) :: Nil => true - case ClassDef(_, `name`, _, _) :: Nil => true - case _ => false - } - + case Import(_, _) :: xs => firstDefinesClassOrObject(xs, name) + case Annotated(_, tree1) :: _ => firstDefinesClassOrObject(List(tree1), name) + case ModuleDef(_, `name`, _) :: _ => true + case ClassDef(_, `name`, _, _) :: _ => true + case _ => false + } /** Is this file the body of a compilation unit which should not * have Predef imported? -- cgit v1.2.3 From ae69de4cb610c2b92fd51052cd32702dd3bd1e9f Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sun, 7 Apr 2013 18:41:37 +0200 Subject: SI-7335 Add logging for a now-impossible* case in Symbol#exists. * Impossible (to the best of my knowledge) because LowPriorityImplicits is now defined in Predef.scala. Were I more sure, we could trip an assertion here, rather than the devWarning. --- src/reflect/scala/reflect/internal/Symbols.scala | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 8ef2805529..4a7b25e6be 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -887,9 +887,23 @@ trait Symbols extends api.Symbols { self: SymbolTable => supersym == NoSymbol || supersym.isIncompleteIn(base) } - // Does not always work if the rawInfo is a SourcefileLoader, see comment - // in "def coreClassesFirst" in Global. - def exists = !isTopLevel || { rawInfo.load(this); rawInfo != NoType } + def exists: Boolean = !isTopLevel || { + val isSourceLoader = rawInfo match { + case sl: SymLoader => sl.fromSource + case _ => false + } + def warnIfSourceLoader() { + if (isSourceLoader) + // Predef is completed early due to its autoimport; we used to get here when type checking its + // parent LowPriorityImplicits. See comment in c5441dc for more elaboration. + // Since the fix for SI-7335 Predef parents must be defined in Predef.scala, and we should not + // get here anymore. + devWarning(s"calling Symbol#exists with sourcefile based symbol loader may give incorrect results."); + } + + rawInfo load this + rawInfo != NoType || { warnIfSourceLoader(); false } + } final def isInitialized: Boolean = validTo != NoPeriod -- cgit v1.2.3 From b0fceebae53fa140619ccf2cfcb8e4cf7f20f88b Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 8 Apr 2013 15:08:51 +0200 Subject: SI-7335 Sharpen up comment about implicit prioritization. --- src/library/scala/Predef.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index 511e5b842a..569157de20 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -484,7 +484,7 @@ private[scala] abstract class LowPriorityImplicits { // These eight implicits exist solely to exclude Null from the domain of // the boxed types, so that e.g. "var x: Int = null" is a compile time // error rather than a delayed null pointer exception by way of the - // conversion from java.lang.Integer. If defined in the same file as + // conversion from java.lang.Integer. If defined in the same template as // Integer2int, they would have higher priority because Null is a subtype // of Integer. We balance that out and create conflict by moving the // definition into the superclass. @@ -531,4 +531,3 @@ private[scala] abstract class LowPriorityImplicits { def apply() = immutable.IndexedSeq.newBuilder[T] } } - -- cgit v1.2.3 From 6a61e172d9de912c74af50e49f0057fbe8d4e500 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Sat, 23 Mar 2013 15:06:22 +0100 Subject: SI-7289 Less strict type application for TypeVar. When a type constructor variable is applied to the wrong number of arguments, return a new type variable whose instance is `ErrorType`. Dissection of the reported test case by @retronym: Define the first implicit: scala> trait Schtroumpf[T] defined trait Schtroumpf scala> implicit def schtroumpf[T, U <: Coll[T], Coll[X] <: Traversable[X]] | (implicit minorSchtroumpf: Schtroumpf[T]): Schtroumpf[U] = ??? schtroumpf: [T, U <: Coll[T], Coll[X] <: Traversable[X]](implicit minorSchtroumpf: Schtroumpf[T])Schtroumpf[U] Call it explicitly => kind error during type inference reported. scala> schtroumpf(null): Schtroumpf[Int] :10: error: inferred kinds of the type arguments (Nothing,Int,Int) do not conform to the expected kinds of the type parameters (type T,type U,type Coll). Int's type parameters do not match type Coll's expected parameters: class Int has no type parameters, but type Coll has one schtroumpf(null): Schtroumpf[Int] ^ :10: error: type mismatch; found : Schtroumpf[U] required: Schtroumpf[Int] schtroumpf(null): Schtroumpf[Int] ^ Add another implicit, and let implicit search weigh them up. scala> implicitly[Schtroumpf[Int]] :10: error: diverging implicit expansion for type Schtroumpf[Int] starting with method schtroumpf implicitly[Schtroumpf[Int]] ^ scala> implicit val qoo = new Schtroumpf[Int]{} qoo: Schtroumpf[Int] = $anon$1@c1b9b03 scala> implicitly[Schtroumpf[Int]] Implicit search compares the two in-scope implicits in `isStrictlyMoreSpecific`, which constructs an existential type: type ET = Schtroumpf[U] forSome { type T; type U <: Coll[T]; type Coll[_] <: Traversable[_] } A subsequent subtype check `ET <:< Schtroumpf[Int]` gets to `withTypeVars`, which replaces the quantified types with type variables, checks conformance of that substitued underlying type against `Schtroumpf[Int]`, and then tries to solve the collected type constraints. The type var trace looks like: [ create] ?T ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) [ create] ?U ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) [ create] ?Coll ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) [ setInst] Nothing ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], T=Nothing ) [ setInst] scala.collection.immutable.Nil.type( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], U=scala.collection.immutable.Nil.type ) [ setInst] =?scala.collection.immutable.Nil.type( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], Coll==?scala.collection.immutable.Nil.type ) [ create] ?T ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) [ setInst] Int ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], T=Int ) [ create] ?T ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) [ create] ?U ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) [ create] ?Coll ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) [ setInst] Nothing ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], T=Nothing ) [ setInst] Int ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], U=Int ) [ setInst] =?Int ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], Coll==?Int ) The problematic part is when `?Int` (the type var originated from `U`) is registered as a lower bound for `Coll`. That happens in `solveOne`: for (tparam2 <- tparams) tparam2.info.bounds.hi.dealias match { case TypeRef(_, `tparam`, _) => log(s"$tvar addLoBound $tparam2.tpeHK.instantiateTypeParams($tparams, $tvars)") tvar addLoBound tparam2.tpeHK.instantiateTypeParams(tparams, tvars) case _ => } --- bincompat-backward.whitelist.conf | 4 +++ bincompat-forward.whitelist.conf | 4 +++ src/reflect/scala/reflect/internal/Types.scala | 17 ++++++----- test/files/neg/t7289.check | 4 +++ test/files/neg/t7289.scala | 39 ++++++++++++++++++++++++++ test/files/neg/t7289_status_quo.check | 22 +++++++++++++++ test/files/neg/t7289_status_quo.scala | 23 +++++++++++++++ 7 files changed, 106 insertions(+), 7 deletions(-) create mode 100644 test/files/neg/t7289.check create mode 100644 test/files/neg/t7289.scala create mode 100644 test/files/neg/t7289_status_quo.check create mode 100644 test/files/neg/t7289_status_quo.scala (limited to 'src') diff --git a/bincompat-backward.whitelist.conf b/bincompat-backward.whitelist.conf index aa06e1d21c..3426dc72e1 100644 --- a/bincompat-backward.whitelist.conf +++ b/bincompat-backward.whitelist.conf @@ -186,6 +186,10 @@ filter { { matchName="scala.reflect.internal.ClassfileConstants.xxxunusedxxxx" problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.Types#TypeVar.setInst" + problemName=IncompatibleResultTypeProblem } ] } diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf index d0893c5a28..c59d0a7dec 100644 --- a/bincompat-forward.whitelist.conf +++ b/bincompat-forward.whitelist.conf @@ -418,6 +418,10 @@ filter { { matchName="scala.reflect.internal.ClassfileConstants.CONSTANT_METHODTYPE" problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.Types#TypeVar.setInst" + problemName=IncompatibleResultTypeProblem } ] } diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index a2c9f1fadf..ee584bed2c 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -3076,12 +3076,14 @@ trait Types extends api.Types { self: SymbolTable => /** The variable's skolemization level */ val level = skolemizationLevel - /** Two occurrences of a higher-kinded typevar, e.g. `?CC[Int]` and `?CC[String]`, correspond to - * ''two instances'' of `TypeVar` that share the ''same'' `TypeConstraint`. + /** Applies this TypeVar to type arguments, if arity matches. * - * `constr` for `?CC` only tracks type constructors anyway, - * so when `?CC[Int] <:< List[Int]` and `?CC[String] <:< Iterable[String]` - * `?CC's` hibounds contains List and Iterable. + * Different applications of the same type constructor variable `?CC`, + * e.g. `?CC[Int]` and `?CC[String]`, are modeled as distinct instances of `TypeVar` + * that share a `TypeConstraint`, so that the comparisons `?CC[Int] <:< List[Int]` + * and `?CC[String] <:< Iterable[String]` result in `?CC` being upper-bounded by `List` and `Iterable`. + * + * Applying the wrong number of type args results in a TypeVar whose instance is set to `ErrorType`. */ def applyArgs(newArgs: List[Type]): TypeVar = ( if (newArgs.isEmpty && typeArgs.isEmpty) @@ -3091,7 +3093,7 @@ trait Types extends api.Types { self: SymbolTable => TypeVar.trace("applyArgs", "In " + originLocation + ", apply args " + newArgs.mkString(", ") + " to " + originName)(tv) } else - throw new Error("Invalid type application in TypeVar: " + params + ", " + newArgs) + TypeVar(typeSymbol).setInst(ErrorType) ) // newArgs.length may differ from args.length (could've been empty before) // @@ -3121,13 +3123,14 @@ trait Types extends api.Types { self: SymbolTable => // // invariant: before mutating constr, save old state in undoLog // (undoLog is used to reset constraints to avoid piling up unrelated ones) - def setInst(tp: Type) { + def setInst(tp: Type): this.type = { // assert(!(tp containsTp this), this) undoLog record this // if we were compared against later typeskolems, repack the existential, // because skolems are only compatible if they were created at the same level val res = if (shouldRepackType) repackExistential(tp) else tp constr.inst = TypeVar.trace("setInst", "In " + originLocation + ", " + originName + "=" + res)(res) + this } def addLoBound(tp: Type, isNumericBound: Boolean = false) { diff --git a/test/files/neg/t7289.check b/test/files/neg/t7289.check new file mode 100644 index 0000000000..e4aeebbc6c --- /dev/null +++ b/test/files/neg/t7289.check @@ -0,0 +1,4 @@ +t7289.scala:8: error: could not find implicit value for parameter e: Test.Schtroumpf[scala.collection.immutable.Nil.type] + implicitly[Schtroumpf[Nil.type]] + ^ +one error found diff --git a/test/files/neg/t7289.scala b/test/files/neg/t7289.scala new file mode 100644 index 0000000000..f4ed3daf76 --- /dev/null +++ b/test/files/neg/t7289.scala @@ -0,0 +1,39 @@ +object Test extends App { + trait Schtroumpf[T] + + implicit def schtroumpf[T, U <: Coll[T], Coll[X] <: Traversable[X]] + (implicit minorSchtroumpf: Schtroumpf[T]): Schtroumpf[U] = ??? + + implicit val qoo: Schtroumpf[Int] = new Schtroumpf[Int]{} + implicitly[Schtroumpf[Nil.type]] +} + +/* +info1 = {scala.tools.nsc.typechecker.Implicits$ImplicitInfo@3468}"qoo: => Test.Schtroumpf[Int]" +info2 = {scala.tools.nsc.typechecker.Implicits$ImplicitInfo@3469}"schtroumpf: [T, U <: Coll[T], Coll[_] <: Traversable[_]](implicit minorSchtroumpf: Test.Schtroumpf[T])Test.Schtroumpf[U]" +isStrictlyMoreSpecific(info1, info2) + isSubType(Test.Schtroumpf[Int], Test.Schtroumpf[U] forSome { T; U <: Coll[T]; Coll[_] <: Traversable[_] }) + isAsSpecificValueType(Test.Schtroumpf[Int], Test.Schtroumpf[U], undef2 = List(type T, type U, type Coll)) + + val et: ExistentialType = Test.Schtroumpf[U] forSome { T; U <: Coll[T]; Coll[_] <: Traversable[_] } + val tp1 = Test.Schtroumpf[Int] + et.withTypeVars(isSubType(tp1, _, depth)) + solve() + tvars = tList(=?Nothing, =?Int, =?=?Int) + + +[ create] ?T ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) +[ create] ?U ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) +[ create] ?Coll ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) +[ setInst] Nothing ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], T=Nothing ) +[ setInst] scala.collection.immutable.Nil.type( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], U=scala.collection.immutable.Nil.type ) +[ setInst] =?scala.collection.immutable.Nil.type( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], Coll==?scala.collection.immutable.Nil.type ) +[ create] ?T ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) +[ setInst] Int ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], T=Int ) +[ create] ?T ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) +[ create] ?U ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) +[ create] ?Coll ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]] ) +[ setInst] Nothing ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], T=Nothing ) +[ setInst] Int ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], U=Int ) +[ setInst] =?Int ( In Test#schtroumpf[T,U <: Coll[T],Coll[_] <: Traversable[_]], Coll==?Int ) +*/ \ No newline at end of file diff --git a/test/files/neg/t7289_status_quo.check b/test/files/neg/t7289_status_quo.check new file mode 100644 index 0000000000..31c072e969 --- /dev/null +++ b/test/files/neg/t7289_status_quo.check @@ -0,0 +1,22 @@ +t7289_status_quo.scala:9: error: could not find implicit value for parameter e: Test1.Ext[List[Int]] + implicitly[Ext[List[Int]]] // fails - not found + ^ +t7289_status_quo.scala:11: error: could not find implicit value for parameter e: Test1.Ext[List[List[List[Int]]]] + implicitly[Ext[List[List[List[Int]]]]] // fails - not found + ^ +t7289_status_quo.scala:15: error: ambiguous implicit values: + both method f in object Test1 of type [A, Coll <: CC[A], CC[X] <: Traversable[X]](implicit xi: Test1.Ext[A])Test1.Ext[Coll] + and value m in object Test1 of type => Test1.Ext[List[List[Int]]] + match expected type Test1.Ext[_ <: List[List[Int]]] + implicitly[Ext[_ <: List[List[Int]]]] // fails - ambiguous + ^ +t7289_status_quo.scala:20: error: could not find implicit value for parameter e: Test1.ExtCov[List[Int]] + implicitly[ExtCov[List[Int]]] // fails - not found + ^ +t7289_status_quo.scala:21: error: could not find implicit value for parameter e: Test1.ExtCov[List[List[Int]]] + implicitly[ExtCov[List[List[Int]]]] // fails - not found + ^ +t7289_status_quo.scala:22: error: could not find implicit value for parameter e: Test1.ExtCov[List[List[List[Int]]]] + implicitly[ExtCov[List[List[List[Int]]]]] // fails - not found + ^ +6 errors found diff --git a/test/files/neg/t7289_status_quo.scala b/test/files/neg/t7289_status_quo.scala new file mode 100644 index 0000000000..39621429a1 --- /dev/null +++ b/test/files/neg/t7289_status_quo.scala @@ -0,0 +1,23 @@ +// record the status quo after this fix +// not clear to @adriaanm why an upper-bounded existential in an invariant position +// is different from putting that upper bound in a covariant position +object Test1 { + trait Ext[T] + implicit def f[A, Coll <: CC[A], CC[X] <: Traversable[X]](implicit xi: Ext[A]): Ext[Coll] = ??? + implicit val m: Ext[List[List[Int]]] = new Ext[List[List[Int]]]{} + + implicitly[Ext[List[Int]]] // fails - not found + implicitly[Ext[List[List[Int]]]] // compiles + implicitly[Ext[List[List[List[Int]]]]] // fails - not found + + // Making Ext[+T] should incur the same behavior as these. (so says @paulp) + implicitly[Ext[_ <: List[Int]]] // compiles + implicitly[Ext[_ <: List[List[Int]]]] // fails - ambiguous + implicitly[Ext[_ <: List[List[List[Int]]]]] // compiles + + // But, we currently get: + trait ExtCov[+T] + implicitly[ExtCov[List[Int]]] // fails - not found + implicitly[ExtCov[List[List[Int]]]] // fails - not found + implicitly[ExtCov[List[List[List[Int]]]]] // fails - not found +} \ No newline at end of file -- cgit v1.2.3 From 72503126d9c29ff029c4c9537234e1fb1d7a0130 Mon Sep 17 00:00:00 2001 From: Uladzimir Abramchuk Date: Fri, 15 Feb 2013 17:19:21 +0300 Subject: SI-6386 typed existential type tree's original now have tpe set Tree reification fails for ExistentialTypeTree. The reason is that the tree passed for reification (see reifyTree at GetTrees.scala) must have not null tpe (see reifyBoundType at GenTrees.scala), which is not true in the case of ExistentialTypeTree. Why is it so? The tree passed to reifyTree was obtained in the reshape phase of reificationusing using original TypeTrees that reporesent pre- typer representation of a type. The problem is that original's tpe for ExistentialTypeTree is not set. So the solution to the issue is to create ExistentialTypeTree's original in a such way that is has actual tpe set. --- src/compiler/scala/tools/nsc/typechecker/Typers.scala | 12 ++++++++++-- test/files/pos/t6386.scala | 5 +++++ 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 test/files/pos/t6386.scala (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 34ba8b46f9..d1d6feae97 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3887,8 +3887,16 @@ trait Typers extends Modes with Adaptations with Tags { if (vd.symbol.tpe.isVolatile) AbstractionFromVolatileTypeError(vd) val tpt1 = typedType(tree.tpt, mode) - existentialTransform(tree.whereClauses map (_.symbol), tpt1.tpe)((tparams, tp) => - TypeTree(newExistentialType(tparams, tp)) setOriginal tree + existentialTransform(tree.whereClauses map (_.symbol), tpt1.tpe)((tparams, tp) => { + val original = tpt1 match { + case tpt : TypeTree => atPos(tree.pos)(ExistentialTypeTree(tpt.original, tree.whereClauses)) + case _ => { + debuglog(s"cannot reconstruct the original for $tree, because $tpt1 is not a TypeTree") + tree + } + } + TypeTree(newExistentialType(tparams, tp)) setOriginal original + } ) } diff --git a/test/files/pos/t6386.scala b/test/files/pos/t6386.scala new file mode 100644 index 0000000000..85098a78f0 --- /dev/null +++ b/test/files/pos/t6386.scala @@ -0,0 +1,5 @@ +import scala.reflect.runtime.universe._ + +object Test extends App { + reify(manifest[Some[_]]) +} \ No newline at end of file -- cgit v1.2.3 From 4e2459e3de5a1265d5bf071fc1029c6c022336c3 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Tue, 9 Apr 2013 17:48:40 -0700 Subject: Reifier -> AST Node test. It's a Node-by-Node tour of the reifier's abilities and occasional foibles. That is one spectacularly attractive checkfile. --- .../scala/reflect/reify/phases/Reshape.scala | 2 +- .../scala/reflect/internal/util/Position.scala | 48 ++++++--- test/files/run/reify-each-node-type.check | 35 +++++++ test/files/run/reify-each-node-type.scala | 108 +++++++++++++++++++++ 4 files changed, 180 insertions(+), 13 deletions(-) create mode 100644 test/files/run/reify-each-node-type.check create mode 100644 test/files/run/reify-each-node-type.scala (limited to 'src') diff --git a/src/compiler/scala/reflect/reify/phases/Reshape.scala b/src/compiler/scala/reflect/reify/phases/Reshape.scala index bc2dbeed3e..5f53f558b4 100644 --- a/src/compiler/scala/reflect/reify/phases/Reshape.scala +++ b/src/compiler/scala/reflect/reify/phases/Reshape.scala @@ -167,7 +167,7 @@ trait Reshape { // if this assumption fails, please, don't be quick to add postprocessing here (like I did before) // but rather try to fix this in Typer, so that it produces quality originals (like it's done for typedAnnotated) if (reifyDebug) println("TypeTree, essential: %s (%s)".format(tt.tpe, tt.tpe.kind)) - if (reifyDebug) println("verdict: rolled back to original %s".format(tt.original)) + if (reifyDebug) println("verdict: rolled back to original %s".format(tt.original.toString.replaceAll("\\s+", " "))) transform(tt.original) } else { // type is deemed to be non-essential diff --git a/src/reflect/scala/reflect/internal/util/Position.scala b/src/reflect/scala/reflect/internal/util/Position.scala index bb8c9e9b26..fe6c7db989 100644 --- a/src/reflect/scala/reflect/internal/util/Position.scala +++ b/src/reflect/scala/reflect/internal/util/Position.scala @@ -20,18 +20,12 @@ object Position { else if (posIn.isDefined) posIn.inUltimateSource(posIn.source) else posIn ) - def file = pos.source.file - def prefix = if (shortenFile) file.name else file.path + val prefix = if (shortenFile) pos.sourceName else pos.sourcePath pos match { case FakePos(fmsg) => fmsg+" "+msg case NoPosition => msg - case _ => - List( - "%s:%s: %s".format(prefix, pos.line, msg), - pos.lineContent.stripLineEnd, - " " * (pos.column - 1) + "^" - ) mkString "\n" + case _ => "%s:%s: %s\n%s\n%s".format(prefix, pos.line, msg, pos.lineContent, pos.lineCarat) } } } @@ -206,12 +200,39 @@ abstract class Position extends scala.reflect.api.Position { self => def column: Int = throw new UnsupportedOperationException("Position.column") + /** A line with a ^ padded with the right number of spaces. + */ + def lineCarat: String = " " * (column - 1) + "^" + + /** The line of code and the corresponding carat pointing line, trimmed + * to the maximum specified width, with the trimmed versions oriented + * around the point to give maximum context. + */ + def lineWithCarat(maxWidth: Int): (String, String) = { + val radius = maxWidth / 2 + var start = math.max(column - radius, 0) + var result = lineContent drop start take maxWidth + + if (result.length < maxWidth) { + result = lineContent takeRight maxWidth + start = lineContent.length - result.length + } + + (result, lineCarat drop start take maxWidth) + } + /** Convert this to a position around `point` that spans a single source line */ def toSingleLine: Position = this - def lineContent: String = - if (isDefined) source.lineToString(line - 1) - else "NO_LINE" + /** The source code corresponding to the range, if this is a range position. + * Otherwise the empty string. + */ + def sourceCode = "" + def sourceName = "" + def sourcePath = "" + def lineContent = "" + def lengthInChars = 0 + def lengthInLines = 0 /** Map this position to a position in an original source * file. If the SourceFile is a normal SourceFile, simply @@ -240,7 +261,10 @@ class OffsetPosition(override val source: SourceFile, override val point: Int) e override def withPoint(off: Int) = new OffsetPosition(source, off) override def withSource(source: SourceFile, shift: Int) = new OffsetPosition(source, point + shift) - override def line: Int = source.offsetToLine(point) + 1 + override def line = source.offsetToLine(point) + 1 + override def sourceName = source.file.name + override def sourcePath = source.file.path + override def lineContent = source.lineToString(line - 1) override def column: Int = { var idx = source.lineToOffset(source.offsetToLine(point)) diff --git a/test/files/run/reify-each-node-type.check b/test/files/run/reify-each-node-type.check new file mode 100644 index 0000000000..af6fd13a7b --- /dev/null +++ b/test/files/run/reify-each-node-type.check @@ -0,0 +1,35 @@ + 1 s Ident + 2 r.List Select + 3 r.List.apply() Apply + 4 r.List.apply(1) Literal + 5 r.List.apply[Int]() TypeApply + 6 (1: Int) Typed + 7 (null: r.List[Int]) AppliedTypeTree + 8 { (); () } Block + 9 { val x: Int = 0; () } ValDef +10 { val x = 0; () } TypeTree +11 if (true) () else () If +12 { def f: Unit = (); () } DefDef +13 { def m = NN.super.q; () } Super +14 { abstract trait A extends AnyRef; () } ClassDef Template +15 { def f(x: Any): Unit = (); () } EmptyTree +16 (null: r.D with r.E) CompoundTypeTree +17 { type T = Int; () } TypeDef +18 { type CC[T >: Nothing <: r.D] = r.C[T]; () } TypeBoundsTree +19 try { 0 } finally Predef.println("") Try +20 ((x: Int) => x) Function +21 { var v = 1; v = 2 } Assign +22 { class A extends AnyRef { def () = { super.(); This +23 new r.List[Int]() New +24 0: @unchecked Annotated +25 (null: r.Outer#Inner) SelectFromTypeTree +26 (null: Nil.type) SingletonTypeTree +27 (null: T forSome { type T >: Nothing <: Any }) ExistentialTypeTree +28 { import r.{A, B=>C}; () } Import +29 { def f: Int = return 0; () } Return +30 { object x extends AnyRef { def () = { super.(); ModuleDef +31 throw new Exception() Throw +32 0 match { case _ => 0 } Match CaseDef +33 0 match { case (1| 2) => 0 } Alternative +34 NN.q match { case (x @ r.List) => 0 } Bind +35 NN.q match { case r.UnSeq(1, (_)*) => 0 } Star diff --git a/test/files/run/reify-each-node-type.scala b/test/files/run/reify-each-node-type.scala new file mode 100644 index 0000000000..a827da766d --- /dev/null +++ b/test/files/run/reify-each-node-type.scala @@ -0,0 +1,108 @@ +import scala.reflect.runtime.universe._ + +object r { + class A + class B + class List[+A] + object List { def apply[A](xs: A*): List[A] = new List[A] } + object Nil extends List[Nothing] + + trait OuterP[A] { + trait Inner + trait InnerP[B] + } + trait Outer { + trait Inner + trait InnerP[B] + } + object Un { def unapply(x: Any) = Some(5) } + object UnSeq { def unapplySeq(x: Any) = Some(Seq(5)) } + class C[T] + class D + trait E + + trait SN { + def q: Any = null + } +} + +object s { + import r._ + + trait NN extends SN { + def act[T](expr: Expr[T]): Unit + + act(reify { s /* Ident */ }) + act(reify { r.List /* Select */ }) + act(reify { List() /* Apply */ }) + act(reify { List(1) /* Literal */ }) + act(reify { List[Int]() /* TypeApply */ }) + act(reify { 1: Int /* Typed */ }) + act(reify { null: List[Int] /* AppliedTypeTree */ }) + act(reify { () ; () /* Block */ }) + act(reify { val x: Int = 0 /* ValDef */ }) + act(reify { val x = 0 /* TypeTree */ }) + act(reify { if (true) () /* If */ }) + act(reify { def f { } /* DefDef */ }) + act(reify { def m = super.q /* Super */ }) + act(reify { trait A /* ClassDef Template */ }) + act(reify { def f(x: Any) { } /* EmptyTree */ }) + act(reify { null: D with E /* CompoundTypeTree */ }) + act(reify { type T = Int /* TypeDef */ }) + act(reify { type CC[T <: D] = C[T] /* TypeBoundsTree */ }) + act(reify { try 0 finally println("") /* Try */ }) + act(reify { (x: Int) => x /* Function */ }) + act(reify { var v = 1 ; v = 2 /* Assign */ }) + act(reify { class A() { def this(x: A) = this() } /* This */ }) + act(reify { new List[Int] /* New */ }) + act(reify { 0: @unchecked /* Annotated */ }) + act(reify { null: Outer#Inner /* SelectFromTypeTree */ }) + act(reify { null: Nil.type /* SingletonTypeTree */ }) + act(reify { null: (T forSome { type T }) /* ExistentialTypeTree */ }) + act(reify { import r.{ A, B => C }; /* Import */ }) + act(reify { def f: Int = return 0 /* Return */ }) + act(reify { object x /* ModuleDef */ }) + act(reify { throw new java.lang.Exception /* Throw */ }) + act(reify { 0 match { case _ => 0 } /* Match CaseDef */ }) + act(reify { 0 match { case 1 | 2 => 0 } /* Alternative */ }) + act(reify { q match { case x @ List => 0 } /* Bind */ }) + act(reify { q match { case UnSeq(1, _*) => 0 } /* Star */ }) + + // ``unexpected: bound type that doesn't have a tpe: Ident(newTypeName("Int"))'' + // act(reify { r.List[T forSome { type T <: Int }]() }) // Was crashing , no longer + // + // error: exception during macro expansion: + // scala.MatchError: collection.this.Seq.unapplySeq[A] (of class scala.reflect.internal.Trees$TypeApply) + // at scala.reflect.reify.phases.Reshape$$anon$1.extractExtractor$1(Reshape.scala:73) + // at scala.reflect.reify.phases.Reshape$$anon$1.transform(Reshape.scala:82) + // at scala.reflect.reify.phases.Reshape$$anon$1.transform(Reshape.scala:24) + // at scala.reflect.internal.Trees$class.itransform(Trees.scala:1290) + // + // act(reify { r.List[Any]() match { case Seq(1, _*) => 1 } } ) + + // act(reify { List[OuterP[Int]#InnerP[Byte]]() }) + // + // SI-7243 + // + // test/files/run/reify-each-node-type.scala:85: error: Cannot materialize r.List.apply[r.OuterP[Int]#InnerP[Byte]]() as { ... } because: + // scala.reflect.macros.TypecheckException: value TypeTreeWithDeferredRefCheck is not a member of type parameter U + // act(reify { List[OuterP[Int]#InnerP[Byte]]() }) + // ^ + // one error found + } +} + +object Test { + var idx = 0 + val seen = scala.collection.mutable.Set[String]() + + object N extends s.NN { + def act[T](expr: Expr[T]): Unit = { + idx += 1 + val ts = expr.tree filter (_ => true) map (_.getClass.getName split "[.$]" last) filterNot seen distinct; + println("%2d %60s %s".format(idx, expr.tree.toString.replaceAll("""\s+""", " ").take(60), ts mkString " ")) + seen ++= ts + } + } + def main(args: Array[String]): Unit = N +} -- cgit v1.2.3 From 67c2d6df8141d77c7ac04aa6f97cbc6e53684473 Mon Sep 17 00:00:00 2001 From: Eugene Vigdorchik Date: Wed, 10 Apr 2013 14:34:08 +0400 Subject: SI-6286 IllegalArgumentException handling specialized method. Specialize assigns SpecialOverride info to a specialized method even when there is a further specialization that should be forwarded to. --- .../tools/nsc/transform/SpecializeTypes.scala | 37 ++++++++++------------ test/files/pos/spec-t6286.scala | 10 ++++++ 2 files changed, 27 insertions(+), 20 deletions(-) create mode 100755 test/files/pos/spec-t6286.scala (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index a71920f787..07b1cb4206 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -976,27 +976,24 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { debuglog("specialized overload %s for %s in %s: %s".format(om, overriding.name.decode, pp(env), om.info)) typeEnv(om) = env addConcreteSpecMethod(overriding) - info(om) = ( - if (overriding.isDeferred) { // abstract override - debuglog("abstract override " + overriding.fullName + " with specialized " + om.fullName) - Forward(overriding) - } - else { - // if the override is a normalized member, 'om' gets the - // implementation from its original target, and adds the - // environment of the normalized member (that is, any - // specialized /method/ type parameter bindings) - val impl = info get overriding match { - case Some(NormalizedMember(target)) => - typeEnv(om) = env ++ typeEnv(overriding) - target - case _ => - overriding - } - info(overriding) = Forward(om setPos overriding.pos) - SpecialOverride(impl) + if (overriding.isDeferred) { // abstract override + debuglog("abstract override " + overriding.fullName + " with specialized " + om.fullName) + info(om) = Forward(overriding) + } + else { + // if the override is a normalized member, 'om' gets the + // implementation from its original target, and adds the + // environment of the normalized member (that is, any + // specialized /method/ type parameter bindings) + info get overriding match { + case Some(NormalizedMember(target)) => + typeEnv(om) = env ++ typeEnv(overriding) + info(om) = Forward(target) + case _ => + info(om) = SpecialOverride(overriding) } - ) + info(overriding) = Forward(om setPos overriding.pos) + } newOverload(overriding, om, env) ifDebug(afterSpecialize(assert( overridden.owner.info.decl(om.name) != NoSymbol, diff --git a/test/files/pos/spec-t6286.scala b/test/files/pos/spec-t6286.scala new file mode 100755 index 0000000000..4d87998ec6 --- /dev/null +++ b/test/files/pos/spec-t6286.scala @@ -0,0 +1,10 @@ +trait Foo[@specialized(Int) A] { + def fun[@specialized(Int) B](init: B)(f: (B, A) => B): B +} + +class Bar(values: Array[Int]) extends Foo[Int] { + def fun[@specialized(Int) C](init: C)(f: (C, Int) => C): C = { + val arr = values + f(init, arr(0)) + } +} -- cgit v1.2.3 From e1af9737d0e68a5a14e2837e14b91ad3bd93f0fb Mon Sep 17 00:00:00 2001 From: Eugene Vigdorchik Date: Wed, 10 Apr 2013 16:58:07 +0400 Subject: Remove scaladoc deprecated option. Remove -external-urls that had been previously deprecated in 2.10. --- src/scaladoc/scala/tools/nsc/doc/Settings.scala | 15 ----- .../scala/tools/nsc/doc/model/MemberLookup.scala | 7 --- test/scaladoc/run/SI-191-deprecated.check | 1 - test/scaladoc/run/SI-191-deprecated.scala | 72 ---------------------- 4 files changed, 95 deletions(-) delete mode 100755 test/scaladoc/run/SI-191-deprecated.check delete mode 100755 test/scaladoc/run/SI-191-deprecated.scala (limited to 'src') diff --git a/src/scaladoc/scala/tools/nsc/doc/Settings.scala b/src/scaladoc/scala/tools/nsc/doc/Settings.scala index 90b94e1336..afffca12d1 100644 --- a/src/scaladoc/scala/tools/nsc/doc/Settings.scala +++ b/src/scaladoc/scala/tools/nsc/doc/Settings.scala @@ -199,12 +199,6 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_)) "Expand all type aliases and abstract types into full template pages. (locally this can be done with the @template annotation)" ) - val docExternalUrls = MultiStringSetting ( - "-external-urls", - "externalUrl(s)", - "(deprecated) comma-separated list of package_names=doc_URL for external dependencies, where package names are ':'-separated" - ) - val docGroups = BooleanSetting ( "-groups", "Group similar functions together (based on the @group annotation)" @@ -254,15 +248,6 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_)) if (url.endsWith(index)) url else url + index } - // Deprecated together with 'docExternalUrls' option. - lazy val extUrlPackageMapping: Map[String, String] = (Map.empty[String, String] /: docExternalUrls.value) { - case (map, binding) => - val idx = binding indexOf "=" - val pkgs = binding substring (0, idx) split ":" - val url = appendIndex(binding substring (idx + 1)) - map ++ (pkgs map (_ -> url)) - } - lazy val extUrlMapping: Map[String, String] = docExternalDoc.value flatMap { s => val idx = s.indexOf("#") if (idx > 0) { diff --git a/src/scaladoc/scala/tools/nsc/doc/model/MemberLookup.scala b/src/scaladoc/scala/tools/nsc/doc/model/MemberLookup.scala index 23259a4ae8..339129bdbc 100644 --- a/src/scaladoc/scala/tools/nsc/doc/model/MemberLookup.scala +++ b/src/scaladoc/scala/tools/nsc/doc/model/MemberLookup.scala @@ -49,13 +49,6 @@ trait MemberLookup extends base.MemberLookupBase { settings.extUrlMapping get path map { url => LinkToExternal(name, url + "#" + name) } - } orElse { - // Deprecated option. - settings.extUrlPackageMapping find { - case (pkg, _) => name startsWith pkg - } map { - case (_, url) => LinkToExternal(name, url + "#" + name) - } } } diff --git a/test/scaladoc/run/SI-191-deprecated.check b/test/scaladoc/run/SI-191-deprecated.check deleted file mode 100755 index 3925a0d464..0000000000 --- a/test/scaladoc/run/SI-191-deprecated.check +++ /dev/null @@ -1 +0,0 @@ -Done. \ No newline at end of file diff --git a/test/scaladoc/run/SI-191-deprecated.scala b/test/scaladoc/run/SI-191-deprecated.scala deleted file mode 100755 index 4ed24ff8d1..0000000000 --- a/test/scaladoc/run/SI-191-deprecated.scala +++ /dev/null @@ -1,72 +0,0 @@ -import scala.tools.nsc.doc.model._ -import scala.tools.nsc.doc.base._ -import scala.tools.nsc.doc.base.comment._ -import scala.tools.partest.ScaladocModelTest -import java.net.{URI, URL} -import java.io.File - -object Test extends ScaladocModelTest { - - override def code = - """ - /** See: - * - [[scala.collection.Map]] Simple linking - * - [[scala.collection.immutable.::]] Linking with symbolic name - * - [[scala.Int]].toLong Linking to a class - * - [[scala.Predef]] Linking to an object - * - [[scala.Int.toLong]] Linking to a method - * - [[scala]] Linking to a package - * - [[scala.AbstractMethodError]] Linking to a member in the package object - * - [[scala.Predef.String]] Linking to a member in an object - * - * Don't look at: - * - [[scala.NoLink]] Not linking :) - */ - object Test { - def foo(param: Any) {} - def barr(l: scala.collection.immutable.List[Any]) {} - def bar(l: List[String]) {} // TODO: Should be able to link to type aliases - def baz(d: java.util.Date) {} // Should not be resolved - } - """ - - def scalaURL = "http://bog.us" - - override def scaladocSettings = "-no-link-warnings -external-urls scala=" + scalaURL - - def testModel(rootPackage: Package) { - import access._ - val test = rootPackage._object("Test") - - def check(memberDef: Def, expected: Int) { - val externals = memberDef.valueParams(0)(0).resultType.refEntity collect { - case (_, (LinkToExternal(name, url), _)) => assert(url.contains(scalaURL)); name - } - assert(externals.size == expected) - } - - check(test._method("foo"), 1) - check(test._method("bar"), 0) - check(test._method("barr"), 2) - check(test._method("baz"), 0) - - val expectedUrls = collection.mutable.Set[String]( - "scala.collection.Map", - "scala.collection.immutable.::", - "scala.Int", - "scala.Predef$", - "scala.Int@toLong:Long", - "scala.package", - "scala.package@AbstractMethodError=AbstractMethodError", - "scala.Predef$@String=String" - ).map(scalaURL + "/index.html#" + _) - - def isExpectedExternalLink(l: EntityLink) = l.link match { - case LinkToExternal(name, url) => assert(expectedUrls contains url, url); true - case _ => false - } - - assert(countLinks(test.comment.get, isExpectedExternalLink) == 8, - countLinks(test.comment.get, isExpectedExternalLink) + " == 8") - } -} -- cgit v1.2.3 From 23dd325bdf9714bc4f2f804d30104d2d2a3ae595 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 12 Apr 2013 08:37:51 +0200 Subject: SI-7360 Don't let a follow-up TypeError obscure the original error. When supplementing a fatal error message with context (current compilation unit, tree, phase, etcetera), we must be cautious to not to trigger another error which will obscure the original one. Currently, `supplementErrorMessage` does its working a try catch that only catches `Exception`. But this fails to catch CyclicReferenceError (<: TypeError <: Throwable), as was seen in a recent mailing list post by Greg Meredith. This commit extends the catch clause. --- src/compiler/scala/tools/nsc/Global.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 7a67ac6246..aea3e0d930 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -1180,7 +1180,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) ("\n" + info1) :: info2 :: info3 mkString "\n\n" } - catch { case x: Exception => errorMessage } + catch { case _: Exception | _: TypeError => errorMessage } /** The id of the currently active run */ -- cgit v1.2.3 From 66904556ef34dc81cbb7c09257b013b3ddb76f78 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 13 Apr 2013 12:08:55 +0200 Subject: SI-7335 Remove special case for import of Predef._ in Predef.scala Perhaps this once was problematic, but in our modern age we can bootstrap perfectly well with this import. --- src/reflect/scala/reflect/internal/TreeInfo.scala | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala index 0ddcc9fd7b..3296353b6b 100644 --- a/src/reflect/scala/reflect/internal/TreeInfo.scala +++ b/src/reflect/scala/reflect/internal/TreeInfo.scala @@ -663,19 +663,9 @@ abstract class TreeInfo { unapply(dissectApplied(tree)) } - /** Does list of trees start with a definition of - * a class of module with given name (ignoring imports) - */ - def firstDefinesClassOrObject(trees: List[Tree], name: Name): Boolean = trees match { - case Import(_, _) :: xs => firstDefinesClassOrObject(xs, name) - case Annotated(_, tree1) :: _ => firstDefinesClassOrObject(List(tree1), name) - case ModuleDef(_, `name`, _) :: _ => true - case ClassDef(_, `name`, _, _) :: _ => true - case _ => false - } - /** Is this file the body of a compilation unit which should not - * have Predef imported? + * have Predef imported? This is the case iff the first import in the + * unit explicitly refers to Predef. */ def noPredefImportForUnit(body: Tree) = { // Top-level definition whose leading imports include Predef. @@ -684,13 +674,7 @@ abstract class TreeInfo { case Import(expr, _) => isReferenceToPredef(expr) case _ => false } - // Compilation unit is class or object 'name' in package 'scala' - def isUnitInScala(tree: Tree, name: Name) = tree match { - case PackageDef(Ident(nme.scala_), defs) => firstDefinesClassOrObject(defs, name) - case _ => false - } - - isUnitInScala(body, nme.Predef) || isLeadingPredefImport(body) + isLeadingPredefImport(body) } def isAbsTypeDef(tree: Tree) = tree match { -- cgit v1.2.3 From ef04619e3032dd513bf2e219a03ecf53e8dc8ce6 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 1 Apr 2013 11:37:57 +0200 Subject: SI-7319 Clear error buffer during Typer reset. Contexts share error/warning buffers with their children, and this also applies ot the shared `startContext`. That context flushes the buffers in `startContext` in `resetContexts`. It also removes `typerReportAnyContextErrors`, which appears to be an elaborate no-op. It is only ever passed a context `c` which is a direct child of `this.context`. So taking a buffered error out of `c` and reissuing it into `this.context` merely re-inserts into into the same error buffer. Consrast this with `silent`, which uses a child context with a fresh error buffer. SI-7319 Flush error buffer in typerReportAnyContextErrors. After this change, we no longer rely on the backstop in resetContexts introduced in the previous commit. --- .../scala/tools/nsc/typechecker/Contexts.scala | 2 ++ .../scala/tools/nsc/typechecker/Typers.scala | 30 +++++++---------- test/files/run/t7319.check | 38 ++++++++++++++++++++++ test/files/run/t7319.scala | 13 ++++++++ 4 files changed, 65 insertions(+), 18 deletions(-) create mode 100644 test/files/run/t7319.check create mode 100644 test/files/run/t7319.scala (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index f2a2ef4d61..6c2945cad3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -84,6 +84,8 @@ trait Contexts { self: Analyzer => case Import(qual, _) => qual.tpe = singleType(qual.symbol.owner.thisType, qual.symbol) case _ => } + sc.flushAndReturnBuffer() + sc.flushAndReturnWarningsBuffer() sc = sc.outer } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index d1d6feae97..d3e9192066 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -507,10 +507,7 @@ trait Typers extends Modes with Adaptations with Tags { @inline final def typerReportAnyContextErrors[T](c: Context)(f: Typer => T): T = { - val res = f(newTyper(c)) - if (c.hasErrors) - context.issue(c.errBuffer.head) - res + f(newTyper(c)) } @inline @@ -1747,9 +1744,7 @@ trait Typers extends Modes with Adaptations with Tags { assert(clazz != NoSymbol, cdef) reenterTypeParams(cdef.tparams) val tparams1 = cdef.tparams mapConserve (typedTypeDef) - val impl1 = typerReportAnyContextErrors(context.make(cdef.impl, clazz, newScope)) { - _.typedTemplate(cdef.impl, parentTypes(cdef.impl)) - } + val impl1 = newTyper(context.make(cdef.impl, clazz, newScope)).typedTemplate(cdef.impl, parentTypes(cdef.impl)) val impl2 = finishMethodSynthesis(impl1, clazz, context) if (clazz.isTrait && clazz.info.parents.nonEmpty && clazz.info.firstParent.typeSymbol == AnyClass) checkEphemeral(clazz, impl2.body) @@ -1790,17 +1785,16 @@ trait Typers extends Modes with Adaptations with Tags { || !linkedClass.isSerializable || clazz.isSerializable ) - val impl1 = typerReportAnyContextErrors(context.make(mdef.impl, clazz, newScope)) { - _.typedTemplate(mdef.impl, { - parentTypes(mdef.impl) ++ ( - if (noSerializable) Nil - else { - clazz.makeSerializable() - List(TypeTree(SerializableClass.tpe) setPos clazz.pos.focus) - } - ) - }) - } + val impl1 = newTyper(context.make(mdef.impl, clazz, newScope)).typedTemplate(mdef.impl, { + parentTypes(mdef.impl) ++ ( + if (noSerializable) Nil + else { + clazz.makeSerializable() + List(TypeTree(SerializableClass.tpe) setPos clazz.pos.focus) + } + ) + }) + val impl2 = finishMethodSynthesis(impl1, clazz, context) // SI-5954. On second compile of a companion class contained in a package object we end up diff --git a/test/files/run/t7319.check b/test/files/run/t7319.check new file mode 100644 index 0000000000..966736915e --- /dev/null +++ b/test/files/run/t7319.check @@ -0,0 +1,38 @@ +Type in expressions to have them evaluated. +Type :help for more information. + +scala> + +scala> class M[A] +defined class M + +scala> implicit def ma0[A](a: A): M[A] = null +warning: there were 1 feature warning(s); re-run with -feature for details +ma0: [A](a: A)M[A] + +scala> implicit def ma1[A](a: A): M[A] = null +warning: there were 1 feature warning(s); re-run with -feature for details +ma1: [A](a: A)M[A] + +scala> def convert[F[X <: F[X]]](builder: F[_ <: F[_]]) = 0 +warning: there were 1 feature warning(s); re-run with -feature for details +convert: [F[X <: F[X]]](builder: F[_ <: F[_]])Int + +scala> convert(Some[Int](0)) +:12: error: no type parameters for method convert: (builder: F[_ <: F[_]])Int exist so that it can be applied to arguments (Some[Int]) + --- because --- +argument expression's type is not compatible with formal parameter type; + found : Some[Int] + required: ?F forSome { type _$1 <: ?F forSome { type _$2 } } + convert(Some[Int](0)) + ^ +:12: error: type mismatch; + found : Some[Int] + required: F[_ <: F[_]] + convert(Some[Int](0)) + ^ + +scala> 0 +res1: Int = 0 + +scala> diff --git a/test/files/run/t7319.scala b/test/files/run/t7319.scala new file mode 100644 index 0000000000..23ffeb977d --- /dev/null +++ b/test/files/run/t7319.scala @@ -0,0 +1,13 @@ +import scala.tools.partest.ReplTest + +object Test extends ReplTest { + // so we can provide the ambiguities, rather than relying in Predef implicits + override def extraSettings = "-Yno-predef" + override def code = """ +class M[A] +implicit def ma0[A](a: A): M[A] = null +implicit def ma1[A](a: A): M[A] = null +def convert[F[X <: F[X]]](builder: F[_ <: F[_]]) = 0 +convert(Some[Int](0)) +0""" // before the fix, this line, and all that followed, re-issued the implicit ambiguity error. +} -- cgit v1.2.3 From 15e9ef8f083e0c0dc75bf51a0784f56df2e2bea8 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 17 Apr 2013 09:19:21 +0200 Subject: SI-7377 Fix retypechecking of patterns on case companion alias Some ancient code in Typers switches from PATTERNmode to EXPRmode when encountering `stableF(...)`. It just typechecks `stableF` and discards the arguments. To the best of Martin's recollection, this has something to do with the need to typecheck patterns rather late in the compiler, after `a.b` had been translated to `a.b()` in `Uncurry`. I'm not able to motivate this with tests using `-Xoldpatmat`; was there ever an even older pattern matcher that ran *after* uncurry? What changed in 2.10.1 to expose this wrinkle? dfbaaa17 fixed `TypeTree.copyAttrs` to copy the original tree. During the descent of `ResetAttrs`, sub-trees are duplicated before begin further transformed. Duplicating the `Match` in 2.10.0 would forget that the original tree of: pat = (a: Int)Foo(_) `----------` `- TypeTree((a: Int)Foo), with original Select(..., "FooAlias") The retypechecking would operate on the `MethodType`, rather than the `Select`, which was not considered a stable application. For 2.10.x, I've just tightened up the condition to only hit this if `args` is empty. I'm almost certain that the code can be removed altogether, and I'll do that when this is merged to master. --- src/compiler/scala/tools/nsc/typechecker/Typers.scala | 7 ++++++- test/files/pos/t7377/Client_2.scala | 11 +++++++++++ test/files/pos/t7377/Macro_1.scala | 7 +++++++ test/files/pos/t7377b.flags | 1 + test/files/pos/t7377b.scala | 13 +++++++++++++ 5 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 test/files/pos/t7377/Client_2.scala create mode 100644 test/files/pos/t7377/Macro_1.scala create mode 100644 test/files/pos/t7377b.flags create mode 100644 test/files/pos/t7377b.scala (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index d1d6feae97..33f60d6676 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -4532,8 +4532,13 @@ trait Typers extends Modes with Adaptations with Tags { def normalTypedApply(tree: Tree, fun: Tree, args: List[Tree]) = { val stableApplication = (fun.symbol ne null) && fun.symbol.isMethod && fun.symbol.isStable - if (stableApplication && isPatternMode) { + if (args.isEmpty && stableApplication && isPatternMode) { // treat stable function applications f() as expressions. + // + // [JZ] According to Martin, this is related to the old pattern matcher, which + // needs to typecheck after a the translation of `x.f` to `x.f()` in a prior + // compilation phase. As part of SI-7377, this has been tightened with `args.isEmpty`, + // but we should remove it altogether in Scala 2.11. typed1(tree, mode & ~PATTERNmode | EXPRmode, pt) } else { val funpt = if (isPatternMode) pt else WildcardType diff --git a/test/files/pos/t7377/Client_2.scala b/test/files/pos/t7377/Client_2.scala new file mode 100644 index 0000000000..5728956cca --- /dev/null +++ b/test/files/pos/t7377/Client_2.scala @@ -0,0 +1,11 @@ +object Test { + M.noop(List(1) match { case Nil => 0; case (x::xs) => x }) + + case class Foo(a: Int) + val FooAlias: Foo.type = Foo + M.noop(Foo(0) match { case FooAlias(_) => 0 }) + + case class Bar() + val BarAlias: Bar.type = Bar + M.noop(Bar() match { case BarAlias() => 0 }) +} diff --git a/test/files/pos/t7377/Macro_1.scala b/test/files/pos/t7377/Macro_1.scala new file mode 100644 index 0000000000..a0ec1d84af --- /dev/null +++ b/test/files/pos/t7377/Macro_1.scala @@ -0,0 +1,7 @@ +import language.experimental._ +import reflect.macros.Context + +object M { + def noopImpl[A](c: Context)(expr: c.Expr[A]): c.Expr[A] = c.Expr(c.typeCheck(c.resetLocalAttrs(expr.tree))) + def noop[A](expr: A): A = macro noopImpl[A] +} diff --git a/test/files/pos/t7377b.flags b/test/files/pos/t7377b.flags new file mode 100644 index 0000000000..cb8324a345 --- /dev/null +++ b/test/files/pos/t7377b.flags @@ -0,0 +1 @@ +-Xoldpatmat \ No newline at end of file diff --git a/test/files/pos/t7377b.scala b/test/files/pos/t7377b.scala new file mode 100644 index 0000000000..aeee800d57 --- /dev/null +++ b/test/files/pos/t7377b.scala @@ -0,0 +1,13 @@ +object Test { + List(1) match { case Nil => 0; case (x::xs) => x } + + case class Foo(a: Int) + val FooAlias: Foo.type = Foo + Foo(0) match { case FooAlias(_) => 0 } + Foo(0) match { case Foo(_) => 0 } + + case class Bar() + val BarAlias: Bar.type = Bar + Bar() match { case BarAlias() => 0 } + Bar() match { case Bar() => 0 } +} -- cgit v1.2.3 From 351d5ec22688a48227b76f417a0dd520934d98d7 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Wed, 17 Apr 2013 14:01:50 -0700 Subject: Absolute path in error message. As soon as you have a directory called "language" lying around, you will appreciate why the advice given regarding SIP-18 should be "import scala.language..." not "import language..." --- .../scala/tools/nsc/typechecker/Typers.scala | 21 ++++++++++++--------- test/files/neg/macro-without-xmacros-a.check | 6 +++--- test/files/neg/macro-without-xmacros-b.check | 6 +++--- test/files/neg/t6040.check | 2 +- test/files/neg/t6952.check | 4 ++-- 5 files changed, 21 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index d1d6feae97..51458de280 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -780,16 +780,19 @@ trait Typers extends Modes with Adaptations with Tags { if (!OK) { val Some(AnnotationInfo(_, List(Literal(Constant(featureDesc: String)), Literal(Constant(required: Boolean))), _)) = featureTrait getAnnotation LanguageFeatureAnnot - val req = if (required) "needs to" else "should" - var raw = featureDesc + " " + req + " be enabled\n" + - "by making the implicit value language." + featureName + " visible." - if (!(currentRun.reportedFeature contains featureTrait)) - raw += "\nThis can be achieved by adding the import clause 'import scala.language." + featureName + "'\n" + - "or by setting the compiler option -language:" + featureName + ".\n" + - "See the Scala docs for value scala.language." + featureName + " for a discussion\n" + - "why the feature " + req + " be explicitly enabled." + val req = if (required) "needs to" else "should" + val fqname = "scala.language." + featureName + val explain = ( + if (currentRun.reportedFeature contains featureTrait) "" else + s"""| + |This can be achieved by adding the import clause 'import $fqname' + |or by setting the compiler option -language:$featureName. + |See the Scala docs for value $fqname for a discussion + |why the feature $req be explicitly enabled.""".stripMargin + ) currentRun.reportedFeature += featureTrait - val msg = raw replace ("#", construct) + + val msg = s"$featureDesc $req be enabled\nby making the implicit value $fqname visible.$explain" replace ("#", construct) if (required) unit.error(pos, msg) else currentRun.featureWarnings.warn(pos, msg) } diff --git a/test/files/neg/macro-without-xmacros-a.check b/test/files/neg/macro-without-xmacros-a.check index ae6c6c695a..ec194be3a9 100644 --- a/test/files/neg/macro-without-xmacros-a.check +++ b/test/files/neg/macro-without-xmacros-a.check @@ -1,5 +1,5 @@ Macros_2.scala:5: error: macro definition needs to be enabled -by making the implicit value language.experimental.macros visible. +by making the implicit value scala.language.experimental.macros visible. This can be achieved by adding the import clause 'import scala.language.experimental.macros' or by setting the compiler option -language:experimental.macros. See the Scala docs for value scala.language.experimental.macros for a discussion @@ -7,11 +7,11 @@ why the feature needs to be explicitly enabled. def foo(x: Int): Int = macro foo_impl ^ Macros_2.scala:7: error: macro definition needs to be enabled -by making the implicit value language.experimental.macros visible. +by making the implicit value scala.language.experimental.macros visible. def bar(x: Int): Int = macro bar_impl ^ Macros_2.scala:11: error: macro definition needs to be enabled -by making the implicit value language.experimental.macros visible. +by making the implicit value scala.language.experimental.macros visible. def quux(x: Int): Int = macro quux_impl ^ three errors found diff --git a/test/files/neg/macro-without-xmacros-b.check b/test/files/neg/macro-without-xmacros-b.check index c3cadcf36a..c97850f0a9 100644 --- a/test/files/neg/macro-without-xmacros-b.check +++ b/test/files/neg/macro-without-xmacros-b.check @@ -1,5 +1,5 @@ Macros_2.scala:3: error: macro definition needs to be enabled -by making the implicit value language.experimental.macros visible. +by making the implicit value scala.language.experimental.macros visible. This can be achieved by adding the import clause 'import scala.language.experimental.macros' or by setting the compiler option -language:experimental.macros. See the Scala docs for value scala.language.experimental.macros for a discussion @@ -7,11 +7,11 @@ why the feature needs to be explicitly enabled. def foo(x: Int): Int = macro Impls.foo_impl ^ Macros_2.scala:5: error: macro definition needs to be enabled -by making the implicit value language.experimental.macros visible. +by making the implicit value scala.language.experimental.macros visible. def bar(x: Int): Int = macro Impls.bar_impl ^ Macros_2.scala:9: error: macro definition needs to be enabled -by making the implicit value language.experimental.macros visible. +by making the implicit value scala.language.experimental.macros visible. def quux(x: Int): Int = macro Impls.quux_impl ^ three errors found diff --git a/test/files/neg/t6040.check b/test/files/neg/t6040.check index f91df0c46d..16c90ede7e 100644 --- a/test/files/neg/t6040.check +++ b/test/files/neg/t6040.check @@ -1,5 +1,5 @@ t6040.scala:1: error: extension of type scala.Dynamic needs to be enabled -by making the implicit value language.dynamics visible. +by making the implicit value scala.language.dynamics visible. This can be achieved by adding the import clause 'import scala.language.dynamics' or by setting the compiler option -language:dynamics. See the Scala docs for value scala.language.dynamics for a discussion diff --git a/test/files/neg/t6952.check b/test/files/neg/t6952.check index f1e1881404..1a591d02c6 100644 --- a/test/files/neg/t6952.check +++ b/test/files/neg/t6952.check @@ -1,5 +1,5 @@ t6952.scala:2: error: extension of type scala.Dynamic needs to be enabled -by making the implicit value language.dynamics visible. +by making the implicit value scala.language.dynamics visible. This can be achieved by adding the import clause 'import scala.language.dynamics' or by setting the compiler option -language:dynamics. See the Scala docs for value scala.language.dynamics for a discussion @@ -7,7 +7,7 @@ why the feature needs to be explicitly enabled. trait B extends Dynamic ^ t6952.scala:3: error: extension of type scala.Dynamic needs to be enabled -by making the implicit value language.dynamics visible. +by making the implicit value scala.language.dynamics visible. trait C extends A with Dynamic ^ two errors found -- cgit v1.2.3 From 3e27fec3cf44bcc523fea6bac39ac9b99b438393 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 18 Apr 2013 23:38:15 +0200 Subject: SI-7388 Be more robust against cycles in error symbol creation. `Symbol#toString` was triggering `CyclicReferenceError` (specifically, `accurateKindString` which calls `owner.primaryConstructor`.) The `toString` output is used when creating an error symbol to assign to the tree after an error (in this case, a non-existent access qualifier.) This commit catches the error, and falls back to just using the symbol's name. --- src/compiler/scala/tools/nsc/typechecker/Infer.scala | 6 +++++- test/files/neg/t7388.check | 4 ++++ test/files/neg/t7388.scala | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 test/files/neg/t7388.check create mode 100644 test/files/neg/t7388.scala (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 7161043dcf..7dd182e3ee 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -286,7 +286,11 @@ trait Infer extends Checkable { // println("set error: "+tree); // throw new Error() // } - def name = newTermName("") + def name = { + val sym = tree.symbol + val nameStr = try sym.toString catch { case _: CyclicReference => sym.nameString } + newTermName(s"") + } def errorClass = if (context.reportErrors) context.owner.newErrorClass(name.toTypeName) else stdErrorClass def errorValue = if (context.reportErrors) context.owner.newErrorValue(name) else stdErrorValue def errorSym = if (tree.isType) errorClass else errorValue diff --git a/test/files/neg/t7388.check b/test/files/neg/t7388.check new file mode 100644 index 0000000000..0a29e04896 --- /dev/null +++ b/test/files/neg/t7388.check @@ -0,0 +1,4 @@ +t7388.scala:1: error: doesnotexist is not an enclosing class +class Test private[doesnotexist]() + ^ +one error found diff --git a/test/files/neg/t7388.scala b/test/files/neg/t7388.scala new file mode 100644 index 0000000000..9ce9ea11b3 --- /dev/null +++ b/test/files/neg/t7388.scala @@ -0,0 +1 @@ +class Test private[doesnotexist]() -- cgit v1.2.3 From 01edd0436c19314ea581f86362b1d547a4b7fdb8 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Fri, 29 Mar 2013 22:45:08 -0700 Subject: SI-7314 Partest locates tools.jar and javac This commit lets partest locate tools.jar the way REPL does, with the addition that java.home.parent is also tried. The partest script will use JAVAC_CMD if set, or else JAVA_HOME, and will try the sibling of JAVACMD if set (on the theory that if you specify java, you are avoiding the path lookup and javac may also be in that special place), or else query the path for javac. The use cases are: no env vars, look around java.home; JDK or JAVA_HOME is set; JAVACMD is set; and finally tools.jar can live in jre/lib/ext and the fallback deep search will find it. These cases have been tried on cygwin with Java installed under s"Program${space}Files", which is usually the most brittle environment. That means tested with bash. The windows partest.bat has not been upgraded or side-graded. --- .../scala/tools/partest/nest/PathSettings.scala | 30 ++++++++++++++++++++++ .../scala/tools/partest/nest/RunnerManager.scala | 2 ++ test/partest | 25 +++++++++++++++--- 3 files changed, 54 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/partest/scala/tools/partest/nest/PathSettings.scala b/src/partest/scala/tools/partest/nest/PathSettings.scala index 7c005b4f61..b1f868c9d2 100644 --- a/src/partest/scala/tools/partest/nest/PathSettings.scala +++ b/src/partest/scala/tools/partest/nest/PathSettings.scala @@ -8,6 +8,7 @@ package nest import scala.tools.nsc.Properties.{ setProp, propOrEmpty, propOrNone, propOrElse } import scala.tools.nsc.util.ClassPath import scala.tools.nsc.io +import scala.util.Properties.{ envOrElse, envOrNone, javaHome, jdkHome } import io.{ Path, File, Directory } object PathSettings { @@ -74,6 +75,35 @@ object PathSettings { lazy val diffUtils: File = findJar(buildPackLibDir.files, "diffutils") getOrElse sys.error(s"No diffutils.jar found in '$buildPackLibDir'.") + + /** The platform-specific support jar. + * Usually this is tools.jar in the jdk/lib directory of the platform distribution. + * The file location is determined by probing the lib directory under JDK_HOME or JAVA_HOME, + * if one of those environment variables is set, then the lib directory under java.home, + * and finally the lib directory under the parent of java.home. Or, as a last resort, + * search deeply under those locations (except for the parent of java.home, on the notion + * that if this is not a canonical installation, then that search would have litte + * chance of succeeding). + */ + lazy val platformTools: Option[File] = { + val jarName = "tools.jar" + def jarPath(path: Path) = (path / "lib" / jarName).toFile + def jarAt(path: Path) = { + val f = jarPath(path) + if (f.isFile) Some(f) else None + } + val jdkDir = { + val d = Directory(jdkHome) + if (d.isDirectory) Some(d) else None + } + def deeply(dir: Directory) = dir.deepFiles find (_.name == jarName) + + val home = envOrNone("JDK_HOME") orElse envOrNone("JAVA_HOME") map (p => Path(p)) + val install = Some(Path(javaHome)) + + (home flatMap jarAt) orElse (install flatMap jarAt) orElse (install map (_.parent) flatMap jarAt) orElse + (jdkDir flatMap deeply) + } } class PathSettings() { diff --git a/src/partest/scala/tools/partest/nest/RunnerManager.scala b/src/partest/scala/tools/partest/nest/RunnerManager.scala index 1c689714c7..fa2b5ea74b 100644 --- a/src/partest/scala/tools/partest/nest/RunnerManager.scala +++ b/src/partest/scala/tools/partest/nest/RunnerManager.scala @@ -74,8 +74,10 @@ object Output { class RunnerManager(kind: String, val fileManager: FileManager, params: TestRunParams) { import fileManager._ + fileManager.CLASSPATH += File.pathSeparator + PathSettings.scalaCheck fileManager.CLASSPATH += File.pathSeparator + PathSettings.diffUtils // needed to put diffutils on test/partest's classpath + PathSettings.platformTools foreach (fileManager.CLASSPATH += File.pathSeparator + _) def runTest(testFile: File): TestState = { val runner = new Runner(testFile, fileManager) { diff --git a/test/partest b/test/partest index 8243316cca..e3270f8eaa 100755 --- a/test/partest +++ b/test/partest @@ -75,6 +75,22 @@ if [ -z "$EXT_CLASSPATH" ] ; then fi fi +# Locate a javac command +# Try: JAVA_HOME, sibling to specific JAVACMD, or PATH +# Don't fail if there is no javac, since not all tests require it. +if [ -z "$JAVAC_CMD" ] ; then + if [ -n "${JAVA_HOME}" ] && [ -f "${JAVA_HOME}/bin/javac" ] ; then + JAVAC_CMD="${JAVA_HOME}/bin/javac" + fi + if [ -z "$JAVAC_CMD" ] && [ -n "$JAVACMD" ] ; then + JDIR=`dirname "${JAVACMD}"` + JAVAC_CMD="${JDIR}/javac" + fi + if [ -z "$JAVAC_CMD" ] ; then + JAVAC_CMD=`type -p javac` + fi +fi + if $cygwin; then if [ "$OS" = "Windows_NT" ] && cygpath -m .>/dev/null 2>/dev/null ; then format=mixed @@ -87,6 +103,9 @@ if $cygwin; then if [ -n "${JAVACMD}" ] ; then JAVACMD=`cygpath --$format "$JAVACMD"` fi + if [ -n "${JAVAC_CMD}" ] ; then + JAVAC_CMD=`cygpath --$format "$JAVAC_CMD"` + fi SCALA_HOME=`cygpath --$format "$SCALA_HOME"` EXT_CLASSPATH=`cygpath --path --$format "$EXT_CLASSPATH"` fi @@ -97,8 +116,8 @@ fi JAVA_OPTS="-Xmx1024M -Xms64M -XX:MaxPermSize=128M $JAVA_OPTS" # the ant task doesn't supply any options by default, -# so don't to that here either -- note that you may want to pass -optimise -# to mimic what happens during nightlies +# so don't do that here either -- note that you may want to pass -optimise +# to mimic what happens during nightlies. # [ -n "$SCALAC_OPTS" ] || SCALAC_OPTS="-deprecation" partestDebugStr="" @@ -114,5 +133,5 @@ fi -Dpartest.javacmd="${JAVACMD}" \ -Dpartest.java_opts="${JAVA_OPTS}" \ -Dpartest.scalac_opts="${SCALAC_OPTS}" \ - -Dpartest.javac_cmd="${JAVA_HOME}/bin/javac" \ + -Dpartest.javac_cmd="${JAVAC_CMD}" \ scala.tools.partest.nest.NestRunner "$@" -- cgit v1.2.3 From 962f88e8cbcf06f9932ab925ff4e5bb3b284a153 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 20 Apr 2013 11:16:46 +0200 Subject: SI-7377 Remove special treatment of `stableFun()` in patterns. As promised in 15e9ef8f08. --- .../scala/tools/nsc/typechecker/Typers.scala | 102 ++++++++++----------- 1 file changed, 46 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 324f83e07f..bf1cc06666 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -4432,68 +4432,58 @@ trait Typers extends Adaptations with Tags { def normalTypedApply(tree: Tree, fun: Tree, args: List[Tree]) = { val stableApplication = (fun.symbol ne null) && fun.symbol.isMethod && fun.symbol.isStable - if (args.isEmpty && stableApplication && isPatternMode) { - // treat stable function applications f() as expressions. - // - // [JZ] According to Martin, this is related to the old pattern matcher, which - // needs to typecheck after a the translation of `x.f` to `x.f()` in a prior - // compilation phase. As part of SI-7377, this has been tightened with `args.isEmpty`, - // but we should remove it altogether in Scala 2.11. - typed1(tree, mode &~ PATTERNmode | EXPRmode, pt) - } else { - val funpt = if (isPatternMode) pt else WildcardType - val appStart = if (Statistics.canEnable) Statistics.startTimer(failedApplyNanos) else null - val opeqStart = if (Statistics.canEnable) Statistics.startTimer(failedOpEqNanos) else null - - def onError(reportError: => Tree): Tree = { - fun match { - case Select(qual, name) - if !isPatternMode && nme.isOpAssignmentName(newTermName(name.decode)) => - val qual1 = typedQualifier(qual) - if (treeInfo.isVariableOrGetter(qual1)) { - if (Statistics.canEnable) Statistics.stopTimer(failedOpEqNanos, opeqStart) - convertToAssignment(fun, qual1, name, args) - } else { - if (Statistics.canEnable) Statistics.stopTimer(failedApplyNanos, appStart) - reportError - } - case _ => + val funpt = if (isPatternMode) pt else WildcardType + val appStart = if (Statistics.canEnable) Statistics.startTimer(failedApplyNanos) else null + val opeqStart = if (Statistics.canEnable) Statistics.startTimer(failedOpEqNanos) else null + + def onError(reportError: => Tree): Tree = { + fun match { + case Select(qual, name) + if !isPatternMode && nme.isOpAssignmentName(newTermName(name.decode)) => + val qual1 = typedQualifier(qual) + if (treeInfo.isVariableOrGetter(qual1)) { + if (Statistics.canEnable) Statistics.stopTimer(failedOpEqNanos, opeqStart) + convertToAssignment(fun, qual1, name, args) + } else { if (Statistics.canEnable) Statistics.stopTimer(failedApplyNanos, appStart) - reportError - } - } - val silentResult = silent( - op = _.typed(fun, mode.forFunMode, funpt), - reportAmbiguousErrors = !mode.inExprMode && context.ambiguousErrors, - newtree = if (mode.inExprMode) tree else context.tree - ) - silentResult match { - case SilentResultValue(fun1) => - val fun2 = if (stableApplication) stabilizeFun(fun1, mode, pt) else fun1 - if (Statistics.canEnable) Statistics.incCounter(typedApplyCount) - val noSecondTry = ( - isPastTyper - || (fun2.symbol ne null) && fun2.symbol.isConstructor - || (fun2.tpe match { case mt: MethodType => mt.isImplicit case _ => false }) - ) - val isFirstTry = !noSecondTry && ( - fun2 match { - case Select(_, _) => mode inExprModeButNot SNDTRYmode - case _ => false + reportError } - ) - if (isFirstTry) - tryTypedApply(fun2, args) - else - doTypedApply(tree, fun2, args, mode, pt) + case _ => + if (Statistics.canEnable) Statistics.stopTimer(failedApplyNanos, appStart) + reportError + } + } + val silentResult = silent( + op = _.typed(fun, mode.forFunMode, funpt), + reportAmbiguousErrors = !mode.inExprMode && context.ambiguousErrors, + newtree = if (mode.inExprMode) tree else context.tree + ) + silentResult match { + case SilentResultValue(fun1) => + val fun2 = if (stableApplication) stabilizeFun(fun1, mode, pt) else fun1 + if (Statistics.canEnable) Statistics.incCounter(typedApplyCount) + val noSecondTry = ( + isPastTyper + || (fun2.symbol ne null) && fun2.symbol.isConstructor + || (fun2.tpe match { case mt: MethodType => mt.isImplicit case _ => false }) + ) + val isFirstTry = !noSecondTry && ( + fun2 match { + case Select(_, _) => mode inExprModeButNot SNDTRYmode + case _ => false + } + ) + if (isFirstTry) + tryTypedApply(fun2, args) + else + doTypedApply(tree, fun2, args, mode, pt) - case SilentTypeError(err) => - onError({issue(err); setError(tree)}) - } + case SilentTypeError(err) => + onError({issue(err); setError(tree)}) } } - // convert new Array[T](len) to evidence[ClassTag[T]].newArray(len) + // convert new Array[T](len) to evidence[ClassTag[T]].newArray(len) // convert new Array^N[T](len) for N > 1 to evidence[ClassTag[Array[...Array[T]...]]].newArray(len) // where Array HK gets applied (N-1) times object ArrayInstantiation { -- cgit v1.2.3 From 578ef1f933c6d067b8e3cfe3343ccc9b9b033af0 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 20 Apr 2013 11:21:43 +0200 Subject: SI-7319 Remove unused method. Detritus spottend after merging SI-7319 from 2.10.x to master. --- src/compiler/scala/tools/nsc/typechecker/Typers.scala | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index bf1cc06666..9536df888e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -489,11 +489,6 @@ trait Typers extends Adaptations with Tags { res } - @inline - final def typerReportAnyContextErrors[T](c: Context)(f: Typer => T): T = { - f(newTyper(c)) - } - @inline final def withSavedContext[T](c: Context)(f: => T) = { val savedErrors = c.flushAndReturnBuffer() -- cgit v1.2.3