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