Skip to content

Match Types: implement cantPossiblyMatch #5996

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Mar 9, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c1b7e84
Minor TypeTestsCasts refactoring
OlivierBlanvillain Feb 11, 2019
6e39fcb
Rename evalOnce to letBind
OlivierBlanvillain Feb 11, 2019
eef623a
Rename cmp to typeComparer
OlivierBlanvillain Feb 11, 2019
6755f52
Remove reduceParallel
OlivierBlanvillain Feb 18, 2019
88cfb7e
Fix spacing for TypeComparer comments
OlivierBlanvillain Feb 21, 2019
bb1515e
Flag ChildrenQueried in hasAnonymousChild
OlivierBlanvillain Feb 22, 2019
f79d937
Implement cantPossiblyMatch
OlivierBlanvillain Mar 1, 2019
60d0e20
Replace Space.inhabited by typeComparer.intersecting
OlivierBlanvillain Feb 28, 2019
d1180cc
Move refineUsingParent to Typer
OlivierBlanvillain Feb 26, 2019
b0c1e7b
Check inhabitation of children in Space
OlivierBlanvillain Feb 28, 2019
c3d23fe
Only trust isSameType for fully instanciated types
OlivierBlanvillain Feb 28, 2019
4f934ad
Use derivesFrom instead of isSubType for classes
OlivierBlanvillain Mar 1, 2019
80c25e3
Handle type parameters using symbol.is(TypeParam)
OlivierBlanvillain Mar 4, 2019
ab74827
Fix AppliedType logic
OlivierBlanvillain Mar 4, 2019
1df0d8b
Revert "Rename evalOnce to letBind"
OlivierBlanvillain Mar 6, 2019
8827eff
Revert "Flag ChildrenQueried in hasAnonymousChild"
OlivierBlanvillain Mar 6, 2019
ffa8acf
Address review
OlivierBlanvillain Mar 6, 2019
e7f6049
Move refineUsingParent to TypeOps
OlivierBlanvillain Mar 6, 2019
f4df58d
Factor out cov. test and use it in the inv. case
OlivierBlanvillain Mar 6, 2019
ea04343
Update inhabited check in Space
OlivierBlanvillain Mar 6, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1139,7 +1139,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}

/** Let bind `tree` unless `tree` is at least idempotent */
def evalOnce(tree: Tree)(within: Tree => Tree)(implicit ctx: Context): Tree =
def letBind(tree: Tree)(within: Tree => Tree)(implicit ctx: Context): Tree =
letBindUnless(TreeInfo.Idempotent, tree)(within)

def runtimeCall(name: TermName, args: List[Tree])(implicit ctx: Context): Tree = {
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/Erasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ object Erasure {
val nullTree = Literal(Constant(null))
val unboxedNull = adaptToType(nullTree, underlying)

evalOnce(tree) { t =>
letBind(tree) { t =>
If(t.select(defn.Object_eq).appliedTo(nullTree),
unboxedNull,
unboxedTree(t))
Expand Down
34 changes: 16 additions & 18 deletions compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -164,19 +164,20 @@ object TypeTestsCasts {
else tp.classSymbol

def foundCls = effectiveClass(expr.tpe.widen)
// println(i"ta $tree, found = $foundCls")

def inMatch =
fun.symbol == defn.Any_typeTest || // new scheme
expr.symbol.is(Case) // old scheme

def transformIsInstanceOf(expr:Tree, testType: Type, flagUnrelated: Boolean): Tree = {
def transformIsInstanceOf(expr: Tree, testType: Type, flagUnrelated: Boolean): Tree = {
def testCls = effectiveClass(testType.widen)

def unreachable(why: => String) =
def unreachable(why: => String): Boolean = {
if (flagUnrelated)
if (inMatch) ctx.error(em"this case is unreachable since $why", expr.sourcePos)
else ctx.warning(em"this will always yield false since $why", expr.sourcePos)
false
}

/** Are `foundCls` and `testCls` classes that allow checks
* whether a test would be always false?
Expand All @@ -191,25 +192,22 @@ object TypeTestsCasts {
// we don't have the logic to handle derived value classes

/** Check whether a runtime test that a value of `foundCls` can be a `testCls`
* can be true in some cases. Issure a warning or an error if that's not the case.
* can be true in some cases. Issues a warning or an error otherwise.
*/
def checkSensical: Boolean =
if (!isCheckable) true
else if (foundCls.isPrimitiveValueClass && !testCls.isPrimitiveValueClass) {
ctx.error("cannot test if value types are references", tree.sourcePos)
false
}
ctx.error("cannot test if value types are references", tree.sourcePos)
false
}
else if (!foundCls.derivesFrom(testCls)) {
if (foundCls.is(Final)) {
val unrelated = !testCls.derivesFrom(foundCls) && (
testCls.is(Final) || !testCls.is(Trait) && !foundCls.is(Trait)
)
if (foundCls.is(Final))
unreachable(i"$foundCls is not a subclass of $testCls")
false
}
else if (!testCls.derivesFrom(foundCls) &&
(testCls.is(Final) ||
!testCls.is(Trait) && !foundCls.is(Trait))) {
else if (unrelated)
unreachable(i"$foundCls and $testCls are unrelated")
false
}
else true
}
else true
Expand Down Expand Up @@ -267,20 +265,20 @@ object TypeTestsCasts {
case _: SingletonType =>
expr.isInstance(testType).withSpan(tree.span)
case OrType(tp1, tp2) =>
evalOnce(expr) { e =>
letBind(expr) { e =>
transformTypeTest(e, tp1, flagUnrelated = false)
.or(transformTypeTest(e, tp2, flagUnrelated = false))
}
case AndType(tp1, tp2) =>
evalOnce(expr) { e =>
letBind(expr) { e =>
transformTypeTest(e, tp1, flagUnrelated)
.and(transformTypeTest(e, tp2, flagUnrelated))
}
case defn.MultiArrayOf(elem, ndims) if isUnboundedGeneric(elem) =>
def isArrayTest(arg: Tree) =
ref(defn.runtimeMethodRef(nme.isArray)).appliedTo(arg, Literal(Constant(ndims)))
if (ndims == 1) isArrayTest(expr)
else evalOnce(expr) { e =>
else letBind(expr) { e =>
derivedTree(e, defn.Any_isInstanceOf, e.tpe)
.and(isArrayTest(e))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class VCInlineMethods extends MiniPhase with IdentityDenotTransformer {
val extensionMeth = extensionMethod(origMeth)

if (!ctParams.isEmpty) {
evalOnce(qual) { ev =>
letBind(qual) { ev =>
val ctArgs = ctParams.map(tparam =>
TypeTree(tparam.typeRef.asSeenFrom(ev.tpe, origCls)))
ref(extensionMeth)
Expand Down