GCD issue in both old and new patmat?

25 views
Skip to first unread message

√iktor Ҡlang

unread,
May 16, 2012, 8:57:43 AM5/16/12
to scala-i...@googlegroups.com
scala> (new IllegalStateException).asInstanceOf[Throwable] match { case e @ (_: IllegalStateException | _: ClassCastException) => val sanity: Exception = e }
<console>:8: error: type mismatch;
 found   : Throwable
 required: Exception
              (new IllegalStateException).asInstanceOf[Throwable] match { case e @ (_: IllegalStateException | _: ClassCastException) => val sanity: Exception = e }

--
Viktor Klang

Akka Tech Lead
Typesafe - The software stack for applications that scale

Twitter: @viktorklang

Eugene Burmako

unread,
May 16, 2012, 9:01:11 AM5/16/12
to scala-i...@googlegroups.com

I think it's because typeTest in ' static' mode emits the test that ensures that the static type of scrutinee conforms to a case. I was also puzzled by that, when tried to implement tag-aware matching for abstract types.

√iktor Ҡlang

unread,
May 16, 2012, 9:05:10 AM5/16/12
to scala-i...@googlegroups.com
Is it a bug, and if so, is there a ticket for it already?

Adriaan Moors

unread,
May 16, 2012, 9:14:11 AM5/16/12
to scala-i...@googlegroups.com
I agree this would be nice, but this is as spec'ed, I believe:

A pattern binder x@p consists of a pattern variable x and a pattern p. The type of the variable x is the static type T of the pattern p.
All alternative patterns are type checked with the expected type of the pattern.  

in your example, the expected type of the alternative pattern is Throwable, and thus, so is the type of e

(btw, to see the types using the compiler/repl:  -Xprint-types -Xprint:typer:
case (e @ ((_{IllegalStateException}: IllegalStateException){IllegalStateException}| (_{ClassCastException}: ClassCastException){ClassCastException}){Throwable}){Throwable} =>
)

Eugene Burmako

unread,
May 16, 2012, 9:15:11 AM5/16/12
to scala-i...@googlegroups.com

No idea, we did not have time to discuss this with Adriaan

On May 16, 2012 4:05 PM, "√iktor Ҡlang" <viktor...@gmail.com> wrote:
Is it a bug, and if so, is there a ticket for it already?



On Wed, May 16, 2012 at 3:01 PM, Eugene Burmako <eugene....@epfl.ch> wrote:
>

> I think it's b...

Eugene Burmako

unread,
May 16, 2012, 9:17:27 AM5/16/12
to scala-i...@googlegroups.com

Does this mean that I cannot match something of static type Tree against, say, Apply?

Adriaan Moors

unread,
May 16, 2012, 9:20:54 AM5/16/12
to scala-i...@googlegroups.com
I think we're talking about different things here.

recall Viktor's example:
(new IllegalStateException).asInstanceOf[Throwable] match { case e @ (_: IllegalStateException | _: ClassCastException) => val sanity: Exception = e }

`e` has type `Throwable` since that's how alternatives are type checked, thus you can't assign it to sanity

it's trivial to fix this in the type checker for this example, but we'd also have to update the spec
don't know if now's a good time for that (well, actually, I would say it's not)

        case Alternative(alts) =>
          val alts1 = alts mapConserve (alt => typed(alt, mode | ALTmode, pt))
          treeCopy.Alternative(tree, alts1) setType lub(alts1 map (_.tpe)) //pt

Miles Sabin

unread,
May 16, 2012, 9:27:46 AM5/16/12
to scala-i...@googlegroups.com
On Wed, May 16, 2012 at 2:20 PM, Adriaan Moors <adriaa...@epfl.ch> wrote:
> I think we're talking about different things here.
>
> recall Viktor's example:
> (new IllegalStateException).asInstanceOf[Throwable] match { case e @ (_:
> IllegalStateException | _: ClassCastException) => val sanity: Exception = e
> }
>
> `e` has type `Throwable` since that's how alternatives are type checked,
> thus you can't assign it to sanity

But surely the LUB here should be Exception not Throwable?

I'm not sure I see how Viktor's example is different from,

scala> class A ; class B extends A ; class C extends A
defined class A
defined class B
defined class C

scala> ((new B) : A) match { case a @ (_ : B | _ : C) => val sanity : A = a }

scala>

Which is just fine.

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://underscoreconsulting.com
http://www.chuusai.com

martin odersky

unread,
May 16, 2012, 9:30:28 AM5/16/12
to scala-i...@googlegroups.com
On Wed, May 16, 2012 at 3:27 PM, Miles Sabin <mi...@milessabin.com> wrote:
On Wed, May 16, 2012 at 2:20 PM, Adriaan Moors <adriaa...@epfl.ch> wrote:
> I think we're talking about different things here.
>
> recall Viktor's example:
> (new IllegalStateException).asInstanceOf[Throwable] match { case e @ (_:
> IllegalStateException | _: ClassCastException) => val sanity: Exception = e
> }
>
> `e` has type `Throwable` since that's how alternatives are type checked,
> thus you can't assign it to sanity

But surely the LUB here should be Exception not Throwable?

No, there is no LUB computed. We can't because types in patterns flow from the root (selector type) to the leaves (variables in patterns),

 
I'm not sure I see how Viktor's example is different from,

scala> class A ; class B extends A ; class C extends A
defined class A
defined class B
defined class C

scala> ((new B) : A) match { case a @ (_ : B | _ : C) => val sanity : A = a }

Selector type is A, so a has type A.

Cheers

 - Martin

Adriaan Moors

unread,
May 16, 2012, 9:31:58 AM5/16/12
to scala-i...@googlegroups.com
Miles, your example is different from Viktor's:

contrast
  val sanity: Exception = (e: Throwable)
to
  val sanity : A = (a: A)

On Wed, May 16, 2012 at 3:27 PM, Miles Sabin <mi...@milessabin.com> wrote:

Miles Sabin

unread,
May 16, 2012, 9:43:22 AM5/16/12
to scala-i...@googlegroups.com
On Wed, May 16, 2012 at 2:30 PM, martin odersky <martin....@epfl.ch> wrote:
> No, there is no LUB computed. We can't because types in patterns flow from
> the root (selector type) to the leaves (variables in patterns),

Fair enough, but it seems a little unfortunate that,

(new IllegalStateException).asInstanceOf[Throwable] match {
case e : IllegalStateException => val sanity: Exception = e
case e : ClassCastException => val sanity : Exception = e
}

which you might naively think is equivalent to Viktor's eg. is
perfectly OK, especially since one of the main uses of pattern
alternatives is to eliminate duplicate case clause RHS's in precisely
this kind of situation.

√iktor Ҡlang

unread,
May 16, 2012, 10:26:43 AM5/16/12
to scala-i...@googlegroups.com
On Wed, May 16, 2012 at 3:43 PM, Miles Sabin <mi...@milessabin.com> wrote:
On Wed, May 16, 2012 at 2:30 PM, martin odersky <martin....@epfl.ch> wrote:
> No, there is no LUB computed. We can't because types in patterns flow from
> the root (selector type) to the leaves (variables in patterns),

Fair enough, but it seems a little unfortunate that,

(new IllegalStateException).asInstanceOf[Throwable] match {
 case e : IllegalStateException => val sanity: Exception = e
 case e : ClassCastException => val sanity : Exception = e
}

which you might naively think is equivalent to Viktor's eg. is
perfectly OK, especially since one of the main uses of pattern
alternatives is to eliminate duplicate case clause RHS's in precisely
this kind of situation.

Heck, I'd even settle for:

case (e: Exception) @ (_: ClassCastException | _: CancelledKeyException | _: IOException | _: ActorInitializationException) ⇒

But I think it's intuitive to assume that the type of the e will be the LUB of the match.

Cheers,
Reply all
Reply to author
Forward
0 new messages