Skip to content

Commit

Permalink
Fix calculation to drop transparent classes
Browse files Browse the repository at this point in the history
Two fixes:

 1. Don't forget about refinements
 2. Don't dealias

Fixes scala#16342

The first fix is essential for $16342. The second fix is just to keep
types tidy and not open aliases needlessly.

The previous incorrect version hid errors in previous regressions scala#15365 and scala#16311
which will need to be re-opened now.
  • Loading branch information
odersky committed Nov 15, 2022
1 parent 970d119 commit 76130f5
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 7 deletions.
15 changes: 8 additions & 7 deletions compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala
Original file line number Diff line number Diff line change
Expand Up @@ -557,8 +557,10 @@ trait ConstraintHandling {
end approximation

private def isTransparent(tp: Type)(using Context): Boolean = tp match
case AndType(tp1, tp2) => isTransparent(tp1) && isTransparent(tp2)
case _ => tp.typeSymbol.isTransparentClass && !tp.isLambdaSub
case AndType(tp1, tp2) =>
isTransparent(tp1) && isTransparent(tp2)
case _ =>
tp.underlyingClassRef(refinementOK = false).typeSymbol.isTransparentClass

/** If `tp` is an intersection such that some operands are transparent trait instances
* and others are not, replace as many transparent trait instances as possible with Any
Expand All @@ -572,18 +574,17 @@ trait ConstraintHandling {
var dropped: List[Type] = List() // the types dropped so far, last one on top

def dropOneTransparentClass(tp: Type): Type =
val tpd = tp.dealias
if isTransparent(tpd) && !kept.contains(tpd) then
dropped = tpd :: dropped
if isTransparent(tp) && !kept.contains(tp) then
dropped = tp :: dropped
defn.AnyType
else tpd match
else tp match
case AndType(tp1, tp2) =>
val tp1w = dropOneTransparentClass(tp1)
if tp1w ne tp1 then tp1w & tp2
else
val tp2w = dropOneTransparentClass(tp2)
if tp2w ne tp2 then tp1 & tp2w
else tpd
else tp
case _ =>
tp

Expand Down
File renamed without changes.
File renamed without changes.
18 changes: 18 additions & 0 deletions tests/pos/i16342.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
type Opaque = Base with Tag

type Base = Any {
type Hack
}

trait Tag

object Opaque {
def apply(value: String): Opaque = value.asInstanceOf[Opaque]

def unapply(userId: Opaque): Option[String] = Option(userId).map(_.value)
def unappy2(userId: Base with Tag): Option[String] = Option(userId).map(_.value)
}

final implicit class Ops(private val userId: Opaque) extends AnyVal {
def value: String = userId.asInstanceOf[String]
}

0 comments on commit 76130f5

Please sign in to comment.