diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2014-03-18 15:47:32 +0100 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2014-03-18 16:40:57 +0100 |
commit | 9f42c09e4e1dd8f56ac98c5e79b45912f111e8de (patch) | |
tree | 4fe4168eaf96dbd3b6ece421bbad10f6331926d6 /test/files/neg/t8431.check | |
parent | df44b2718dcc489a057d2a60cdaadffed2ce0df5 (diff) | |
download | scala-9f42c09e4e1dd8f56ac98c5e79b45912f111e8de.tar.gz scala-9f42c09e4e1dd8f56ac98c5e79b45912f111e8de.tar.bz2 scala-9f42c09e4e1dd8f56ac98c5e79b45912f111e8de.zip |
SI-8341 Refine handoff of undet. params from implicit search
In SI-7944 / 251c2b93, we discovered that typechecking of an implicit
candidate could leave orphaned undetermined type parameters in the
implicit search context. This resulted in naked type parameters
leaking into implicit expansions. The fix seemed easy: just copy
any symbols from `implicitSearchContext.undetparams` to the enclosing
context (other than ones in `SearchResult#subst`).
However, the test case in this ticket reveals a subtle flaw in that
fix: `implicitSerachContext.undetparams` only contains the type params
from the most recently typechecked candidate!
Why? Implicit search uses the same context to typecheck all plausibly
compatible candidates. The typechecking itself is driven by
`typedImplicit1`.
Side note, that explains the heisenbug behaviour noted in the ticket:
Not *all* plausibly implicit candidates are typechecked. If
the current 'best' eligible candidate is more specific than the next
candidate, we can skip that altogether.Implicit search actually
exploits this for performance by ordering the candidates according to
usage statistics. This reordering, means that commenting out lines
elsewhere in the file changed the behaviour!
This commit simply stores the undet. tparams in the `SearchResult`,
where it is safe from the vaguries of typechecking other candidates.
That makes `Test1` and `Test2` with in the enclosed test case fail
uniformly, both with each other, and with an explicit call to
the view.
This is ostensibly a regression from 2.10.3. To get there,
we need an implicit search that has to infer `Nothing` in a covariant
position. In 2.10.3, we would just let the `G` out into the wild,
which did the right thing for the wrong reasons.
Diffstat (limited to 'test/files/neg/t8431.check')
-rw-r--r-- | test/files/neg/t8431.check | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/test/files/neg/t8431.check b/test/files/neg/t8431.check new file mode 100644 index 0000000000..75351a8ae7 --- /dev/null +++ b/test/files/neg/t8431.check @@ -0,0 +1,27 @@ +t8431.scala:24: error: type mismatch; + found : CanBuildFrom[Invariant[Nothing]] + required: CanBuildFrom[Invariant[G]] + s.combined // fail + ^ +t8431.scala:24: error: value combined is not a member of Invariant[Nothing] + s.combined // fail + ^ +t8431.scala:35: error: type mismatch; + found : CanBuildFrom[Invariant[Nothing]] + required: CanBuildFrom[Invariant[G]] + s.combined // was okay! + ^ +t8431.scala:35: error: value combined is not a member of Invariant[Nothing] + s.combined // was okay! + ^ +t8431.scala:45: error: type mismatch; + found : CanBuildFrom[Invariant[Nothing]] + required: CanBuildFrom[Invariant[G]] + convert2(s).combined + ^ +t8431.scala:48: error: type mismatch; + found : CanBuildFrom[Invariant[Nothing]] + required: CanBuildFrom[Invariant[G]] + {val c1 = convert2(s); c1.combined} + ^ +6 errors found |