summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-10-08 18:31:44 +0000
committerMartin Odersky <odersky@gmail.com>2009-10-08 18:31:44 +0000
commit9cf9ab263b60ed2ae8ff5c7710a7f59695fc92e7 (patch)
treea35cfe628c41ba4da25d7a1d9077b4298ecf3e67 /src/compiler
parentadb677e4bc0c2fc7e822615c08384875e06a64ee (diff)
downloadscala-9cf9ab263b60ed2ae8ff5c7710a7f59695fc92e7.tar.gz
scala-9cf9ab263b60ed2ae8ff5c7710a7f59695fc92e7.tar.bz2
scala-9cf9ab263b60ed2ae8ff5c7710a7f59695fc92e7.zip
Definite fix for #2060; fix for #2392.
Added aliases for Vector and Traversable to scala package object.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala62
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala23
3 files changed, 55 insertions, 34 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index bacd4ef9dc..0003a50823 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -1479,8 +1479,8 @@ trait Symbols {
override def toString(): String =
if (isValueParameter && owner.isSetter)
"parameter of setter "+owner.nameString
- else if (isPackageObjectClass)
- "package object "+nameString
+ else if (isPackageObject || isPackageObjectClass)
+ "package object "+owner.nameString
else
compose(List(kindString,
if (isClassConstructor) owner.simpleName.decode+idString else nameString))
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index e9ca2dd7c5..133c0c1b3e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -174,6 +174,15 @@ self: Analyzer =>
}
}
+ /** An extractor for unary function types arg => res
+ */
+ object Function1 {
+ def unapply(tp: Type) = tp match {
+ case TypeRef(_, sym, List(arg, res)) if (sym == FunctionClass(1)) => Some(arg, res)
+ case _ => None
+ }
+ }
+
/** 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.
* @param pt The original expected type of the implicit.
@@ -344,32 +353,33 @@ self: Analyzer =>
*/
val wildPt = approximate(pt)
- /** Does type `tp' match wildPt?
- * This is the case if either `wildPt' is a HasMethodMatching type
- * and `tp' has a method matching wildPt, or otherwise if
- * `tp' stripped of universal quantifiers is compatible with `wildPt'.
- */
- def matchesWildPt(tp: Type) = wildPt match {
- case HasMethodMatching(name, argtpes, restpe) =>
- (tp.member(name) filter (m => isApplicableSafe(List(), m.tpe, argtpes, restpe))) != NoSymbol
- case _ =>
- isCompatible(depoly(tp), wildPt)
- }
-
- /** Does type `tp' match prototype `pt'?
- * This is the case if either `pt' is a HasMethodMatching type
- * and `tp' has a member matching `pt', or otherwise if
- * `tp' is compatible with `pt'.
+ /** Does type `tp' match expected type `pt'
+ * This is the case if either `pt' is a unary function type with a
+ * HasMethodMatching type as result, and `tp' is a unary function
+ * or method type whose result type has a method whose name and type
+ * correspond to the HasMethodMatching type,
+ * or otherwise if `tp' is compatible with `pt'.
*/
- def matchesPt(tp: Type, pt: Type) = pt match {
- case HasMethodMatching(name, argtpes, restpe) =>
- (tp.member(name) filter (m => isApplicableSafe(undetParams, m.tpe, argtpes, restpe))) != NoSymbol
- case _ =>
- isCompatible(tp, pt)
- }
+ def matchesPt(tp: Type, pt: Type, undet: List[Symbol]) =
+ isCompatible(tp, pt) || {
+ pt match {
+ case Function1(arg, HasMethodMatching(name, argtpes, restpe)) =>
+ normalize(tp) match {
+ case Function1(arg1, res1) =>
+ (arg <:< arg1) &&
+ (res1.member(name) filter (m => isApplicableSafe(undet, m.tpe, argtpes, restpe))) != NoSymbol
+ case _ =>
+ false
+ }
+ case _ =>
+ false
+ }
+ }
- if (traceImplicits) println("typed impl for "+wildPt+"? "+info.name+":"+depoly(info.tpe)+"/"+undetParams+"/"+isPlausiblyCompatible(info.tpe, wildPt)+"/"+matchesWildPt(info.tpe))
- if (isPlausiblyCompatible(info.tpe, wildPt) && matchesWildPt(info.tpe) && isStable(info.pre)) {
+ if (traceImplicits) println("typed impl for "+wildPt+"? "+info.name+":"+depoly(info.tpe)+"/"+undetParams+"/"+isPlausiblyCompatible(info.tpe, wildPt)+"/"+matchesPt(depoly(info.tpe), wildPt, List()))
+ if (isPlausiblyCompatible(info.tpe, wildPt) &&
+ matchesPt(depoly(info.tpe), wildPt, List()) &&
+ isStable(info.pre)) {
val itree = atPos(tree.pos.focus) {
if (info.pre == NoPrefix) Ident(info.name)
@@ -408,7 +418,7 @@ self: Analyzer =>
if (itree2.tpe.isError) SearchFailure
else if (hasMatchingSymbol(itree1)) {
val tvars = undetParams map freshVar
- if (matchesPt(itree2.tpe, pt.instantiateTypeParams(undetParams, tvars))) {
+ if (matchesPt(itree2.tpe, pt.instantiateTypeParams(undetParams, tvars), undetParams)) {
if (traceImplicits) println("tvars = "+tvars+"/"+(tvars map (_.constr)))
val targs = solvedTypes(tvars, undetParams, undetParams map varianceInType(pt),
false, lubDepth(List(itree2.tpe, pt)))
@@ -422,7 +432,7 @@ self: Analyzer =>
// println("RESULT = "+itree+"///"+itree1+"///"+itree2)//DEBUG
result
} else {
- if (traceImplicits) println("incompatible???")
+ if (traceImplicits) println("incompatible: "+itree2.tpe+" does not match "+pt.instantiateTypeParams(undetParams, tvars))
SearchFailure
}
} else if (settings.XlogImplicits.value)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 68f6009127..030c71b0bf 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -300,9 +300,11 @@ trait Typers { self: Analyzer =>
}
/** Check that `tpt' refers to a non-refinement class type */
- def checkClassType(tpt: Tree, existentialOK: Boolean) {
+ def checkClassType(tpt: Tree, existentialOK: Boolean, stablePrefix: Boolean) {
def check(tpe: Type): Unit = tpe.normalize match {
- case TypeRef(_, sym, _) if sym.isClass && !sym.isRefinementClass => ;
+ case TypeRef(pre, sym, _) if sym.isClass && !sym.isRefinementClass =>
+ if (stablePrefix && phase.id <= currentRun.typerPhase.id && !pre.isStable)
+ error(tpt.pos, "type "+pre+" is not a stable prefix")
case ErrorType => ;
case PolyType(_, restpe) => check(restpe)
case ExistentialType(_, restpe) if existentialOK => check(restpe)
@@ -988,7 +990,7 @@ trait Typers { self: Analyzer =>
}
def adaptToMember(qual: Tree, searchTemplate: Type): Tree = {
- val qtpe = qual.tpe.widen
+ var qtpe = qual.tpe.widen
if (qual.isTerm &&
((qual.symbol eq null) || !qual.symbol.isTerm || qual.symbol.isValue) &&
phase.id <= currentRun.typerPhase.id && !qtpe.isError &&
@@ -998,6 +1000,10 @@ trait Typers { self: Analyzer =>
// a value that needs to be coerced, so we check whether the implicit value has an `apply` method
// (if we allow this, we get divergence, e.g., starting at `conforms` during ant quick.bin)
// note: implicit arguments are still inferred (this kind of "chaining" is allowed)
+ if (qtpe.normalize.isInstanceOf[ExistentialType]) {
+ qtpe = qtpe.normalize.skolemizeExistential(context.owner, qual)
+ qual setType qtpe
+ }
val coercion = inferView(qual, qtpe, searchTemplate, true)
if (coercion != EmptyTree)
typedQualifier(atPos(qual.pos)(Apply(coercion, List(qual))))
@@ -1158,7 +1164,7 @@ trait Typers { self: Analyzer =>
def validateParentClass(parent: Tree, superclazz: Symbol) {
if (!parent.tpe.isError) {
val psym = parent.tpe.typeSymbol.initialize
- checkClassType(parent, false)
+ checkClassType(parent, false, true)
if (psym != superclazz) {
if (psym.isTrait) {
val ps = psym.info.parents
@@ -1283,6 +1289,11 @@ trait Typers { self: Analyzer =>
.typedTemplate(mdef.impl, parentTypes(mdef.impl))
val impl2 = addSyntheticMethods(impl1, clazz, context)
+ if (mdef.name == nme.PACKAGEkw)
+ for (m <- mdef.symbol.info.members)
+ if (m.isClass && m.hasFlag(CASE))
+ context.error(if (m.pos.isDefined) m.pos else mdef.pos,
+ "implementation restriction: "+mdef.symbol+" cannot contain case "+m)
treeCopy.ModuleDef(mdef, typedMods, mdef.name, impl2) setType NoType
}
@@ -2856,7 +2867,7 @@ trait Typers { self: Analyzer =>
def typedNew(tpt: Tree) = {
var tpt1 = typedTypeConstructor(tpt)
- checkClassType(tpt1, false)
+ checkClassType(tpt1, false, true)
if (tpt1.hasSymbol && !tpt1.symbol.typeParams.isEmpty) {
context.undetparams = cloneSymbols(tpt1.symbol.typeParams)
tpt1 = TypeTree()
@@ -2953,7 +2964,7 @@ trait Typers { self: Analyzer =>
val targs = args map (_.tpe)
checkBounds(tree.pos, NoPrefix, NoSymbol, tparams, targs, "")
if (fun.symbol == Predef_classOf) {
- checkClassType(args.head, true)
+ checkClassType(args.head, true, false)
atPos(tree.pos) { gen.mkClassOf(targs.head) }
} else {
if (phase.id <= currentRun.typerPhase.id &&