summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-07-23 18:22:29 +0000
committerMartin Odersky <odersky@gmail.com>2007-07-23 18:22:29 +0000
commit16d3cf1f8f22c04559145b35bb5f6c0aacfb0d8c (patch)
tree75b5420467e9dae2ef88d6a4aca220b0f907fa2f
parent2d3a640e0bff8c79f99c070cf33f9ef921642a18 (diff)
downloadscala-16d3cf1f8f22c04559145b35bb5f6c0aacfb0d8c.tar.gz
scala-16d3cf1f8f22c04559145b35bb5f6c0aacfb0d8c.tar.bz2
scala-16d3cf1f8f22c04559145b35bb5f6c0aacfb0d8c.zip
many bug fixes; short syntax for structural types.
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala10
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala4
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala3
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala19
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala63
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala89
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala18
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala91
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala138
-rw-r--r--src/library/scala/collection/immutable/TreeSet.scala6
-rw-r--r--test/files/neg/bug835.check9
-rw-r--r--test/files/neg/bug875.check12
-rw-r--r--test/files/pos/bug602.scala4
-rwxr-xr-xtest/files/run/existentials.scala3
-rw-r--r--test/files/run/regularpatmatnew.scala2
-rw-r--r--test/files/run/withIndex.check2
-rw-r--r--test/files/run/withIndex.scala7
19 files changed, 307 insertions, 179 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index c0cefd5347..68a34def62 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -722,7 +722,10 @@ trait Parsers {
/** InfixType ::= CompoundType {id [nl] CompoundType}
*/
def infixType(isPattern: Boolean, mode: Int): Tree =
- infixTypeRest(inCurrentPos, annotType(isPattern), isPattern, mode)
+ infixTypeRest(inCurrentPos, infixTypeFirst(isPattern), isPattern, mode)
+
+ def infixTypeFirst(isPattern: boolean) =
+ if (inToken == LBRACE) scalaAnyRefConstr else annotType(isPattern)
def infixTypeRest(pos: ScanPosition, t0: Tree, isPattern: Boolean, mode: Int): Tree = {
val t = compoundTypeRest(pos, t0, isPattern)
@@ -742,9 +745,10 @@ trait Parsers {
}
/** CompoundType ::= AnnotType {with AnnotType} [Refinement]
+ * | Refinement
*/
def compoundType(isPattern: Boolean): Tree =
- compoundTypeRest(inCurrentPos, annotType(isPattern), isPattern)
+ compoundTypeRest(inCurrentPos, infixTypeFirst(isPattern), isPattern)
def compoundTypeRest(pos: ScanPosition, t: Tree, isPattern: Boolean): Tree = {
var ts = new ListBuffer[Tree] + t
@@ -1129,7 +1133,7 @@ trait Parsers {
}
}
- /* SimpleExpr ::= new ClassTemplate
+ /* SimpleExpr ::= new (ClassTemplate | TemplateBody)
* | BlockExpr
* | SimpleExpr1 [`_']
* SimpleExpr1 ::= literal
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index fcee9c4d0e..2848469215 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -140,7 +140,9 @@ abstract class TreeBuilder {
/** Create tree representing an object creation <new parents { stats }> */
def makeNew(parents: List[Tree], self: ValDef, stats: List[Tree], argss: List[List[Tree]]): Tree =
- if (parents.tail.isEmpty && stats.isEmpty)
+ if (parents.isEmpty)
+ makeNew(List(scalaAnyRefConstr), self, stats, argss)
+ else if (parents.tail.isEmpty && stats.isEmpty)
New(parents.head, argss)
else {
val x = nme.ANON_CLASS_NAME.toTypeName
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index dd2ac94f49..947e3c1151 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -215,6 +215,7 @@ trait Symbols {
final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR)
final def isAnonymousClass = isClass && (originalName startsWith nme.ANON_CLASS_NAME)
// startsWith necessary because name may grow when lifted and also because of anonymous function classes
+ def isAnonymousFunction = hasFlag(SYNTHETIC) && (originalName startsWith nme.ANON_FUN_NAME)
final def isRefinementClass = isClass && name == nme.REFINE_CLASS_NAME.toTypeName; // no lifting for refinement classes
final def isModuleClass = isClass && hasFlag(MODULE)
final def isPackageClass = isClass && hasFlag(PACKAGE)
@@ -585,7 +586,7 @@ trait Symbols {
def typeConstructor: Type =
throw new Error("typeConstructor inapplicable for " + this)
- def tpeHK = if(isType) typeConstructor else tpe // @M! used in memberType
+ def tpeHK = if (isType) typeConstructor else tpe // @M! used in memberType
/** The type parameters of this symbol */
def unsafeTypeParams: List[Symbol] =
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index b78cbb5583..57c8e4e60b 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -1957,7 +1957,7 @@ A type's typeSymbol should never be inspected directly.
override def toString =
lobounds.mkString("[ _>:(", ",", ") ") +
- hibounds.mkString("| _<:(", ",", ") | _= ") + inst
+ hibounds.mkString("| _<:(", ",", ") ] _= ") + inst
}
/** A prototype for mapping a function over all possible types
@@ -2166,15 +2166,15 @@ A type's typeSymbol should never be inspected directly.
def toInstance(pre: Type, clazz: Symbol): Type =
if ((pre eq NoType) || (pre eq NoPrefix) || !clazz.isClass) mapOver(tp) //@M! see test pos/tcpoly_return_overriding.scala why mapOver is necessary
else {
- val symclazz = sym.owner;
def throwError =
- throw new Error("" + tp + " in " + symclazz +
+ throw new Error("" + tp + sym.locationString +
" cannot be instantiated from " + pre.widen);
def instParam(ps: List[Symbol], as: List[Type]): Type =
if (ps.isEmpty) throwError
else if (sym eq ps.head) // @M! don't just replace the whole thing, might be followed by type application
appliedType(as.head, List.mapConserve(args)(this)) // @M: was as.head
else instParam(ps.tail, as.tail);
+ val symclazz = sym.owner
if (symclazz == clazz && (pre.widen.typeSymbol isNonBottomSubClass symclazz))
pre.baseType(symclazz) match {
case TypeRef(_, basesym, baseargs) =>
@@ -2609,6 +2609,17 @@ A type's typeSymbol should never be inspected directly.
* @return true, iff `tp1' and `tp2' denote
* equivalent types.
*/
+ var si = 0
+ def isSameType0(tp1: Type, tp2: Type): Boolean = {
+ for (i <- 0 until si) print(" ");
+ println(tp1+" =:= "+tp2)
+ si += 1
+ if (si > 10) throw new Error()
+ val res = isSameType0(tp1, tp2)
+ si -= 1
+ res
+ }
+
def isSameType(tp1: Type, tp2: Type): Boolean = {
(tp1, tp2) match {
case (ErrorType, _) => true
@@ -2777,7 +2788,7 @@ A type's typeSymbol should never be inspected directly.
(phase.erasedTypes || pre1 <:< pre2) &&
(sym2 == AnyClass || isSubArgs(args1, args2, sym1.typeParams)) //@M: Any is kind-polymorphic
||
- sym1.isAbstractType && !(tp1 =:= tp1.bounds.hi) && (tp1.bounds.hi <:< tp2)
+ sym1.isAbstractType && !(tp1 =:= tp1.bounds.hi) && (tp1.bounds.hi <:< tp2)
||
sym2.isAbstractType && !(tp2 =:= tp2.bounds.lo) && (tp1 <:< tp2.bounds.lo)
||
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 09cfa4a627..ce5a62aff1 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -793,7 +793,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
List(TypeTree(tp) setPos targ.pos)) setPos fn.pos,
List()) setPos tree.pos
targ.tpe match {
- case SingleType(pre, sym) =>
+ case SingleType(_, _) | ThisType(_) | SuperType(_, _) =>
val cmpOp = if (targ.tpe <:< AnyValClass.tpe) Any_equals else Object_eq
atPos(tree.pos) {
Apply(Select(qual, cmpOp), List(gen.mkAttributedQualifier(targ.tpe)))
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index d0e2bf1eca..736a5539b5 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -412,14 +412,14 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
val ncases = transformCaseDefs(cases)
var checkExhaustive = true
- def isUnsealedAnnotation(tpe: Type) = tpe match {
+ def isUncheckedAnnotation(tpe: Type) = tpe match {
case AnnotatedType(List(AnnotationInfo(atp, _, _)), _) if atp.typeSymbol == UncheckedClass =>
true
case _ =>
false
}
nselector match {
- case Typed(nselector1, tpt) if isUnsealedAnnotation(tpt.tpe) =>
+ case Typed(nselector1, tpt) if isUncheckedAnnotation(tpt.tpe) =>
nselector = nselector1
checkExhaustive = false
case _ =>
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 812896337f..7c3bd8d65e 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -235,8 +235,9 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
* to:
*
* class $anon() extends Object() with PartialFunction[T, R] with ScalaObject {
- * def apply(x: T): R = body;
- * def isDefinedAt(x: T): boolean = x match {
+ * def apply(x: T): R = (x: @unchecked) match {
+ * { case P_i if G_i => E_i }_i=1..n
+ * def isDefinedAt(x: T): boolean = (x: @unchecked) match {
* case P_1 if G_1 => true
* ...
* case P_n if G_n => true
@@ -264,29 +265,43 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
anonClass.info.decls enter applyMethod;
for (vparam <- fun.vparams) vparam.symbol.owner = applyMethod;
new ChangeOwnerTraverser(fun.symbol, applyMethod).traverse(fun.body);
- var members = List(
- DefDef(Modifiers(FINAL), nme.apply, List(), List(fun.vparams), TypeTree(restpe), fun.body)
- setSymbol applyMethod);
- if (fun.tpe.typeSymbol == PartialFunctionClass) {
- val isDefinedAtMethod = anonClass.newMethod(fun.pos, nme.isDefinedAt)
- .setFlag(FINAL).setInfo(MethodType(formals, BooleanClass.tpe))
- anonClass.info.decls enter isDefinedAtMethod
- def idbody(idparam: Symbol) = fun.body match {
- case Match(_, cases) =>
- val substParam = new TreeSymSubstituter(List(fun.vparams.head.symbol), List(idparam));
- def transformCase(cdef: CaseDef): CaseDef =
- substParam(
- resetAttrs(
- CaseDef(cdef.pat.duplicate, cdef.guard.duplicate, Literal(true))))
- if (cases exists treeInfo.isDefaultCase) Literal(true)
- else
- Match(
- Ident(idparam),
- (cases map transformCase) :::
- List(CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(false))))
- }
- members = DefDef(isDefinedAtMethod, vparamss => idbody(vparamss.head.head)) :: members;
+ def applyMethodDef(body: Tree) =
+ DefDef(Modifiers(FINAL), nme.apply, List(), List(fun.vparams), TypeTree(restpe), body)
+ .setSymbol(applyMethod)
+ def mkUnchecked(tree: Tree) = tree match {
+ case Match(selector, cases) =>
+ atPos(tree.pos) {
+ Match(
+ Annotated(Annotation(New(TypeTree(UncheckedClass.tpe), List(List())), List()), selector),
+ cases)
+ }
+ case _ =>
+ tree
}
+ val members =
+ if (fun.tpe.typeSymbol == PartialFunctionClass) {
+ val isDefinedAtMethod = anonClass.newMethod(fun.pos, nme.isDefinedAt)
+ .setFlag(FINAL).setInfo(MethodType(formals, BooleanClass.tpe))
+ anonClass.info.decls enter isDefinedAtMethod
+ def idbody(idparam: Symbol) = fun.body match {
+ case Match(_, cases) =>
+ val substParam = new TreeSymSubstituter(List(fun.vparams.head.symbol), List(idparam));
+ def transformCase(cdef: CaseDef): CaseDef =
+ substParam(
+ resetAttrs(
+ CaseDef(cdef.pat.duplicate, cdef.guard.duplicate, Literal(true))))
+ if (cases exists treeInfo.isDefaultCase) Literal(true)
+ else
+ Match(
+ Ident(idparam),
+ (cases map transformCase) :::
+ List(CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(false))))
+ }
+ List(applyMethodDef(mkUnchecked(fun.body)),
+ DefDef(isDefinedAtMethod, vparamss => mkUnchecked(idbody(vparamss.head.head))))
+ } else {
+ List(applyMethodDef(fun.body))
+ }
localTyper.typed {
atPos(fun.pos) {
Block(
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index ad8fb895c4..a18e2b80eb 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -574,6 +574,11 @@ trait Infer {
*/
def isStrictlyBetterExpr(tpe1: Type, tpe2: Type) = {
def isNullary(tpe: Type) = tpe.paramSectionCount == 0 || tpe.paramTypes.isEmpty
+ def isMethod(tpe: Type) = tpe match {
+ case MethodType(_, _) | PolyType(_, _) => true
+ case _ => false
+ }
+ isMethod(tpe2) && !isMethod(tpe1) ||
isNullary(tpe1) && !isNullary(tpe2) ||
isStrictlyBetter(tpe1, tpe2)
}
@@ -850,7 +855,8 @@ trait Infer {
def computeArgs =
try {
val targs = solvedTypes(tvars, undetparams, undetparams map varianceInType(restpe), true)
- checkBounds(tree.pos, NoPrefix, NoSymbol, undetparams, targs, "inferred ")
+// checkBounds(tree.pos, NoPrefix, NoSymbol, undetparams, targs, "inferred ")
+// no checkBounds here. If we enable it, test bug602 fails.
new TreeTypeSubstituter(undetparams, targs).traverse(tree)
} catch {
case ex: NoInstance =>
@@ -914,44 +920,51 @@ trait Infer {
}
}
- def checkCheckable(pos: Position, tp: Type) {
- def patternWarning(tp: Type, prefix: String) =
- context.unit.uncheckedWarning(pos, prefix+tp+" in type pattern is unchecked since it is eliminated by erasure")
- def isLocalBinding(sym: Symbol) =
- sym.isAbstractType &&
- (sym.name == nme.WILDCARD.toTypeName || {
- val e = context.scope.lookupEntry(sym.name)
- (e ne null) && e.sym == sym && e.owner == context.scope
- })
- tp match {
- case SingleType(pre, _) =>
- checkCheckable(pos, pre)
- case TypeRef(pre, sym, args) =>
- if (sym.isAbstractType)
- patternWarning(tp, "abstract type ")
- else if (sym == AllClass || sym == AllRefClass)
- error(pos, "this type cannot be used in a type pattern")
- else
- for (arg <- args) {
- if (sym == ArrayClass) checkCheckable(pos, arg)
- else arg match {
- case TypeRef(_, sym, _) if isLocalBinding(sym) =>
- ;
- case _ =>
- patternWarning(arg, "non variable type-argument ")
+ def checkCheckable(pos: Position, tp: Type, kind: String) {
+ def patternWarning(tp: Type, prefix: String) = {
+ context.unit.uncheckedWarning(pos, prefix+tp+" in type"+kind+" is unchecked since it is eliminated by erasure")
+ }
+ def check(tp: Type, bound: List[Symbol]) {
+ def isLocalBinding(sym: Symbol) =
+ sym.isAbstractType &&
+ ((bound contains sym) ||
+ sym.name == nme.WILDCARD.toTypeName || {
+ val e = context.scope.lookupEntry(sym.name)
+ (e ne null) && e.sym == sym && e.owner == context.scope
+ })
+ tp match {
+ case SingleType(pre, _) =>
+ check(pre, bound)
+ case TypeRef(pre, sym, args) =>
+ if (sym.isAbstractType)
+ patternWarning(tp, "abstract type ")
+ else if (sym == AllClass || sym == AllRefClass)
+ error(pos, "this type cannot be used in a type pattern")
+ else
+ for (arg <- args) {
+ if (sym == ArrayClass) check(arg, bound)
+ else arg match {
+ case TypeRef(_, sym, _) if isLocalBinding(sym) =>
+ ;
+ case _ =>
+ patternWarning(arg, "non variable type-argument ")
+ }
}
- }
- checkCheckable(pos, pre)
- case RefinedType(parents, decls) =>
- if (decls.isEmpty) for (p <- parents) checkCheckable(pos, p)
- else patternWarning(tp, "refinement ")
- case ThisType(_) =>
- ;
- case NoPrefix =>
- ;
- case _ =>
- patternWarning(tp, "type ")
+ check(pre, bound)
+ case RefinedType(parents, decls) =>
+ if (decls.isEmpty) for (p <- parents) check(p, bound)
+ else patternWarning(tp, "refinement ")
+ case ExistentialType(quantified, tp1) =>
+ check(tp1, bound ::: quantified)
+ case ThisType(_) =>
+ ;
+ case NoPrefix =>
+ ;
+ case _ =>
+ patternWarning(tp, "type ")
+ }
}
+ check(tp, List())
}
/** Type intersection of simple type <code>tp1</code> with general
@@ -972,7 +985,7 @@ trait Infer {
}
def inferTypedPattern(pos: Position, pattp: Type, pt: Type): Type = {
- checkCheckable(pos, pattp)
+ checkCheckable(pos, pattp, " pattern")
if (!(pattp <:< pt)) {
val tpparams = freeTypeParamsOfTerms.collect(pattp)
if (settings.debug.value) log("free type params (1) = " + tpparams)
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 13f19feb24..9fd430187e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -61,6 +61,7 @@ abstract class RefChecks extends InfoTransform {
class RefCheckTransformer(unit: CompilationUnit) extends Transformer {
var localTyper: analyzer.Typer = typer;
+ var currentApplication: Tree = EmptyTree
// Override checking ------------------------------------------------------------
@@ -729,7 +730,17 @@ abstract class RefChecks extends InfoTransform {
}
}
+ def isRepeatedParamArg(tree: Tree) = currentApplication match {
+ case Apply(fn, args) =>
+ !args.isEmpty && (args.last eq tree) &&
+ fn.tpe.paramTypes.length == args.length &&
+ fn.tpe.paramTypes.last.typeSymbol == RepeatedParamClass
+ case _ =>
+ false
+ }
+
val savedLocalTyper = localTyper
+ val savedCurrentApplication = currentApplication
val sym = tree.symbol
var result = tree
tree match {
@@ -775,6 +786,7 @@ abstract class RefChecks extends InfoTransform {
case Apply(fn, args) =>
checkSensible(tree.pos, fn, args)
+ currentApplication = tree
case If(cond, thenpart, elsepart) =>
cond.tpe match {
@@ -787,6 +799,11 @@ abstract class RefChecks extends InfoTransform {
case New(tpt) =>
enterReference(tree.pos, tpt.tpe.typeSymbol)
+ case Typed(expr, tpt @ Ident(name)) if (name == nme.WILDCARD_STAR.toTypeName) =>
+ if (!isRepeatedParamArg(tree))
+ unit.error(tree.pos, "no `: _*' annotation allowed here\n"+
+ "(such annotations are only allowed in arguments to *-parameters)")
+
case Ident(name) =>
if (sym.isSourceMethod && sym.hasFlag(CASE))
result = toConstructor(tree.pos, tree.tpe)
@@ -825,6 +842,7 @@ abstract class RefChecks extends InfoTransform {
case _ =>
}
localTyper = savedLocalTyper
+ currentApplication = savedCurrentApplication
result
} catch {
case ex: TypeError =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index 2c08481680..69cc39cdc9 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -37,9 +37,10 @@ trait SyntheticMethods { self: Analyzer =>
* @param unit ...
* @return ...
*/
- def addSyntheticMethods(templ: Template, clazz: Symbol, context: Context): Template = {
+ def addSyntheticMethods(templ: Template, clazz: Symbol, context: Context): Template = try {
- val localTyper = newTyper(context)
+ val localContext = if (reporter.hasErrors) context.makeSilent(false) else context
+ val localTyper = newTyper(localContext)
def hasImplementation(name: Name): Boolean = {
val sym = clazz.info.nonPrivateMember(name)
@@ -124,14 +125,14 @@ trait SyntheticMethods { self: Analyzer =>
def equalsMethod: Tree = {
val method = syntheticMethod(
nme.equals_, 0, MethodType(List(AnyClass.tpe), BooleanClass.tpe))
- localTyper.typed {
+ val methodDef =
DefDef(
method,
{ vparamss =>
val that = Ident(vparamss.head.head)
val constrParamTypes = clazz.primaryConstructor.tpe.paramTypes
val hasVarArgs = !constrParamTypes.isEmpty && constrParamTypes.last.typeSymbol == RepeatedParamClass
- if (clazz.isStatic) {
+ if (false && clazz.isStatic) {
val target = getMember(ScalaRunTimeModule, if (hasVarArgs) nme._equalsWithVarArgs else nme._equals)
Apply(
Select(
@@ -172,7 +173,7 @@ trait SyntheticMethods { self: Analyzer =>
}
}
)
- }
+ localTyper.typed(methodDef)
}
def isSerializable(clazz: Symbol): Boolean =
@@ -243,51 +244,55 @@ trait SyntheticMethods { self: Analyzer =>
!sym.hasFlag(PRIVATE | PROTECTED) && sym.privateWithin == NoSymbol
if (!phase.erasedTypes) {
+ try {
+ if (clazz hasFlag CASE) {
+ // case classes are implicitly declared serializable
+ clazz.attributes = AnnotationInfo(SerializableAttr.tpe, List(), List()) :: clazz.attributes
- if (clazz hasFlag CASE) {
- // case classes are implicitly declared serializable
- clazz.attributes = AnnotationInfo(SerializableAttr.tpe, List(), List()) :: clazz.attributes
+ for (stat <- templ.body) {
+ if (stat.isDef && stat.symbol.isMethod && stat.symbol.hasFlag(CASEACCESSOR) && !isPublic(stat.symbol)) {
+ ts += newAccessorMethod(stat)
+ stat.symbol.resetFlag(CASEACCESSOR)
+ }
+ }
- for (stat <- templ.body) {
- if (stat.isDef && stat.symbol.isMethod && stat.symbol.hasFlag(CASEACCESSOR) && !isPublic(stat.symbol)) {
- ts += newAccessorMethod(stat)
- stat.symbol.resetFlag(CASEACCESSOR)
+ if (clazz.info.nonPrivateDecl(nme.tag) == NoSymbol) ts += tagMethod
+ if (clazz.isModuleClass) {
+ if (!hasOverridingImplementation(Object_toString)) ts += moduleToStringMethod
+ } else {
+ if (!hasOverridingImplementation(Object_hashCode)) ts += forwardingMethod(nme.hashCode_)
+ if (!hasOverridingImplementation(Object_toString)) ts += forwardingMethod(nme.toString_)
+ if (!hasOverridingImplementation(Object_equals)) ts += equalsMethod
}
- }
- if (clazz.info.nonPrivateDecl(nme.tag) == NoSymbol) ts += tagMethod
- if (clazz.isModuleClass) {
- if (!hasOverridingImplementation(Object_toString)) ts += moduleToStringMethod
- } else {
- if (!hasOverridingImplementation(Object_hashCode)) ts += forwardingMethod(nme.hashCode_)
- if (!hasOverridingImplementation(Object_toString)) ts += forwardingMethod(nme.toString_)
- if (!hasOverridingImplementation(Object_equals)) ts += equalsMethod
+ if (!hasOverridingImplementation(Product_productPrefix)) ts += productPrefixMethod
+ val accessors = clazz.caseFieldAccessors
+ if (!hasOverridingImplementation(Product_productArity))
+ ts += productArityMethod(accessors.length)
+ if (!hasOverridingImplementation(Product_productElement))
+ ts += productElementMethod(accessors)
}
- if (!hasOverridingImplementation(Product_productPrefix)) ts += productPrefixMethod
- val accessors = clazz.caseFieldAccessors
- if (!hasOverridingImplementation(Product_productArity))
- ts += productArityMethod(accessors.length)
- if (!hasOverridingImplementation(Product_productElement))
- ts += productElementMethod(accessors)
- }
-
- if (clazz.isModuleClass && isSerializable(clazz)) {
- // If you serialize a singleton and then deserialize it twice,
- // you will have two instances of your singleton, unless you implement
- // the readResolve() method (see http://www.javaworld.com/javaworld/
- // jw-04-2003/jw-0425-designpatterns_p.html)
- if (!hasImplementation(nme.readResolve)) ts += readResolveMethod
+ if (clazz.isModuleClass && isSerializable(clazz)) {
+ // If you serialize a singleton and then deserialize it twice,
+ // you will have two instances of your singleton, unless you implement
+ // the readResolve() method (see http://www.javaworld.com/javaworld/
+ // jw-04-2003/jw-0425-designpatterns_p.html)
+ if (!hasImplementation(nme.readResolve)) ts += readResolveMethod
+ }
+ if (!forCLDC && !forMSIL)
+ for (sym <- clazz.info.decls.toList)
+ if (!sym.getAttributes(BeanPropertyAttr).isEmpty)
+ if (sym.isGetter)
+ addBeanGetterMethod(sym)
+ else if (sym.isSetter)
+ addBeanSetterMethod(sym)
+ else if (sym.isMethod || sym.isType)
+ context.unit.error(sym.pos, "attribute `BeanProperty' is not applicable to " + sym)
+ } catch {
+ case ex: TypeError =>
+ if (!reporter.hasErrors) throw ex
}
- if (!forCLDC && !forMSIL)
- for (sym <- clazz.info.decls.toList)
- if (!sym.getAttributes(BeanPropertyAttr).isEmpty)
- if (sym.isGetter)
- addBeanGetterMethod(sym)
- else if (sym.isSetter)
- addBeanSetterMethod(sym)
- else if (sym.isMethod || sym.isType)
- context.unit.error(sym.pos, "attribute `BeanProperty' is not applicable to " + sym)
}
val synthetics = ts.toList
copy.Template(
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index cc77cab65a..0fee0c07dc 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -253,6 +253,12 @@ trait Typers { self: Analyzer =>
)
case SingleType(pre, sym) =>
checkNotLocked(sym)
+/*
+ case TypeBounds(lo, hi) =>
+ var ok = true
+ for (t <- lo) ok = ok & checkNonCyclic(pos, t)
+ ok
+*/
case st: SubType =>
checkNonCyclic(pos, st.supertype)
case ct: CompoundType =>
@@ -296,12 +302,10 @@ trait Typers { self: Analyzer =>
}
}
- def checkRegPatOK(pos: Position, mode: Int) {
- if ((mode & REGPATmode) == 0) {
+ def checkRegPatOK(pos: Position, mode: Int) =
+ if ((mode & REGPATmode) == 0)
error(pos, "no regular expression pattern allowed here\n"+
"(regular expression patterns are only allowed in arguments to *-parameters)")
- }
- }
/** Check that type of given tree does not contain local or private
* components.
@@ -342,7 +346,7 @@ trait Typers { self: Analyzer =>
else if (hiddenSymbols exists (_.isErroneous)) setError(tree)
else if (isFullyDefined(pt)) tree setType pt //todo: eliminate
else if (tp1.typeSymbol.isAnonymousClass) // todo: eliminate
- check(owner, scope, pt, tree setType anonymousClassRefinement(tp1.typeSymbol))
+ check(owner, scope, pt, tree setType classBound(tp1.typeSymbol))
else if (owner == NoSymbol)
tree setType packSymbols(hiddenSymbols.reverse, tp1)
else { // privates
@@ -1249,11 +1253,7 @@ trait Typers { self: Analyzer =>
copy.LabelDef(ldef, ldef.name, ldef.params, rhs1) setType restpe
}
- /**
- * @param clazz ...
- * @return ...
- */
- def anonymousClassRefinement(clazz: Symbol): Type = {
+ def classBound(clazz: Symbol): Type = {
val tp = refinedType(clazz.info.parents, clazz.owner)
val thistp = tp.typeSymbol.thisType
for (sym <- clazz.info.decls.toList) {
@@ -1460,17 +1460,7 @@ trait Typers { self: Analyzer =>
List.mapConserve(args)(arg => typedArg(arg, mode, 0, WildcardType))
def typedArgs(args: List[Tree], mode: Int, originalFormals: List[Type], adaptedFormals: List[Type]) = {
- val varargs = isVarArgs(originalFormals)
- if (!args.isEmpty)
- args.last match {
- case Typed(expr, Ident(name)) if (name == nme.WILDCARD_STAR.toTypeName) =>
- if (!varargs)
- error(args.last.pos, "_*-argument does not correspond to *-parameter")
- else if (originalFormals.length != adaptedFormals.length)
- error(args.last.pos, "_*-argument may not appear after other arguments matching a *-parameter")
- case _ =>
- }
- if (varargs && (mode & PATTERNmode) != 0) {
+ if (isVarArgs(originalFormals)) {
val nonVarCount = originalFormals.length - 1
val prefix =
List.map2(args take nonVarCount, adaptedFormals take nonVarCount) ((arg, formal) =>
@@ -1528,7 +1518,8 @@ trait Typers { self: Analyzer =>
case ex => errorTree(tree, "wrong number of arguments for "+treeSymTypeMsg(fun))
}
} else if (formals.length != args1.length) {
- errorTree(tree, "wrong number of arguments for "+treeSymTypeMsg(fun))
+ if (mt.isErroneous) setError(tree)
+ else errorTree(tree, "wrong number of arguments for "+treeSymTypeMsg(fun))
} else {
val tparams = context.undetparams
context.undetparams = List()
@@ -1737,7 +1728,7 @@ trait Typers { self: Analyzer =>
protected def existentialBound(sym: Symbol): Type =
if (sym.isClass)
parameterizedType(
- sym.typeParams, mkTypeBounds(AllClass.tpe, anonymousClassRefinement(sym)))
+ sym.typeParams, mkTypeBounds(AllClass.tpe, classBound(sym)))
else if (sym.isAbstractType)
sym.info
else if (sym.isTerm)
@@ -1772,7 +1763,7 @@ trait Typers { self: Analyzer =>
/** Compute an existential type from raw hidden symbols `syms' and type `tp'
*/
- def packSymbols(hidden: List[Symbol], tp: Type) =
+ def packSymbols(hidden: List[Symbol], tp: Type): Type =
if (hidden.isEmpty) tp
else {
// Console.println("original type: "+tp)
@@ -1784,14 +1775,22 @@ trait Typers { self: Analyzer =>
res
}
+ class SymInstance(val sym: Symbol, val tp: Type) {
+ override def equals(other: Any): Boolean = other match {
+ case that: SymInstance =>
+ this.sym == that.sym && this.tp =:= that.tp
+ case _ =>
+ false
+ }
+ override def hashCode: Int = sym.hashCode * 41 + tp.hashCode
+ }
+
def packedType(tree: Tree, owner: Symbol): Type = {
def defines(tree: Tree, sym: Symbol) =
sym.isExistentialSkolem && sym.unpackLocation == tree ||
tree.isDef && tree.symbol == sym
- def isAnonymousFunction(sym: Symbol) =
- (sym hasFlag SYNTHETIC) && (sym.name == nme.ANON_FUN_NAME)
def isVisibleParameter(sym: Symbol) =
- (sym hasFlag PARAM) && (sym.owner == owner) && (sym.isType || !isAnonymousFunction(owner))
+ (sym hasFlag PARAM) && (sym.owner == owner) && (sym.isType || !owner.isAnonymousFunction)
def containsDef(owner: Symbol, sym: Symbol): Boolean =
(!(sym hasFlag PACKAGE)) && {
var o = sym.owner
@@ -1800,30 +1799,63 @@ trait Typers { self: Analyzer =>
}
var localSyms = collection.immutable.Set[Symbol]()
var boundSyms = collection.immutable.Set[Symbol]()
+ var localInstances = collection.immutable.Map[SymInstance, Symbol]()
+ // add all local symbols of `tp' to `localSyms'
+ // expanding higher-kinded types into individual copies for esach instance.
def addLocals(tp: Type) {
def isLocal(sym: Symbol): Boolean =
if (owner == NoSymbol) tree exists (defines(_, sym))
else containsDef(owner, sym)
- def addIfLocal(sym: Symbol) {
- if (sym != NoSymbol &&
- !sym.isRefinementClass &&
- !(localSyms contains sym) && !(boundSyms contains sym) &&
- isLocal(sym)) {
- localSyms += sym
- addLocals(existentialBound(sym))
+ def addIfLocal(sym: Symbol, tp: Type) {
+ if (sym != NoSymbol && !sym.isRefinementClass && isLocal(sym) &&
+ !(localSyms contains sym) && !(boundSyms contains sym) ) {
+ if (sym.typeParams.isEmpty) {
+ localSyms += sym
+ addLocals(existentialBound(sym))
+ } else if (tp.typeArgs.isEmpty) {
+ unit.error(tree.pos,
+ "implementation restriction: can't existentially abstract over higher-kinded type" + tp)
+ } else {
+ val inst = new SymInstance(sym, tp)
+ if (!(localInstances contains inst)) {
+ val bound = existentialBound(sym) match {
+ case PolyType(tparams, restpe) =>
+ restpe.subst(tparams, tp.typeArgs)
+ case t =>
+ t
+ }
+ val local = sym.owner.newAbstractType(
+ sym.pos, unit.fresh.newName(sym.name.toString))
+ .setFlag(sym.flags)
+ .setInfo(bound)
+ localInstances += (inst -> local)
+ addLocals(bound)
}
+ }
+ }
}
for (t <- tp) {
t match {
- case ExistentialType(tparams, _) => boundSyms ++= tparams
+ case ExistentialType(tparams, _) =>
+ boundSyms ++= tparams
case _ =>
}
- addIfLocal(t.termSymbol)
- addIfLocal(t.typeSymbol)
+ addIfLocal(t.termSymbol, t)
+ addIfLocal(t.typeSymbol, t)
+ }
+ }
+ val substLocals = new TypeMap {
+ def apply(t: Type): Type = t match {
+ case TypeRef(_, sym, args) if (sym.isLocal && args.length > 0) =>
+ localInstances.get(new SymInstance(sym, t)) match {
+ case Some(local) => typeRef(NoPrefix, local, List())
+ case None => mapOver(t)
+ }
+ case _ => mapOver(t)
}
}
addLocals(tree.tpe)
- packSymbols(localSyms.toList, tree.tpe)
+ packSymbols(localSyms.toList ::: localInstances.values.toList, substLocals(tree.tpe))
}
protected def typedExistentialTypeTree(tree: ExistentialTypeTree): Tree = {
@@ -2043,14 +2075,6 @@ trait Typers { self: Analyzer =>
errorTree(expr1, "_ must follow method; cannot follow " + expr1.tpe)
}
- def typedWildcardStar(expr1: Tree, tpt: Tree) = expr1.tpe.baseType(SeqClass) match {
- case TypeRef(_, _, List(elemtp)) =>
- copy.Typed(tree, expr1, tpt setType elemtp) setType elemtp
- case _ =>
- //todo: do this: errorTree(tree, "`: _*' annotation only legal for method arguments")
- setError(tree)
- }
-
def typedTypeApply(fun: Tree, args: List[Tree]): Tree = fun.tpe match {
case OverloadedType(pre, alts) =>
inferPolyAlternatives(fun, args map (_.tpe))
@@ -2074,11 +2098,14 @@ trait Typers { self: Analyzer =>
Literal(Constant(targs.head)) setPos tree.pos setType Predef_classOfType(targs.head)
// @M: targs.head.normalize is not necessary --> toTypeKind eventually normalizes the type
} else {
+ if (phase.id <= currentRun.typerPhase.id &&
+ fun.symbol == Any_isInstanceOf && !targs.isEmpty)
+ checkCheckable(tree.pos, targs.head, "")
val resultpe0 = restpe.instantiateTypeParams(tparams, targs)
//@M TODO -- probably ok
//@M example why asSeenFrom is necessary: class Foo[a] { def foo[m[x]]: m[a] } (new Foo[Int]).foo[List] : List[Int]
//@M however, asSeenFrom widens a singleton type, thus cannot use it for those types
- val resultpe = if(resultpe0.isInstanceOf[SingletonType]) resultpe0 else resultpe0.asSeenFrom(prefixType(fun), fun.symbol.owner)
+ val resultpe = if (resultpe0.isInstanceOf[SingletonType]) resultpe0 else resultpe0.asSeenFrom(prefixType(fun), fun.symbol.owner)
copy.TypeApply(tree, fun, args) setType resultpe
}
} else {
@@ -2394,6 +2421,10 @@ trait Typers { self: Analyzer =>
var defEntry: ScopeEntry = null // the scope entry of defSym, if defined in a local scope
var cx = context
+ if ((mode & PATTERNmode) != 0)
+ // ignore current variable scope in patterns to enforce linearity
+ cx = cx.outer
+
while (defSym == NoSymbol && cx != NoContext) {
pre = cx.enclClass.prefix
defEntry = cx.scope.lookupEntry(name)
@@ -2602,6 +2633,11 @@ trait Typers { self: Analyzer =>
case Bind(name, body) =>
typedBind(name, body)
+ case UnApply(fun, args) =>
+ val fun1 = typed(fun)
+ val args1 = List.mapConserve(args)(typedPattern(_, WildcardType))
+ copy.UnApply(tree, fun1, args1) setType pt
+
case ArrayValue(elemtpt, elems) =>
typedArrayValue(elemtpt, elems)
@@ -2654,7 +2690,13 @@ trait Typers { self: Analyzer =>
typedEta(checkDead(typed1(expr, mode, pt)))
case Typed(expr, tpt @ Ident(name)) if (name == nme.WILDCARD_STAR.toTypeName) =>
- typedWildcardStar(typed(expr, mode & stickyModes, seqType(pt)), tpt)
+ val expr1 = typed(expr, mode & stickyModes, seqType(pt))
+ expr1.tpe.baseType(SeqClass) match {
+ case TypeRef(_, _, List(elemtp)) =>
+ copy.Typed(tree, expr1, tpt setType elemtp) setType elemtp
+ case _ =>
+ setError(tree)
+ }
case Typed(expr, tpt) =>
val tpt1 = typedType(tpt)
diff --git a/src/library/scala/collection/immutable/TreeSet.scala b/src/library/scala/collection/immutable/TreeSet.scala
index 8236a06bfd..bed77fcc64 100644
--- a/src/library/scala/collection/immutable/TreeSet.scala
+++ b/src/library/scala/collection/immutable/TreeSet.scala
@@ -16,12 +16,6 @@ package scala.collection.immutable
object TreeSet {
/** The empty set of this type
- * @deprecated use <code>empty</code> instead
- */
- @deprecated
- def Empty[A <% Ordered[A]] = empty[A]
-
- /** The empty set of this type
*/
def empty[A <% Ordered[A]] = new TreeSet[A]
diff --git a/test/files/neg/bug835.check b/test/files/neg/bug835.check
index 83db589280..79ea97b71f 100644
--- a/test/files/neg/bug835.check
+++ b/test/files/neg/bug835.check
@@ -1,4 +1,9 @@
-bug835.scala:2: error: _*-argument may not appear after other arguments matching a *-parameter
+bug835.scala:2: error: no `: _*' annotation allowed here
+(such annotations are only allowed in arguments to *-parameters)
+ Console.println(List(List(1, 2, 3) : _*, List(4, 5, 6) : _*))
+ ^
+bug835.scala:2: error: no `: _*' annotation allowed here
+(such annotations are only allowed in arguments to *-parameters)
Console.println(List(List(1, 2, 3) : _*, List(4, 5, 6) : _*))
^
-one error found
+two errors found
diff --git a/test/files/neg/bug875.check b/test/files/neg/bug875.check
index 63ad0f7eb0..d547c8d69c 100644
--- a/test/files/neg/bug875.check
+++ b/test/files/neg/bug875.check
@@ -1,13 +1,17 @@
-bug875.scala:3: error: _*-argument may not appear after other arguments matching a *-parameter
+bug875.scala:3: error: no `: _*' annotation allowed here
+(such annotations are only allowed in arguments to *-parameters)
val ys = List(1, 2, 3, xs: _*)
^
-bug875.scala:6: error: _*-argument does not correspond to *-parameter
+bug875.scala:6: error: no `: _*' annotation allowed here
+(such annotations are only allowed in arguments to *-parameters)
mkList(xs: _*)
^
-bug875.scala:15: error: _*-argument may not appear after other arguments matching a *-parameter
+bug875.scala:15: error: no `: _*' annotation allowed here
+(such annotations are only allowed in arguments to *-parameters)
f(true, 1, xs: _*)
^
-bug875.scala:16: error: _*-argument may not appear after other arguments matching a *-parameter
+bug875.scala:16: error: no `: _*' annotation allowed here
+(such annotations are only allowed in arguments to *-parameters)
g(1, xs:_*)
^
four errors found
diff --git a/test/files/pos/bug602.scala b/test/files/pos/bug602.scala
index 60aef1dfd0..5877d08ddc 100644
--- a/test/files/pos/bug602.scala
+++ b/test/files/pos/bug602.scala
@@ -1,6 +1,10 @@
package com.mosol.sl;
case class Span[K <: Ordered[K]](low: Option[K], high: Option[K]) extends Function1[K, boolean] {
+ override def equals(x$1: Any): Boolean = x$1 match {
+ case Span((low$0 @ _), (high$0 @ _)) if low$0.equals(low).$amp$amp(high$0.equals(high)) => true
+ case _ => false
+ }
def apply(k: K): boolean = this match {
case Span(Some(low), Some(high)) => (k >= low && k <= high)
case Span(Some(low), None) => (k >= low)
diff --git a/test/files/run/existentials.scala b/test/files/run/existentials.scala
index a08a9da9b3..9dc9855a75 100755
--- a/test/files/run/existentials.scala
+++ b/test/files/run/existentials.scala
@@ -52,6 +52,9 @@ object Bug1189 {
object Test extends Application {
+ val x = { class I[T]; (new C(new I[String]), new C(new I[Int])) }
+ val y: (C[X], C[Y]) forSome { type X; type Y } = x
+
def foo(x : Counter[T] { def name : String } forSome { type T }) = x match {
case ctr: Counter[t] =>
val c = ctr.newCounter
diff --git a/test/files/run/regularpatmatnew.scala b/test/files/run/regularpatmatnew.scala
index 0457cd6d6c..c610b80444 100644
--- a/test/files/run/regularpatmatnew.scala
+++ b/test/files/run/regularpatmatnew.scala
@@ -105,7 +105,7 @@ object Test {
case Bar(xs@_*) => xs // this should be optimized away to a pattern Bar(xs)
case _ => Nil
}
- assertEquals("res instance"+res.isInstanceOf[Seq[Con]]+" res(0)="+res(0), true, res.isInstanceOf[Seq[Foo]] && res(0) == Foo() )
+ assertEquals("res instance"+res.isInstanceOf[Seq[Con] forSome { type Con }]+" res(0)="+res(0), true, res.isInstanceOf[Seq[Foo] forSome { type Foo}] && res(0) == Foo() )
}
}
diff --git a/test/files/run/withIndex.check b/test/files/run/withIndex.check
index 6a9c7aaadb..e8060bb1d7 100644
--- a/test/files/run/withIndex.check
+++ b/test/files/run/withIndex.check
@@ -1,3 +1,5 @@
+warning: there were unchecked warnings; re-run with -unchecked for details
+one warning found
List((a,0), (b,1), (c,2))
List((a,0), (b,1), (c,2))
List((a,0), (b,1), (c,2))
diff --git a/test/files/run/withIndex.scala b/test/files/run/withIndex.scala
index fd79cd808a..d06dde89f0 100644
--- a/test/files/run/withIndex.scala
+++ b/test/files/run/withIndex.scala
@@ -9,7 +9,12 @@ object Test {
Console.println(lst.zipWithIndex.toList)
Console.println(itr.zipWithIndex.toList)
Console.println(str.zipWithIndex.toList)
- assert(ary.zipWithIndex.isInstanceOf[Array[Pair[String,Int]]])
+ assert {
+ ary.zipWithIndex match {
+ case _: Array[Pair[String,Int]] => true
+ case _ => false
+ }
+ }
val emptyArray = new Array[String](0)
val emptyList: List[String] = Nil