Skip to content

Commit

Permalink
Revert #11784
Browse files Browse the repository at this point in the history
The original PR fixes a trivial issue. However, the fix has both false
positives and negatives. It's not easy to do the right thing. Therefore,
it's simpler to remove the original fixes.
  • Loading branch information
liufengyun committed Jul 4, 2023
1 parent 67ffb4b commit c3ae358
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 59 deletions.
64 changes: 5 additions & 59 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4364,65 +4364,11 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
withMode(Mode.GadtConstraintInference) {
TypeComparer.constrainPatternType(tree.tpe, pt)
}

// approximate type params with bounds
def approx = new ApproximatingTypeMap {
var alreadyExpanding: List[TypeRef] = Nil
def apply(tp: Type) = tp.dealias match
case tp: TypeRef if !tp.symbol.isClass =>
if alreadyExpanding contains tp then tp else
val saved = alreadyExpanding
alreadyExpanding ::= tp
val res = expandBounds(tp.info.bounds)
alreadyExpanding = saved
res
case _ =>
mapOver(tp)
}

// Is it possible that a value of `clsA` is equal to a value of `clsB`?
// This ignores user-defined equals methods, but makes an exception
// for numeric classes.
def canOverlap(clsA: ClassSymbol, clsB: ClassSymbol): Boolean =
clsA.mayHaveCommonChild(clsB)
|| clsA.isNumericValueClass // this is quite coarse, but matches to what was done before
|| clsB.isNumericValueClass

// Can type `a` possiblly have a common instance with type `b`?
def canEqual(a: Type, b: Type): Boolean = trace(i"canEqual $a $b"):
b match
case _: TypeRef | _: AppliedType if b.typeSymbol.isClass =>
a match
case a: TermRef if a.symbol.isOneOf(Module | Enum) =>
(a frozen_<:< b) // fast track
|| (a frozen_<:< approx(b))
case _: TypeRef | _: AppliedType if a.typeSymbol.isClass =>
if a.isNullType then !b.isNotNull
else canOverlap(a.typeSymbol.asClass, b.typeSymbol.asClass)
case a: TypeProxy =>
canEqual(a.superType, b)
case a: AndOrType =>
canEqual(a.tp1, b) || canEqual(a.tp2, b)
case b: TypeProxy =>
canEqual(a, b.superType)
case b: AndOrType =>
// we lose precision with and/or types, but it's hard to do better and
// still compute `canEqual(A & B, B & A) = true`.
canEqual(a, b.tp1) || canEqual(a, b.tp2)

if !canEqual(tree.tpe, pt) then
// We could check whether `equals` is overridden.
// Reasons for not doing so:
// - it complicates the protocol
// - such code patterns usually implies hidden errors in the code
// - it's safe/sound to reject the code
report.error(TypeMismatch(tree.tpe, pt, Some(tree), "\npattern type is incompatible with expected type"), tree.srcPos)
else
val cmp =
untpd.Apply(
untpd.Select(untpd.TypedSplice(tree), nme.EQ),
untpd.TypedSplice(dummyTreeOfType(pt)))
typedExpr(cmp, defn.BooleanType)
val cmp =
untpd.Apply(
untpd.Select(untpd.TypedSplice(tree), nme.EQ),
untpd.TypedSplice(dummyTreeOfType(pt)))
typedExpr(cmp, defn.BooleanType)
case _ =>

private def checkInterestingResultInStatement(t: Tree)(using Context): Boolean = {
Expand Down
File renamed without changes.

0 comments on commit c3ae358

Please sign in to comment.