@@ -4212,7 +4212,7 @@ object Types {
4212
4212
// ----- TypeOf -------------------------------------------------------------------------
4213
4213
4214
4214
/** Type that represents the precise type of a given term.
4215
- * Precision is only kept for Apply, TypeApply and If trees.
4215
+ * Precision is only kept for Apply, TypeApply, If and Match trees.
4216
4216
*
4217
4217
* The idea behind this type is to be able to compute more precise types
4218
4218
* when more information is available.
@@ -4226,6 +4226,7 @@ object Types {
4226
4226
* TypeOf(u, Apply(fun, args)) ~ SuspendedApply(u, fun, args)
4227
4227
* TypeOf(u, TypeApply(fun, args)) ~ SuspendedTypeApply(u, fun, args)
4228
4228
* TypeOf(u, If(cond, thenp, elsep)) ~ SuspendedIf(u, cond, thenp, elsep)
4229
+ * TypeOf(u, Match(selector, cases)) ~ SuspendedMatch(u, selector, cases)
4229
4230
*
4230
4231
* Where u is the type that the tree would have had otherwise.
4231
4232
*
@@ -4254,13 +4255,16 @@ object Types {
4254
4255
}
4255
4256
case nil => args2.isEmpty
4256
4257
}
4258
+ // FIXME: compareArgs is incorrect for Match. Add compareCaseDef.
4257
4259
(this .tree, that.tree) match {
4258
4260
case (t1 : Apply , t2 : Apply ) =>
4259
4261
(t1.fun.tpe eql t2.fun.tpe) && compareArgs(t1.args, t2.args)
4260
4262
case (t1 : TypeApply , t2 : TypeApply ) =>
4261
4263
(t1.fun.tpe eql t2.fun.tpe) && compareArgs(t1.args, t2.args)
4262
4264
case (t1 : If , t2 : If ) =>
4263
4265
(t1.cond.tpe eql t2.cond.tpe) && (t1.thenp.tpe eql t2.thenp.tpe) && (t1.elsep.tpe eql t2.elsep.tpe)
4266
+ case (t1 : Match , t2 : Match ) =>
4267
+ (t1.selector.tpe eql t2.selector.tpe) && compareArgs(t1.cases, t2.cases)
4264
4268
case (t1, t2) =>
4265
4269
false
4266
4270
}
@@ -4273,6 +4277,7 @@ object Types {
4273
4277
override def computeHash (bs : Hashable .Binders ) = {
4274
4278
val delta = tree match {
4275
4279
case _ : If => 11
4280
+ case _ : Match => 17
4276
4281
case _ : Apply => 23
4277
4282
case _ : TypeApply => 29
4278
4283
}
@@ -4290,7 +4295,6 @@ object Types {
4290
4295
4291
4296
def apply (underlyingTp : Type , tree : untpd.Tree )(implicit ctx : Context ): TypeOf = {
4292
4297
assert(! ctx.erasedTypes)
4293
- assert(isLegalTopLevelTree(tree.asInstanceOf [Tree ]))
4294
4298
val tree1 = tree.clone.asInstanceOf [Tree ]
4295
4299
// This is a safety net to keep us from touching a TypeOf's tree's type.
4296
4300
// Assuming we never look at this type, it would be safe to simply reuse
@@ -4304,7 +4308,7 @@ object Types {
4304
4308
def unapply (to : TypeOf ): Option [(Type , Tree )] = Some ((to.underlyingTp, to.tree))
4305
4309
4306
4310
def isLegalTopLevelTree (tree : Tree ): Boolean = tree match {
4307
- case _ : TypeApply | _ : Apply | _ : If => true
4311
+ case _ : TypeApply | _ : Apply | _ : If | _ : Match => true
4308
4312
case _ => false
4309
4313
}
4310
4314
@@ -4346,16 +4350,6 @@ object Types {
4346
4350
tp
4347
4351
4348
4352
object If {
4349
- /** For explicit creation in patmat */
4350
- def apply (condTp : Type , thenTp : Type , elseTp : Type )(implicit ctx : Context ): TypeOf = {
4351
- val thenTree = dummyTreeOfType(thenTp)
4352
- val elseTree = dummyTreeOfType(elseTp)
4353
- val ifTree = untpd.If (dummyTreeOfType(condTp), thenTree, elseTree)
4354
- ctx.typeAssigner.assignType(ifTree, thenTree, elseTree)(ctx.enterTypeOf()).tpe
4355
- .asInstanceOf [TypeOf ]
4356
- }
4357
-
4358
- /** For unpickling */
4359
4353
def apply (underlyingTp : Type , condTp : Type , thenTp : Type , elseTp : Type )(implicit ctx : Context ): TypeOf =
4360
4354
TypeOf (underlyingTp, untpd.If (
4361
4355
dummyTreeOfType(condTp),
@@ -4380,35 +4374,32 @@ object Types {
4380
4374
}
4381
4375
4382
4376
object Match {
4383
- def apply (underlyingTp : Type , tree : Match )(implicit ctx : Context ): Type =
4384
- new transform.PatternMatcher .Translator (NoType , null )(ctx.enterTypeOf())
4385
- .typeTranslateMatch(tree)
4386
- // def apply(underlyingTp: Type, selectorTp: Type,
4387
- // caseTriples: List[(Type, Type, Type)])(implicit ctx: Context): TypeOf =
4388
- // TypeOf(underlyingTp, untpd.Match(
4389
- // dummyTreeOfType(selectorTp),
4390
- // caseTriples.map { case (patTp, guardTp, bodyTp) =>
4391
- // ast.tpd.CaseDef(
4392
- // dummyTreeOfType(patTp),
4393
- // if (guardTp.exists) dummyTreeOfType(guardTp) else EmptyTree,
4394
- // dummyTreeOfType(bodyTp))
4395
- // }
4396
- // ))
4397
-
4398
- // def unapply(to: TypeOf): Option[(Type, List[(Type, Type, Type)])] = to.tree match {
4399
- // case Trees.Match(selector, cases) =>
4400
- // val caseTriples = cases.map { cse => (cse.pat.tpe, cse.guard.tpe, cse.body.tpe) }
4401
- // Some((selector.tpe, caseTriples))
4402
- // case _ => None
4403
- // }
4404
-
4405
- // def derived(to: TypeOf)(selectorTp: Type, caseTriples: List[(Type, Type, Type)])(implicit ctx: Context): Type =
4406
- // finalizeDerived(to, to.tree match {
4407
- // case Trees.Match(selector, cases) =>
4408
- // val ctx1 = ctx.enterTypeOf()
4409
- // val cases1 = casesWithTpes(cases, caseTriples)(ctx1)
4410
- // cpy.Match(to.tree)(treeWithTpe(selector, selectorTp), cases1)(ctx1)
4411
- // })
4377
+ def apply (underlyingTp : Type , selectorTp : Type ,
4378
+ caseTriples : List [(Type , Type , Type )])(implicit ctx : Context ): TypeOf =
4379
+ TypeOf (underlyingTp, untpd.Match (
4380
+ dummyTreeOfType(selectorTp),
4381
+ caseTriples.map { case (patTp, guardTp, bodyTp) =>
4382
+ ast.tpd.CaseDef (
4383
+ dummyTreeOfType(patTp),
4384
+ if (guardTp.exists) dummyTreeOfType(guardTp) else EmptyTree ,
4385
+ dummyTreeOfType(bodyTp))
4386
+ }
4387
+ ))
4388
+
4389
+ def unapply (to : TypeOf ): Option [(Type , List [(Type , Type , Type )])] = to.tree match {
4390
+ case Trees .Match (selector, cases) =>
4391
+ val caseTriples = cases.map { cse => (cse.pat.tpe, cse.guard.tpe, cse.body.tpe) }
4392
+ Some ((selector.tpe, caseTriples))
4393
+ case _ => None
4394
+ }
4395
+
4396
+ def derived (to : TypeOf )(selectorTp : Type , caseTriples : List [(Type , Type , Type )])(implicit ctx : Context ): Type =
4397
+ finalizeDerived(to, to.tree match {
4398
+ case Trees .Match (selector, cases) =>
4399
+ val ctx1 = ctx.enterTypeOf()
4400
+ val cases1 = casesWithTpes(cases, caseTriples)(ctx1)
4401
+ cpy.Match (to.tree)(treeWithTpe(selector, selectorTp), cases1)(ctx1)
4402
+ })
4412
4403
}
4413
4404
4414
4405
object Apply {
@@ -4527,6 +4518,9 @@ object Types {
4527
4518
object Generic {
4528
4519
def unapply (to : TypeOf ): Option [List [Type ]] = to.tree match {
4529
4520
case Trees .If (cond, thenb, elseb) => Some (cond.tpe :: thenb.tpe :: elseb.tpe :: Nil )
4521
+ case Trees .Match (selector, cases) =>
4522
+ val caseTriplesFlattened = cases.flatMap { cse => List (cse.pat.tpe, cse.guard.tpe, cse.body.tpe) }
4523
+ Some (selector.tpe :: caseTriplesFlattened)
4530
4524
case Trees .Apply (fn, args) => Some (fn.tpe :: args.map(_.tpe))
4531
4525
case Trees .TypeApply (fn, args) => Some (fn.tpe :: args.map(_.tpe))
4532
4526
}
@@ -4693,6 +4687,9 @@ object Types {
4693
4687
TypeOf .Apply .derived(tp)(this (tree.fun.tpe), tree.args.map(t => this (t.tpe)))
4694
4688
case tree : If =>
4695
4689
TypeOf .If .derived(tp)(this (tree.cond.tpe), this (tree.thenp.tpe), this (tree.elsep.tpe))
4690
+ case tree : Match =>
4691
+ val caseTriples = tree.cases.map { cse => (this (cse.pat.tpe), this (cse.guard.tpe), this (cse.body.tpe)) }
4692
+ TypeOf .Match .derived(tp)(this (tree.selector.tpe), caseTriples)
4696
4693
case tree =>
4697
4694
throw new AssertionError (s " TypeOf shouldn't contain $tree as top-level node. " )
4698
4695
}
0 commit comments