Skip to content

Commit cdffc9a

Browse files
oderskymichelou
authored andcommitted
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 f160cc3 commit cdffc9a

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
@@ -427,47 +427,45 @@ object TypeOps:
427427
sym.is(Package) || sym.isStatic && isStaticPrefix(pre.prefix)
428428
case _ => true
429429

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

473471
/** 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)