diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/TreeGen.scala | 14 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | 17 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Flags.scala | 7 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Symbols.scala | 3 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Types.scala | 42 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Mixin.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | 75 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 14 | ||||
-rw-r--r-- | src/library/scala/collection/TraversableViewLike.scala | 7 | ||||
-rw-r--r-- | src/library/scala/collection/immutable/Range.scala | 18 | ||||
-rw-r--r-- | test/files/jvm/t1342.check | 2 | ||||
-rw-r--r-- | test/files/jvm/t1342/JI.java | 3 | ||||
-rw-r--r-- | test/files/jvm/t1342/SI.scala | 10 |
13 files changed, 177 insertions, 37 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 89762ce258..db5c2f2afe 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -271,7 +271,6 @@ abstract class TreeGen DefDef(accessor setFlag lateDEFERRED, EmptyTree) def mkRuntimeCall(meth: Name, args: List[Tree]): Tree = { - assert(meth.toString != "boxArray") // !!! can be removed once arrays are in. Apply(Select(mkAttributedRef(ScalaRunTimeModule), meth), args) } @@ -302,6 +301,19 @@ abstract class TreeGen def mkForwarder(target: Tree, vparamss: List[List[Symbol]]) = (target /: vparamss)((fn, vparams) => Apply(fn, vparams map paramToArg)) + /** Applies a wrapArray call to an array, making it a WrappedArray + */ + def mkWrapArray(tree: Tree, elemtp: Type) = { + val predef = mkAttributedRef(PredefModule) + val meth = + if ((elemtp <:< AnyRefClass.tpe) && !isPhantomClass(elemtp.typeSymbol) || + isValueClass(elemtp.typeSymbol)) + Select(predef, "wrapArray") + else + TypeApply(Select(predef, "genericWrapArray"), List(TypeTree(elemtp))) + Apply(meth, List(tree)) + } + /** Used in situations where you need to access value of an expression several times */ def evalOnce(expr: Tree, owner: Symbol, unit: CompilationUnit)(within: (() => Tree) => Tree): Tree = { diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index d17018d47e..a4f228cffb 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -241,6 +241,8 @@ self => var assumedClosingParens = collection.mutable.Map(RPAREN -> 0, RBRACKET -> 0, RBRACE -> 0) + var inFunReturnType = false + protected def skip(targetToken: Int) { var nparens = 0 var nbraces = 0 @@ -2113,7 +2115,13 @@ self => val tparams = typeParamClauseOpt(name, contextBoundBuf) val vparamss = paramClauses(name, contextBoundBuf.toList, false) newLineOptWhenFollowedBy(LBRACE) - var restype = typedOpt() + val savedInFunReturnType = inFunReturnType + var restype = try { + inFunReturnType = true + typedOpt() + } finally { + inFunReturnType = savedInFunReturnType + } val rhs = if (isStatSep || in.token == RBRACE) { if (restype.isEmpty) restype = scalaUnitConstr @@ -2508,8 +2516,6 @@ self => (self, stats.toList) } - - /** RefineStatSeq ::= RefineStat {semi RefineStat} * RefineStat ::= Dcl * | type TypeDef @@ -2521,7 +2527,10 @@ self => if (isDclIntro) { // don't IDE hook stats ++= joinComment(defOrDcl(in.offset, NoMods)) } else if (!isStatSep) { - syntaxErrorOrIncomplete("illegal start of declaration", true) + syntaxErrorOrIncomplete( + "illegal start of declaration"+ + (if (inFunReturnType) " (possible cause: missing `=' in front of current method body)" + else ""), true) } if (in.token != RBRACE) acceptStatSep() } diff --git a/src/compiler/scala/tools/nsc/symtab/Flags.scala b/src/compiler/scala/tools/nsc/symtab/Flags.scala index dabdd32e69..9b1380d5e8 100644 --- a/src/compiler/scala/tools/nsc/symtab/Flags.scala +++ b/src/compiler/scala/tools/nsc/symtab/Flags.scala @@ -83,6 +83,7 @@ object Flags { final val LOCKED = 0x8000000000L // temporary flag to catch cyclic dependencies final val SPECIALIZED = 0x10000000000L// symbol is a generated specialized member final val DEFAULTINIT = 0x20000000000L// symbol is a generated specialized member + final val VBRIDGE = 0x40000000000L// symbol is a varargs bridge final val InitialFlags = 0x0001FFFFFFFFFFFFL // flags that are enabled from phase 1. final val LateFlags = 0x00FE000000000000L // flags that override flags in 0x1FC. @@ -232,7 +233,10 @@ object Flags { /** These modifiers appear in TreePrinter output. */ final val PrintableFlags: Long = ExplicitFlags | LOCAL | SYNTHETIC | STABLE | CASEACCESSOR | - ACCESSOR | SUPERACCESSOR | PARAMACCESSOR | BRIDGE | STATIC + ACCESSOR | SUPERACCESSOR | PARAMACCESSOR | BRIDGE | STATIC | VBRIDGE + + /** The two bridge flags */ + final val BRIDGES = BRIDGE | VBRIDGE final val FieldFlags: Long = MUTABLE | CASEACCESSOR | PARAMACCESSOR | STATIC | FINAL | PRESUPER | LAZY @@ -321,6 +325,7 @@ object Flags { case SUPERACCESSOR => "<superaccessor>" case PARAMACCESSOR => "<paramaccessor>" + case VBRIDGE => "<...bridge>" case _ => "" } diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index ce8a2edbfa..bf2ff9d9a3 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -1514,7 +1514,8 @@ trait Symbols { /** If settings.uniqid is set, the symbol's id, else "" */ final def idString: String = - if (settings.uniqid.value) "#"+id else "" + if (settings.uniqid.value) "#"+id // +" in "+owner.name+"#"+owner.id // DEBUG + else "" /** String representation, including symbol's kind * e.g., "class Foo", "method Bar". diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index 710e7e1487..1183d26fc2 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -426,33 +426,47 @@ trait Types { * Members appear in linearization order of their owners. * Members with the same owner appear in reverse order of their declarations. */ - def members: List[Symbol] = findMember(nme.ANYNAME, 0, 0, false)(NoSymbol).alternatives + def members: List[Symbol] = findMember(nme.ANYNAME, 0, 0, false).alternatives /** A list of all non-private members of this type (defined or inherited) */ def nonPrivateMembers: List[Symbol] = - findMember(nme.ANYNAME, PRIVATE | BRIDGE, 0, false)(NoSymbol).alternatives + findMember(nme.ANYNAME, PRIVATE | BRIDGES, 0, false).alternatives + + /** A list of all non-private members of this type (defined or inherited), + * admitting members with given flags `admit` + */ + def nonPrivateMembersAdmitting(admit: Long): List[Symbol] = + findMember(nme.ANYNAME, (PRIVATE | BRIDGES) & ~admit, 0, false).alternatives /** A list of all implicit symbols of this type (defined or inherited) */ def implicitMembers: List[Symbol] = - findMember(nme.ANYNAME, BRIDGE, IMPLICIT, false)(NoSymbol).alternatives + findMember(nme.ANYNAME, BRIDGES, IMPLICIT, false).alternatives /** A list of all deferred symbols of this type (defined or inherited) */ def deferredMembers: List[Symbol] = - findMember(nme.ANYNAME, BRIDGE, DEFERRED, false)(NoSymbol).alternatives + findMember(nme.ANYNAME, BRIDGES, DEFERRED, false).alternatives /** The member with given name, * an OverloadedSymbol if several exist, NoSymbol if none exist */ - def member(name: Name): Symbol = findMember(name, BRIDGE, 0, false)(NoSymbol) + def member(name: Name): Symbol = findMember(name, BRIDGES, 0, false) /** The non-private member with given name, - * an OverloadedSymbol if several exist, NoSymbol if none exist */ + * an OverloadedSymbol if several exist, NoSymbol if none exist. + * Bridges are excluded from the result + */ def nonPrivateMember(name: Name): Symbol = - findMember(name, PRIVATE | BRIDGE, 0, false)(NoSymbol) + findMember(name, PRIVATE | BRIDGES, 0, false) + + /** The non-private member with given name, admitting members with given flags `admit` + * an OverloadedSymbol if several exist, NoSymbol if none exist + */ + def nonPrivateMemberAdmitting(name: Name, admit: Long): Symbol = + findMember(name, (PRIVATE | BRIDGES) & ~admit, 0, false) /** The non-local member with given name, * an OverloadedSymbol if several exist, NoSymbol if none exist */ - def nonLocalMember(name: Name)(from : Symbol): Symbol = - findMember(name, LOCAL | BRIDGE, 0, false)(from) + def nonLocalMember(name: Name): Symbol = + findMember(name, LOCAL | BRIDGES, 0, false) /** The least type instance of given class which is a supertype * of this type */ @@ -730,16 +744,15 @@ trait Types { * @param excludedFlags Returned members do not have these flags * @param requiredFlags Returned members do have these flags * @param stableOnly If set, return only members that are types or stable values - * @param from ?? */ //TODO: use narrow only for modules? (correct? efficiency gain?) - def findMember(name: Name, excludedFlags: Int, requiredFlags: Long, stableOnly: Boolean)(from:Symbol): Symbol = { + def findMember(name: Name, excludedFlags: Long, requiredFlags: Long, stableOnly: Boolean): Symbol = { // if this type contains type variables, get rid of them; // without this, the matchesType call would lead to type variables on both sides // of a subtyping/equality judgement, which can lead to recursive types being constructed. // See (t0851) for a situation where this happens. if (!this.isGround) - return typeVarToOriginMap(this).findMember(name, excludedFlags, requiredFlags, stableOnly)(from) + return typeVarToOriginMap(this).findMember(name, excludedFlags, requiredFlags, stableOnly) if (util.Statistics.enabled) findMemberCount += 1 // val startTime = if (util.Statistics.enabled) System.nanoTime() else 0l @@ -943,8 +956,7 @@ trait Types { // todo see whether we can do without override def isError: Boolean = true override def decls: Scope = new ErrorScope(NoSymbol) - override def findMember(name: Name, excludedFlags: Int, - requiredFlags: Long, stableOnly: Boolean)(from : Symbol): Symbol = { + override def findMember(name: Name, excludedFlags: Long, requiredFlags: Long, stableOnly: Boolean): Symbol = { var sym = decls lookup name if (sym == NoSymbol) { sym = NoSymbol.newErrorSymbol(name) @@ -3421,7 +3433,7 @@ A type's typeSymbol should never be inspected directly. } else if ((pre eq NoPrefix) || (pre eq NoType) || sym.owner.isPackageClass) { sym } else { - var rebind0 = pre.findMember(sym.name, BRIDGE, 0, true)(NoSymbol) + var rebind0 = pre.findMember(sym.name, BRIDGE, 0, true) if (rebind0 == NoSymbol) { if (sym.isAliasType) throw missingAliasException assert(false, pre+"."+sym+" does no longer exist, phase = "+phase) diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 9a23418594..8133478c88 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -237,7 +237,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { val imember = member.overriddenSymbol(iface) //Console.println("mixin member "+member+":"+member.tpe+member.locationString+" "+imember+" "+imember.overridingSymbol(clazz)+" to "+clazz+" with scope "+clazz.info.decls)//DEBUG if (imember.overridingSymbol(clazz) == NoSymbol && - clazz.info.findMember(member.name, 0, lateDEFERRED, false)(NoSymbol).alternatives.contains(imember)) { + clazz.info.findMember(member.name, 0, lateDEFERRED, false).alternatives.contains(imember)) { val member1 = addMember( clazz, member.cloneSymbol(clazz) setPos clazz.pos resetFlag (DEFERRED | lateDEFERRED)) diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index aa3eafc29d..99bf3916a2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -59,6 +59,15 @@ abstract class RefChecks extends InfoTransform { PolyType(List(), tp) } else tp + val toJavaRepeatedParam = new TypeMap { + def apply(tp: Type) = tp match { + case TypeRef(pre, RepeatedParamClass, args) => + typeRef(pre, JavaRepeatedParamClass, args) + case _ => + mapOver(tp) + } + } + class RefCheckTransformer(unit: CompilationUnit) extends Transformer { var localTyper: analyzer.Typer = typer; @@ -91,6 +100,61 @@ abstract class RefChecks extends InfoTransform { // Override checking ------------------------------------------------------------ + def hasRepeatedParam(tp: Type): Boolean = tp match { + case MethodType(formals, restpe) => + formals.nonEmpty && formals.last.tpe.typeSymbol == RepeatedParamClass || + hasRepeatedParam(restpe) + case PolyType(_, restpe) => + hasRepeatedParam(restpe) + case _ => + false + } + + /** Add bridges for vararg methods that extend Java vararg methods + */ + def addVarargBridges(clazz: Symbol): List[Tree] { + val self = clazz.thisType + + val bridges = new ListBuffer[Tree] + + def varargBridge(member: Symbol, bridgetpe: Type): Tree = { + val bridge = member.cloneSymbolImpl(clazz) + .setPos(clazz.pos).setFlag(member.flags | VBRIDGE) + bridge.setInfo(bridgetpe.cloneInfo(bridge)) + clazz.info.decls enter bridge + val List(params) = bridge.paramss + val TypeRef(_, JavaRepeatedParamClass, List(elemtp)) = params.last.tpe + val (initargs, List(lastarg0)) = (params map Ident) splitAt (params.length - 1) + val lastarg = gen.wildcardStar(gen.mkWrapArray(lastarg0, elemtp)) + val body = Apply(Select(This(clazz), member), initargs ::: List(lastarg)) + localTyper.typed { + /*util.trace("generating varargs bridge")*/(DefDef(bridge, body)) + } + } + + // For all concrete non-private members that have a (Scala) repeated parameter: + // compute the corresponding method type `jtpe` with a Java repeated parameter + // if a method with type `jtpe` exists and that method is not a varargs bridge + // then create a varargs bridge of type `jtpe` that forwards to the + // member method with the Scala vararg type. + for (member <- clazz.info.nonPrivateMembers) { + if (!(member hasFlag DEFERRED) && hasRepeatedParam(member.info)) { + val jtpe = toJavaRepeatedParam(self.memberType(member)) + val inherited = clazz.info.nonPrivateMemberAdmitting(member.name, VBRIDGE) filter ( + sym => (self.memberType(sym) matches jtpe) && !(sym hasFlag VBRIDGE) + // this is a bit tortuous: we look for non-private members or bridges + // if we find a bridge everything is OK. If we find another member, + // we need to create a bridge + ) + if (inherited.exists) { + bridges += varargBridge(member, jtpe) + } + } + } + + bridges.toList + } + /** 1. Check all members of class `clazz' for overriding conditions. * That is for overriding member M and overridden member O: * @@ -325,14 +389,15 @@ abstract class RefChecks extends InfoTransform { // Bridge symbols qualify. // Used as a fall back if no overriding symbol of a Java abstract method can be found def javaErasedOverridingSym(sym: Symbol): Symbol = - clazz.tpe.findMember(sym.name, PRIVATE, 0, false)(NoSymbol).filter(other => + clazz.tpe.nonPrivateMemberAdmitting(sym.name, BRIDGE).filter(other => !other.isDeferred && (other hasFlag JAVA) && { val tp1 = erasure.erasure(clazz.thisType.memberType(sym)) val tp2 = erasure.erasure(clazz.thisType.memberType(other)) atPhase(currentRun.erasurePhase.next)(tp1 matches tp2) }) - for (member <- clazz.tpe.nonPrivateMembers) + + for (member <- clazz.tpe.nonPrivateMembersAdmitting(VBRIDGE)) if (member.isDeferred && !(clazz hasFlag ABSTRACT) && !isAbstractTypeWithoutFBound(member) && !((member hasFlag JAVA) && javaErasedOverridingSym(member) != NoSymbol)) { @@ -346,6 +411,7 @@ abstract class RefChecks extends InfoTransform { " and overrides incomplete superclass member " + infoString(other) else "")) } + // 3. Check that concrete classes do not have deferred definitions // that are not implemented in a subclass. // Note that this is not the same as (2); In a situation like @@ -912,11 +978,14 @@ abstract class RefChecks extends InfoTransform { case ValDef(_, _, _, _) => checkDeprecatedOvers() - case Template(_, _, _) => + case Template(parents, self, body) => localTyper = localTyper.atOwner(tree, currentOwner) validateBaseTypes(currentOwner) checkDefaultsInOverloaded(currentOwner) + val bridges = addVarargBridges(currentOwner) checkAllOverrides(currentOwner) + if (bridges.nonEmpty) + result = treeCopy.Template(tree, parents, self, body ::: bridges) case TypeTree() => val existentialParams = new ListBuffer[Symbol] diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 9c5edf7e86..4e821f30a5 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -669,12 +669,12 @@ trait Typers { self: Analyzer => } /** The member with given name of given qualifier tree */ - def member(qual: Tree, name: Name)(from : Symbol) = qual.tpe match { + def member(qual: Tree, name: Name) = qual.tpe match { case ThisType(clazz) if (context.enclClass.owner.hasTransOwner(clazz)) => qual.tpe.member(name) case _ => if (phase.next.erasedTypes) qual.tpe.member(name) - else qual.tpe.nonLocalMember(name)(from) + else qual.tpe.nonLocalMember(name) } def silent(op: Typer => Tree): AnyRef /* in fact, TypeError or Tree */ = { @@ -837,7 +837,7 @@ trait Typers { self: Analyzer => } case _ => def applyPossible = { - def applyMeth = member(adaptToName(tree, nme.apply), nme.apply)(context.owner) + def applyMeth = member(adaptToName(tree, nme.apply), nme.apply) if ((mode & TAPPmode) != 0) tree.tpe.typeParams.isEmpty && applyMeth.filter(! _.tpe.typeParams.isEmpty) != NoSymbol else @@ -1035,7 +1035,7 @@ trait Typers { self: Analyzer => * If no conversion is found, return `qual' unchanged. */ def adaptToName(qual: Tree, name: Name) = - if (member(qual, name)(context.owner) != NoSymbol) qual + if (member(qual, name) != NoSymbol) qual else adaptToMember(qual, HasMember(name)) private def typePrimaryConstrBody(clazz : Symbol, cbody: Tree, tparams: List[Symbol], enclTparams: List[Symbol], vparamss: List[List[ValDef]]): Tree = { @@ -1662,10 +1662,10 @@ trait Typers { self: Analyzer => val tparams1 = ddef.tparams mapConserve typedTypeDef val vparamss1 = ddef.vparamss mapConserve (_ mapConserve typedValDef) - for (vparams1 <- vparamss1; vparam1 <- vparams1 dropRight 1) { + for (vparams1 <- vparamss1; vparam1 <- vparams1 dropRight 1) if (isRepeatedParamType(vparam1.symbol.tpe)) error(vparam1.pos, "*-parameter must come last") - } + var tpt1 = checkNoEscaping.privates(meth, typedType(ddef.tpt)) if (!settings.Xexperimental.value) { for (vparams <- vparamss1; vparam <- vparams) { @@ -3296,7 +3296,7 @@ trait Typers { self: Analyzer => } tree.symbol } else { - member(qual, name)(context.owner) + member(qual, name) } if (sym == NoSymbol && name != nme.CONSTRUCTOR && (mode & EXPRmode) != 0) { val qual1 = adaptToName(qual, name) diff --git a/src/library/scala/collection/TraversableViewLike.scala b/src/library/scala/collection/TraversableViewLike.scala index 2f33776b74..8177658026 100644 --- a/src/library/scala/collection/TraversableViewLike.scala +++ b/src/library/scala/collection/TraversableViewLike.scala @@ -145,16 +145,15 @@ self => override def ++[B >: A, That](that: Traversable[B])(implicit bf: CanBuildFrom[This, B, That]): That = { newAppended(that).asInstanceOf[That] -// was: val b = bf(repr) -// if (b.isInstanceOf[NoBuilder[_]]) newAppended(that).asInstanceOf[That] -// else super.++[B, That](that)(bf) +// was: if (bf.isInstanceOf[ByPassCanBuildFrom]) newAppended(that).asInstanceOf[That] +// else super.++[B, That](that)(bf) } override def ++[B >: A, That](that: Iterator[B])(implicit bf: CanBuildFrom[This, B, That]): That = ++[B, That](that.toStream) override def map[B, That](f: A => B)(implicit bf: CanBuildFrom[This, B, That]): That = { newMapped(f).asInstanceOf[That] -// was: val b = bf(repr) +// val b = bf(repr) // if (b.isInstanceOf[NoBuilder[_]]) newMapped(f).asInstanceOf[That] // else super.map[B, That](f)(bf) } diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index 54a871decf..18b457e090 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -101,6 +101,9 @@ class Range(val start: Int, val end: Int, val step: Int) extends IndexedSeq[Int] final override def reverse: Range = new Range.Inclusive(last, start, -step) + /** Make range inclusive. + * @pre if (step > 0) end != MaxInt else end != MinInt + */ def inclusive = new Range.Inclusive(start, end, step) def contains(x: Int): Boolean = @@ -136,9 +139,24 @@ object Range { override protected def copy(start: Int, end: Int, step: Int): Range = new Inclusive(start, end, step) } + /** Make a range from `start` until `end` (exclusive) with step value 1. + */ def apply(start: Int, end: Int, step: Int): Range = new Range(start, end, step) + + /** Make an range from `start` to `end` inclusive with step value 1. + * @pre end != MaxInt + */ def apply(start: Int, end: Int): Range with ByOne = new Range(start, end, 1) with ByOne + + /** Make an inclusive range from start to end with given step value. + * @pre step != 0 + * @pre if (step > 0) end != MaxInt else end != MinInt + */ def inclusive(start: Int, end: Int, step: Int): Range.Inclusive = new Inclusive(start, end, step) + + /** Make an inclusive range from start to end with step value 1. + * @pre end != MaxInt + */ def inclusive(start: Int, end: Int): Range.Inclusive with ByOne = new Inclusive(start, end, 1) with ByOne trait ByOne extends Range { diff --git a/test/files/jvm/t1342.check b/test/files/jvm/t1342.check new file mode 100644 index 0000000000..814f4a4229 --- /dev/null +++ b/test/files/jvm/t1342.check @@ -0,0 +1,2 @@ +one +two diff --git a/test/files/jvm/t1342/JI.java b/test/files/jvm/t1342/JI.java new file mode 100644 index 0000000000..2de46d9084 --- /dev/null +++ b/test/files/jvm/t1342/JI.java @@ -0,0 +1,3 @@ +interface JI { + void varArgsMethod( String ... args ); +} diff --git a/test/files/jvm/t1342/SI.scala b/test/files/jvm/t1342/SI.scala new file mode 100644 index 0000000000..8e3b753210 --- /dev/null +++ b/test/files/jvm/t1342/SI.scala @@ -0,0 +1,10 @@ +class SI extends JI { + def varArgsMethod( args : String*) { + for( arg <- args ) println( arg ) + } +} + +object Test extends Application { + val x: JI = new SI + x.varArgsMethod("one", "two") +} |