summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-03-30 16:21:49 +0000
committerMartin Odersky <odersky@gmail.com>2009-03-30 16:21:49 +0000
commit20f986ecf42cf3018bf3a90b84b2f84669838b10 (patch)
tree11f4510c6822ccc98deeaa086faaa6a36469a1a5
parent070c60f7472f8c0352287e9d68df8bd35a8ae0a4 (diff)
downloadscala-20f986ecf42cf3018bf3a90b84b2f84669838b10.tar.gz
scala-20f986ecf42cf3018bf3a90b84b2f84669838b10.tar.bz2
scala-20f986ecf42cf3018bf3a90b84b2f84669838b10.zip
changed overloaing resolution to make Builders ...
changed overloaing resolution to make Builders work. generalized companion object generation in Namers. Fixed a problem in Types that made the collection build crash.
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala12
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala76
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala15
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Unapplies.scala15
-rw-r--r--src/library/scala/runtime/BoxesRunTime.java2
-rw-r--r--test/files/neg/implicits.check7
-rw-r--r--test/files/neg/overload.check8
8 files changed, 89 insertions, 48 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 828a59f35a..599196ee01 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -1437,7 +1437,7 @@ A type's typeSymbol should never be inspected directly.
*/
override def bounds: TypeBounds =
- if (sym.isAbstractType) transform(thisInfo.bounds).asInstanceOf[TypeBounds] // ??? seems to be doing asSeenFrom twice
+ if (sym.isAbstractType) thisInfo.bounds // transform(thisInfo.bounds).asInstanceOf[TypeBounds] // ??? seems to be doing asSeenFrom twice
else super.bounds
override def parents: List[Type] = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 0efdc6fbe2..6c7a126ccc 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -105,7 +105,7 @@ self: Analyzer =>
}
/** A sentinel indicating no implicit was found */
- val NoImplicitInfo = new ImplicitInfo(null, null, null)
+ val NoImplicitInfo = new ImplicitInfo(null, NoType, NoSymbol)
/** A class that sets up an implicit search. For more info, see comments for `inferImplicit`.
* @param tree The tree for which the implicit needs to be inserted.
@@ -463,20 +463,16 @@ self: Analyzer =>
// Also check that applicable infos that did not get selected are not
// in (a companion object of) a subclass of (a companion object of) the class
// containing the winning info.
+ /*
for (alt <- applicable.keySet) {
- /** Is (the companion class of) `sym1` a subclass of (the compansion class of) `sym2`? */
- def isSubClassOrObject(sym1: Symbol, sym2: Symbol): Boolean =
- sym1 != NoSymbol && (sym1 isSubClass sym2) ||
- sym1.isModuleClass && isSubClassOrObject(sym1.linkedClassOfClass, sym2) ||
- sym2.isModuleClass && isSubClassOrObject(sym1, sym2.linkedClassOfClass)
-
- if (alt.sym.owner != best.sym.owner && isSubClassOrObject(alt.sym.owner, best.sym.owner)) {
+ if (isProperSubClassOrObject(alt.sym.owner, best.sym.owner)) {
ambiguousImplicitError(best, alt,
"most specific definition is:",
"yet alternative definition ",
"is defined in a subclass.\n Both definitions ")
}
}
+ */
applicable(best)
}
} // end searchImplicit
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 1a07103e24..55140899ac 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -675,11 +675,11 @@ trait Infer {
* @param ftpe2 ...
* @return ...
*/
- def isMoreSpecific(ftpe1: Type, ftpe2: Type): Boolean = ftpe1 match {
+ def isAsSpecific(ftpe1: Type, ftpe2: Type): Boolean = ftpe1 match {
case OverloadedType(pre, alts) =>
- alts exists (alt => isMoreSpecific(pre.memberType(alt), ftpe2))
+ alts exists (alt => isAsSpecific(pre.memberType(alt), ftpe2))
case et: ExistentialType =>
- et.withTypeVars(isMoreSpecific(_, ftpe2)) // !!! why isStrictly?
+ et.withTypeVars(isAsSpecific(_, ftpe2)) // !!! why isStrictly?
case MethodType(formals @ (x :: xs), _) =>
isApplicable(List(), ftpe2, formals, WildcardType)
case PolyType(_, MethodType(formals @ (x :: xs), _)) =>
@@ -689,29 +689,58 @@ trait Infer {
case _ =>
ftpe2 match {
case OverloadedType(pre, alts) =>
- alts forall (alt => isMoreSpecific(ftpe1, pre.memberType(alt)))
+ alts forall (alt => isAsSpecific(ftpe1, pre.memberType(alt)))
case et: ExistentialType =>
- et.withTypeVars(isMoreSpecific(ftpe1, _))
+ et.withTypeVars(isAsSpecific(ftpe1, _))
case MethodType(_, _) | PolyType(_, MethodType(_, _)) =>
true
case _ =>
- isMoreSpecificValueType(ftpe1, ftpe2, List(), List())
+ isAsSpecificValueType(ftpe1, ftpe2, List(), List())
}
}
/*
def isStrictlyMoreSpecific(ftpe1: Type, ftpe2: Type): Boolean =
- ftpe1.isError || isMoreSpecific(ftpe1, ftpe2) &&
- (!isMoreSpecific(ftpe2, ftpe1) ||
+ ftpe1.isError || isAsSpecific(ftpe1, ftpe2) &&
+ (!isAsSpecific(ftpe2, ftpe1) ||
!ftpe1.isInstanceOf[OverloadedType] && ftpe2.isInstanceOf[OverloadedType] ||
phase.erasedTypes && covariantReturnOverride(ftpe1, ftpe2))
*/
- def isStrictlyMoreSpecific(ftpe1: Type, ftpe2: Type, sym1: Symbol, sym2: Symbol): Boolean =
- ftpe1.isError || isMoreSpecific(ftpe1, ftpe2) &&
- (!isMoreSpecific(ftpe2, ftpe1) ||
- (sym1.owner isSubClass sym2.owner) && (sym1.owner != sym2.owner) ||
- !ftpe1.isInstanceOf[OverloadedType] && ftpe2.isInstanceOf[OverloadedType] ||
- phase.erasedTypes && covariantReturnOverride(ftpe1, ftpe2))
+ /** Is sym1 (or its companion class in case it is a module) a subclass of
+ * sym2 (or its companion class in case it is a module)?
+ */
+ def isProperSubClassOrObject(sym1: Symbol, sym2: Symbol): Boolean =
+ sym1 != sym2 && sym1 != NoSymbol && (sym1 isSubClass sym2) ||
+ sym1.isModuleClass && isProperSubClassOrObject(sym1.linkedClassOfClass, sym2) ||
+ sym2.isModuleClass && isProperSubClassOrObject(sym1, sym2.linkedClassOfClass)
+ /** is symbol `sym1` defined in a proper subclass of symbol `sym2`?
+ */
+ def isInProperSubClassOrObject(sym1: Symbol, sym2: Symbol) =
+ sym2 == NoSymbol || isProperSubClassOrObject(sym1.owner, sym2.owner)
+
+ def isStrictlyMoreSpecific(ftpe1: Type, ftpe2: Type, sym1: Symbol, sym2: Symbol): Boolean =
+ ftpe1.isError || {
+ val specificCount = (if (isAsSpecific(ftpe1, ftpe2)) 1 else 0) -
+ (if (isAsSpecific(ftpe2, ftpe1) &&
+ // todo: move to isAsSepecific test
+ (!ftpe2.isInstanceOf[OverloadedType] || ftpe1.isInstanceOf[OverloadedType]) &&
+ (!phase.erasedTypes || covariantReturnOverride(ftpe1, ftpe2))) 1 else 0)
+ val subClassCount = (if (isInProperSubClassOrObject(sym1, sym2)) 1 else 0) -
+ (if (isInProperSubClassOrObject(sym2, sym1)) 1 else 0)
+ specificCount + subClassCount > 0
+ }
+/*
+ ftpe1.isError || {
+ if (isAsSpecific(ftpe1, ftpe2))
+ (!isAsSpecific(ftpe2, ftpe1) ||
+ isProperSubClassOrObject(sym1.owner, sym2.owner) ||
+ !ftpe1.isInstanceOf[OverloadedType] && ftpe2.isInstanceOf[OverloadedType] ||
+ phase.erasedTypes && covariantReturnOverride(ftpe1, ftpe2))
+ else
+ !isAsSpecific(ftpe2, ftpe1) &&
+ isProperSubClassOrObject(sym1.owner, sym2.owner)
+ }
+*/
private def covariantReturnOverride(ftpe1: Type, ftpe2: Type): Boolean = (ftpe1, ftpe2) match {
case (MethodType(_, rtpe1), MethodType(_, rtpe2)) =>
rtpe1 <:< rtpe2 || rtpe2.typeSymbol == ObjectClass
@@ -719,11 +748,11 @@ trait Infer {
false
}
- private def isMoreSpecificValueType(tpe1: Type, tpe2: Type, undef1: List[Symbol], undef2: List[Symbol]): Boolean = (tpe1, tpe2) match {
+ private def isAsSpecificValueType(tpe1: Type, tpe2: Type, undef1: List[Symbol], undef2: List[Symbol]): Boolean = (tpe1, tpe2) match {
case (PolyType(tparams1, rtpe1), _) =>
- isMoreSpecificValueType(rtpe1, tpe2, undef1 ::: tparams1, undef2)
+ isAsSpecificValueType(rtpe1, tpe2, undef1 ::: tparams1, undef2)
case (_, PolyType(tparams2, rtpe2)) =>
- isMoreSpecificValueType(tpe1, rtpe2, undef1, undef2 ::: tparams2)
+ isAsSpecificValueType(tpe1, rtpe2, undef1, undef2 ::: tparams2)
case _ =>
existentialAbstraction(undef1, tpe1) <:< existentialAbstraction(undef2, tpe2)
}
@@ -1291,16 +1320,18 @@ trait Infer {
/* -- Overload Resolution ---------------------------------------------- */
+/*
def checkNotShadowed(pos: Position, pre: Type, best: Symbol, eligible: List[Symbol]) =
if (!phase.erasedTypes)
for (alt <- eligible) {
- if (alt.owner != best.owner && alt.owner.isSubClass(best.owner))
+ if (isProperSubClassOrObject(alt.owner, best.owner))
error(pos,
"erroneous reference to overloaded definition,\n"+
"most specific definition is: "+best+best.locationString+" of type "+pre.memberType(best)+
",\nyet alternative definition "+alt+alt.locationString+" of type "+pre.memberType(alt)+
"\nis defined in a subclass")
}
+*/
/** Assign <code>tree</code> the symbol and type of the alternative which
* matches prototype <code>pt</code>, if it exists.
@@ -1310,6 +1341,7 @@ trait Infer {
def inferExprAlternative(tree: Tree, pt: Type): Unit = tree.tpe match {
case OverloadedType(pre, alts) => tryTwice {
var alts1 = alts filter (alt => isWeaklyCompatible(pre.memberType(alt), pt))
+ val applicable = alts1
var secondTry = false
if (alts1.isEmpty) {
alts1 = alts
@@ -1346,9 +1378,9 @@ trait Infer {
setError(tree)
}
} else {
- val applicable = alts1 filter (alt =>
- global.typer.infer.isWeaklyCompatible(pre.memberType(alt), pt))
- checkNotShadowed(tree.pos, pre, best, applicable)
+// val applicable = alts1 filter (alt =>
+// global.typer.infer.isWeaklyCompatible(pre.memberType(alt), pt))
+// checkNotShadowed(tree.pos, pre, best, applicable)
tree.setSymbol(best).setType(pre.memberType(best))
}
}
@@ -1387,7 +1419,7 @@ trait Infer {
setError(tree)
()
} else {
- checkNotShadowed(tree.pos, pre, best, applicable)
+// checkNotShadowed(tree.pos, pre, best, applicable)
tree.setSymbol(best).setType(pre.memberType(best))
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 3a7880f326..325ed5f8f1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -286,6 +286,16 @@ trait Namers { self: Analyzer =>
else if (owner.isTerm || owner.isPackageClass) List()
else applicableTypeParams(owner.owner) ::: owner.typeParams
+ /** If no companion object for clazz exists yet, create one by applying `creator` to
+ * class definition tree.
+ * @return the companion object symbol.
+ */
+ def ensureCompanionObject(tree: ClassDef, creator: ClassDef => Tree): Symbol = {
+ val m: Symbol = context.scope.lookupWithContext(tree.name.toTermName)(context.owner).filter(! _.isSourceMethod)
+ if (m.isModule && inCurrentScope(m) && (inIDE || currentRun.compiles(m))) m
+ else enterSyntheticSym(creator(tree))
+ }
+
def enterSym(tree: Tree): Context = try {
def finishWith(tparams: List[TypeDef]) {
@@ -317,10 +327,7 @@ trait Namers { self: Analyzer =>
tree.symbol = enterClassSymbol(tree)
finishWith(tparams)
if ((mods.flags & CASE) != 0) {
- var m: Symbol = context.scope.lookupWithContext(tree.name.toTermName)(context.owner).filter(! _.isSourceMethod)
- if (!(m.isModule && inCurrentScope(m) && (inIDE || currentRun.compiles(m)))) {
- m = enterSyntheticSym(caseModuleDef(tree))
- }
+ val m = ensureCompanionObject(tree, caseModuleDef)
caseClassOfModuleClass(m.moduleClass) = tree
}
case tree @ ModuleDef(mods, name, _) =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
index 80794f6b61..84bddd5f97 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
@@ -133,11 +133,16 @@ trait Unapplies { self: Analyzer =>
/** The module corresponding to a case class; without any member definitions
*/
- def caseModuleDef(cdef: ClassDef): ModuleDef = atPos(cdef.pos) {
- var parents = List(gen.scalaScalaObjectConstr)
- if (!(cdef.mods hasFlag ABSTRACT) && cdef.tparams.isEmpty && constrParamss(cdef).length == 1)
- parents = gen.scalaFunctionConstr(constrParamss(cdef).head map (_.tpt),
- Ident(cdef.name)) :: parents
+ def caseModuleDef(cdef: ClassDef): ModuleDef =
+ companionModuleDef(
+ cdef,
+ if (!(cdef.mods hasFlag ABSTRACT) && cdef.tparams.isEmpty && constrParamss(cdef).length == 1)
+ List(gen.scalaFunctionConstr(constrParamss(cdef).head map (_.tpt), Ident(cdef.name)),
+ gen.scalaScalaObjectConstr)
+ else
+ List(gen.scalaScalaObjectConstr))
+
+ def companionModuleDef(cdef: ClassDef, parents: List[Tree]): ModuleDef = atPos(cdef.pos) {
ModuleDef(
Modifiers(cdef.mods.flags & AccessFlags | SYNTHETIC, cdef.mods.privateWithin),
cdef.name.toTermName,
diff --git a/src/library/scala/runtime/BoxesRunTime.java b/src/library/scala/runtime/BoxesRunTime.java
index 89b141f71f..7b8d6bb672 100644
--- a/src/library/scala/runtime/BoxesRunTime.java
+++ b/src/library/scala/runtime/BoxesRunTime.java
@@ -42,6 +42,8 @@ public class BoxesRunTime {
/* BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING */
+ // for 2.8: change to valueOf methods.
+
private static int charLowBound = 0;
private static int charUpBound = 255;
private static Character[] charCache = new Character[charUpBound - charLowBound + 1];
diff --git a/test/files/neg/implicits.check b/test/files/neg/implicits.check
index 409d6ce6a7..b84586fc16 100644
--- a/test/files/neg/implicits.check
+++ b/test/files/neg/implicits.check
@@ -2,10 +2,9 @@ implicits.scala:21: error: type mismatch;
found : Pos
required: ?{val +: ?}
Note that implicit conversions are not applicable because they are ambiguous:
- most specific definition is: method pos2int in object Super of type (Pos)int
- yet alternative definition method any2plus in object Sub of type (Any)Sub.Plus
- is defined in a subclass.
- Both definitions are possible conversion functions from Pos to ?{val +: ?}
+ both method any2plus in object Sub of type (Any)Sub.Plus
+ and method pos2int in object Super of type (Pos)int
+ are possible conversion functions from Pos to ?{val +: ?}
f(p+1)
^
one error found
diff --git a/test/files/neg/overload.check b/test/files/neg/overload.check
index 5f7644eda7..760702778b 100644
--- a/test/files/neg/overload.check
+++ b/test/files/neg/overload.check
@@ -1,7 +1,7 @@
-overload.scala:10: error: erroneous reference to overloaded definition,
-most specific definition is: method f in class C of type (int)Unit,
-yet alternative definition method f in class D of type (Any)Unit
-is defined in a subclass
+overload.scala:10: error: ambiguous reference to overloaded definition,
+both method f in class D of type (Any)Unit
+and method f in class C of type (int)Unit
+match argument types (Int)
(new D).f(1)
^
one error found