Skip to content

Commit 2d852d7

Browse files
committed
Better fix: Fix isMatch
An applied type that is an alias of an applied match type is an applied match type itself. Previously that was not the case, which led to typed that could logically be reduced but were not.
1 parent da6b00d commit 2d852d7

File tree

3 files changed

+67
-41
lines changed

3 files changed

+67
-41
lines changed

compiler/src/dotty/tools/dotc/core/TypeOps.scala

Lines changed: 39 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -420,47 +420,45 @@ object TypeOps:
420420
sym.is(Package) || sym.isStatic && isStaticPrefix(pre.prefix)
421421
case _ => true
422422

423-
def apply(tp: Type): Type =
424-
val tp1 = tp match
425-
case tp: TermRef
426-
if toAvoid(tp.symbol) || partsToAvoid(Nil, tp.info).nonEmpty =>
427-
tp.info.widenExpr.dealias match {
428-
case info: SingletonType => apply(info)
429-
case info => range(defn.NothingType, apply(info))
430-
}
431-
case tp: TypeRef if toAvoid(tp.symbol) =>
432-
tp.info match {
433-
case info: AliasingBounds =>
434-
apply(info.alias)
435-
case TypeBounds(lo, hi) =>
436-
range(atVariance(-variance)(apply(lo)), apply(hi))
437-
case info: ClassInfo =>
438-
range(defn.NothingType, apply(classBound(info)))
439-
case _ =>
440-
emptyRange // should happen only in error cases
441-
}
442-
case tp: ThisType =>
443-
// ThisType is only used inside a class.
444-
// Therefore, either they don't appear in the type to be avoided, or
445-
// it must be a class that encloses the block whose type is to be avoided.
446-
tp
447-
case tp: SkolemType if partsToAvoid(Nil, tp.info).nonEmpty =>
448-
range(defn.NothingType, apply(tp.info))
449-
case tp: TypeVar if mapCtx.typerState.constraint.contains(tp) =>
450-
val lo = TypeComparer.instanceType(
451-
tp.origin, fromBelow = variance > 0 || variance == 0 && tp.hasLowerBound)(using mapCtx)
452-
val lo1 = apply(lo)
453-
if (lo1 ne lo) lo1 else tp
454-
case tp: LazyRef =>
455-
if localParamRefs.contains(tp.ref) then tp
456-
else if isExpandingBounds then emptyRange
457-
else mapOver(tp)
458-
case tl: HKTypeLambda =>
459-
localParamRefs ++= tl.paramRefs
460-
mapOver(tl)
461-
case _ =>
462-
mapOver(tp)
463-
if tp1 ne tp then tp1.normalized else tp
423+
def apply(tp: Type): Type = tp match
424+
case tp: TermRef
425+
if toAvoid(tp.symbol) || partsToAvoid(Nil, tp.info).nonEmpty =>
426+
tp.info.widenExpr.dealias match {
427+
case info: SingletonType => apply(info)
428+
case info => range(defn.NothingType, apply(info))
429+
}
430+
case tp: TypeRef if toAvoid(tp.symbol) =>
431+
tp.info match {
432+
case info: AliasingBounds =>
433+
apply(info.alias)
434+
case TypeBounds(lo, hi) =>
435+
range(atVariance(-variance)(apply(lo)), apply(hi))
436+
case info: ClassInfo =>
437+
range(defn.NothingType, apply(classBound(info)))
438+
case _ =>
439+
emptyRange // should happen only in error cases
440+
}
441+
case tp: ThisType =>
442+
// ThisType is only used inside a class.
443+
// Therefore, either they don't appear in the type to be avoided, or
444+
// it must be a class that encloses the block whose type is to be avoided.
445+
tp
446+
case tp: SkolemType if partsToAvoid(Nil, tp.info).nonEmpty =>
447+
range(defn.NothingType, apply(tp.info))
448+
case tp: TypeVar if mapCtx.typerState.constraint.contains(tp) =>
449+
val lo = TypeComparer.instanceType(
450+
tp.origin, fromBelow = variance > 0 || variance == 0 && tp.hasLowerBound)(using mapCtx)
451+
val lo1 = apply(lo)
452+
if (lo1 ne lo) lo1 else tp
453+
case tp: LazyRef =>
454+
if localParamRefs.contains(tp.ref) then tp
455+
else if isExpandingBounds then emptyRange
456+
else mapOver(tp)
457+
case tl: HKTypeLambda =>
458+
localParamRefs ++= tl.paramRefs
459+
mapOver(tl)
460+
case _ =>
461+
mapOver(tp)
464462
end apply
465463

466464
/** Three deviations from standard derivedSelect:

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,10 @@ object Types {
423423
def isMatch(using Context): Boolean = stripped match {
424424
case _: MatchType => true
425425
case tp: HKTypeLambda => tp.resType.isMatch
426+
case tp: AppliedType =>
427+
tp.tycon match
428+
case tycon: TypeRef => tycon.info.isInstanceOf[MatchAlias]
429+
case _ => false
426430
case _ => false
427431
}
428432

tests/pos/i12178.scala

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
opaque type LabelTagged[TLabel <: Singleton & String, TValue] = TValue
2+
3+
object LabelTagged:
4+
def apply[TLabel <: Singleton & String, TValue]
5+
(
6+
label: TLabel,
7+
value: TValue,
8+
)
9+
: LabelTagged[TLabel, TValue] = value
10+
11+
extension[TLabel <: Singleton & String, TValue] (labelTagged: LabelTagged[TLabel, TValue])
12+
def value
13+
: TValue = labelTagged
14+
15+
def label
16+
(using label: ValueOf[TLabel])
17+
: TLabel
18+
= label.value
19+
20+
@main def hello(): Unit = {
21+
val foo: LabelTagged["foo", Int] = LabelTagged("foo", 10)
22+
println(label(foo)) // OK
23+
//println(foo.label) // not OK
24+
}

0 commit comments

Comments
 (0)