summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-10-28 14:41:00 +0000
committerMartin Odersky <odersky@gmail.com>2009-10-28 14:41:00 +0000
commit0ce248ef65575dce910c82e5714d808851557669 (patch)
tree289a451fe6a621cd4fbc7345f1ec3094c3e819d2 /src
parentcf53536f9e1b668e9e05c280db84ef2eb502765c (diff)
downloadscala-0ce248ef65575dce910c82e5714d808851557669.tar.gz
scala-0ce248ef65575dce910c82e5714d808851557669.tar.bz2
scala-0ce248ef65575dce910c82e5714d808851557669.zip
Fixed #1342.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala14
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala17
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Flags.scala7
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala3
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala42
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala75
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala14
-rw-r--r--src/library/scala/collection/TraversableViewLike.scala7
-rw-r--r--src/library/scala/collection/immutable/Range.scala18
10 files changed, 162 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 {