Scala Programming Language
  1. Scala Programming Language
  2. SI-5967

Repeated parameter A* doesn't behave like Seq[A] on a pattern match

    Details

      Description

      This doesn't compile:

      def f(a: Int*) = a match {
        case 0 :: Nil => "List(0)! My favorite Seq!"
        case _ => a.toString
      }
      
      error: constructor cannot be instantiated to expected type;
       found   : collection.immutable.::[B]
       required: Int*
      

      But this does:

      def f(a: Int*) = (a: Seq[Int]) match {
        case 0 :: Nil => "List(0)! My favorite Seq!"
        case _ => a.toString
      }
      

      I think it's obvious, but per the spec, the identifier a should already have the type Seq[Int] inside the body of f in either case, yet in the first case, the compiler seems to think that a has a type which is a strict subtype of Seq[Int] and which List does not extend.

      Seems related to (if not a dupe of) SI-4176.

        Issue Links

          Activity

          Hide
          Jason Zaugg added a comment -

          Easy enough to remedy, but the solution feels a bit dirty. Suggestions for improvement welcome.

          https://github.com/retronym/scala/compare/ticket/4176

          Show
          Jason Zaugg added a comment - Easy enough to remedy, but the solution feels a bit dirty. Suggestions for improvement welcome. https://github.com/retronym/scala/compare/ticket/4176
          Hide
          Ryan Hendrickson added a comment -

          Sorry if this is a dumb thought, but would it be less dirty to fix this in typedIdent rather than typedMatch? I'm thinking something like changing that final call to stabilize (line 4751 in your commit) from

          stabilize(tree2, pre2, mode, pt)
          

          to

          val tree3 = stabilize(tree2, pre2, mode, pt)
          tree3 setType dropRepeatedParamType(tree3.tpe)
          

          Unless this is bad for some reason, it seems like it represents the general idea of "identifiers referring to repeated parameter symbols should have Seq type rather than <repeated> type" better than fixing it ad-hoc for pattern matching. (And maybe—I haven't tried this, just a shot in the dark—it would mean you don't need dropRepeatedParamType inside widenIfNecessary anymore to ensure that val a2 = a doesn't get a's <repeated>ness.)

          Show
          Ryan Hendrickson added a comment - Sorry if this is a dumb thought, but would it be less dirty to fix this in typedIdent rather than typedMatch? I'm thinking something like changing that final call to stabilize ( line 4751 in your commit) from stabilize(tree2, pre2, mode, pt) to val tree3 = stabilize(tree2, pre2, mode, pt) tree3 setType dropRepeatedParamType(tree3.tpe) Unless this is bad for some reason, it seems like it represents the general idea of "identifiers referring to repeated parameter symbols should have Seq type rather than <repeated> type" better than fixing it ad-hoc for pattern matching. (And maybe—I haven't tried this, just a shot in the dark—it would mean you don't need dropRepeatedParamType inside widenIfNecessary anymore to ensure that val a2 = a doesn't get a 's <repeated>ness.)
          Hide
          Jason Zaugg added a comment -

          Sounds like a good suggestion; I'll see how it pans out.

          Show
          Jason Zaugg added a comment - Sounds like a good suggestion; I'll see how it pans out.
          Hide
          Adriaan Moors added a comment -

          not sure that would work, since I think we rely on the special <repeated> type for overload resolution (see some of the recent bugs regarding overloading and varargs)

          Show
          Adriaan Moors added a comment - not sure that would work, since I think we rely on the special <repeated> type for overload resolution (see some of the recent bugs regarding overloading and varargs)
          Hide
          Ryan Hendrickson added a comment -

          Changing typedIdent shouldn't change anything about the type of the parameter symbol, which is what gets looked at when overload resolution is performed, right?

          Show
          Ryan Hendrickson added a comment - Changing typedIdent shouldn't change anything about the type of the parameter symbol, which is what gets looked at when overload resolution is performed, right?
          Hide
          Adriaan Moors added a comment -

          right, my mistake

          Show
          Adriaan Moors added a comment - right, my mistake
          Show
          Jason Zaugg added a comment - https://github.com/scala/scala/pull/771

            People

            • Assignee:
              Jason Zaugg
              Reporter:
              Ryan Hendrickson
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development