diff options
43 files changed, 510 insertions, 95 deletions
diff --git a/src/compiler/scala/reflect/macros/compiler/Errors.scala b/src/compiler/scala/reflect/macros/compiler/Errors.scala index 9b56e417e2..45bb87fc47 100644 --- a/src/compiler/scala/reflect/macros/compiler/Errors.scala +++ b/src/compiler/scala/reflect/macros/compiler/Errors.scala @@ -44,14 +44,18 @@ trait Errors extends Traces { message + suffix } - private def abbreviateCoreAliases(s: String): String = List("WeakTypeTag", "Expr").foldLeft(s)((res, x) => res.replace("c.universe." + x, "c." + x)) + private def abbreviateCoreAliases(s: String): String = { + val coreAliases = List("WeakTypeTag", "Expr", "Tree") + coreAliases.foldLeft(s)((res, x) => res.replace("c.universe." + x, "c." + x)) + } - private def showMeth(pss: List[List[Symbol]], restpe: Type, abbreviate: Boolean) = { - var argsPart = (pss map (ps => ps map (_.defString) mkString ("(", ", ", ")"))).mkString - if (abbreviate) argsPart = abbreviateCoreAliases(argsPart) - var retPart = restpe.toString + private def showMeth(pss: List[List[Symbol]], restpe: Type, abbreviate: Boolean, untype: Boolean) = { + def preprocess(tpe: Type) = if (untype) untypeMetalevel(tpe) else tpe + var pssPart = (pss map (ps => ps map (p => p.defStringSeenAs(preprocess(p.info))) mkString ("(", ", ", ")"))).mkString + if (abbreviate) pssPart = abbreviateCoreAliases(pssPart) + var retPart = preprocess(restpe).toString if (abbreviate || macroDdef.tpt.tpe == null) retPart = abbreviateCoreAliases(retPart) - argsPart + ": " + retPart + pssPart + ": " + retPart } // not exactly an error generator, but very related @@ -86,8 +90,9 @@ trait Errors extends Traces { private def compatibilityError(message: String) = implRefError( "macro implementation has wrong shape:"+ - "\n required: " + showMeth(rparamss, rret, abbreviate = true) + - "\n found : " + showMeth(aparamss, aret, abbreviate = false) + + "\n required: " + showMeth(rparamss, rret, abbreviate = true, untype = false) + + "\n or : " + showMeth(rparamss, rret, abbreviate = true, untype = true) + + "\n found : " + showMeth(aparamss, aret, abbreviate = false, untype = false) + "\n" + message) def MacroImplNonTagImplicitParameters(params: List[Symbol]) = compatibilityError("macro implementations cannot have implicit parameters other than WeakTypeTag evidences") diff --git a/src/compiler/scala/reflect/macros/util/Helpers.scala b/src/compiler/scala/reflect/macros/util/Helpers.scala index f40c6bb7e6..dd23b0fc32 100644 --- a/src/compiler/scala/reflect/macros/util/Helpers.scala +++ b/src/compiler/scala/reflect/macros/util/Helpers.scala @@ -55,6 +55,13 @@ trait Helpers { case tp => typeRef(pre, MacroContextExprClass, List(tp)) } + /** Transforms c.Expr[T] types into c.Tree and leaves the rest unchanged. + */ + def untypeMetalevel(tp: Type): Type = transparentShallowTransform(RepeatedParamClass, tp) { + case ExprClassOf(_) => typeRef(tp.prefix, TreesTreeType, Nil) + case tp => tp + } + /** Decreases metalevel of the type, i.e. transforms: * * c.Expr[T] to T * * Anything else to Any diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 1c5354502b..e765c9165a 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -688,7 +688,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) uncurry -> "uncurry, translate function values to anonymous classes", tailCalls -> "replace tail calls by jumps", specializeTypes -> "@specialized-driven class and method specialization", - explicitOuter -> "this refs to outer pointers, translate patterns", + explicitOuter -> "this refs to outer pointers", erasure -> "erase types, add interfaces for traits", postErasure -> "clean up erased inline classes", lazyVals -> "allocate bitmaps, translate lazy vals into lazified defs", diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala index f7b194a6ca..8a4e565ced 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala @@ -113,7 +113,7 @@ trait Logic extends Debugging { // symbols are propositions abstract case class Sym(variable: Var, const: Const) extends Prop { - private[this] val id = Sym.nextSymId + private val id: Int = Sym.nextSymId override def toString = variable +"="+ const +"#"+ id } @@ -125,6 +125,7 @@ trait Logic extends Debugging { (uniques findEntryOrUpdate newSym) } private def nextSymId = {_symId += 1; _symId}; private var _symId = 0 + implicit val SymOrdering: Ordering[Sym] = Ordering.by(_.id) } def /\(props: Iterable[Prop]) = if (props.isEmpty) True else props.reduceLeft(And(_, _)) @@ -279,7 +280,7 @@ trait Logic extends Debugging { def eqFreePropToSolvable(p: Prop): Formula def cnfString(f: Formula): String - type Model = Map[Sym, Boolean] + type Model = collection.immutable.SortedMap[Sym, Boolean] val EmptyModel: Model val NoModel: Model diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala index 6267585ea8..1902606d86 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala @@ -26,9 +26,12 @@ trait Solving extends Logic { type Formula = FormulaBuilder def formula(c: Clause*): Formula = ArrayBuffer(c: _*) - type Clause = Set[Lit] + type Clause = collection.Set[Lit] // a clause is a disjunction of distinct literals - def clause(l: Lit*): Clause = l.toSet + def clause(l: Lit*): Clause = ( + // neg/t7020.scala changes output 1% of the time, the non-determinism is quelled with this linked set + mutable.LinkedHashSet(l: _*) + ) type Lit def Lit(sym: Sym, pos: Boolean = true): Lit @@ -134,7 +137,7 @@ trait Solving extends Logic { def cnfString(f: Formula) = alignAcrossRows(f map (_.toList) toList, "\\/", " /\\\n") // adapted from http://lara.epfl.ch/w/sav10:simple_sat_solver (original by Hossein Hojjat) - val EmptyModel = Map.empty[Sym, Boolean] + val EmptyModel = collection.immutable.SortedMap.empty[Sym, Boolean] val NoModel: Model = null // returns all solutions, if any (TODO: better infinite recursion backstop -- detect fixpoint??) @@ -229,9 +232,8 @@ trait Solving extends Logic { } } - if (Statistics.canEnable) Statistics.stopTimer(patmatAnaDPLL, start) - - satisfiableWithModel + if (Statistics.canEnable) Statistics.stopTimer(patmatAnaDPLL, start) + satisfiableWithModel } } } diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala b/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala index 9e98dcbc8b..f4d6b39d02 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Quasiquotes.scala @@ -15,7 +15,7 @@ abstract class Quasiquotes extends Parsers if (settings.Yquasiquotedebug.value) println(msg) lazy val (universe: Tree, args, parts, parse, reify, method) = c.macroApplication match { - case Apply(Select(Select(Apply(Select(universe0, _), List(Apply(_, parts0))), interpolator0), method0), args0) => + case Apply(build.SyntacticTypeApplied(Select(Select(Apply(Select(universe0, _), List(Apply(_, parts0))), interpolator0), method0), _), args0) => debug(s"\nparse prefix:\nuniverse=$universe0\nparts=$parts0\ninterpolator=$interpolator0\nmethod=$method0\nargs=$args0\n") val parts1 = parts0.map { case lit @ Literal(Constant(s: String)) => s -> lit.pos diff --git a/src/library/scala/collection/IterableLike.scala b/src/library/scala/collection/IterableLike.scala index f79b5afce9..a621572061 100644 --- a/src/library/scala/collection/IterableLike.scala +++ b/src/library/scala/collection/IterableLike.scala @@ -152,7 +152,7 @@ self => * * @param size the number of elements per group * @return An iterator producing ${coll}s of size `size`, except the - * last will be truncated if the elements don't divide evenly. + * last will be less than size `size` if the elements don't divide evenly. */ def grouped(size: Int): Iterator[Repr] = for (xs <- iterator grouped size) yield { diff --git a/src/library/scala/collection/convert/Wrappers.scala b/src/library/scala/collection/convert/Wrappers.scala index 4410ddc7d8..56f1802509 100644 --- a/src/library/scala/collection/convert/Wrappers.scala +++ b/src/library/scala/collection/convert/Wrappers.scala @@ -212,6 +212,15 @@ private[collection] trait Wrappers { } } } + + override def containsKey(key: AnyRef): Boolean = try { + // Note: Subclass of collection.Map with specific key type may redirect generic + // contains to specific contains, which will throw a ClassCastException if the + // wrong type is passed. This is why we need a type cast to A inside a try/catch. + underlying.contains(key.asInstanceOf[A]) + } catch { + case ex: ClassCastException => false + } } case class MutableMapWrapper[A, B](underlying: mutable.Map[A, B]) extends MapWrapper[A, B](underlying) { diff --git a/src/library/scala/concurrent/ExecutionContext.scala b/src/library/scala/concurrent/ExecutionContext.scala index fa264e5d7f..d3c5a6b019 100644 --- a/src/library/scala/concurrent/ExecutionContext.scala +++ b/src/library/scala/concurrent/ExecutionContext.scala @@ -16,7 +16,7 @@ import scala.util.Try /** * An `ExecutionContext` is an abstraction over an entity that can execute program logic. */ -@implicitNotFound("Cannot find an implicit ExecutionContext, either require one yourself or import ExecutionContext.Implicits.global") +@implicitNotFound("Cannot find an implicit ExecutionContext, either import scala.concurrent.ExecutionContext.Implicits.global or use a custom one") trait ExecutionContext { /** Runs a block of code on this execution context. diff --git a/src/reflect/scala/reflect/api/Quasiquotes.scala b/src/reflect/scala/reflect/api/Quasiquotes.scala index 8e993af382..3687ccba63 100644 --- a/src/reflect/scala/reflect/api/Quasiquotes.scala +++ b/src/reflect/scala/reflect/api/Quasiquotes.scala @@ -7,7 +7,7 @@ trait Quasiquotes { self: Universe => // using the mechanism implemented in `scala.tools.reflect.FastTrack` implicit class Quasiquote(ctx: StringContext) { protected trait api { - def apply(args: Any*): Any = macro ??? + def apply[T](args: T*): Any = macro ??? def unapply(scrutinee: Any): Any = macro ??? } object q extends api diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 1e2dd6b7d3..8e822ca4f0 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -18,7 +18,7 @@ import internal.pickling.ByteCodecs import internal.pickling.UnPickler import scala.collection.mutable.{ HashMap, ListBuffer } import internal.Flags._ -import ReflectionUtils.{staticSingletonInstance, innerSingletonInstance, scalacShouldntLoadClass} +import ReflectionUtils._ import scala.language.existentials import scala.runtime.{ScalaRunTime, BoxesRunTime} @@ -777,33 +777,19 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni /** * The Scala owner of the Scala class corresponding to the Java class `jclazz` */ - private def sOwner(jclazz: jClass[_]): Symbol = - if (jclazz.isMemberClass) { - val jEnclosingClass = jclazz.getEnclosingClass - val sEnclosingClass = classToScala(jEnclosingClass) - followStatic(sEnclosingClass, jclazz.javaFlags) - } else if (jclazz.isLocalClass0) { - val jEnclosingMethod = jclazz.getEnclosingMethod - if (jEnclosingMethod != null) { - methodToScala(jEnclosingMethod) - } else { - val jEnclosingConstructor = jclazz.getEnclosingConstructor - constructorToScala(jEnclosingConstructor) - } - } else if (jclazz.isPrimitive || jclazz.isArray) { - ScalaPackageClass - } else if (jclazz.getPackage != null) { - val jPackage = jclazz.getPackage - packageToScala(jPackage).moduleClass - } else { - // @eb: a weird classloader might return a null package for something with a non-empty package name - // for example, http://groups.google.com/group/scala-internals/browse_thread/thread/7be09ff8f67a1e5c - // in that case we could invoke packageNameToScala(jPackageName) and, probably, be okay - // however, I think, it's better to blow up, since weirdness of the class loader might bite us elsewhere - // [martin] I think it's better to be forgiving here. Restoring packageNameToScala. - val jPackageName = jclazz.getName take jclazz.getName.lastIndexOf('.') - packageNameToScala(jPackageName).moduleClass - } + // @eb: a weird classloader might return a null package for something with a non-empty package name + // for example, http://groups.google.com/group/scala-internals/browse_thread/thread/7be09ff8f67a1e5c + // in that case we could invoke packageNameToScala(jPackageName) and, probably, be okay + // however, I think, it's better to blow up, since weirdness of the class loader might bite us elsewhere + // [martin] I think it's better to be forgiving here. Restoring packageNameToScala. + private def sOwner(jclazz: jClass[_]): Symbol = jclazz match { + case PrimitiveOrArray() => ScalaPackageClass + case EnclosedInMethod(jowner) => methodToScala(jowner) + case EnclosedInConstructor(jowner) => constructorToScala(jowner) + case EnclosedInClass(jowner) => followStatic(classToScala(jowner), jclazz.javaFlags) + case EnclosedInPackage(jowner) => packageToScala(jowner).moduleClass + case _ => packageNameToScala(jclazz.getName take jclazz.getName.lastIndexOf('.')).moduleClass + } /** * The Scala owner of the Scala symbol corresponding to the Java member `jmember` diff --git a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala index 710ec02acd..813c0e1386 100644 --- a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala +++ b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala @@ -84,4 +84,18 @@ private[scala] object ReflectionUtils { def scalacShouldntLoadClassfile(fileName: String) = isTraitImplementation(fileName) def scalacShouldntLoadClass(name: scala.reflect.internal.SymbolTable#Name) = scalacShouldntLoadClassfile(name + ".class") + + object PrimitiveOrArray { + def unapply(jclazz: jClass[_]) = jclazz.isPrimitive || jclazz.isArray + } + + class EnclosedIn[T](enclosure: jClass[_] => T) { + def unapply(jclazz: jClass[_]): Option[T] = if (enclosure(jclazz) != null) Some(enclosure(jclazz)) else None + } + + object EnclosedInMethod extends EnclosedIn(_.getEnclosingMethod) + object EnclosedInConstructor extends EnclosedIn(_.getEnclosingConstructor) + object EnclosedInClass extends EnclosedIn(_.getEnclosingClass) + object EnclosedInPackage extends EnclosedIn(_.getPackage) } + diff --git a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala index c6059ac402..30a3855d70 100644 --- a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala +++ b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala @@ -97,9 +97,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => if (isCompilerUniverse) super.enter(sym) else { val existing = super.lookupEntry(sym.name) - // commented out to provide a hotfix for strange class files that javac sometimes emits - // see more details at: https://groups.google.com/forum/#!topic/scala-internals/hcnUFk75MgQ - // assert(existing == null || existing.sym.isMethod, s"pkgClass = $pkgClass, sym = $sym, existing = $existing") + assert(existing == null || existing.sym.isMethod, s"pkgClass = $pkgClass, sym = $sym, existing = $existing") super.enter(sym) } } diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.js b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.js index 96689ae701..c201b324e7 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.js +++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/index.js @@ -383,51 +383,56 @@ function compilePattern(query) { // Filters all focused templates and packages. This function should be made less-blocking. // @param query The string of the query function textFilter() { - scheduler.clear("filter"); - - $('#tpl').html(''); - var query = $("#textfilter input").attr("value") || ''; var queryRegExp = compilePattern(query); - var index = 0; + if ((typeof textFilter.lastQuery === "undefined") || (textFilter.lastQuery !== query)) { + + textFilter.lastQuery = query; - var searchLoop = function () { - var packages = Index.keys(Index.PACKAGES).sort(); + scheduler.clear("filter"); - while (packages[index]) { - var pack = packages[index]; - var children = Index.PACKAGES[pack]; - index++; + $('#tpl').html(''); - if (focusFilterState) { - if (pack == focusFilterState || - pack.indexOf(focusFilterState + '.') == 0) { - ; - } else { - continue; + var index = 0; + + var searchLoop = function () { + var packages = Index.keys(Index.PACKAGES).sort(); + + while (packages[index]) { + var pack = packages[index]; + var children = Index.PACKAGES[pack]; + index++; + + if (focusFilterState) { + if (pack == focusFilterState || + pack.indexOf(focusFilterState + '.') == 0) { + ; + } else { + continue; + } } - } - var matched = $.grep(children, function (child, i) { - return queryRegExp.test(child.name); - }); + var matched = $.grep(children, function (child, i) { + return queryRegExp.test(child.name); + }); - if (matched.length > 0) { - $('#tpl').append(Index.createPackageTree(pack, matched, - focusFilterState)); - scheduler.add('filter', searchLoop); - return; + if (matched.length > 0) { + $('#tpl').append(Index.createPackageTree(pack, matched, + focusFilterState)); + scheduler.add('filter', searchLoop); + return; + } } - } - $('#tpl a.packfocus').click(function () { - focusFilter($(this).parent().parent()); - }); - configureHideFilter(); - }; + $('#tpl a.packfocus').click(function () { + focusFilter($(this).parent().parent()); + }); + configureHideFilter(); + }; - scheduler.add('filter', searchLoop); + scheduler.add('filter', searchLoop); + } } /* Configures the hide tool by adding the hide link to all packages. */ diff --git a/test/files/filters b/test/files/filters index 9a9b439784..70d7dcff70 100644 --- a/test/files/filters +++ b/test/files/filters @@ -1,3 +1,6 @@ # #Java HotSpot(TM) 64-Bit Server VM warning: Failed to reserve shared memory (errno = 28). Java HotSpot\(TM\) .* warning: +# Hotspot receiving VM options through the $_JAVA_OPTIONS +# env variable outputs them on stderr +Picked up _JAVA_OPTIONS: diff --git a/test/files/neg/macro-bundle-object.check b/test/files/neg/macro-bundle-object.check index e122001427..8c19271b51 100644 --- a/test/files/neg/macro-bundle-object.check +++ b/test/files/neg/macro-bundle-object.check @@ -1,5 +1,6 @@ macro-bundle-object.scala:11: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] + or : (c: scala.reflect.macros.Context): c.Tree found : : Nothing number of parameter sections differ def foo = macro Bundle.impl diff --git a/test/files/neg/macro-invalidimpl.check b/test/files/neg/macro-invalidimpl.check index aaf4f88fc2..e39cc8105b 100644 --- a/test/files/neg/macro-invalidimpl.check +++ b/test/files/neg/macro-invalidimpl.check @@ -32,12 +32,14 @@ match expected type ? ^ Macros_Test_2.scala:31: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Unit] + or : (c: scala.reflect.macros.Context): c.Tree found : (c: scala.reflect.macros.Context)(): c.Expr[Unit] number of parameter sections differ def foo1 = macro Impls6.fooEmpty ^ Macros_Test_2.scala:32: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(): c.Expr[Unit] + or : (c: scala.reflect.macros.Context)(): c.Tree found : (c: scala.reflect.macros.Context): c.Expr[Unit] number of parameter sections differ def bar1() = macro Impls6.fooNullary diff --git a/test/files/neg/macro-invalidret.check b/test/files/neg/macro-invalidret.check index 8c6ed4eb45..6cf62c292b 100644 --- a/test/files/neg/macro-invalidret.check +++ b/test/files/neg/macro-invalidret.check @@ -1,11 +1,13 @@ Macros_Test_2.scala:2: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] + or : (c: scala.reflect.macros.Context): c.Tree found : (c: scala.reflect.macros.Context): Int type mismatch for return type: Int does not conform to c.Expr[Any] def foo1 = macro Impls.foo1 ^ Macros_Test_2.scala:3: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] + or : (c: scala.reflect.macros.Context): c.Tree found : (c: scala.reflect.macros.Context): reflect.runtime.universe.Literal type mismatch for return type: reflect.runtime.universe.Literal does not conform to c.Expr[Any] def foo2 = macro Impls.foo2 diff --git a/test/files/neg/macro-invalidsig-params-badtype.check b/test/files/neg/macro-invalidsig-params-badtype.check index 3cc1c9abf1..86aa08291f 100644 --- a/test/files/neg/macro-invalidsig-params-badtype.check +++ b/test/files/neg/macro-invalidsig-params-badtype.check @@ -1,5 +1,6 @@ Impls_Macros_1.scala:8: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Int]): c.Expr[Any] + or : (c: scala.reflect.macros.Context)(x: c.Tree): c.Tree found : (c: scala.reflect.macros.Context)(x: Int): Nothing type mismatch for parameter x: c.Expr[Int] does not conform to Int def foo(x: Int) = macro Impls.foo diff --git a/test/files/neg/macro-invalidsig.check b/test/files/neg/macro-invalidsig.check index cbdaf51081..732380d4b3 100644 --- a/test/files/neg/macro-invalidsig.check +++ b/test/files/neg/macro-invalidsig.check @@ -1,65 +1,76 @@ Macros_Test_2.scala:2: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] + or : (c: scala.reflect.macros.Context): c.Tree found : (c: scala.reflect.macros.Context)(implicit evidence$2: Numeric[U]): c.universe.Literal macro implementations cannot have implicit parameters other than WeakTypeTag evidences def foo[U] = macro Impls1.foo[U] ^ Macros_Test_2.scala:6: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] + or : (c: scala.reflect.macros.Context): c.Tree found : : Nothing number of parameter sections differ def foo = macro Impls2.foo ^ Macros_Test_2.scala:10: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] + or : (c: scala.reflect.macros.Context): c.Tree found : (c: scala.reflect.api.Universe): Nothing type mismatch for parameter c: scala.reflect.macros.Context does not conform to scala.reflect.api.Universe def foo = macro Impls3.foo ^ Macros_Test_2.scala:14: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] + or : (c: scala.reflect.macros.Context): c.Tree found : (cs: scala.reflect.macros.Context*): Nothing types incompatible for parameter cs: corresponding is not a vararg parameter def foo = macro Impls4.foo ^ Macros_Test_2.scala:18: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Any]): c.Expr[Any] + or : (c: scala.reflect.macros.Context)(x: c.Tree): c.Tree found : (c: scala.reflect.macros.Context): Nothing number of parameter sections differ def foo(x: Any) = macro Impls5.foo ^ Macros_Test_2.scala:22: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Int]): c.Expr[Unit] + or : (c: scala.reflect.macros.Context)(x: c.Tree): c.Tree found : (c: scala.reflect.macros.Context)(implicit x: c.Expr[Int]): c.Expr[Unit] macro implementations cannot have implicit parameters other than WeakTypeTag evidences def foo[U](x: Int) = macro Impls6.foo[T, U] ^ Macros_Test_2.scala:26: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Int]): c.Expr[Any] + or : (c: scala.reflect.macros.Context)(x: c.Tree): c.Tree found : (c: scala.reflect.macros.Context)(x: c.Expr[Int], y: c.Expr[Int]): Nothing parameter lists have different length, found extra parameter y: c.Expr[Int] def foo(x: Int) = macro Impls7.foo ^ Macros_Test_2.scala:30: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Int]): c.Expr[Any] + or : (c: scala.reflect.macros.Context)(x: c.Tree): c.Tree found : (c: scala.reflect.macros.Context)(x: c.universe.Symbol): Nothing type mismatch for parameter x: c.Expr[Int] does not conform to c.universe.Symbol def foo(x: Int) = macro Impls8.foo ^ Macros_Test_2.scala:34: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Int], y: c.Expr[Int]): c.Expr[Any] + or : (c: scala.reflect.macros.Context)(x: c.Tree, y: c.Tree): c.Tree found : (c: scala.reflect.macros.Context)(xs: c.Expr[Int]*): Nothing parameter lists have different length, required extra parameter y: c.Expr[Int] def foo(x: Int, y: Int) = macro Impls9.foo ^ Macros_Test_2.scala:38: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Int], y: c.Expr[Int]): c.Expr[Any] + or : (c: scala.reflect.macros.Context)(x: c.Tree, y: c.Tree): c.Tree found : (c: scala.reflect.macros.Context)(y: c.Expr[Int], x: c.Expr[Int]): Nothing parameter names differ: x != y def foo(x: Int, y: Int) = macro Impls10.foo ^ Macros_Test_2.scala:42: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] + or : (c: scala.reflect.macros.Context): c.Tree found : (c: scala.reflect.macros.Context)(U: c.universe.Type): Nothing number of parameter sections differ def foo[U] = macro Impls11.foo[U] diff --git a/test/files/neg/macro-quasiquotes.check b/test/files/neg/macro-quasiquotes.check index 96ef75dd32..d000bb5316 100644 --- a/test/files/neg/macro-quasiquotes.check +++ b/test/files/neg/macro-quasiquotes.check @@ -1,6 +1,7 @@ Macros_1.scala:14: error: macro implementation has wrong shape: required: (x: Impls.this.c.Expr[Int]): Impls.this.c.Expr[Any] - found : (x: Impls.this.c.universe.Block): Impls.this.c.universe.Tree + or : (x: Impls.this.c.Tree): Impls.this.c.Tree + found : (x: Impls.this.c.universe.Block): Impls.this.c.Tree type mismatch for parameter x: Impls.this.c.Expr[Int] does not conform to Impls.this.c.universe.Block def m3(x: Int) = macro Impls.impl3 ^ diff --git a/test/files/neg/t3871.check b/test/files/neg/t3871.check new file mode 100644 index 0000000000..b920357ee6 --- /dev/null +++ b/test/files/neg/t3871.check @@ -0,0 +1,7 @@ +t3871.scala:4: error: variable foo in class Sub2 cannot be accessed in Sub2 + Access to protected method foo not permitted because + enclosing class Base is not a subclass of + class Sub2 where target is defined + s.foo = true + ^ +one error found diff --git a/test/files/neg/t3871.scala b/test/files/neg/t3871.scala new file mode 100644 index 0000000000..fc459867df --- /dev/null +++ b/test/files/neg/t3871.scala @@ -0,0 +1,11 @@ +class Base { + def mkNew() = { + val s = new Sub2 + s.foo = true + s + } +} + +class Sub2 extends Base { + protected var foo = false +} diff --git a/test/files/neg/t3871b.check b/test/files/neg/t3871b.check new file mode 100644 index 0000000000..6ab5ddfaf1 --- /dev/null +++ b/test/files/neg/t3871b.check @@ -0,0 +1,97 @@ +t3871b.scala:61: error: not found: value protOT + protOT // not allowed + ^ +t3871b.scala:77: error: method prot in class A cannot be accessed in E.this.A + Access to protected method prot not permitted because + prefix type E.this.A does not conform to + class B in class E where the access take place + a.prot // not allowed, prefix type `A` does not conform to `B` + ^ +t3871b.scala:79: error: value protT is not a member of E.this.B + b.protT // not allowed + ^ +t3871b.scala:80: error: value protT is not a member of E.this.C + c.protT // not allowed + ^ +t3871b.scala:81: error: value protT is not a member of E.this.A + a.protT // not allowed + ^ +t3871b.scala:91: error: method prot in class A cannot be accessed in E.this.A + Access to protected method prot not permitted because + prefix type E.this.A does not conform to + object B in class E where the access take place + a.prot // not allowed + ^ +t3871b.scala:93: error: value protT is not a member of E.this.B + b.protT // not allowed + ^ +t3871b.scala:94: error: value protT is not a member of E.this.C + c.protT // not allowed + ^ +t3871b.scala:95: error: value protT is not a member of E.this.A + a.protT // not allowed + ^ +t3871b.scala:102: error: method prot in class A cannot be accessed in E.this.B + Access to protected method prot not permitted because + enclosing class Z in class E is not a subclass of + class A in class E where target is defined + b.prot // not allowed + ^ +t3871b.scala:103: error: method prot in class A cannot be accessed in E.this.C + Access to protected method prot not permitted because + enclosing class Z in class E is not a subclass of + class A in class E where target is defined + c.prot // not allowed + ^ +t3871b.scala:104: error: method prot in class A cannot be accessed in E.this.A + Access to protected method prot not permitted because + enclosing class Z in class E is not a subclass of + class A in class E where target is defined + a.prot // not allowed + ^ +t3871b.scala:109: error: value protT is not a member of E.this.B + b.protT // not allowed + ^ +t3871b.scala:110: error: value protT is not a member of E.this.C + c.protT // not allowed + ^ +t3871b.scala:111: error: value protT is not a member of E.this.A + a.protT // not allowed + ^ +t3871b.scala:120: error: method prot in class A cannot be accessed in Other.this.e.B + Access to protected method prot not permitted because + enclosing class Other is not a subclass of + class A in class E where target is defined + b.prot // not allowed + ^ +t3871b.scala:121: error: method prot in class A cannot be accessed in Other.this.e.C + Access to protected method prot not permitted because + enclosing class Other is not a subclass of + class A in class E where target is defined + c.prot // not allowed + ^ +t3871b.scala:122: error: method prot in class A cannot be accessed in Other.this.e.A + Access to protected method prot not permitted because + enclosing class Other is not a subclass of + class A in class E where target is defined + a.prot // not allowed + ^ +t3871b.scala:123: error: method protE in class A cannot be accessed in Other.this.e.B + Access to protected method protE not permitted because + enclosing class Other is not a subclass of + class A in class E where target is defined + b.protE // not allowed + ^ +t3871b.scala:124: error: method protE in class A cannot be accessed in Other.this.e.A + Access to protected method protE not permitted because + enclosing class Other is not a subclass of + class A in class E where target is defined + a.protE // not allowed + ^ +t3871b.scala:125: error: method protE in class A cannot be accessed in Other.this.e.C + Access to protected method protE not permitted because + enclosing class Other is not a subclass of + class A in class E where target is defined + c.protE // not allowed + ^ +21 errors found diff --git a/test/files/neg/t3871b.scala b/test/files/neg/t3871b.scala new file mode 100644 index 0000000000..b490b7789a --- /dev/null +++ b/test/files/neg/t3871b.scala @@ -0,0 +1,127 @@ +/** + +The protected modifier applies to class member definitions. Protected members of a class can be accessed from within + + 0a. the companion module of any of those classes + +A protected identifier x may be used as a member name in a selection r.x only +if one of the following applies: + 1a. The access is within the template defining the member, or, + if a qualification C is given, + 1b. inside the package C, or + 1c. the class C , or its companion module, or + 2. r is one of the reserved words this and super, or + 3. r’s type conforms to a type-instance of the class which contains the access. + + 4. A different form of qualification is protected[this]. A member M marked with this + modifier is called object-protected; it can be accessed only from within the object + in which it is defined. That is, a selection p.M is only legal if the prefix is this + or O.this, for some class O enclosing the reference. In addition, the restrictions + for unqualified protected apply. +*/ + +object E { + val e = new E + import e._ + def n(a: A, b: B, c: C) = { + b.protE // 1c + c.protE // 1c + a.protE // 1c + A.protOE // 1c + } +} + +class E { + object A { + protected def protO = 2 + protected[E] def protOE = 3 + protected[this] def protOT = 3 + } + class A { + protected def prot = 2 + protected[E] def protE = 3 + protected[this] def protT = 4 + + // 1a + prot; protE; protT + def foo = {prot; protE; protT} + new { prot; protE } + def this(a: Any) = {this(); prot; protE; protT} + object B extends A { + A.this.prot + A.this.protE + A.this.protT + } + + import A._ + // 0a + protO + // 3 + protOE + protOT // not allowed + } + + class B extends A { + // 1b + this.prot; this.protE; + super.prot; super.protE; + + // 4 + this.protT + // 4 !!! "or the super keyword" + super.protT + + def n(a: A, b: B, c: C) = { + b.prot // 3 + c.prot // 3 + a.prot // not allowed, prefix type `A` does not conform to `B` + + b.protT // not allowed + c.protT // not allowed + a.protT // not allowed + } + } + object B { + def n(a: A, b: B, c: C) = { + b.prot // 3 !!! + c.prot // 3 !!! + // Wording of 3 seems insufficient, missing: + // "... (if the access is from a class), or + // the type instance of companion class (if the access is from a module)" + a.prot // not allowed + + b.protT // not allowed + c.protT // not allowed + a.protT // not allowed + } + } + class C extends B + + class Z { + def n(a: A, b: B, c: C) = { + b.prot // not allowed + c.prot // not allowed + a.prot // not allowed + b.protE // 2 + a.protE // 2 + c.protE // 2 + + b.protT // not allowed + c.protT // not allowed + a.protT // not allowed + } + } +} + +class Other { + val e = new E + import e._ + def n(a: A, b: B, c: C) = { + b.prot // not allowed + c.prot // not allowed + a.prot // not allowed + b.protE // not allowed + a.protE // not allowed + c.protE // not allowed + } +} diff --git a/test/files/neg/t5689.check b/test/files/neg/t5689.check index ad9b79cdcb..8cf0534e77 100644 --- a/test/files/neg/t5689.check +++ b/test/files/neg/t5689.check @@ -1,5 +1,6 @@ t5689.scala:4: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(i: c.Expr[Double]): c.Expr[String] + or : (c: scala.reflect.macros.Context)(i: c.Tree): c.Tree found : (c: scala.reflect.macros.Context)(i: c.Expr[Double]): c.Expr[Int] type mismatch for return type: c.Expr[Int] does not conform to c.Expr[String] def returnsString(i: Double): String = macro returnsIntImpl diff --git a/test/files/neg/t6123-explaintypes-macros.check b/test/files/neg/t6123-explaintypes-macros.check index ebcb8069d5..43f8371326 100644 --- a/test/files/neg/t6123-explaintypes-macros.check +++ b/test/files/neg/t6123-explaintypes-macros.check @@ -2,6 +2,7 @@ c.universe.Expr[Any]* <: c.universe.Expr[String]*? false BadMac_2.scala:6: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(format: c.Expr[String], params: c.Expr[Any]*): c.Expr[Unit] + or : (c: scala.reflect.macros.Context)(format: c.Tree, params: Tree*): c.Tree found : (c: scala.reflect.macros.Context)(format: c.Expr[String], params: c.Expr[String]*): c.Expr[Unit] type mismatch for parameter params: c.Expr[Any]* does not conform to c.Expr[String]* def printf(format: String, params: Any*): Unit = macro printf_impl diff --git a/test/files/neg/t6446-additional.check b/test/files/neg/t6446-additional.check index 6dfe072913..c91333830a 100755 --- a/test/files/neg/t6446-additional.check +++ b/test/files/neg/t6446-additional.check @@ -12,7 +12,7 @@ superaccessors 6 add super accessors in traits and nested classes uncurry 10 uncurry, translate function values to anonymous classes tailcalls 11 replace tail calls by jumps specialize 12 @specialized-driven class and method specialization - explicitouter 13 this refs to outer pointers, translate patterns + explicitouter 13 this refs to outer pointers erasure 14 erase types, add interfaces for traits posterasure 15 clean up erased inline classes lazyvals 16 allocate bitmaps, translate lazy vals into lazified defs diff --git a/test/files/neg/t6446-missing.check b/test/files/neg/t6446-missing.check index ba5e30dc05..b2d5ddd686 100755 --- a/test/files/neg/t6446-missing.check +++ b/test/files/neg/t6446-missing.check @@ -13,7 +13,7 @@ superaccessors 6 add super accessors in traits and nested classes uncurry 10 uncurry, translate function values to anonymous classes tailcalls 11 replace tail calls by jumps specialize 12 @specialized-driven class and method specialization - explicitouter 13 this refs to outer pointers, translate patterns + explicitouter 13 this refs to outer pointers erasure 14 erase types, add interfaces for traits posterasure 15 clean up erased inline classes lazyvals 16 allocate bitmaps, translate lazy vals into lazified defs diff --git a/test/files/neg/t6446-show-phases.check b/test/files/neg/t6446-show-phases.check index 10a9e08b86..48d4f37b3e 100644 --- a/test/files/neg/t6446-show-phases.check +++ b/test/files/neg/t6446-show-phases.check @@ -12,7 +12,7 @@ superaccessors 6 add super accessors in traits and nested classes uncurry 10 uncurry, translate function values to anonymous classes tailcalls 11 replace tail calls by jumps specialize 12 @specialized-driven class and method specialization - explicitouter 13 this refs to outer pointers, translate patterns + explicitouter 13 this refs to outer pointers erasure 14 erase types, add interfaces for traits posterasure 15 clean up erased inline classes lazyvals 16 allocate bitmaps, translate lazy vals into lazified defs diff --git a/test/disabled/neg/t7020.check b/test/files/neg/t7020.check index f9600ca7fc..76390b243d 100644 --- a/test/disabled/neg/t7020.check +++ b/test/files/neg/t7020.check @@ -1,17 +1,17 @@ t7020.scala:3: warning: match may not be exhaustive. -It would fail on the following inputs: List((x: Int forSome x not in (1, 2, 4, 5, 6, 7))), List((x: Int forSome x not in (1, 2, 4, 5, 6, 7)), _), List(1, _), List(2, _), List(4, _), List(5, _), List(6, _), List(7, _), List(??, _), List(_, _) +It would fail on the following inputs: List((x: Int forSome x not in (1, 2, 4, 5, 6, 7))), List((x: Int forSome x not in (1, 2, 4, 5, 6, 7)), _), List(1, _), List(2, _), List(4, _), List(5, _), List(6, _), List(7, _), List(_, _) List(5) match { ^ t7020.scala:10: warning: match may not be exhaustive. -It would fail on the following inputs: List((x: Int forSome x not in (1, 2, 4, 5, 6, 7))), List((x: Int forSome x not in (1, 2, 4, 5, 6, 7)), _), List(1, _), List(2, _), List(4, _), List(5, _), List(6, _), List(7, _), List(??, _), List(_, _) +It would fail on the following inputs: List((x: Int forSome x not in (1, 2, 4, 5, 6, 7))), List((x: Int forSome x not in (1, 2, 4, 5, 6, 7)), _), List(1, _), List(2, _), List(4, _), List(5, _), List(6, _), List(7, _), List(_, _) List(5) match { ^ t7020.scala:17: warning: match may not be exhaustive. -It would fail on the following inputs: List((x: Int forSome x not in (1, 2, 4, 5, 6, 7))), List((x: Int forSome x not in (1, 2, 4, 5, 6, 7)), _), List(1, _), List(2, _), List(4, _), List(5, _), List(6, _), List(7, _), List(??, _), List(_, _) +It would fail on the following inputs: List((x: Int forSome x not in (1, 2, 4, 5, 6, 7))), List((x: Int forSome x not in (1, 2, 4, 5, 6, 7)), _), List(1, _), List(2, _), List(4, _), List(5, _), List(6, _), List(7, _), List(_, _) List(5) match { ^ t7020.scala:24: warning: match may not be exhaustive. -It would fail on the following inputs: List((x: Int forSome x not in (1, 2, 4, 5, 6, 7))), List((x: Int forSome x not in (1, 2, 4, 5, 6, 7)), _), List(1, _), List(2, _), List(4, _), List(5, _), List(6, _), List(7, _), List(??, _), List(_, _) +It would fail on the following inputs: List((x: Int forSome x not in (1, 2, 4, 5, 6, 7))), List((x: Int forSome x not in (1, 2, 4, 5, 6, 7)), _), List(1, _), List(2, _), List(4, _), List(5, _), List(6, _), List(7, _), List(_, _) List(5) match { ^ error: No warnings can be incurred under -Xfatal-warnings. diff --git a/test/disabled/neg/t7020.flags b/test/files/neg/t7020.flags index e8fb65d50c..e8fb65d50c 100644 --- a/test/disabled/neg/t7020.flags +++ b/test/files/neg/t7020.flags diff --git a/test/disabled/neg/t7020.scala b/test/files/neg/t7020.scala index cc5421bab1..cc5421bab1 100644 --- a/test/disabled/neg/t7020.scala +++ b/test/files/neg/t7020.scala diff --git a/test/files/neg/t7494-no-options.check b/test/files/neg/t7494-no-options.check index 0bde84c96c..b5dc0e3d4f 100644 --- a/test/files/neg/t7494-no-options.check +++ b/test/files/neg/t7494-no-options.check @@ -13,7 +13,7 @@ superaccessors 6 add super accessors in traits and nested classes uncurry 10 uncurry, translate function values to anonymous classes tailcalls 11 replace tail calls by jumps specialize 12 @specialized-driven class and method specialization - explicitouter 13 this refs to outer pointers, translate patterns + explicitouter 13 this refs to outer pointers erasure 14 erase types, add interfaces for traits posterasure 15 clean up erased inline classes lazyvals 16 allocate bitmaps, translate lazy vals into lazified defs diff --git a/test/files/neg/t7519-b.check b/test/files/neg/t7519-b.check new file mode 100644 index 0000000000..08d819eeec --- /dev/null +++ b/test/files/neg/t7519-b.check @@ -0,0 +1,6 @@ +Use_2.scala:6: error: type mismatch; + found : String + required: Q + val x: Q = ex.Mac.mac("asdf") + ^ +one error found diff --git a/test/files/neg/t7519-b/Mac_1.scala b/test/files/neg/t7519-b/Mac_1.scala new file mode 100644 index 0000000000..55b583d24b --- /dev/null +++ b/test/files/neg/t7519-b/Mac_1.scala @@ -0,0 +1,14 @@ +// get expected error message without package declaration +package ex + +import scala.language.experimental.macros +import scala.reflect.macros._ + +object IW { + def foo(a: String): String = ??? +} +object Mac { + def mac(s: String): String = macro macImpl + def macImpl(c: Context)(s: c.Expr[String]): c.Expr[String] = + c.universe.reify(IW.foo(s.splice)) +} diff --git a/test/files/neg/t7519-b/Use_2.scala b/test/files/neg/t7519-b/Use_2.scala new file mode 100644 index 0000000000..413e40e25e --- /dev/null +++ b/test/files/neg/t7519-b/Use_2.scala @@ -0,0 +1,8 @@ +trait Q +trait K + +object Use { + implicit def cd[T](p: T)(implicit ev: T => K): Q = ??? + val x: Q = ex.Mac.mac("asdf") +} + diff --git a/test/files/run/programmatic-main.check b/test/files/run/programmatic-main.check index 10d2ed5af7..cfa3ed3fb4 100644 --- a/test/files/run/programmatic-main.check +++ b/test/files/run/programmatic-main.check @@ -12,7 +12,7 @@ superaccessors 6 add super accessors in traits and nested classes uncurry 10 uncurry, translate function values to anonymous classes tailcalls 11 replace tail calls by jumps specialize 12 @specialized-driven class and method specialization - explicitouter 13 this refs to outer pointers, translate patterns + explicitouter 13 this refs to outer pointers erasure 14 erase types, add interfaces for traits posterasure 15 clean up erased inline classes lazyvals 16 allocate bitmaps, translate lazy vals into lazified defs diff --git a/test/files/run/reflection-fancy-java-classes.check b/test/files/run/reflection-fancy-java-classes.check new file mode 100644 index 0000000000..258208dd99 --- /dev/null +++ b/test/files/run/reflection-fancy-java-classes.check @@ -0,0 +1,12 @@ +===== JAVA POV ===== +class Foo_1$1 +getEnclosingClass = class Foo_1 +getEnclosingMethod = null +getEnclosingConstructor = null +isMemberClass = false +isLocalClass = false +isAnonymousClass = true + +===== SCALA POV ===== +class 1 +object Foo_1 diff --git a/test/files/run/reflection-fancy-java-classes/Foo_1.java b/test/files/run/reflection-fancy-java-classes/Foo_1.java new file mode 100644 index 0000000000..f6fd76124b --- /dev/null +++ b/test/files/run/reflection-fancy-java-classes/Foo_1.java @@ -0,0 +1,5 @@ +public class Foo_1 { + public static Bar bar = new Bar(); + private static class Bar { + } +}
\ No newline at end of file diff --git a/test/files/run/reflection-fancy-java-classes/Test_2.scala b/test/files/run/reflection-fancy-java-classes/Test_2.scala new file mode 100644 index 0000000000..271960ee79 --- /dev/null +++ b/test/files/run/reflection-fancy-java-classes/Test_2.scala @@ -0,0 +1,20 @@ +import scala.reflect.runtime.{universe => ru} +import scala.reflect.runtime.{currentMirror => cm} + +object Test extends App { + println("===== JAVA POV =====") + val jfancy = Class.forName("Foo_1$1") + println(jfancy) + println("getEnclosingClass = " + jfancy.getEnclosingClass) + println("getEnclosingMethod = " + jfancy.getEnclosingMethod) + println("getEnclosingConstructor = " + jfancy.getEnclosingConstructor) + println("isMemberClass = " + jfancy.isMemberClass) + println("isLocalClass = " + jfancy.isLocalClass) + println("isAnonymousClass = " + jfancy.isAnonymousClass) + + println("") + println("===== SCALA POV =====") + val sfancy = cm.classSymbol(jfancy) + println(sfancy) + println(sfancy.owner) +}
\ No newline at end of file diff --git a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala index 9284903623..f68656d0f7 100644 --- a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala @@ -199,4 +199,13 @@ object TermConstructionProps extends QuasiquoteProperties("term construction") { def withEvidence = q"def foo[T: X]" assert(!(withEvidence ≈ withEvidence)) } + + property("make sure inference doesn't infer any") = test { + val l1 = List(q"foo") + val l2 = List(q"bar") + val baz = q"baz" + assert(q"f(..${l1 ++ l2})" ≈ q"f(foo, bar)") + assert(q"f(..${l1 ++ l2}, $baz)" ≈ q"f(foo, bar, baz)") + assert(q"f(${if (true) q"a" else q"b"})" ≈ q"f(a)") + } } diff --git a/test/junit/scala/collection/convert/MapWrapperTest.scala b/test/junit/scala/collection/convert/MapWrapperTest.scala new file mode 100644 index 0000000000..060b6b5937 --- /dev/null +++ b/test/junit/scala/collection/convert/MapWrapperTest.scala @@ -0,0 +1,49 @@ +package scala.collection.convert + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@RunWith(classOf[JUnit4]) +class MapWrapperTest { + + /* Test for SI-7883 */ + @Test + def testContains() { + import scala.collection.JavaConverters.mapAsJavaMapConverter + import scala.language.reflectiveCalls // for accessing containsCounter + + // A HashMap which throws an exception when the iterator() method is called. + // Before the fix for SI-7883, calling MapWrapper.containsKey() used to + // iterate through every element of the wrapped Map, and thus would crash + // in this case. + val scalaMap = new scala.collection.mutable.HashMap[String, String] { + var containsCounter = 0 // keep track of how often contains() has been called. + override def iterator = throw new UnsupportedOperationException + + override def contains(key: String): Boolean = { + containsCounter += 1 + super.contains(key) + } + } + + val javaMap = scalaMap.asJava + + scalaMap("hello") = "world" + scalaMap(null) = "null's value" + + assertEquals(0, scalaMap.containsCounter) + assertTrue(javaMap.containsKey("hello")) // positive test + assertTrue(javaMap.containsKey(null)) // positive test, null key + + assertFalse(javaMap.containsKey("goodbye")) // negative test + // Note: this case does NOT make it to scalaMap's contains() method because the runtime + // cast fails in MapWrapper, so the containsCounter is not incremented in this case. + assertFalse(javaMap.containsKey(42)) // negative test, wrong key type + + assertEquals(Some("null's value"), scalaMap.remove(null)) + assertFalse(javaMap.containsKey(null)) // negative test, null key + assertEquals(4, scalaMap.containsCounter) + } +} |