diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Symbols.scala | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 62 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 23 | ||||
-rw-r--r-- | src/library/scala/Range.scala | 12 | ||||
-rw-r--r-- | src/library/scala/collection/Vector.scala | 2 | ||||
-rw-r--r-- | src/library/scala/package.scala | 23 | ||||
-rw-r--r-- | test/files/jvm/inner.scala | 4 |
7 files changed, 81 insertions, 49 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 && diff --git a/src/library/scala/Range.scala b/src/library/scala/Range.scala index 5a27fa21de..c808a3db10 100644 --- a/src/library/scala/Range.scala +++ b/src/library/scala/Range.scala @@ -11,7 +11,7 @@ package scala import annotation.experimental -import collection.immutable.Vector + import collection.VectorView import util.control.Exception.catching import util.Hashable @@ -39,7 +39,7 @@ import util.Hashable abstract class GenericRange[T] (val start: T, val end: T, val step: T, val isInclusive: Boolean = false) (implicit num: Integral[T]) -extends VectorView[T, Vector[T]] with RangeToString[T] with Hashable { +extends VectorView[T, collection.immutable.Vector[T]] with RangeToString[T] with Hashable { import num._ // todo? - we could lift the length restriction by implementing a range as a sequence of @@ -50,7 +50,7 @@ extends VectorView[T, Vector[T]] with RangeToString[T] with Hashable { // By adjusting end based on isInclusive, we can treat all ranges as exclusive. private lazy val trueEnd: T = if (isInclusive) end + step else end - protected def underlying = Vector.empty[T] + protected def underlying = collection.immutable.Vector.empty[T] /** Create a new range with the start and end values of this range and * a new <code>step</code>. @@ -129,7 +129,7 @@ extends VectorView[T, Vector[T]] with RangeToString[T] with Hashable { } } -private[scala] trait RangeToString[T] extends VectorView[T, Vector[T]] { +private[scala] trait RangeToString[T] extends VectorView[T, collection.immutable.Vector[T]] { // The default toString() tries to print every element and will exhaust memory // if the Range is unduly large. This interacts poorly with the REPL. override def toString() = { @@ -179,11 +179,11 @@ object GenericRange * @since 2.5 */ class Range(val start: Int, val end: Int, val step: Int) -extends VectorView[Int, Vector[Int]] with RangeToString[Int] +extends VectorView[Int, collection.immutable.Vector[Int]] with RangeToString[Int] { require(step != 0) - protected def underlying = Vector.empty[Int] + protected def underlying = collection.immutable.Vector.empty[Int] /** Create a new range with the start and end values of this range and * a new <code>step</code>. diff --git a/src/library/scala/collection/Vector.scala b/src/library/scala/collection/Vector.scala index cf802ca095..78228b6650 100644 --- a/src/library/scala/collection/Vector.scala +++ b/src/library/scala/collection/Vector.scala @@ -36,4 +36,6 @@ trait Vector[+A] extends Seq[A] object Vector extends SeqFactory[Vector] { implicit def builderFactory[A]: BuilderFactory[A, Vector[A], Coll] = new VirtualBuilderFactory[A] def newBuilder[A]: Builder[A, Vector[A]] = mutable.Vector.newBuilder[A] + + @deprecated("use collection.mutable.Vector instead") type Mutable[A] = scala.collection.mutable.Vector[A] } diff --git a/src/library/scala/package.scala b/src/library/scala/package.scala index 39f9dc3dcc..e5572ede30 100644 --- a/src/library/scala/package.scala +++ b/src/library/scala/package.scala @@ -10,20 +10,18 @@ package object scala { + + type Travarsable[+A] = scala.collection.Traversable[A] + val Traversable = scala.collection.Traversable + type Iterable[+A] = scala.collection.Iterable[A] val Iterable = scala.collection.Iterable - @deprecated("use Iterable instead") type Collection[+A] = Iterable[A] - @deprecated("use Iterable instead") val Collection = Iterable - type Seq[+A] = scala.collection.Seq[A] val Seq = scala.collection.Seq - @deprecated("use Seq instead") type Sequence[+A] = scala.collection.Seq[A] - @deprecated("use Seq instead") val Sequence = scala.collection.Seq - - type RandomAccessSeq[+A] = scala.collection.Vector[A] - val RandomAccessSeq = scala.collection.Vector + type Vector[+A] = scala.collection.Vector[A] + val Vector = scala.collection.Vector type Iterator[+A] = scala.collection.Iterator[A] val Iterator = scala.collection.Iterator @@ -43,4 +41,13 @@ package object scala { type StringBuilder = scala.collection.mutable.StringBuilder val StringBuilder = scala.collection.mutable.StringBuilder + + @deprecated("use Iterable instead") type Collection[+A] = Iterable[A] + @deprecated("use Iterable instead") val Collection = Iterable + + @deprecated("use Seq instead") type Sequence[+A] = scala.collection.Seq[A] + @deprecated("use Seq instead") val Sequence = scala.collection.Seq + + @deprecated("use Vector instead") type RandomAccessSeq[+A] = scala.collection.Vector[A] + @deprecated("use Vector instead") val RandomAccessSeq = scala.collection.Vector } diff --git a/test/files/jvm/inner.scala b/test/files/jvm/inner.scala index ce4de718e6..51e3909ef3 100644 --- a/test/files/jvm/inner.scala +++ b/test/files/jvm/inner.scala @@ -32,7 +32,9 @@ class A { } } - class Impl2 extends Impl(1) with Itf#Itf2 { + val impl = new Impl(0) + + class Impl2 extends Impl(1) with impl.Itf2 { def method2 = { println(abc) } |