Permalink
Browse files

SI-5330, SI-6014 deal with existential self-type

This has been broken since b7b81ca#L0L567.
The existential rash is treated in a similar manner as in fc24db4.

Conceptually, the fix would be `def selfTypeSkolemized =
widen.skolemizeExistential.narrow`, but simply widening before
narrowing achieves the same thing. Since we're in existential voodoo
territory, let's go for the minimal fix: replacing `this.narrow` by
`widen.narrow`.

--
Original patch by @retronym in #1074, refined by @paulp to
only perform widen.narrow incantation if there are
existentials present in the widened type, as
narrowing is expensive when the type is not a singleton.

The result is that compiling the entirety of quick, that
code path is hit only 143 times.  All the other calls hit
.narrow directly as before.  It looks like the definition
of negligible in the diff of -Ystatistics when compiling
src/library/scala/collection:

    < #symbols                      : 306315
    ---
    > #symbols                      : 306320
    12c13
    < #unique types                 : 293859
    ---
    > #unique types                 : 293865

I'm assuming based on the 2/1000ths of a percent increase
in symbol and type creation that wall clock is manageable,
but I didn't measure it.
  • Loading branch information...
1 parent 8501088 commit 65778d760fd7b80b8f0fb9e3cfe87cc87e3523ae @adriaanm adriaanm committed Nov 14, 2012
@@ -325,6 +325,18 @@ trait Types extends api.Types { self: SymbolTable =>
}
}
+ /** Same as a call to narrow unless existentials are visible
+ * after widening the type. In that case, narrow from the widened
+ * type instead of the proxy. This gives buried existentials a
+ * chance to make peace with the other types. See SI-5330.
+ */
+ private def narrowForFindMember(tp: Type): Type = {
+ val w = tp.widen
+ // Only narrow on widened type when we have to -- narrow is expensive unless the target is a singleton type.
+ if ((tp ne w) && containsExistential(w)) w.narrow
+ else tp.narrow
+ }
+
/** The base class for all types */
abstract class Type extends TypeApiImpl with Annotatable[Type] {
/** Types for which asSeenFrom always is the identity, no matter what
@@ -1079,7 +1091,7 @@ trait Types extends api.Types { self: SymbolTable =>
(other ne sym) &&
((other.owner eq sym.owner) ||
(flags & PRIVATE) != 0 || {
- if (self eq null) self = this.narrow
+ if (self eq null) self = narrowForFindMember(this)
if (symtpe eq null) symtpe = self.memberType(sym)
!(self.memberType(other) matches symtpe)
})}) {
@@ -1161,7 +1173,7 @@ trait Types extends api.Types { self: SymbolTable =>
if ((member ne sym) &&
((member.owner eq sym.owner) ||
(flags & PRIVATE) != 0 || {
- if (self eq null) self = this.narrow
+ if (self eq null) self = narrowForFindMember(this)
if (membertpe eq null) membertpe = self.memberType(member)
!(membertpe matches self.memberType(sym))
})) {
@@ -1176,7 +1188,7 @@ trait Types extends api.Types { self: SymbolTable =>
(other ne sym) &&
((other.owner eq sym.owner) ||
(flags & PRIVATE) != 0 || {
- if (self eq null) self = this.narrow
+ if (self eq null) self = narrowForFindMember(this)
if (symtpe eq null) symtpe = self.memberType(sym)
!(self.memberType(other) matches symtpe)
})}) {
View
@@ -0,0 +1,22 @@
+trait FM[A] {
+ def map(f: A => Any)
+}
+
+trait M[A] extends FM[A] {
+ def map(f: A => Any)
+}
+
+trait N[A] extends FM[A]
+
+object test {
+ def kaboom(xs: M[_]) = xs map (x => ()) // missing parameter type.
+
+ def okay1[A](xs: M[A]) = xs map (x => ())
+ def okay2(xs: FM[_]) = xs map (x => ())
+ def okay3(xs: N[_]) = xs map (x => ())
+}
+
+class CC2(xs: List[_]) {
+ def f(x1: Any, x2: Any) = null
+ def g = xs map (x => f(x, x))
+}
@@ -0,0 +1,6 @@
+abstract trait Base {
+ def foo: this.type
+};
+class Derived[T] extends Base {
+ def foo: Nothing = sys.error("!!!")
+}
@@ -0,0 +1,5 @@
+object t5330c {
+ val s: Set[_ >: Char] = Set('A')
+ s forall ("ABC" contains _)
+ s.forall( c => "ABC".toSeq.contains( c ))
+}
View
@@ -0,0 +1,13 @@
+object Test {
+ case class CC[T](key: T)
+ type Alias[T] = Seq[CC[T]]
+
+ def f(xs: Seq[CC[_]]) = xs map { case CC(x) => CC(x) } // ok
+ def g(xs: Alias[_]) = xs map { case CC(x) => CC(x) } // fails
+ // ./a.scala:11: error: missing parameter type for expanded function
+ // The argument types of an anonymous function must be fully known. (SLS 8.5)
+ // Expected type was: ?
+ // def g(xs: Alias[_]) = xs map { case CC(x) => CC(x) } // fails
+ // ^
+ // one error found
+}

0 comments on commit 65778d7

Please sign in to comment.