Skip to content

Commit 673698d

Browse files
authored
Merge pull request #13881 from dotty-staging/fix-13820
2 parents e7cbbd6 + 11cb3bd commit 673698d

File tree

3 files changed

+38
-26
lines changed

3 files changed

+38
-26
lines changed

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,7 @@ class Typer extends Namer
876876
wildName = nme.WILDCARD_STAR)
877877
}
878878
else {
879-
def typedTpt = checkSimpleKinded(typedType(tree.tpt))
879+
def typedTpt = checkSimpleKinded(typedType(tree.tpt, mapPatternBounds = true))
880880
def handlePattern: Tree = {
881881
val tpt1 = typedTpt
882882
if !ctx.isAfterTyper && pt != defn.ImplicitScrutineeTypeRef then
@@ -1683,7 +1683,9 @@ class Typer extends Namer
16831683
/** Type a case of a type match */
16841684
def typedTypeCase(cdef: untpd.CaseDef, selType: Type, pt: Type)(using Context): CaseDef = {
16851685
def caseRest(using Context) = {
1686-
val pat1 = withMode(Mode.Pattern)(checkSimpleKinded(typedType(cdef.pat)))
1686+
val pat1 = withMode(Mode.Pattern) {
1687+
checkSimpleKinded(typedType(cdef.pat, mapPatternBounds = true))
1688+
}
16871689
val pat2 = indexPattern(cdef).transform(pat1)
16881690
var body1 = typedType(cdef.body, pt)
16891691
if !body1.isType then
@@ -1924,7 +1926,7 @@ class Typer extends Namer
19241926
// wildcard identifiers `_` instead.
19251927
TypeTree(tparamBounds).withSpan(arg.span)
19261928
case _ =>
1927-
typed(desugaredArg, argPt)
1929+
typedType(desugaredArg, argPt, mapPatternBounds = true)
19281930
}
19291931
else desugaredArg.withType(UnspecifiedErrorType)
19301932
}
@@ -1991,36 +1993,18 @@ class Typer extends Namer
19911993
assignType(cpy.ByNameTypeTree(tree)(result1), result1)
19921994
}
19931995

1994-
def typedTypeBoundsTree(tree: untpd.TypeBoundsTree, pt: Type)(using Context): Tree = {
1996+
def typedTypeBoundsTree(tree: untpd.TypeBoundsTree, pt: Type)(using Context): Tree =
19951997
val TypeBoundsTree(lo, hi, alias) = tree
19961998
val lo1 = typed(lo)
19971999
val hi1 = typed(hi)
19982000
val alias1 = typed(alias)
1999-
20002001
val lo2 = if (lo1.isEmpty) typed(untpd.TypeTree(defn.NothingType)) else lo1
20012002
val hi2 = if (hi1.isEmpty) typed(untpd.TypeTree(defn.AnyType)) else hi1
2002-
20032003
if !alias1.isEmpty then
20042004
val bounds = TypeBounds(lo2.tpe, hi2.tpe)
20052005
if !bounds.contains(alias1.tpe) then
20062006
report.error(em"type ${alias1.tpe} outside bounds $bounds", tree.srcPos)
2007-
2008-
val tree1 = assignType(cpy.TypeBoundsTree(tree)(lo2, hi2, alias1), lo2, hi2, alias1)
2009-
if (ctx.mode.is(Mode.Pattern))
2010-
// Associate a pattern-bound type symbol with the wildcard.
2011-
// The bounds of the type symbol can be constrained when comparing a pattern type
2012-
// with an expected type in typedTyped. The type symbol and the defining Bind node
2013-
// are eliminated once the enclosing pattern has been typechecked; see `indexPattern`
2014-
// in `typedCase`.
2015-
//val ptt = if (lo.isEmpty && hi.isEmpty) pt else
2016-
if (ctx.isAfterTyper) tree1
2017-
else {
2018-
val boundName = WildcardParamName.fresh().toTypeName
2019-
val wildcardSym = newPatternBoundSymbol(boundName, tree1.tpe & pt, tree.span)
2020-
untpd.Bind(boundName, tree1).withType(wildcardSym.typeRef)
2021-
}
2022-
else tree1
2023-
}
2007+
assignType(cpy.TypeBoundsTree(tree)(lo2, hi2, alias1), lo2, hi2, alias1)
20242008

20252009
def typedBind(tree: untpd.Bind, pt: Type)(using Context): Tree = {
20262010
if !isFullyDefined(pt, ForceDegree.all) then
@@ -2698,7 +2682,9 @@ class Typer extends Namer
26982682
val pts =
26992683
if (arity == pt.tupleArity) pt.tupleElementTypes
27002684
else List.fill(arity)(defn.AnyType)
2701-
val elems = tree.trees.lazyZip(pts).map(typed(_, _))
2685+
val elems = tree.trees.lazyZip(pts).map(
2686+
if ctx.mode.is(Mode.Type) then typedType(_, _, mapPatternBounds = true)
2687+
else typed(_, _))
27022688
if (ctx.mode.is(Mode.Type))
27032689
elems.foldRight(TypeTree(defn.EmptyTupleModule.termRef): Tree)((elemTpt, elemTpts) =>
27042690
AppliedTypeTree(TypeTree(defn.PairClass.typeRef), List(elemTpt, elemTpts)))
@@ -3029,8 +3015,24 @@ class Typer extends Namer
30293015

30303016
def typedExpr(tree: untpd.Tree, pt: Type = WildcardType)(using Context): Tree =
30313017
withoutMode(Mode.PatternOrTypeBits)(typed(tree, pt))
3032-
def typedType(tree: untpd.Tree, pt: Type = WildcardType)(using Context): Tree = // todo: retract mode between Type and Pattern?
3033-
withMode(Mode.Type) { typed(tree, pt) }
3018+
3019+
def typedType(tree: untpd.Tree, pt: Type = WildcardType, mapPatternBounds: Boolean = false)(using Context): Tree =
3020+
val tree1 = withMode(Mode.Type) { typed(tree, pt) }
3021+
if mapPatternBounds && ctx.mode.is(Mode.Pattern) && !ctx.isAfterTyper then
3022+
tree1 match
3023+
case tree1: TypeBoundsTree =>
3024+
// Associate a pattern-bound type symbol with the wildcard.
3025+
// The bounds of the type symbol can be constrained when comparing a pattern type
3026+
// with an expected type in typedTyped. The type symbol and the defining Bind node
3027+
// are eliminated once the enclosing pattern has been typechecked; see `indexPattern`
3028+
// in `typedCase`.
3029+
val boundName = WildcardParamName.fresh().toTypeName
3030+
val wildcardSym = newPatternBoundSymbol(boundName, tree1.tpe & pt, tree.span)
3031+
untpd.Bind(boundName, tree1).withType(wildcardSym.typeRef)
3032+
case tree1 =>
3033+
tree1
3034+
else tree1
3035+
30343036
def typedPattern(tree: untpd.Tree, selType: Type = WildcardType)(using Context): Tree =
30353037
withMode(Mode.Pattern)(typed(tree, selType))
30363038

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
trait Expr { type T }
2+
3+
def foo[A](e: Expr { type T = A }) = e match
4+
case e1: Expr { type T <: Int } => // error: type test cannot be checked at runtime
5+
val i: Int = ??? : e1.T

tests/pos/i13820.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
trait Expr { type T }
2+
3+
def foo[A](e: Expr { type T = A }) = e match
4+
case e1: Expr { type T <: Int } =>
5+
val i: Int = ??? : e1.T

0 commit comments

Comments
 (0)