object Test extends App { class Wrapped[W](var x: W) // must be invariant (to trigger the bug) class AbsWrapperCov[+B] // must be covariant case class Wrapper[T](underlying: Wrapped[T]) extends AbsWrapperCov[T]
def unwrap[A](it: AbsWrapperCov[A]): Wrapped[A] = it match { case Wrapper(wrapped) => wrapped // after inferTypedPattern: ?T <: A&0 // -Yvirtpatmat says: // matchRes4 = <error: value wrapped>; // found : Test.Wrapped[T] where type T <: A // required: Test.Wrapped[A] // which is the right thing to do, I'd say (try running this test) // however, the plain pattern matcher accepts this program // what's worse, the standard library relies on stuff like this type checking...
// from JavaConversions: // // implicit def asJavaIterator[A](it: Iterator[A]): ju.Iterator[A] = it match { // case JIteratorWrapper(wrapped) => wrapped // case _ => IteratorWrapper(it) // }
}
class A { def imNotAB = println("notB")} class Bval w = new Wrapped(new A) unwrap[Any](Wrapper(w)).x = new B
w.x.imNotAB
}
See also https://issues.scala-lang.org/browse/SI-5189
scala> case class Foo[T, U](f: T => U)
defined class Foo
// uh-oh, Any => Any should be Nothing => Any.
scala> def f(x: Any) = x match { case Foo(bar) => bar }
f: (x: Any)Any => Any
scala> def f(x: Any) = x match { case Foo(bar) => bar(5) }
f: (x: Any)Any
scala> f(Foo((x: String) => x))
java.lang.ClassCastException: java.lang.Integer cannot be cast to
java.lang.String
at $anonfun$1.apply(<console>:11)
at .f(<console>:9)
at .<init>(<console>:11)
--
Daniel C. Sobral
I travel to the future all the time.
So given:
class A[+T]
class B[T] extends A[T]
The pattern matcher allows people to treat the same term as an A[+T]
for the purposes of variance checks but a B[T] for the purposes of
member selection. There's probably no way to fix it without breaking
code. We can fix JavaConversions easily enough by casting if we can't
think of anything better.
There's probably no way to fix it without breakingcode.
We can fix JavaConversions easily enough by casting if we can't
think of anything better.
I vaguely remember that when I wrote an ancestor of that pattern match
I expected to have to cast, and was pleasantly surprised that I didn't
need to. In retrospect I should have hit the big red button.
FTR, I'd be delighted to see JavaConversions removed altogether.
Cheers,
Miles
--
Miles Sabin
tel: +44 7813 944 528
gtalk: mi...@milessabin.com
skype: milessabin
g+: http://www.milessabin.com
http://twitter.com/milessabin
http://www.chuusai.com/
FWIW, to me it seems that the type-checking of the pattern *body* that
seems to be wrong (it should not matter what pattern matcher
implementation does or does not do with it)
In your example,
- `it' has type AbsWrapperCov[A]
- the pattern Wrapped(...) has type Wrapper[T0] <: AbsWrapperCov[A]
for some fixed T0 <: A
- consequently, `wrapped' has type Wrapped[T0] with the same fixed T0<A.
That is all fine. In the body, though,
- `wrapped' is returned in a place where we expect Wrapped[A].
This is what should fail, since Wrapped is invariant and we don't have
any evidence that T0 == A.
I am not sure I understand what your fix does, but judging from the
error output, it seems that `wrapped' has the right bound already.
BTW keep in mind it's been years, I may be missing a lot here : )
Hope this helps,
Burak
--
Burak Emir
--
http://burak.emir.googlepages.com
it seems that `wrapped' has the right bound already.