@@ -448,11 +448,12 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
448
448
return typed(untpd.Apply (untpd.TypedSplice (arg), tree.expr), pt)
449
449
case _ =>
450
450
}
451
- case tref : TypeRef if tref.symbol.isClass && ! ctx.isAfterTyper =>
452
- val setBefore = ctx.mode is Mode .GADTflexible
453
- tpt1.tpe.<:< (pt)(ctx.addMode(Mode .GADTflexible ))
454
- if (! setBefore) ctx.retractMode(Mode .GADTflexible )
455
451
case _ =>
452
+ if (! ctx.isAfterTyper) {
453
+ val setBefore = ctx.mode is Mode .GADTflexible
454
+ tpt1.tpe.<:< (pt)(ctx.addMode(Mode .GADTflexible ))
455
+ if (! setBefore) ctx.retractMode(Mode .GADTflexible )
456
+ }
456
457
}
457
458
ascription(tpt1, isWildcard = true )
458
459
}
@@ -762,17 +763,37 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
762
763
def typedCase (tree : untpd.CaseDef , pt : Type , selType : Type , gadtSyms : Set [Symbol ])(implicit ctx : Context ): CaseDef = track(" typedCase" ) {
763
764
val originalCtx = ctx
764
765
765
- def caseRest (pat : Tree )(implicit ctx : Context ) = {
766
- pat foreachSubTree {
767
- case b : Bind =>
768
- if (ctx.scope.lookup(b.name) == NoSymbol ) ctx.enter(b.symbol)
769
- else ctx.error(d " duplicate pattern variable: ${b.name}" , b.pos)
770
- case _ =>
766
+ /** - replace all references to symbols associated with wildcards by their GADT bounds
767
+ * - enter all symbols introduced by a Bind in current scope
768
+ */
769
+ val indexPattern = new TreeMap {
770
+ val elimWildcardSym = new TypeMap {
771
+ def apply (t : Type ) = t match {
772
+ case ref @ TypeRef (_, tpnme.WILDCARD ) if ctx.gadt.bounds.contains(ref.symbol) =>
773
+ ctx.gadt.bounds(ref.symbol)
774
+ case TypeAlias (ref @ TypeRef (_, tpnme.WILDCARD )) if ctx.gadt.bounds.contains(ref.symbol) =>
775
+ ctx.gadt.bounds(ref.symbol)
776
+ case _ =>
777
+ mapOver(t)
778
+ }
771
779
}
780
+ override def transform (tree : Tree )(implicit ctx : Context ) =
781
+ super .transform(tree.withType(elimWildcardSym(tree.tpe))) match {
782
+ case b : Bind =>
783
+ if (ctx.scope.lookup(b.name) == NoSymbol ) ctx.enter(b.symbol)
784
+ else ctx.error(d " duplicate pattern variable: ${b.name}" , b.pos)
785
+ b.symbol.info = elimWildcardSym(b.symbol.info)
786
+ b
787
+ case t => t
788
+ }
789
+ }
790
+
791
+ def caseRest (pat : Tree )(implicit ctx : Context ) = {
792
+ val pat1 = indexPattern.transform(pat)
772
793
val guard1 = typedExpr(tree.guard, defn.BooleanType )
773
794
val body1 = ensureNoLocalRefs(typedExpr(tree.body, pt), pt, ctx.scope.toList)
774
795
.ensureConforms(pt)(originalCtx) // insert a cast if body does not conform to expected type if we disregard gadt bounds
775
- assignType(cpy.CaseDef (tree)(pat , guard1, body1), body1)
796
+ assignType(cpy.CaseDef (tree)(pat1 , guard1, body1), body1)
776
797
}
777
798
778
799
val gadtCtx =
@@ -963,11 +984,30 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
963
984
assignType(cpy.ByNameTypeTree (tree)(result1), result1)
964
985
}
965
986
987
+ /** Define a new symbol associated with a Bind or pattern wildcard and
988
+ * make it gadt narrowable.
989
+ */
990
+ private def newPatternBoundSym (name : Name , info : Type , pos : Position )(implicit ctx : Context ) = {
991
+ val flags = if (name.isTypeName) BindDefinedType else EmptyFlags
992
+ val sym = ctx.newSymbol(ctx.owner, name, flags | Case , info, coord = pos)
993
+ if (name.isTypeName) ctx.gadt.setBounds(sym, info.bounds)
994
+ sym
995
+ }
996
+
966
997
def typedTypeBoundsTree (tree : untpd.TypeBoundsTree )(implicit ctx : Context ): TypeBoundsTree = track(" typedTypeBoundsTree" ) {
967
998
val TypeBoundsTree (lo, hi) = desugar.typeBoundsTree(tree)
968
999
val lo1 = typed(lo)
969
1000
val hi1 = typed(hi)
970
- assignType(cpy.TypeBoundsTree (tree)(lo1, hi1), lo1, hi1)
1001
+ val tree1 = assignType(cpy.TypeBoundsTree (tree)(lo1, hi1), lo1, hi1)
1002
+ if (ctx.mode.is(Mode .Pattern )) {
1003
+ // Associate a pattern-bound type symbol with the wildcard.
1004
+ // The bounds of the type symbol can be constrained when comparing a pattern type
1005
+ // with an expected type in typedTyped. The type symbol is eliminated once
1006
+ // the enclosing pattern has been typechecked; see `indexPattern` in `typedCase`.
1007
+ val wildcardSym = newPatternBoundSym(tpnme.WILDCARD , tree1.tpe, tree.pos)
1008
+ tree1.withType(wildcardSym.typeRef)
1009
+ }
1010
+ else tree1
971
1011
}
972
1012
973
1013
def typedBind (tree : untpd.Bind , pt : Type )(implicit ctx : Context ): Tree = track(" typedBind" ) {
@@ -983,8 +1023,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
983
1023
tpd.cpy.UnApply (body1)(fn, Nil ,
984
1024
typed(untpd.Bind (tree.name, arg).withPos(tree.pos), arg.tpe) :: Nil )
985
1025
case _ =>
986
- val flags = if (tree.isType) BindDefinedType else EmptyFlags
987
- val sym = ctx.newSymbol(ctx.owner, tree.name, flags | Case , body1.tpe, coord = tree.pos)
1026
+ val sym = newPatternBoundSym(tree.name, body1.tpe, tree.pos)
988
1027
assignType(cpy.Bind (tree)(tree.name, body1), sym)
989
1028
}
990
1029
}
0 commit comments