Skip to content

Don't unsoundly maximise types to Any/Nothing #15509

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

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 6 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,13 @@ jobs:
run: cp -vf .github/workflows/repositories /root/.sbt/ ; true

- name: Test
# DON'T add dist/pack!
# Adding dist/pack bootstraps the compiler
# which undermines the point of these tests:
# to quickly run the tests without the cost of bootstrapping
# and also to run tests when the compiler doesn't bootstrap
run: |
./project/scripts/sbt ";dist/pack; compile ;test"
./project/scripts/sbt ";compile ;test"
./project/scripts/cmdTests

test:
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Applications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1341,7 +1341,7 @@ trait Applications extends Compatibility {
// Constraining only fails if the pattern cannot possibly match,
// but useless pattern checks detect more such cases, so we simply rely on them instead.
withMode(Mode.GadtConstraintInference)(TypeComparer.constrainPatternType(unapplyArgType, selType))
val patternBound = maximizeType(unapplyArgType, tree.span)
val patternBound = maximizeType(unapplyArgType, unapplyFn.span.endPos)
if (patternBound.nonEmpty) unapplyFn = addBinders(unapplyFn, patternBound)
unapp.println(i"case 2 $unapplyArgType ${ctx.typerState.constraint}")
unapplyArgType
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/Inferencing.scala
Original file line number Diff line number Diff line change
Expand Up @@ -405,8 +405,8 @@ object Inferencing {
val patternBindings = new mutable.ListBuffer[(Symbol, TypeParamRef)]
vs foreachBinding { (tvar, v) =>
if !tvar.isInstantiated then
if (v == 1) tvar.instantiate(fromBelow = false)
else if (v == -1) tvar.instantiate(fromBelow = true)
if (v == 1 && tvar.hasUpperBound) tvar.instantiate(fromBelow = false)
else if (v == -1 && tvar.hasLowerBound) tvar.instantiate(fromBelow = true)
else {
val bounds = TypeComparer.fullBounds(tvar.origin)
if bounds.hi <:< bounds.lo || bounds.hi.classSymbol.is(Final) then
Expand Down
2 changes: 2 additions & 0 deletions compiler/test/dotty/tools/scripting/BashScriptsTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import scala.language.unsafeNulls
import java.nio.file.Paths
import org.junit.{Test, AfterClass}
import org.junit.Assert.assertEquals
import org.junit.experimental.categories.Category

import vulpix.TestConfiguration

Expand Down Expand Up @@ -156,6 +157,7 @@ class BashScriptsTests:
* verify that scriptPath.sc sees a valid script.path property,
* and that it's value is the path to "scriptPath.sc".
*/
@Category(Array(classOf[BootstrappedOnlyTests]))
@Test def verifyScriptPathProperty =
val scriptFile = testFiles.find(_.getName == "scriptPath.sc").get
val expected = s"${scriptFile.getName}"
Expand Down
2 changes: 2 additions & 0 deletions compiler/test/dotty/tools/scripting/ExpressionTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import scala.language.unsafeNulls
import java.nio.file.Paths
import org.junit.{Test, AfterClass}
import org.junit.Assert.assertEquals
import org.junit.experimental.categories.Category

import vulpix.TestConfiguration

Expand All @@ -15,6 +16,7 @@ import ScriptTestEnv.*
/**
* +. test scala -e <expression>
*/
@Category(Array(classOf[BootstrappedOnlyTests]))
class ExpressionTest:
/*
* verify -e <expression> works.
Expand Down
13 changes: 13 additions & 0 deletions tests/neg/i14983.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
sealed trait Tree[+A]
final case class Leaf[+B](v: B) extends Tree[B]
final case class Node[+C](xs: List[C]) extends Tree[List[C]]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change this to

Suggested change
final case class Node[+C](xs: List[C]) extends Tree[List[C]]
final case class Node[+C <: AnyRef](xs: List[C]) extends Tree[List[C]]

and use Integer instead of Int, and it's goes back to breaking


object Test:
def meth[X](tree: Tree[X]): X = tree match
case Leaf(v) => v
case Node(x) => List("boom") // error

def main(args: Array[String]): Unit =
val tree = Node(List(42))
val res = meth(tree)
assert(res.head == 42) // was: ClassCastException: class java.lang.String cannot be cast to class java.lang.Integer
13 changes: 13 additions & 0 deletions tests/run/i14983.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
sealed trait Tree[+A]
final case class Leaf[+B](v: B) extends Tree[B]
final case class Node[+C](xs: List[C]) extends Tree[List[C]]

object Test:
def meth[X](tree: Tree[X]): X = tree match
case Leaf(v) => v
case Node(x) => x // ok

def main(args: Array[String]): Unit =
val tree = Node(List(42))
val res = meth(tree)
assert(res.head == 42) // ok