diff options
author | Adriaan Moors <adriaan.moors@epfl.ch> | 2009-09-29 16:32:28 +0000 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2009-09-29 16:32:28 +0000 |
commit | 1575d9b94e889661c660c6b35b915afa5833b2b9 (patch) | |
tree | 03e5d6b79a7899d2c57079f33845633e8ceb8070 /test/files | |
parent | 72789e9bb8c2474563c405ee8087b5e21be5993d (diff) | |
download | scala-1575d9b94e889661c660c6b35b915afa5833b2b9.tar.gz scala-1575d9b94e889661c660c6b35b915afa5833b2b9.tar.bz2 scala-1575d9b94e889661c660c6b35b915afa5833b2b9.zip |
fixed #2316: No longer cache entire SearchResul...
fixed #2316: No longer cache entire SearchResult when looking for implicits in the parts of the expected type. (patch by retronym -- see ticket)
A SearchResult may contain symbols local to the scope of the search that
were used as implicit parameters, so they are not safely cacheable. The
fix for #2101 does not suffice. That patch avoided bound symbols being
duplicated, but the problem is much worse.
The implicits for an expected type depend on more than just that type,
so we cannot cache them using the expected type as a key.
The neg/t2316 test illustrates this: T1 may provide two implicits, one
requires an implicit T2, another an implicit T3. If an implicit T1
is first required when only a T2 is in scope, the SearchResult will
describe the corresponding implicit. Now, if we enter an implicit value
of type T3 into scope, the search should fail (it is ambiguous), but the
cache does not take this new fact into account.
The patch replaces the erroneous aggressive caching with a more
conservative version that only caches ImplicitInfo's.
Diffstat (limited to 'test/files')
-rw-r--r-- | test/files/neg/t2316.check | 7 | ||||
-rw-r--r-- | test/files/neg/t2316.scala | 43 | ||||
-rw-r--r-- | test/files/run/t2316.scala | 32 |
3 files changed, 82 insertions, 0 deletions
diff --git a/test/files/neg/t2316.check b/test/files/neg/t2316.check new file mode 100644 index 0000000000..fea1745663 --- /dev/null +++ b/test/files/neg/t2316.check @@ -0,0 +1,7 @@ +t2316.scala:28: error: ambiguous implicit values: + both method T1FromT3 in object T1 of type (implicit t3: test.T3)test.T1 + and method T1FromT2 in object T1 of type (implicit t2: test.T2)test.T1 + match expected type test.T1 + val t1 = requireT1 + ^ +one error found diff --git a/test/files/neg/t2316.scala b/test/files/neg/t2316.scala new file mode 100644 index 0000000000..ccda9d5aac --- /dev/null +++ b/test/files/neg/t2316.scala @@ -0,0 +1,43 @@ +object test { + case class T1(val source: String) + + + object T1 { + implicit def T1FromT2(implicit t2: T2): T1 = T1("implicit def T1FromT2") + implicit def T1FromT3(implicit t3: T3): T1 = T1("implicit def T1FromT3") + } + + trait T2 { + } + + object T2 { + implicit val t2: T2 = new T2 {} + } + + trait T3 + + def requireT1(implicit t1: T1) = t1 + + { + val t1 = requireT1 + assert(t1.source == "implicit def T1FromT2") + } + + { + implicit def t3: T3 = new T3 {} + val t1 = requireT1 + assert(t1.source == "implicit def T1FromT2") + + // Expected a compile error here, but because T1.T1FromT2(T2.t2) was cached as a non-local implicit + // expression for type T1, this is not checked! + // + // (fragment of implicit-cache-error2.scala):26: error: ambiguous implicit values: + // both method T1FromT3 in object T1 of type (implicit t3: this.T3)this.T1 + // and method T1FromT2 in object T1 of type (implicit t2: this.T2)this.T1 + // match expected type this.T1 + // val t1 = requireT1 + // ^ + // one error found + + } +}
\ No newline at end of file diff --git a/test/files/run/t2316.scala b/test/files/run/t2316.scala new file mode 100644 index 0000000000..a3d5bf890b --- /dev/null +++ b/test/files/run/t2316.scala @@ -0,0 +1,32 @@ +case class T1(source: String) + +object T1 { + implicit def T1FromT2(implicit t2: T2) = new T1(t2.source) +} + +case class T2(source: String) + +object A { + def requireT1(implicit t1: T1) = t1 + + object B1 { + implicit val t2_b1 = new T2("from B1") + requireT1 + } + + object B2 { + def t1 = { + implicit val t2_b2 = new T2("from B2") + // Implicits.cacheResult returns T1.T1FromT2(t2_b1) here, which is bogus. Even though T1.T1FromT2 was found + // outside of the scope of A.B1, this implicit expression should _not_ be cached, as it includes the bound + // variable t2_b1 from this scope. + requireT1 + } + } +} + +object Test { + def main(args: Array[String]) { + assert(A.B2.t1.source == "from B2") + } +}
\ No newline at end of file |