summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Cunei <antonio.cunei@epfl.ch>2010-09-28 12:31:56 +0000
committerAntonio Cunei <antonio.cunei@epfl.ch>2010-09-28 12:31:56 +0000
commit16dd1e6bfd7e55930becedf03f54261a0faa814e (patch)
treeaaaec04a0167db3939f97ec0ad9465a4de3277c4
parent394bc2928b6ad24306038a4c4a73611b2ec13ae3 (diff)
downloadscala-16dd1e6bfd7e55930becedf03f54261a0faa814e.tar.gz
scala-16dd1e6bfd7e55930becedf03f54261a0faa814e.tar.bz2
scala-16dd1e6bfd7e55930becedf03f54261a0faa814e.zip
Merged revisions 23111 via svnmerge from
https://lampsvn.epfl.ch/svn-repos/scala/scala/trunk ........ r23111 | moors | 2010-09-27 15:27:35 +0200 (Mon, 27 Sep 2010) | 3 lines closes #3873. fixed unsoundness in dependent method types reported by Ingo. review by maier as no good deed goes unpunished ........
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala89
-rw-r--r--test/files/neg/t3873.check6
-rw-r--r--test/files/neg/t3873.flags1
-rw-r--r--test/files/neg/t3873.scala12
4 files changed, 34 insertions, 74 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index deffa1d852..a7f8db28b2 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -3493,85 +3493,26 @@ A type's typeSymbol should never be inspected directly.
else mapOver(tp)
}
-/*
- /** Most of the implementation for MethodType.resultType. The
- * caller also needs to existentially quantify over the
- * variables in existentialsNeeded.
- */
- class InstantiateDeBruijnMap(actuals: List[Type]) extends TypeMap {
- def apply(tp: Type): Type = tp match {
- case DeBruijnIndex(level, pid) =>
- if (level == 1)
- if (pid < actuals.length) actuals(pid) else tp
- else DeBruijnIndex(level - 1, pid)
- case _ =>
- mapOver(tp)
- }
-
+ class InstantiateDependentMap(params: List[Symbol], actuals: List[Type]) extends TypeMap {
override val dropNonConstraintAnnotations = true
- private var existSyms = immutable.Map.empty[Int, Symbol]
- def existentialsNeeded: List[Symbol] = existSyms.values.toList
-
- /* Return the type symbol for referencing a parameter index
- * inside the existential quantifier. */
- def existSymFor(actualIdx: Int, oldSym: Symbol) =
- if (existSyms.isDefinedAt(actualIdx))
- existSyms(actualIdx)
- else {
- val symowner = oldSym.owner // what should be used??
- val bound = singletonBounds(actuals(actualIdx))
-
- val sym = symowner.newExistential(oldSym.pos, oldSym.name+".type")
- sym.setInfo(bound)
- sym.setFlag(oldSym.flags)
-
- existSyms = existSyms + (actualIdx -> sym)
- sym
- }
-
- override def mapOver(arg: Tree, giveup: ()=>Nothing): Tree = {
- object treeTrans extends TypeMapTransformer {
- override def transform(tree: Tree): Tree =
- tree match {
- case Ident(name) =>
- tree.tpe.withoutAnnotations match {
- case DeBruijnIndex(level, pid) =>
- if (level == 1) {
- if (actuals(pid).isStable)
- mkAttributedQualifier(actuals(pid), tree.symbol)
- else {
- val sym = existSymFor(pid, tree.symbol)
- (Ident(tree.symbol.name)
- copyAttrs tree
- setType typeRef(NoPrefix, sym, Nil))
- }
- } else
- Ident(name)
- .setPos(tree.pos)
- .setSymbol(tree.symbol)
- .setType(DeBruijnIndex(level-1, pid))
- case _ =>
- super.transform(tree)
-
- }
- case _ => super.transform(tree)
- }
+ object ParamWithActual {
+ def unapply(sym: Symbol): Option[Type] = {
+ val pid = params indexOf sym
+ if(pid != -1) Some(actuals(pid)) else None
}
-
- treeTrans.transform(arg)
}
- }
-*/
- class InstantiateDependentMap(params: List[Symbol], actuals: List[Type]) extends SubstTypeMap(params, actuals) {
- override protected def renameBoundSyms(tp: Type): Type = tp match {
- case MethodType(ps, restp) => tp // the whole point of this substitution is to instantiate these args
- case _ => super.renameBoundSyms(tp)
- }
- // TODO: should we optimise this? only need to consider singletontypes
-
- override val dropNonConstraintAnnotations = true
+ def apply(tp: Type): Type =
+ mapOver(tp) match {
+ case SingleType(NoPrefix, ParamWithActual(arg)) if arg isStable => arg // unsound to replace args by unstable actual #3873
+ // (soundly) expand type alias selections on implicit arguments, see depmet_implicit_oopsla* test cases -- typically, `param.isImplicit`
+ case tp1@TypeRef(SingleType(NoPrefix, param@ParamWithActual(arg)), sym, targs) =>
+ val res = typeRef(arg, sym, targs)
+ if(res.typeSymbolDirect isAliasType) res.dealias
+ else tp1
+ case tp1 => tp1 // don't return the original `tp`, which may be different from `tp1`, due to `dropNonConstraintAnnotations`
+ }
def existentialsNeeded: List[Symbol] = existSyms.filter(_ ne null).toList
diff --git a/test/files/neg/t3873.check b/test/files/neg/t3873.check
new file mode 100644
index 0000000000..54d6abdf63
--- /dev/null
+++ b/test/files/neg/t3873.check
@@ -0,0 +1,6 @@
+t3873.scala:11: error: type mismatch;
+ found : Test.a.B
+ required: a.B
+ wrongf(new A)(a.b) // should not compile -- TODO: improve error message? the "a" is ambiguous
+ ^
+one error found
diff --git a/test/files/neg/t3873.flags b/test/files/neg/t3873.flags
new file mode 100644
index 0000000000..1c26b24745
--- /dev/null
+++ b/test/files/neg/t3873.flags
@@ -0,0 +1 @@
+-Ydependent-method-types \ No newline at end of file
diff --git a/test/files/neg/t3873.scala b/test/files/neg/t3873.scala
new file mode 100644
index 0000000000..e7815f0937
--- /dev/null
+++ b/test/files/neg/t3873.scala
@@ -0,0 +1,12 @@
+class A {
+ class B
+ def b: B = new B
+}
+
+object Test {
+ def wrongf(a: A)(b: a.B): a.B = b
+
+ val a = new A
+ wrongf(a)(a.b)
+ wrongf(new A)(a.b) // should not compile -- TODO: improve error message? the "a" is ambiguous
+} \ No newline at end of file