diff options
-rw-r--r-- | project/plugins.sbt | 2 | ||||
-rw-r--r-- | src/dotty/tools/backend/sjs/JSCodeGen.scala | 21 | ||||
-rw-r--r-- | src/dotty/tools/dotc/config/Settings.scala | 10 | ||||
-rw-r--r-- | src/dotty/tools/dotc/parsing/JavaParsers.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/parsing/Parsers.scala | 45 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/Erasure.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/Memoize.scala | 9 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/MixinOps.scala | 18 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 20 | ||||
-rw-r--r-- | test/dotc/tests.scala | 88 | ||||
-rw-r--r-- | tests/neg/Variances.scala | 15 | ||||
-rw-r--r-- | tests/neg/i1059.scala | 10 | ||||
-rw-r--r-- | tests/pos-scala2/i1059.scala | 10 | ||||
-rw-r--r-- | tests/pos/Variances.scala | 15 | ||||
-rw-r--r-- | tests/pos/i1174.scala | 19 | ||||
-rw-r--r-- | tests/run/no-useless-forwarders.scala | 17 |
17 files changed, 253 insertions, 52 deletions
diff --git a/project/plugins.sbt b/project/plugins.sbt index 0c8b7737e..57bd46581 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -7,4 +7,4 @@ addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "4.0.0") addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "0.8.0") -addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.7") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.8") diff --git a/src/dotty/tools/backend/sjs/JSCodeGen.scala b/src/dotty/tools/backend/sjs/JSCodeGen.scala index 0aa211bc8..ec75a1c4d 100644 --- a/src/dotty/tools/backend/sjs/JSCodeGen.scala +++ b/src/dotty/tools/backend/sjs/JSCodeGen.scala @@ -557,21 +557,7 @@ class JSCodeGen()(implicit ctx: Context) { } } - /* Work around https://github.com/scala-js/scala-js/issues/2259 - * TODO Remove this when we upgrade to Scala.js 0.6.8. - */ - val methodDef1 = if (!sym.owner.is(Trait)) { - methodDef - } else { - val workaroundBody = js.Block( - js.Apply(js.ClassOf(jstpe.ClassType(encodeClassFullName(sym.owner))), - js.Ident("isPrimitive__Z"), Nil)(jstpe.BooleanType), - methodDef.body) - methodDef.copy(body = workaroundBody)( - methodDef.optimizerHints, methodDef.hash) - } - - Some(methodDef1) + Some(methodDef) } } } @@ -2386,8 +2372,9 @@ class JSCodeGen()(implicit ctx: Context) { /** Gen JS code to load the JavaScript global scope. */ private def genLoadJSGlobal()(implicit pos: Position): js.Tree = { - // TODO Change this when upgrading to Scala.js 0.6.8 - js.JSBracketSelect(js.JSEnvInfo(), js.StringLiteral("global")) + js.JSBracketSelect( + js.JSBracketSelect(js.JSLinkingInfo(), js.StringLiteral("envInfo")), + js.StringLiteral("global")) } /** Generate a Class[_] value (e.g. coming from classOf[T]) */ diff --git a/src/dotty/tools/dotc/config/Settings.scala b/src/dotty/tools/dotc/config/Settings.scala index eddeb83ab..f30cedaa0 100644 --- a/src/dotty/tools/dotc/config/Settings.scala +++ b/src/dotty/tools/dotc/config/Settings.scala @@ -119,11 +119,13 @@ object Settings { case (ListTag, _) => if (argRest.isEmpty) missingArg else update((argRest split ",").toList, args) + case (StringTag, _) if choices.nonEmpty => + if (argRest.isEmpty) missingArg + else if (!choices.contains(argRest)) + fail(s"$arg is not a valid choice for $name", args) + else update(argRest, args) case (StringTag, arg2 :: args2) => - if (choices.nonEmpty && !(choices contains arg2)) - fail(s"$arg2 is not a valid choice for $name", args2) - else - update(arg2, args2) + update(arg2, args2) case (IntTag, arg2 :: args2) => try { val x = arg2.toInt diff --git a/src/dotty/tools/dotc/parsing/JavaParsers.scala b/src/dotty/tools/dotc/parsing/JavaParsers.scala index b4d01a0da..fbb362354 100644 --- a/src/dotty/tools/dotc/parsing/JavaParsers.scala +++ b/src/dotty/tools/dotc/parsing/JavaParsers.scala @@ -175,6 +175,8 @@ object JavaParsers { /** Consume one token of the specified type, or * signal an error if it is not there. + * + * @return The offset at the start of the token to accept */ def accept(token: Int): Int = { val offset = in.offset diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala index 6ec75a8b2..44a70886e 100644 --- a/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/src/dotty/tools/dotc/parsing/Parsers.scala @@ -227,6 +227,8 @@ object Parsers { /** Consume one token of the specified type, or * signal an error if it is not there. + * + * @return The offset at the start of the token to accept */ def accept(token: Int): Int = { val offset = in.offset @@ -234,7 +236,7 @@ object Parsers { syntaxErrorOrIncomplete(expectedMsg(token)) } if (in.token == token) in.nextToken() - in.offset + offset } /** semi = nl {nl} | `;' @@ -259,11 +261,19 @@ object Parsers { } finally inFunReturnType = saved } + private val isScala2Mode = + ctx.settings.language.value.contains(nme.Scala2.toString) + + def migrationWarningOrError(msg: String, offset: Int = in.offset) = + if (isScala2Mode) + ctx.migrationWarning(msg, source atPos Position(offset)) + else + syntaxError(msg, offset) + /** Cannot use ctx.featureEnabled because accessing the context would force too much */ private def testScala2Mode(msg: String, pos: Position = Position(in.offset)) = { - val s2 = ctx.settings.language.value.contains(nme.Scala2.toString) - if (s2) ctx.migrationWarning(msg, source atPos pos) - s2 + if (isScala2Mode) ctx.migrationWarning(msg, source atPos pos) + isScala2Mode } /* ---------- TREE CONSTRUCTION ------------------------------------------- */ @@ -1011,7 +1021,7 @@ object Parsers { val uscoreStart = in.skipToken() if (isIdent(nme.raw.STAR)) { in.nextToken() - if (in.token != RPAREN) syntaxError("`_*' can be used only for last argument") + if (in.token != RPAREN) syntaxError("`_*' can be used only for last argument", uscoreStart) Typed(t, atPos(uscoreStart) { Ident(tpnme.WILDCARD_STAR) }) } else { syntaxErrorOrIncomplete("`*' expected"); t @@ -1309,7 +1319,20 @@ object Parsers { */ val pattern2 = () => infixPattern() match { case p @ Ident(name) if isVarPattern(p) && in.token == AT => - atPos(p.pos.start, in.skipToken()) { Bind(name, infixPattern()) } + val pos = in.skipToken() + + // compatibility for Scala2 `x @ _*` syntax + infixPattern() match { + case pt @ Ident(tpnme.WILDCARD_STAR) => + migrationWarningOrError("The syntax `x @ _*' is no longer supported; use `x : _*' instead", p.pos.start) + atPos(p.pos.start, pos) { Typed(p, pt) } + case p => + atPos(p.pos.start, pos) { Bind(name, p) } + } + case p @ Ident(tpnme.WILDCARD_STAR) => + // compatibility for Scala2 `_*` syntax + migrationWarningOrError("The syntax `_*' is no longer supported; use `x : _*' instead", p.pos.start) + atPos(p.pos.start) { Typed(Ident(nme.WILDCARD), p) } case p => p } @@ -1337,7 +1360,15 @@ object Parsers { case t => simplePatternRest(t) } case USCORE => - wildcardIdent() + val wildIndent = wildcardIdent() + + // compatibility for Scala2 `x @ _*` and `_*` syntax + // `x: _*' is parsed in `ascription' + if (isIdent(nme.raw.STAR)) { + in.nextToken() + if (in.token != RPAREN) syntaxError("`_*' can be used only for last argument", wildIndent.pos) + atPos(wildIndent.pos) { Ident(tpnme.WILDCARD_STAR) } + } else wildIndent case LPAREN => atPos(in.offset) { makeTupleOrParens(inParens(patternsOpt())) } case LBRACE => diff --git a/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled b/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled index 65362f199..7b37c5881 100644 --- a/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled +++ b/src/dotty/tools/dotc/transform/DropEmptyCompanions.scala.disabled @@ -30,7 +30,7 @@ import dotty.tools.dotc.transform.TreeTransforms.TransformerInfo */ class DropEmptyCompanions extends MiniPhaseTransform { thisTransform => import ast.tpd._ - override def phaseName = "dropEmpty" + override def phaseName = "dropEmptyCompanions" override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[Flatten]) override def transformPackageDef(pdef: PackageDef)(implicit ctx: Context, info: TransformerInfo) = { diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala index 3445b4c44..8d890902e 100644 --- a/src/dotty/tools/dotc/transform/Erasure.scala +++ b/src/dotty/tools/dotc/transform/Erasure.scala @@ -611,7 +611,7 @@ object Erasure extends TypeTestsCasts{ traverse(newStats, oldStats) } - private final val NoBridgeFlags = Flags.Accessor | Flags.Deferred | Flags.Lazy + private final val NoBridgeFlags = Flags.Accessor | Flags.Deferred | Flags.Lazy | Flags.ParamAccessor /** Create a bridge DefDef which overrides a parent method. * diff --git a/src/dotty/tools/dotc/transform/Memoize.scala b/src/dotty/tools/dotc/transform/Memoize.scala index b775496ae..1e4f8831b 100644 --- a/src/dotty/tools/dotc/transform/Memoize.scala +++ b/src/dotty/tools/dotc/transform/Memoize.scala @@ -68,6 +68,10 @@ import Decorators._ } lazy val field = sym.field.orElse(newField).asTerm + + def adaptToField(tree: Tree) = + if (tree.isEmpty) tree else tree.ensureConforms(field.info.widen) + if (sym.is(Accessor, butNot = NoFieldNeeded)) if (sym.isGetter) { def skipBlocks(t: Tree): Tree = t match { @@ -85,14 +89,15 @@ import Decorators._ case _ => var rhs = tree.rhs.changeOwnerAfter(sym, field, thisTransform) if (isWildcardArg(rhs)) rhs = EmptyTree - val fieldDef = transformFollowing(ValDef(field, rhs)) + + val fieldDef = transformFollowing(ValDef(field, adaptToField(rhs))) val getterDef = cpy.DefDef(tree)(rhs = transformFollowingDeep(ref(field))(ctx.withOwner(sym), info)) Thicket(fieldDef, getterDef) } } else if (sym.isSetter) { if (!sym.is(ParamAccessor)) { val Literal(Constant(())) = tree.rhs } // this is intended as an assertion field.setFlag(Mutable) // necessary for vals mixed in from Scala2 traits - val initializer = Assign(ref(field), ref(tree.vparamss.head.head.symbol)) + val initializer = Assign(ref(field), adaptToField(ref(tree.vparamss.head.head.symbol))) cpy.DefDef(tree)(rhs = transformFollowingDeep(initializer)(ctx.withOwner(sym), info)) } else tree // curiously, some accessors from Scala2 have ' ' suffixes. They count as diff --git a/src/dotty/tools/dotc/transform/MixinOps.scala b/src/dotty/tools/dotc/transform/MixinOps.scala index db89f939b..6cebf7197 100644 --- a/src/dotty/tools/dotc/transform/MixinOps.scala +++ b/src/dotty/tools/dotc/transform/MixinOps.scala @@ -41,11 +41,21 @@ class MixinOps(cls: ClassSymbol, thisTransform: DenotTransformer)(implicit ctx: ctx.atPhase(thisTransform) { implicit ctx => cls.info.member(sym.name).hasAltWith(_.symbol == sym) } - + + /** Does `method` need a forwarder to in class `cls` + * Method needs a forwarder in those cases: + * - there's a class defining a method with same signature + * - there are multiple traits defining method with same signature + */ def needsForwarder(meth: Symbol): Boolean = { - lazy val overridenSymbols = meth.allOverriddenSymbols - def needsDisambiguation = !overridenSymbols.forall(_ is Deferred) - def hasNonInterfaceDefinition = overridenSymbols.forall(!_.owner.is(Trait)) + lazy val competingMethods = cls.baseClasses.iterator + .filter(_ ne meth.owner) + .map(meth.overriddenSymbol) + .filter(_.exists) + .toList + + def needsDisambiguation = competingMethods.exists(x=> !(x is Deferred)) // multiple implementations are available + def hasNonInterfaceDefinition = competingMethods.exists(!_.owner.is(Trait)) // there is a definition originating from class meth.is(Method, butNot = PrivateOrAccessorOrDeferred) && isCurrent(meth) && (needsDisambiguation || hasNonInterfaceDefinition || meth.owner.is(Scala2x)) diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 8189f3c67..3b8ada2a8 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -842,7 +842,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit val proto2 = // the computed type of the `elemtpt` field if (!tree.elemtpt.isEmpty) WildcardType else if (isFullyDefined(proto1, ForceDegree.none)) proto1 - else if (tree.elems.isEmpty && tree.isInstanceOf[Trees.JavaSeqLiteral[_]]) + else if (tree.elems.isEmpty && tree.isInstanceOf[Trees.JavaSeqLiteral[_]]) defn.ObjectType // generic empty Java varargs are of type Object[] else ctx.typeComparer.lub(elems1.tpes) val elemtpt1 = typed(tree.elemtpt, proto2) @@ -961,13 +961,23 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit assignType(cpy.TypeBoundsTree(tree)(lo1, hi1), lo1, hi1) } - def typedBind(tree: untpd.Bind, pt: Type)(implicit ctx: Context): Bind = track("typedBind") { + def typedBind(tree: untpd.Bind, pt: Type)(implicit ctx: Context): Tree = track("typedBind") { val pt1 = fullyDefinedType(pt, "pattern variable", tree.pos) val body1 = typed(tree.body, pt1) typr.println(i"typed bind $tree pt = $pt1 bodytpe = ${body1.tpe}") - val flags = if (tree.isType) BindDefinedType else EmptyFlags - val sym = ctx.newSymbol(ctx.owner, tree.name, flags, body1.tpe, coord = tree.pos) - assignType(cpy.Bind(tree)(tree.name, body1), sym) + body1 match { + case UnApply(fn, Nil, arg :: Nil) if tree.body.isInstanceOf[untpd.Typed] => + // A typed pattern `x @ (_: T)` with an implicit `ctag: ClassTag[T]` + // was rewritten to `x @ ctag(_)`. + // Rewrite further to `ctag(x @ _)` + assert(fn.symbol.owner == defn.ClassTagClass) + tpd.cpy.UnApply(body1)(fn, Nil, + typed(untpd.Bind(tree.name, arg).withPos(tree.pos), arg.tpe) :: Nil) + case _ => + val flags = if (tree.isType) BindDefinedType else EmptyFlags + val sym = ctx.newSymbol(ctx.owner, tree.name, flags, body1.tpe, coord = tree.pos) + assignType(cpy.Bind(tree)(tree.name, body1), sym) + } } def typedAlternative(tree: untpd.Alternative, pt: Type)(implicit ctx: Context): Alternative = track("typedAlternative") { diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index 062625c23..48242f2d1 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -51,8 +51,11 @@ class tests extends CompilerTest { val sourceDir = "./src/" val dottyDir = sourceDir + "dotty/" val toolsDir = dottyDir + "tools/" + val backendDir = toolsDir + "backend/" val dotcDir = toolsDir + "dotc/" val coreDir = dotcDir + "core/" + val parsingDir = dotcDir + "parsing/" + val replDir = dotcDir + "repl/" val typerDir = dotcDir + "typer/" @Test def pickle_pickleOK = compileDir(testsDir, "pickling", testPickling) @@ -193,11 +196,35 @@ class tests extends CompilerTest { @Test def java_all = compileFiles(javaDir, twice) //@Test def dotc_compilercommand = compileFile(dotcDir + "config/", "CompilerCommand") + //TASTY tests @Test def tasty_new_all = compileFiles(newDir, testPickling) + + @Test def tasty_dotty = compileDir(sourceDir, "dotty", testPickling) + @Test def tasty_annotation_internal = compileDir(s"${dottyDir}annotation/", "internal", testPickling) + @Test def tasty_runtime = compileDir(s"$dottyDir", "runtime", testPickling) + + //TODO: issues with ./src/dotty/runtime/vc/VCPrototype.scala + //@Test def tasty_runtime_vc = compileDir(s"${dottyDir}runtime/", "vc", testPickling) + + @Test def tasty_tools = compileDir(dottyDir, "tools", testPickling) + + //TODO: issue with ./src/dotty/tools/backend/jvm/DottyBackendInterface.scala + @Test def tasty_backend_jvm = compileList("tasty_backend_jvm", List( + "CollectEntryPoints.scala", "GenBCode.scala", "LabelDefs.scala", + "scalaPrimitives.scala" + ) map (s"${backendDir}jvm/" + _), testPickling) + + //TODO: issue with ./src/dotty/tools/backend/sjs/JSCodeGen.scala + @Test def tasty_backend_sjs = compileList("tasty_backend_sjs", List( + "GenSJSIR.scala", "JSDefinitions.scala", "JSEncoding.scala", "JSInterop.scala", + "JSPositions.scala", "JSPrimitives.scala", "ScopedVar.scala" + ) map (s"${backendDir}sjs/" + _), testPickling) + + @Test def tasty_dotc = compileDir(toolsDir, "dotc", testPickling) + @Test def tasty_dotc_ast = compileDir(dotcDir, "ast", testPickling) @Test def tasty_dotc_config = compileDir(dotcDir, "config", testPickling) - @Test def tasty_dotc_printing = compileDir(dotcDir, "printing", testPickling) - //@Test def tasty_dotc_reporting = compileDir(dotcDir, "reporting", testPickling) - @Test def tasty_dotc_util = compileDir(dotcDir, "util", testPickling) + + //TODO: issue with ./src/dotty/tools/dotc/core/Types.scala @Test def tasty_core = compileList("tasty_core", List( "Annotations.scala", "Constants.scala", "Constraint.scala", "ConstraintHandling.scala", "ConstraintRunInfo.scala", "Contexts.scala", "Decorators.scala", "Definitions.scala", @@ -208,15 +235,56 @@ class tests extends CompilerTest { "TypeApplications.scala", "TypeComparer.scala", "TypeErasure.scala", "TypeOps.scala", "TyperState.scala", "Uniques.scala" ) map (coreDir + _), testPickling) - @Test def tasty_typer = compileList("tasty_typer", List( - "Applications.scala", "Checking.scala", "ConstFold.scala", "ErrorReporting.scala", - "EtaExpansion.scala", "FrontEnd.scala", "Implicits.scala", "ImportInfo.scala", - "Inferencing.scala", "Mode.scala", "ProtoTypes.scala", "ReTyper.scala", "RefChecks.scala", - "TypeAssigner.scala", "Typer.scala", "VarianceChecker.scala", "Variances.scala" - ) map (typerDir + _), testPickling) - @Test def tasty_tasty = compileDir(coreDir, "tasty", testPickling) + @Test def tasty_classfile = compileDir(coreDir, "classfile", testPickling) + @Test def tasty_tasty = compileDir(coreDir, "tasty", testPickling) @Test def tasty_unpickleScala2 = compileDir(coreDir, "unpickleScala2", testPickling) + + //TODO: issue with ./src/dotty/tools/dotc/parsing/Parsers.scala + @Test def tasty_dotc_parsing = compileList("tasty_dotc_parsing", List( + "CharArrayReader.scala", "JavaParsers.scala", "JavaScanners.scala", "JavaTokens.scala", + "MarkupParserCommon.scala", "MarkupParsers.scala", "package.scala" ,"Scanners.scala", + "ScriptParsers.scala", "SymbolicXMLBuilder.scala", "Tokens.scala", "Utility.scala" + ) map (parsingDir + _), testPickling) + + @Test def tasty_dotc_printing = compileDir(dotcDir, "printing", testPickling) + + //TODO: issues with ./src/dotty/tools/dotc/repl/CompilingInterpreter.scala, + //./src/dotty/tools/dotc/repl/InterpreterLoop.scala + @Test def tasty_dotc_repl = compileList("tasty_dotc_repl", List( + "AbstractFileClassLoader.scala", "ConsoleWriter.scala", "InteractiveReader.scala", + "Interpreter.scala", "Main.scala", "NewLinePrintWriter.scala", "REPL.scala", "SimpleReader.scala" + ) map (replDir + _), testPickling) + + //@Test def tasty_dotc_reporting = compileDir(dotcDir, "reporting", testPickling) + @Test def tasty_dotc_rewrite = compileDir(dotcDir, "rewrite", testPickling) + + //TODO: issues with LazyVals.scala, PatternMatcher.scala + @Test def tasty_dotc_transform = compileList("tasty_dotc_transform", List( + "AugmentScala2Traits.scala", "CapturedVars.scala", "CheckReentrant.scala", "CheckStatic.scala", + "ClassOf.scala", "CollectEntryPoints.scala", "Constructors.scala", "CrossCastAnd.scala", + "CtxLazy.scala", "ElimByName.scala", "ElimErasedValueType.scala", "ElimRepeated.scala", + "ElimStaticThis.scala", "Erasure.scala", "ExpandPrivate.scala", "ExpandSAMs.scala", + "ExplicitOuter.scala", "ExplicitSelf.scala", "ExtensionMethods.scala", "FirstTransform.scala", + "Flatten.scala", "FullParameterization.scala", "FunctionalInterfaces.scala", "GetClass.scala", + "Getters.scala", "InterceptedMethods.scala", "LambdaLift.scala", "LiftTry.scala", "LinkScala2ImplClasses.scala", + "MacroTransform.scala", "Memoize.scala", "Mixin.scala", "MixinOps.scala", "NonLocalReturns.scala", + "NormalizeFlags.scala", "OverridingPairs.scala", "ParamForwarding.scala", "Pickler.scala", "PostTyper.scala", + "ResolveSuper.scala", "RestoreScopes.scala", "SeqLiterals.scala", "Splitter.scala", "SuperAccessors.scala", + "SymUtils.scala", "SyntheticMethods.scala", "TailRec.scala", "TreeChecker.scala", "TreeExtractors.scala", + "TreeGen.scala", "TreeTransform.scala", "TypeTestsCasts.scala", "TypeUtils.scala", "ValueClasses.scala", + "VCElideAllocations.scala", "VCInlineMethods.scala" + ) map (s"${dotcDir}transform/" + _), testPickling) + + //TODO: issue with ./src/dotty/tools/dotc/typer/Namer.scala + @Test def tasty_typer = compileList("tasty_typer", List( + "Applications.scala", "Checking.scala", "ConstFold.scala", "ErrorReporting.scala", + "EtaExpansion.scala", "FrontEnd.scala", "Implicits.scala", "ImportInfo.scala", + "Inferencing.scala", "Mode.scala", "ProtoTypes.scala", "ReTyper.scala", "RefChecks.scala", + "TypeAssigner.scala", "Typer.scala", "VarianceChecker.scala", "Variances.scala" + ) map (typerDir + _), testPickling) + + @Test def tasty_dotc_util = compileDir(dotcDir, "util", testPickling) @Test def tasty_tools_io = compileDir(toolsDir, "io", testPickling) @Test def tasty_tests = compileDir(testsDir, "tasty", testPickling) } diff --git a/tests/neg/Variances.scala b/tests/neg/Variances.scala new file mode 100644 index 000000000..0ceb64452 --- /dev/null +++ b/tests/neg/Variances.scala @@ -0,0 +1,15 @@ +trait HasY { type Y } + +// These are neg-tests corresponding to the pos-test Variances.scala +// where all the variance annotations have been inverted. +trait Foo1[+X] { def bar[Y <: X](y: Y) = y } // error +trait Foo2[+X] { def bar(x: HasY { type Y <: X })(y: x.Y) = y } // error +trait Foo3[-X] { def bar[Y >: X](y: Y) = y } // error +trait Foo4[-X] { def bar(x: HasY { type Y >: X })(y: x.Y) = y } // error + +// These are neg-tests corresponding to the pos-test Variances.scala +// where all the bounds have been flipped. +trait Foo5[-X] { def bar[Y >: X](y: Y) = y } // error +trait Foo6[-X] { def bar(x: HasY { type Y >: X })(y: x.Y) = y } // error +trait Foo7[+X] { def bar[Y <: X](y: Y) = y } // error +trait Foo8[+X] { def bar(x: HasY { type Y <: X })(y: x.Y) = y } // error diff --git a/tests/neg/i1059.scala b/tests/neg/i1059.scala new file mode 100644 index 000000000..1fb89afd0 --- /dev/null +++ b/tests/neg/i1059.scala @@ -0,0 +1,10 @@ +object Repeated { + val list = List(1, 2, 3) + + list match { + case List(_, _, _, _ @ _*) => 0 // error: only allowed in Scala2 mode + case List(_, _, _*) => 1 // error: only allowed in Scala2 mode + case List(_, _: _*) => 2 + case Nil => 3 + } +} diff --git a/tests/pos-scala2/i1059.scala b/tests/pos-scala2/i1059.scala new file mode 100644 index 000000000..cd23e1916 --- /dev/null +++ b/tests/pos-scala2/i1059.scala @@ -0,0 +1,10 @@ +object Repeated { + val list = List(1, 2, 3) + + list match { + case List(_, _, _, _ @ _*) => 0 + case List(_, _, _*) => 1 + case List(_, _: _*) => 2 + case Nil => 3 + } +} diff --git a/tests/pos/Variances.scala b/tests/pos/Variances.scala new file mode 100644 index 000000000..5c448ec88 --- /dev/null +++ b/tests/pos/Variances.scala @@ -0,0 +1,15 @@ +trait HasY { type Y } + +// This works in scalac. +trait Foo1[-X] { def bar[Y <: X](y: Y) = y } + +// A variant of Foo1 using a dependent method type (doesn't work using +// scalac) +trait Foo2[-X] { def bar(x: HasY { type Y <: X })(y: x.Y) = y } + +// This works in scalac. +trait Foo3[+X] { def bar[Y >: X](y: Y) = y } + +// A variant of Foo3 using a dependent method type (doesn't work +// using scalac) +trait Foo4[+X] { def bar(x: HasY { type Y >: X })(y: x.Y) = y } diff --git a/tests/pos/i1174.scala b/tests/pos/i1174.scala new file mode 100644 index 000000000..5875a38ad --- /dev/null +++ b/tests/pos/i1174.scala @@ -0,0 +1,19 @@ +import scala.reflect.ClassTag +import scala.util._ + +object Main { + class A + + def constructAs[TTT <: A](implicit ev: ClassTag[TTT]): Try[TTT] = Try { + new A() + }.flatMap { + case ev(inst) => + val b: TTT = inst + Success(inst) + case inst: TTT => + Success(inst) + case _ => + val tag = implicitly[ClassTag[TTT]] + Failure(new ClassCastException(s"Failed to construct instance of class ${tag.runtimeClass.getName}")) + } +} diff --git a/tests/run/no-useless-forwarders.scala b/tests/run/no-useless-forwarders.scala new file mode 100644 index 000000000..699295027 --- /dev/null +++ b/tests/run/no-useless-forwarders.scala @@ -0,0 +1,17 @@ +trait A { + def foo(a: Int): Int = a + def bar(a: Int): Int +} + +trait B { + def bar(a: Int): Int = a +} + +object Test extends A with B{ + def main(args: Array[String]) = { + assert(!this.getClass.getDeclaredMethods.exists{x: java.lang.reflect.Method => x.getName == "foo"}, + "no forwarder is needed here") + assert(!this.getClass.getDeclaredMethods.exists{x: java.lang.reflect.Method => x.getName == "bar"}, + "no forwarder is needed here") + } +} |