Scala Toolchain for Eclipse is an open source project powered by Assembla

Assembla offers free public and private SVN/Git repositories and project hosting with bug/issue tracking and collaboration tools.

scala-eclipse-toolchain

Commit a3799c585a78ca8ba9bc0c28c76e76842098cf15

User picture

Working my way through pattern matcher sequence issues mostly caused
by the special handling of Lists. Also deleting all kinds of
useless or almost useless code which is presently only clutter.

Closes #2756, #2800, #3050, #3530, #3972, no review.

git-svn-id: https://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@24812 5e8d7ff9-d8ef-0310-90f0-a4852d11357a

Files Affected

 
874d2a95b2ae791019dd5e1ce81ab1b94bbd4588a3799c585a78ca8ba9bc0c28c76e76842098cf15
88
    context: MatrixContext): Tree =
88
    context: MatrixContext): Tree =
89
  {
89
  {
90
    import context._
90
    import context._
 
 
91
    TRACE("handlePattern", "(%s: %s) match { %s cases }", selector, selector.tpe, cases.size)
91
 
92
 
92
    val matrixInit: MatrixInit = {
93
    val matrixInit: MatrixInit = {
93
      val v = copyVar(selector, isChecked, selector.tpe, "temp")
94
      val v = copyVar(selector, isChecked, selector.tpe, "temp")
874d2a95b2ae791019dd5e1ce81ab1b94bbd4588a3799c585a78ca8ba9bc0c28c76e76842098cf15
39
 
39
 
40
    def data: MatrixContext#MatrixInit
40
    def data: MatrixContext#MatrixInit
41
 
41
 
42
    lazy val MatrixInit(roots, cases, failTree)  = data
42
    lazy val MatrixInit(roots, cases, failTree) = data
43
    lazy val ExpandedMatrix(rows, targets)       = expand(roots, cases)
43
    lazy val (rows, targets)                    = expand(roots, cases).unzip
44
    lazy val expansion: Rep                      = make(roots, rows)
44
    lazy val expansion: Rep                     = make(roots, rows)
45
 
45
 
46
    val shortCuts   = new ListBuffer[Symbol]()
46
    private val shortCuts = mutable.HashMap[Int, Symbol]()
47
 
47
 
48
    final def shortCut(theLabel: Symbol): Int = {
48
    final def createShortCut(theLabel: Symbol): Int = {
49
      shortCuts += theLabel
49
      val key = shortCuts.size + 1
50
      -shortCuts.length
50
      shortCuts(key) = theLabel
 
 
51
      -key
51
    }
52
    }
52
 
53
 
53
    /** first time bx is requested, a LabelDef is returned. next time, a jump.
54
    /** first time bx is requested, a LabelDef is returned. next time, a jump.
...
 
...
 
55
     */
56
     */
56
    final def requestBody(bx: Int, subst: Bindings): Tree = {
57
    final def requestBody(bx: Int, subst: Bindings): Tree = {
57
      // shortcut
58
      // shortcut
58
      if (bx < 0) Apply(ID(shortCuts(-bx-1)), Nil)
59
      if (bx < 0) Apply(ID(shortCuts(-bx)), Nil)
59
      else targets(bx) labelBody subst
60
      else targets(bx) labelBody subst
60
    }
61
    }
61
 
62
 
62
    /** the injection here handles alternatives and unapply type tests */
63
    /** This is the recursively focal point for translating the current
63
    final def make(tvars: PatternVarGroup, row1: List[Row]): Rep = {
64
     *  list of pattern variables and a list of pattern match rows into 
64
      // TRACE("make(%s%s)", pp(tvars.pvs, 1, true), pp(row1, 1, true))
65
     *  a tree suitable for entering erasure.
65
      def classifyPat(opat: Pattern, j: Int): Pattern = opat simplify tvars(j)
66
     *
 
 
67
     *  The first time it is called, the variables are (copies of) the
 
 
68
     *  original pattern matcher roots, and the rows correspond to the
 
 
69
     *  original casedefs.
 
 
70
     */
 
 
71
    final def make(roots1: PatternVarGroup, rows1: List[Row]): Rep = {
 
 
72
      traceCategory("New Match", "%sx%s (%s)", roots1.size, rows1.size, roots1.syms.mkString(", "))
 
 
73
      def classifyPat(opat: Pattern, j: Int): Pattern = opat simplify roots1(j)
66
 
74
 
67
      val rows = row1 flatMap (_ expandAlternatives classifyPat)
75
      val newRows = rows1 flatMap (_ expandAlternatives classifyPat)
68
      if (rows.length != row1.length) make(tvars, rows)  // recursive call if any change
76
      if (rows1.length != newRows.length) make(roots1, newRows)  // recursive call if any change
69
      else Rep(tvars, rows).checkExhaustive
77
      else Rep(roots1, newRows).checkExhaustive
70
    }
78
    }
71
 
79
 
72
    override def toString() = "MatchMatrix(%s) { %s }".format(matchResultType, indentAll(targets))
80
    override def toString() = "MatchMatrix(%s) { %s }".format(matchResultType, indentAll(targets))
...
 
...
 
181
          case UnapplyParamType(tpe) => !(scrut.tpe <:< tpe)
189
          case UnapplyParamType(tpe) => !(scrut.tpe <:< tpe)
182
        }
190
        }
183
      }
191
      }
184
      
 
 
185
      object TypedUnapply {
 
 
186
        def unapply(x: Tree): Option[Boolean] = condOpt(x) {
 
 
187
          case Typed(UnapplyParamType(tpe), tpt) => !(tpt.tpe <:< tpe)
 
 
188
        }
 
 
189
      }
 
 
190
 
192
 
191
      def mkRule(rest: Rep): RuleApplication = {
193
      def mkRule(rest: Rep): RuleApplication = {
192
        tracing("Rule")(head match {
194
        tracing("Rule")(head match {
193
          case x if isEquals(x.tree.tpe)        => new MixEquals(this, rest)
195
          case x if isEquals(x.tree.tpe)        => new MixEquals(this, rest)
194
          case x: SequencePattern               => new MixSequence(this, rest, x)
196
          case x: SequencePattern               => new MixSequence(this, rest, x)
195
          case AnyUnapply(false)                => new MixUnapply(this, rest, false)
197
          case AnyUnapply(false)                => new MixUnapply(this, rest)
196
          case _ =>
198
          case _ =>
197
            isPatternSwitch(scrut, ps) match {
199
            isPatternSwitch(scrut, ps) match {
198
              case Some(x)  => new MixLiteralInts(x, rest)
200
              case Some(x)  => new MixLiteralInts(x, rest)
...
 
...
 
327
 
329
 
328
    /** mixture rule for unapply pattern
330
    /** mixture rule for unapply pattern
329
     */
331
     */
330
    class MixUnapply(val pmatch: PatternMatch, val rest: Rep, typeTest: Boolean) extends RuleApplication {
332
    class MixUnapply(val pmatch: PatternMatch, val rest: Rep) extends RuleApplication {
331
      val uapattern = head match { case x: UnapplyPattern => x ; case _ => abort("XXX") }
333
      val uapattern = head match { case x: UnapplyPattern => x ; case _ => abort("XXX") }
332
      val ua @ UnApply(app, args) = head.tree
334
      val ua @ UnApply(app, args) = head.tree
333
 
335
 
...
 
...
 
494
        val compareFn: Tree => Tree         = (t: Tree) => compareOp((t DOT methodOp)(LIT(pivotLen)), ZERO)
496
        val compareFn: Tree => Tree         = (t: Tree) => compareOp((t DOT methodOp)(LIT(pivotLen)), ZERO)
495
 
497
 
496
        // wrapping in a null check on the scrutinee
498
        // wrapping in a null check on the scrutinee
 
 
499
        // XXX this needs to use the logic in "def condition"
497
        nullSafe(compareFn, FALSE)(scrut.id)
500
        nullSafe(compareFn, FALSE)(scrut.id)
 
 
501
        // condition(head.tpe, scrut.id, head.boundVariables.nonEmpty)
498
      }
502
      }
499
      lazy val success  = squeezedBlock(pvs map (_.valDef), remake(successRows, pvs, hasStar).toTree)
503
      lazy val success  = squeezedBlock(pvs map (_.valDef), remake(successRows, pvs, hasStar).toTree)
500
      lazy val failure  = remake(failRows).toTree
504
      lazy val failure  = remake(failRows).toTree
...
 
...
 
521
 
525
 
522
      lazy val success = remake(List(
526
      lazy val success = remake(List(
523
        rest.rows.head.insert2(List(NoPattern), head.boundVariables, scrut.sym),
527
        rest.rows.head.insert2(List(NoPattern), head.boundVariables, scrut.sym),
524
        Row(emptyPatterns(1 + rest.tvars.size), NoBinding, EmptyTree, shortCut(label))
528
        Row(emptyPatterns(1 + rest.tvars.size), NoBinding, EmptyTree, createShortCut(label))
525
      )).toTree
529
      )).toTree
526
 
530
 
527
      lazy val failure = LabelDef(label, Nil, labelBody)
531
      lazy val failure = LabelDef(label, Nil, labelBody)
...
 
...
 
615
    case class Row(pats: List[Pattern], subst: Bindings, guard: Tree, bx: Int) {
619
    case class Row(pats: List[Pattern], subst: Bindings, guard: Tree, bx: Int) {
616
      private def nobindings = subst.get().isEmpty
620
      private def nobindings = subst.get().isEmpty
617
      private def bindstr = if (nobindings) "" else pp(subst)
621
      private def bindstr = if (nobindings) "" else pp(subst)
618
      // if (pats exists (p => !p.isDefault))
 
 
619
      //   traceCategory("Row", "%s%s", pats, bindstr)
 
 
620
 
622
 
621
      /** Extracts the 'i'th pattern. */
623
      /** Extracts the 'i'th pattern. */
622
      def extractColumn(i: Int) = {
624
      def extractColumn(i: Int) = {
...
 
...
 
654
        "Row(%d)(%s%s)".format(bx, pp(pats), bs)
656
        "Row(%d)(%s%s)".format(bx, pp(pats), bs)
655
      }
657
      }
656
    }
658
    }
657
    
 
 
658
    object ExpandedMatrix {
 
 
659
      def unapply(x: ExpandedMatrix) = Some((x.rows, x.targets))
 
 
660
      def apply(rowz: List[(Row, FinalState)]) =
 
 
661
        new ExpandedMatrix(rowz map (_._1), rowz map (_._2) toIndexedSeq)
 
 
662
    }
 
 
663
    
 
 
664
    class ExpandedMatrix(val rows: List[Row], val targets: IndexedSeq[FinalState]) {
 
 
665
      require(rows.size == targets.size)
 
 
666
      
 
 
667
      override def toString() = {        
 
 
668
        def vprint(vs: List[Any]) = if (vs.isEmpty) "" else ": %s".format(pp(vs))
 
 
669
        def rprint(r: Row) = pp(r)
 
 
670
        def tprint(t: FinalState) = 
 
 
671
          if (t.params.isEmpty) " ==> %s".format(pp(t.body))
 
 
672
          else " ==>\n        %s".format(pp(t.params -> t.body))
 
 
673
          
 
 
674
        val xs = rows zip targets map { case (r,t) => rprint(r) + tprint(t) }
 
 
675
        val ppstr = pp(xs, newlines = true)
 
 
676
                    
 
 
677
        "ExpandedMatrix(%d rows)".format(rows.size) + ppstr
 
 
678
      }
 
 
679
    }
 
 
680
 
659
 
681
    case class FinalState(bx: Int, body: Tree, params: List[Symbol]) {
660
    case class FinalState(bx: Int, body: Tree, params: List[Symbol]) {
682
      private var referenceCount = 0
661
      private var referenceCount = 0
...
 
...
 
761
        else "Rep(%dx%d)%s%s".format(tvars.size, rows.size, ppn(tvars), ppn(rows))
740
        else "Rep(%dx%d)%s%s".format(tvars.size, rows.size, ppn(tvars), ppn(rows))
762
    }
741
    }
763
 
742
 
764
    /** Expands the patterns recursively. */
743
    /** Expands the patterns recursively. */    
765
    final def expand(roots: List[PatternVar], cases: List[CaseDef]) =
744
    final def expand(roots: List[PatternVar], cases: List[CaseDef]) = tracing("expand") {
766
      tracing("Expanded")(ExpandedMatrix(
745
      for ((CaseDef(pat, guard, body), index) <- cases.zipWithIndex) yield {        
767
        for ((CaseDef(pat, guard, body), index) <- cases.zipWithIndex) yield {
746
        val subtrees = pat match {
768
          def mkRow(ps: List[Tree]) = Row(toPats(ps), NoBinding, guard, index)
747
          case x if roots.length <= 1 => List(x)
769
 
748
          case Apply(_, args)         => args
770
          val pattern = Pattern(pat)
749
          case WILD()                 => emptyTrees(roots.length)
771
          val row = mkRow(pat match {
750
        }
772
            case x if roots.length <= 1 => List(x)
751
        val row   = Row(toPats(subtrees), NoBinding, guard, index)
773
            case Apply(_, args)         => args
752
        val state = FinalState(index, body, Pattern(pat).deepBoundVariables)
774
            case WILD()                 => emptyTrees(roots.length)
753
 
775
          })
754
        row -> state
776
          
755
      }
777
          row -> FinalState(index, body, pattern.deepBoundVariables)
756
    }
778
        })
 
 
779
      )
 
 
780
 
757
 
781
    /** returns the condition in "if (cond) k1 else k2" 
758
    /** returns the condition in "if (cond) k1 else k2" 
782
     */
759
     */
874d2a95b2ae791019dd5e1ce81ab1b94bbd4588a3799c585a78ca8ba9bc0c28c76e76842098cf15
89
    }
89
    }
90
 
90
 
91
    // Wrap this pattern's bindings around (_: Type)
91
    // Wrap this pattern's bindings around (_: Type)
92
    def rebindToType(tpe: Type, annotatedType: Type = null): Pattern = {
92
    def rebindToType(tpe: Type, ascription: Type = null): Pattern = {
93
      val aType = if (annotatedType == null) tpe else annotatedType
93
      val aType = if (ascription == null) tpe else ascription
94
      rebindTo(Typed(WILD(tpe), TypeTree(aType)) setType tpe)
94
      rebindTo(Typed(WILD(tpe), TypeTree(aType)) setType tpe)
95
    }
95
    }
96
 
96
 
...
 
...
 
104
 
104
 
105
    // Like rebindToEqualsCheck, but subtly different.  Not trying to be
105
    // Like rebindToEqualsCheck, but subtly different.  Not trying to be
106
    // mysterious -- I haven't sorted it all out yet.
106
    // mysterious -- I haven't sorted it all out yet.
107
    def rebindToObjectCheck(): Pattern = {
107
    def rebindToObjectCheck(): Pattern =
108
      val sType = sufficientType
108
      rebindToType(mkEqualsRef(sufficientType), sufficientType)
109
      rebindToType(mkEqualsRef(sType), sType)
 
 
110
    }
 
 
111
 
109
 
112
    /** Helpers **/    
110
    /** Helpers **/    
113
    private def wrapBindings(vs: List[Symbol], pat: Tree): Tree = vs match {
111
    private def wrapBindings(vs: List[Symbol], pat: Tree): Tree = vs match {
874d2a95b2ae791019dd5e1ce81ab1b94bbd4588a3799c585a78ca8ba9bc0c28c76e76842098cf15
27
  type PatternMatch       = MatchMatrix#PatternMatch
27
  type PatternMatch       = MatchMatrix#PatternMatch
28
  private type PatternVar = MatrixContext#PatternVar
28
  private type PatternVar = MatrixContext#PatternVar
29
 
29
 
 
 
30
  // private def unapplyArgs(x: Any) = x match {
 
 
31
  //   case UnApply(Apply(TypeApply(_, targs), args), _) => (targs map (_.symbol), args map (_.symbol))
 
 
32
  //   case _                                            => (Nil, Nil)
 
 
33
  // }
 
 
34
  //   
 
 
35
  // private def unapplyCall(x: Any) = x match {
 
 
36
  //   case UnApply(t, _)  => treeInfo.methPart(t).symbol
 
 
37
  //   case _              => NoSymbol
 
 
38
  // }
 
 
39
 
30
  // Fresh patterns
40
  // Fresh patterns
31
  def emptyPatterns(i: Int): List[Pattern] = List.fill(i)(NoPattern)
41
  def emptyPatterns(i: Int): List[Pattern] = List.fill(i)(NoPattern)
32
  def emptyTrees(i: Int): List[Tree] = List.fill(i)(EmptyTree)
42
  def emptyTrees(i: Int): List[Tree] = List.fill(i)(EmptyTree)
...
 
...
 
45
    val Ident(name) = tree
55
    val Ident(name) = tree
46
    require(isVarPattern(tree) && name != nme.WILDCARD)
56
    require(isVarPattern(tree) && name != nme.WILDCARD)
47
 
57
 
48
    override def irrefutableFor(tpe: Type) = true
 
 
49
    override def description = "%s".format(name)
58
    override def description = "%s".format(name)
50
  }
59
  }
51
 
60
 
52
  // 8.1.1 (b)
61
  // 8.1.1 (b)
53
  case class WildcardPattern() extends Pattern {
62
  case class WildcardPattern() extends Pattern {
54
    val tree = EmptyTree
63
    val tree = EmptyTree
55
    override def irrefutableFor(tpe: Type) = true
 
 
56
    override def isDefault = true
64
    override def isDefault = true
57
    override def description = "_"
65
    override def description = "_"
58
  }
66
  }
...
 
...
 
62
    private val Typed(expr, tpt) = tree
70
    private val Typed(expr, tpt) = tree
63
 
71
 
64
    override def subpatternsForVars: List[Pattern] = List(Pattern(expr))
72
    override def subpatternsForVars: List[Pattern] = List(Pattern(expr))
65
    
 
 
66
    override def irrefutableFor(tpe: Type) = tpe <:< tree.tpe
 
 
67
    override def simplify(pv: PatternVar) = Pattern(expr) match {
73
    override def simplify(pv: PatternVar) = Pattern(expr) match {
68
      case ExtractorPattern(ua) if pv.sym.tpe <:< tpt.tpe  => this rebindTo expr
74
      case ExtractorPattern(ua) if pv.sym.tpe <:< tpt.tpe => this rebindTo expr
69
      case _                                                => this
75
      case _                                              => this
70
    }
76
    }
71
    override def description = "Typ(%s: %s)".format(Pattern(expr), tpt)
77
    override def description = "Typ(%s: %s)".format(Pattern(expr), tpt)
72
  }
78
  }
...
 
...
 
159
      if (isColonColon) "%s :: %s".format(Pattern(args(0)), Pattern(args(1)))
165
      if (isColonColon) "%s :: %s".format(Pattern(args(0)), Pattern(args(1)))
160
      else "%s(%s)".format(name, toPats(args).mkString(", "))
166
      else "%s(%s)".format(name, toPats(args).mkString(", "))
161
    }
167
    }
162
      
 
 
163
    // XXX todo
 
 
164
    // override def irrefutableFor(tpe: Type) = false
 
 
165
  }  
168
  }  
166
  // 8.1.6
169
  // 8.1.6
167
  case class TuplePattern(tree: Apply) extends ApplyPattern {
170
  case class TuplePattern(tree: Apply) extends ApplyPattern {
168
    // XXX todo
 
 
169
    // override def irrefutableFor(tpe: Type) = false
 
 
170
    override def description = "((%s))".format(args.size, toPats(args).mkString(", "))
171
    override def description = "((%s))".format(args.size, toPats(args).mkString(", "))
171
  }
172
  }
172
 
173
 
173
  // 8.1.7
174
  // 8.1.7 / 8.1.8 (unapply and unapplySeq calls)
174
  case class ExtractorPattern(tree: UnApply) extends UnapplyPattern {
175
  case class ExtractorPattern(tree: UnApply) extends UnapplyPattern {
175
    private val Apply(fn, _) = unfn
 
 
176
    private val MethodType(List(arg, _*), _) = fn.tpe
 
 
177
    private def uaTyped = Typed(tree, TypeTree(arg.tpe)) setType arg.tpe
 
 
178
 
 
 
179
    override def necessaryType = arg.tpe
 
 
180
    
 
 
181
    override def simplify(pv: PatternVar) =
176
    override def simplify(pv: PatternVar) =
182
      if (pv.sym.tpe <:< arg.tpe) this
177
      if (pv.tpe <:< arg.tpe) this
183
      else this rebindTo uaTyped
178
      else this rebindTo uaTyped
184
      
179
 
185
    override def description = "UnApp(%s => %s)".format(necessaryType, resTypesString)
180
    override def description = "Unapply(%s => %s)".format(necessaryType, resTypesString)
186
  }
181
  }
187
 
182
 
188
  // 8.1.8 (unapplySeq calls)
183
  case class SequenceExtractorPattern(tree: UnApply, elems: List[Tree]) extends UnapplyPattern with SequenceLikePattern {
189
  case class SequenceExtractorPattern(tree: UnApply) extends UnapplyPattern with SequenceLikePattern {
184
    override def simplify(pv: PatternVar) = {
190
 
185
      pv.sym setFlag NO_EXHAUSTIVE
191
    lazy val UnApply(
186
      
192
      Apply(TypeApply(Select(_, nme.unapplySeq), List(tptArg)), _),
187
      if (pv.tpe <:< arg.tpe) this
193
      List(ArrayValue(_, elems))
188
      else this rebindTo uaTyped
194
    ) = tree
189
    }
195
 
190
 
196
    /** For folding a list into a well-typed x :: y :: etc :: tree. */
191
    override def description = "UnapplySeq(%s => %s)".format(necessaryType, resTypesString)
197
    private def listFolder = {
192
  }
198
      val tpe = tptArg.tpe
193
 
199
      val MethodType(_, TypeRef(pre, sym, _)) = ConsClass.primaryConstructor.tpe
194
  // Special List handling.  It was like that when I got here.
200
      val consRef                             = typeRef(pre, sym, List(tpe))
195
  case class ListExtractorPattern(tree: UnApply, tpt: Tree, elems: List[Tree]) extends UnapplyPattern with SequenceLikePattern {    
201
      val listRef                             = typeRef(pre, ListClass, List(tpe))
196
    private val cons    = ConsClass.primaryConstructor.tpe.resultType
202
 
197
    private val consRef = typeRef(cons.prefix, ConsClass, List(tpt.tpe))
203
      def fold(x: Tree, xs: Tree) = unbind(x) match {
198
    private val listRef = typeRef(cons.prefix, ListClass, List(tpt.tpe))
204
        case _: Star  => Pattern(x) rebindTo WILD(x.tpe) boundTree  // this is using boundVariables instead of deepBoundVariables
199
 
205
        case _        =>
200
    // Fold a list into a well-typed x :: y :: etc :: tree.
206
          val dummyMethod = new TermSymbol(NoSymbol, NoPosition, "matching$dummy")
201
    private def listFolder(x: Tree, xs: Tree) = unbind(x) match {
207
          val consType    = MethodType(dummyMethod newSyntheticValueParams List(tpe, listRef), consRef)
202
      case _: Star  => Pattern(x) rebindTo WILD(x.tpe) boundTree
208
 
203
      case _        =>
209
          Apply(TypeTree(consType), List(x, xs)) setType consRef
204
        val dummyMethod = new TermSymbol(NoSymbol, NoPosition, "matching$dummy")
210
      }
205
        val consType    = MethodType(dummyMethod newSyntheticValueParams List(tpt.tpe, listRef), consRef)
211
 
206
 
212
      fold _
207
        Apply(TypeTree(consType), List(x, xs)) setType consRef
213
    }
208
    }
214
 
209
    override def necessaryType = if (nonStarPatterns.nonEmpty) consRef else listRef
215
    // @pre: is not right-ignoring (no star pattern) ; no exhaustivity check
 
 
216
    override def simplify(pv: PatternVar) = {
210
    override def simplify(pv: PatternVar) = {
217
      pv.sym setFlag NO_EXHAUSTIVE
211
      pv.sym setFlag NO_EXHAUSTIVE
218
      this rebindTo elems.foldRight(gen.mkNil)(listFolder)
212
 
 
 
213
      if (pv.tpe <:< necessaryType)
 
 
214
        this rebindTo elems.foldRight(gen.mkNil)(listFolder)
 
 
215
      else
 
 
216
        this rebindTo (Typed(tree, TypeTree(necessaryType)) setType necessaryType)
219
    }
217
    }
220
    override def description = "UnSeq(%s => %s)".format(tptArg, resTypesString)
218
    override def description = "List(%s => %s)".format(tpt.tpe, resTypesString)
221
  }
219
  }
222
 
220
 
223
  trait SequenceLikePattern extends Pattern {
221
  trait SequenceLikePattern extends Pattern {
224
    def elems: List[Tree]
222
    def elems: List[Tree]
225
    def elemPatterns = toPats(elems)
223
    override def hasStar = elems.nonEmpty && isStar(elems.last)
226
 
 
 
227
    def nonStarPatterns: List[Pattern] = if (hasStar) elemPatterns.init else elemPatterns
 
 
228
    def nonStarLength = nonStarPatterns.length
 
 
229
    def isAllDefaults = nonStarPatterns forall (_.isDefault)
 
 
230
 
224
 
231
    def isShorter(other: SequenceLikePattern) = nonStarLength < other.nonStarLength
225
    def elemPatterns    = toPats(elems)
232
    def isSameLength(other: SequenceLikePattern) = nonStarLength == other.nonStarLength
226
    def nonStarElems    = if (hasStar) elems.init else elems
 
 
227
    def nonStarPatterns = toPats(nonStarElems)
 
 
228
    def nonStarLength   = nonStarElems.length
233
  }
229
  }
234
 
230
 
235
  // 8.1.8 (b) (literal ArrayValues)
231
  // 8.1.8 (b) (literal ArrayValues)
...
 
...
 
273
    private val cache = new collection.mutable.HashMap[Tree, Pattern]
269
    private val cache = new collection.mutable.HashMap[Tree, Pattern]
274
    def clear() = cache.clear()
270
    def clear() = cache.clear()
275
 
271
 
276
    def unadorn(x: Tree): Tree = x match {
 
 
277
      case Typed(expr, _) => unadorn(expr)
 
 
278
      case Bind(_, x)     => unadorn(x)
 
 
279
      case _              => x
 
 
280
    }
 
 
281
 
 
 
282
    def isRightIgnoring(t: Tree) = cond(unadorn(t)) {
 
 
283
      case ArrayValue(_, xs) if !xs.isEmpty => isStar(unadorn(xs.last))
 
 
284
    }
 
 
285
    
 
 
286
    def apply(tree: Tree): Pattern = {
272
    def apply(tree: Tree): Pattern = {
287
      if (cache contains tree)
273
      if (cache contains tree)
288
        return cache(tree)
274
        return cache(tree)
...
 
...
 
321
 
307
 
322
  object UnapplyPattern {
308
  object UnapplyPattern {
323
    private object UnapplySeq {
309
    private object UnapplySeq {
324
      private object TypeApp {
310
      def unapply(x: UnApply) = x match {
325
        def unapply(x: Any) = condOpt(x) { 
311
        case UnApply(
326
          case TypeApply(sel @ Select(stor, nme.unapplySeq), List(tpe)) if stor.symbol eq ListModule => tpe
312
        Apply(TypeApply(Select(qual, nme.unapplySeq), List(tpt)), _),
327
        }
313
        List(ArrayValue(_, elems))) =>
328
      }
314
          Some(qual.symbol, tpt, elems)
329
      def unapply(x: UnApply) = condOpt(x) {
315
        case _ =>
330
        case UnApply(Apply(TypeApp(tptArg), _), List(ArrayValue(_, xs))) => (tptArg, xs)
316
          None
331
      }
317
       }
332
    }
318
    }
333
 
319
 
334
    def apply(x: UnApply): Pattern = {
320
    def apply(x: UnApply): Pattern = x match {
335
      x match {
321
      case UnapplySeq(container, tpt, elems) =>
336
        case UnapplySeq(_, _) => SequenceExtractorPattern(x)
322
        if (container == ListModule) ListExtractorPattern(x, tpt, elems)
337
        case _                => ExtractorPattern(x)
323
        else SequenceExtractorPattern(x, elems)
338
      }
324
      case _ =>
 
 
325
        ExtractorPattern(x)
339
    }
326
    }
340
  }
327
  }
341
 
328
 
...
 
...
 
401
 
388
 
402
  sealed trait UnapplyPattern extends Pattern {
389
  sealed trait UnapplyPattern extends Pattern {
403
    lazy val UnApply(unfn, args) = tree
390
    lazy val UnApply(unfn, args) = tree
404
    override def subpatternsForVars: List[Pattern] = toPats(args)
391
    lazy val Apply(fn, _) = unfn
 
 
392
    lazy val MethodType(List(arg, _*), _) = fn.tpe
 
 
393
    protected def uaTyped = Typed(tree, TypeTree(arg.tpe)) setType arg.tpe
 
 
394
    
 
 
395
    override def necessaryType = arg.tpe
 
 
396
    override def subpatternsForVars = args match {
 
 
397
      case List(ArrayValue(elemtpe, elems)) => toPats(elems)
 
 
398
      case _                                => toPats(args)
 
 
399
    }
405
 
400
 
406
    def resTypes = analyzer.unapplyTypeList(unfn.symbol, unfn.tpe)
401
    def resTypes = analyzer.unapplyTypeList(unfn.symbol, unfn.tpe)
407
    def resTypesString = resTypes match {
402
    def resTypesString = resTypes match {
...
 
...
 
433
 
428
 
434
    // returns either a simplification of this pattern or identity.
429
    // returns either a simplification of this pattern or identity.
435
    def simplify(pv: PatternVar): Pattern = this
430
    def simplify(pv: PatternVar): Pattern = this
436
    def simplify(): Pattern = this simplify null
 
 
437
 
431
 
438
    // the right number of dummies for this pattern
432
    // the right number of dummies for this pattern
439
    def dummies: List[Pattern] = Nil
433
    def dummies: List[Pattern] = Nil
440
 
434
 
441
    // 8.1.13
 
 
442
    // A pattern p is irrefutable for type T if any of the following applies:
 
 
443
    //   1) p is a variable pattern
 
 
444
    //   2) p is a typed pattern x: T', and T <: T'
 
 
445
    //   3) p is a constructor pattern C(p1,...,pn), the type T is an instance of class C,
 
 
446
    //      the primary constructor of type T has argument types T1,...,Tn and and each
 
 
447
    //      pi is irrefutable for Ti.
 
 
448
    def irrefutableFor(tpe: Type) = false
 
 
449
    
 
 
450
    // does this pattern completely cover that pattern (i.e. latter cannot be matched)
 
 
451
    def completelyCovers(second: Pattern) = false
 
 
452
    
 
 
453
    // Is this a default pattern (untyped "_" or an EmptyTree inserted by the matcher)
435
    // Is this a default pattern (untyped "_" or an EmptyTree inserted by the matcher)
454
    def isDefault = false
436
    def isDefault = false
455
 
437
 
...
 
...
 
460
    // (nullness and guards will still be checked.)
442
    // (nullness and guards will still be checked.)
461
    def sufficientType = tpe
443
    def sufficientType = tpe
462
 
444
 
463
    // XXX have to determine if this can be made useful beyond an extractor barrier.
 
 
464
    // Default sufficient type might be NothingClass.tpe, tpe.narrow, ...
 
 
465
    
 
 
466
    // the subpatterns for this pattern (at the moment, that means constructor arguments)
445
    // the subpatterns for this pattern (at the moment, that means constructor arguments)
467
    def subpatterns(pm: MatchMatrix#PatternMatch): List[Pattern] = pm.dummies
446
    def subpatterns(pm: MatchMatrix#PatternMatch): List[Pattern] = pm.dummies
468
 
447
 
469
    def    sym  = tree.symbol
448
    def    sym  = tree.symbol
470
    def    tpe  = tree.tpe
449
    def    tpe  = tree.tpe
471
    def prefix  = tpe.prefix
 
 
472
    def isEmpty = tree.isEmpty
450
    def isEmpty = tree.isEmpty
473
 
451
 
474
    def isSymValid = (sym != null) && (sym != NoSymbol)
452
    def isModule    = sym.isModule || tpe.termSymbol.isModule
475
    def isModule = sym.isModule || tpe.termSymbol.isModule
 
 
476
    def isCaseClass = tpe.typeSymbol.isCase
453
    def isCaseClass = tpe.typeSymbol.isCase
477
    def isObject = isSymValid && prefix.isStable  // XXX not entire logic
454
    def isObject    = (sym != null) && (sym != NoSymbol) && tpe.prefix.isStable  // XXX not entire logic
478
    
 
 
479
    def unadorn(t: Tree): Tree = Pattern unadorn t
 
 
480
    
 
 
481
    private def isStar(x: Tree) = cond(unadorn(x)) { case Star(_) => true }
 
 
482
    private def endsStar(xs: List[Tree]) = xs.nonEmpty && isStar(xs.last)
 
 
483
 
455
 
484
    def isStarSequence = isSequence && hasStar
456
    def hasStar = false
485
    def isSequence = cond(unadorn(tree)) {
 
 
486
      case ArrayValue(_, _) => true
 
 
487
    }
 
 
488
    def hasStar = cond(unadorn(tree)) {
 
 
489
      case ArrayValue(_, xs) if endsStar(xs)  => true
 
 
490
    }
 
 
491
 
457
 
492
    def setType(tpe: Type): this.type = {
458
    def setType(tpe: Type): this.type = {
493
      tree setType tpe
459
      tree setType tpe
874d2a95b2ae791019dd5e1ce81ab1b94bbd4588a3799c585a78ca8ba9bc0c28c76e76842098cf15
392
            if (guard == EmptyTree) EmptyTree
392
            if (guard == EmptyTree) EmptyTree
393
            else {
393
            else {
394
              val guardDef = makeGuardDef(used, guard)
394
              val guardDef = makeGuardDef(used, guard)
395
              nguard       += transform(guardDef) // building up list of guards
395
              nguard += transform(guardDef) // building up list of guards
396
 
396
 
397
              localTyper typed (Ident(guardDef.symbol) APPLY (used map Ident))
397
              localTyper typed (Ident(guardDef.symbol) APPLY (used map Ident))
398
            }
398
            }
874d2a95b2ae791019dd5e1ce81ab1b94bbd4588a3799c585a78ca8ba9bc0c28c76e76842098cf15
2466
        /* --- begin unapply  --- */
2466
        /* --- begin unapply  --- */
2467
 
2467
 
2468
        case otpe if inPatternMode(mode) && unapplyMember(otpe).exists =>
2468
        case otpe if inPatternMode(mode) && unapplyMember(otpe).exists =>
2469
          val unapp = unapplyMember(otpe)
 
 
2470
          assert(unapp.exists, tree)
 
 
2471
          val unappType = otpe.memberType(unapp)
 
 
2472
          val argDummyType = pt // was unappArg
 
 
2473
         // @S: do we need to memoize this?
 
 
2474
          val argDummy =  context.owner.newValue(fun.pos, nme.SELECTOR_DUMMY)
 
 
2475
            .setFlag(SYNTHETIC)
 
 
2476
            .setInfo(argDummyType)
 
 
2477
          if (args.length > MaxTupleArity)
2469
          if (args.length > MaxTupleArity)
2478
            error(fun.pos, "too many arguments for unapply pattern, maximum = "+MaxTupleArity)
2470
            error(fun.pos, "too many arguments for unapply pattern, maximum = "+MaxTupleArity)
2479
          val arg = Ident(argDummy) setType argDummyType
2471
 
2480
          val oldArgType = arg.tpe
2472
          def freshArgType(tp: Type): (Type, List[Symbol]) = (tp: @unchecked) match {
2481
          if (!isApplicableSafe(List(), unappType, List(arg.tpe), WildcardType)) {
2473
            case MethodType(param :: _, _) => 
 
 
2474
              (param.tpe, Nil)
 
 
2475
            case PolyType(tparams, restype) => 
 
 
2476
              val tparams1 = cloneSymbols(tparams)
 
 
2477
              (freshArgType(restype)._1.substSym(tparams, tparams1), tparams1)
 
 
2478
            case OverloadedType(_, _) =>
 
 
2479
              error(fun.pos, "cannot resolve overloaded unapply")
 
 
2480
              (ErrorType, Nil)
 
 
2481
          }
 
 
2482
 
 
 
2483
          val unapp     = unapplyMember(otpe)          
 
 
2484
          val unappType = otpe.memberType(unapp)
 
 
2485
          val argDummy  = context.owner.newValue(fun.pos, nme.SELECTOR_DUMMY) setFlag SYNTHETIC setInfo pt
 
 
2486
          val arg       = Ident(argDummy) setType pt
 
 
2487
          
 
 
2488
          if (!isApplicableSafe(Nil, unappType, List(pt), WildcardType)) {
2482
            //Console.println("UNAPP: need to typetest, arg.tpe = "+arg.tpe+", unappType = "+unappType)
2489
            //Console.println("UNAPP: need to typetest, arg.tpe = "+arg.tpe+", unappType = "+unappType)
2483
            def freshArgType(tp: Type): (Type, List[Symbol]) = tp match {
 
 
2484
              case MethodType(params, _) => 
 
 
2485
                (params(0).tpe, Nil)
 
 
2486
              case PolyType(tparams, restype) => 
 
 
2487
                val tparams1 = cloneSymbols(tparams)
 
 
2488
                (freshArgType(restype)._1.substSym(tparams, tparams1), tparams1)
 
 
2489
              case OverloadedType(_, _) =>
 
 
2490
                error(fun.pos, "cannot resolve overloaded unapply")
 
 
2491
                (ErrorType, Nil)
 
 
2492
            }
 
 
2493
            val (unappFormal, freeVars) = freshArgType(unappType.skolemizeExistential(context.owner, tree))
2490
            val (unappFormal, freeVars) = freshArgType(unappType.skolemizeExistential(context.owner, tree))
2494
            val context1 = context.makeNewScope(context.tree, context.owner)
2491
            val context1 = context.makeNewScope(context.tree, context.owner)
2495
            freeVars foreach context1.scope.enter
2492
            freeVars foreach context1.scope.enter
 
 
2493
 
2496
            val typer1 = newTyper(context1)
2494
            val typer1 = newTyper(context1)
2497
            val pattp = typer1.infer.inferTypedPattern(tree.pos, unappFormal, arg.tpe)
2495
            val pattp  = typer1.infer.inferTypedPattern(tree.pos, unappFormal, arg.tpe)
2498
 
2496
 
2499
            // turn any unresolved type variables in freevars into existential skolems
2497
            // turn any unresolved type variables in freevars into existential skolems
2500
            val skolems = freeVars map { fv =>
2498
            val skolems = freeVars map { fv =>
...
 
...
 
2504
              skolem
2502
              skolem
2505
            }
2503
            }
2506
            arg.tpe = pattp.substSym(freeVars, skolems)
2504
            arg.tpe = pattp.substSym(freeVars, skolems)
2507
            //todo: replace arg with arg.asInstanceOf[inferTypedPattern(unappFormal, arg.tpe)] instead.
2505
            argDummy setInfo arg.tpe
2508
            argDummy.setInfo(arg.tpe) // bq: this line fixed #1281. w.r.t. comment ^^^, maybe good enough?
 
 
2509
          }
2506
          }
2510
 
2507
 
2511
          // setType null is necessary so that ref will be stabilized; see bug 881
2508
          // setType null is necessary so that ref will be stabilized; see bug 881
...
 
...
 
2517
            val formals1 = formalTypes(formals0, args.length)
2514
            val formals1 = formalTypes(formals0, args.length)
2518
            if (sameLength(formals1, args)) {
2515
            if (sameLength(formals1, args)) {
2519
              val args1 = typedArgs(args, mode, formals0, formals1)
2516
              val args1 = typedArgs(args, mode, formals0, formals1)
2520
              if (!isFullyDefined(pt)) assert(false, tree+" ==> "+UnApply(fun1, args1)+", pt = "+pt)
2517
              assert(isFullyDefined(pt), tree+" ==> "+UnApply(fun1, args1)+", pt = "+pt)
2521
              val itype =  glb(List(pt, arg.tpe))
2518
 
2522
              // restore old type (arg is a dummy tree, just needs to pass typechecking)
2519
              val itype = glb(List(pt, arg.tpe))
2523
              arg.tpe = oldArgType
2520
              arg.tpe = pt    // restore type (arg is a dummy tree, just needs to pass typechecking)
2524
              UnApply(fun1, args1) setPos tree.pos setType itype
2521
              UnApply(fun1, args1) setPos tree.pos setType itype
2525
            } else {
2522
            }
 
 
2523
            else {
2526
              errorTree(tree, "wrong number of arguments for "+treeSymTypeMsg(fun))
2524
              errorTree(tree, "wrong number of arguments for "+treeSymTypeMsg(fun))
2527
            }
2525
            }
2528
          }
2526
          }
...
 
...
 
3890
        case UnApply(fun, args) =>
3888
        case UnApply(fun, args) =>
3891
          val fun1 = typed(fun)
3889
          val fun1 = typed(fun)
3892
          val tpes = formalTypes(unapplyTypeList(fun.symbol, fun1.tpe), args.length)
3890
          val tpes = formalTypes(unapplyTypeList(fun.symbol, fun1.tpe), args.length)
3893
          val args1 = (args, tpes).zipped map (typedPattern(_, _))
3891
          val args1 = (args, tpes).zipped map typedPattern
3894
          treeCopy.UnApply(tree, fun1, args1) setType pt
3892
          treeCopy.UnApply(tree, fun1, args1) setType pt
3895
 
3893
 
3896
        case ArrayValue(elemtpt, elems) =>
3894
        case ArrayValue(elemtpt, elems) =>
874d2a95b2ae791019dd5e1ce81ab1b94bbd4588a3799c585a78ca8ba9bc0c28c76e76842098cf15
 
 
1
object CompilerCrash {
 
 
2
  def main(args: Array[String]) {
 
 
3
    args match {
 
 
4
      case Array("a", a @ _*) => { } // The code compiles fine if this line is commented out or "@ _*" is deleted or this line is swapped
for the next line
 
 
5
      case Array("b") => { } // The code compiles fine if this line is commented out 
 
 
6
      case Array("c", c) => {
 
 
7
        0 // The code compiles fine if this line is commented out
 
 
8
      }
 
 
9
    }
 
 
10
  }
 
 
11
}
874d2a95b2ae791019dd5e1ce81ab1b94bbd4588a3799c585a78ca8ba9bc0c28c76e76842098cf15
 
 
1
false
 
 
2
false
 
 
3
List()
 
 
4
false
 
 
5
false
 
 
6
false
 
 
7
false
 
 
8
Vector(1)
 
 
9
false
 
 
10
false
 
 
11
true
 
 
12
false
 
 
13
false
 
 
14
false
874d2a95b2ae791019dd5e1ce81ab1b94bbd4588a3799c585a78ca8ba9bc0c28c76e76842098cf15
 
 
1
object Test {
 
 
2
  def f1 = ("": Any) match { case List(x @ _*) => x ; case _ => false }
 
 
3
  def f2 = (5: Any) match { case List(x @ _*) => x ; case _ => false }
 
 
4
  def f3 = (Nil: Any) match { case List(x @ _*) => x ; case _ => false }
 
 
5
  def f4 = (Array(1): Any) match { case List(x @ _*) => x ; case _ => false }
 
 
6
 
 
 
7
  def f5 = ("": Any) match { case Array(x @ _*) => x ; case _ => false }
 
 
8
  def f6 = (5: Any) match { case Array(x @ _*) => x ; case _ => false }
 
 
9
  def f7 = (Nil: Any) match { case Array(x @ _*) => x ; case _ => false }
 
 
10
  def f8 = (Array(1): Any) match { case Array(x @ _*) => x ; case _ => false }
 
 
11
 
 
 
12
  def f9 = ("": Any) match { case x @ List(_*) => x ; case _ => false }
 
 
13
  def f10 = ("": Any) match { case List(_*) => true ; case _ => false }
 
 
14
  def f11 = (Nil: Any) match { case List(_*) => true ; case _ => false }
 
 
15
  def f12 = ("": Any) match { case x @ Array(_*) => x ; case _ => false }
 
 
16
  def f13 = ("": Any) match { case Array(_*) => true ; case _ => false }
 
 
17
  def f14 = (Nil: Any) match { case Array(_*) => true ; case _ => false }
 
 
18
 
 
 
19
 
 
 
20
  def main(args: Array[String]): Unit = {
 
 
21
    println(f1)
 
 
22
    println(f2)
 
 
23
    println(f3)
 
 
24
    println(f4)
 
 
25
    println(f5)
 
 
26
    println(f6)
 
 
27
    println(f7)
 
 
28
    println(f8)
 
 
29
    println(f9)
 
 
30
    println(f10)
 
 
31
    println(f11)
 
 
32
    println(f12)
 
 
33
    println(f13)
 
 
34
    println(f14)
 
 
35
  }
 
 
36
}
874d2a95b2ae791019dd5e1ce81ab1b94bbd4588a3799c585a78ca8ba9bc0c28c76e76842098cf15
 
 
1
object Test {
 
 
2
  def main(args: Array[String]): Unit = {
 
 
3
    val x = 
 
 
4
      try { ("": Any) match { case List(_*) => true } }
 
 
5
      catch { case _ => false }
 
 
6
 
 
 
7
    assert(!x)
 
 
8
  }
 
 
9
}
874d2a95b2ae791019dd5e1ce81ab1b94bbd4588a3799c585a78ca8ba9bc0c28c76e76842098cf15
1
Some List
1
two
 
 
2
three
 
 
3
list: 4
 
 
4
list: 0
 
 
5
list: 5
 
 
6
not a list
 
 
7
 
 
 
8
two
 
 
9
three
 
 
10
list: 4
 
 
11
list: 0
 
 
12
list: 5
874d2a95b2ae791019dd5e1ce81ab1b94bbd4588a3799c585a78ca8ba9bc0c28c76e76842098cf15
1
object Test {
1
object Test {
 
 
2
  def f(x: Any) = println(x match {
 
 
3
    case List(_, _)    => "two"
 
 
4
    case List(_, _, _) => "three"
 
 
5
    case xs @ List(_*) => "list: " + xs.length
 
 
6
    case _             => "not a list"
 
 
7
  })
 
 
8
 
 
 
9
  def f2[T](x: List[T]) = println(x match {
 
 
10
    case List(_, _)       => "two"
 
 
11
    case List(_, _, _)    => "three"
 
 
12
    case List(xs @ _*)    => "list: " + xs.length
 
 
13
    // bug: the default case is marked unreachable
 
 
14
    // case _                => "not a list"
 
 
15
  })
 
 
16
 
2
  def main(args: Array[String]) {
17
  def main(args: Array[String]) {
3
    val list = List(1,2,3)
18
    f(List(1, 2))
4
    list match {
19
    f(List('a', 'b', 'c'))
5
      case List(_, _) => println("List with two elements")
20
    f(List('a', 'b', 'c', 'd'))
6
      case List(_*) => println("Some List")
21
    f(Nil)
7
    }
22
    f(List(1,2,3,4,5))
 
 
23
    f(null)
 
 
24
    
 
 
25
    println
 
 
26
    
 
 
27
    f2(List(1, 2))
 
 
28
    f2(List('a', 'b', 'c'))
 
 
29
    f2(List('a', 'b', 'c', 'd'))
 
 
30
    f2(Nil)
 
 
31
    f2(List(1,2,3,4,5))
 
 
32
    // bug: this NPEs on xs.length
 
 
33
    // f2(null)
8
  }
34
  }
9
}
35
}