Skip to content

Commit 060a17a

Browse files
authored
Merge pull request #9370 from TheElectronWill/dont-trust-java
2 parents cdfb92c + 2bc92db commit 060a17a

File tree

7 files changed

+81
-12
lines changed

7 files changed

+81
-12
lines changed

compiler/src/dotty/tools/dotc/transform/Pickler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class Pickler extends Phase {
8989

9090
override def runOn(units: List[CompilationUnit])(using Context): List[CompilationUnit] = {
9191
val result = super.runOn(units)
92-
if (ctx.settings.YtestPickler.value)
92+
if ctx.settings.YtestPickler.value
9393
testUnpickler(
9494
using ctx.fresh
9595
.setPeriod(Period(ctx.runId + 1, FirstPhaseId))

compiler/src/dotty/tools/dotc/typer/FrontEnd.scala

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,10 @@ class FrontEnd extends Phase {
4040

4141
def monitor(doing: String)(body: => Unit)(using Context): Unit =
4242
try body
43-
catch {
43+
catch
4444
case NonFatal(ex) =>
4545
report.echo(s"exception occurred while $doing ${ctx.compilationUnit}")
4646
throw ex
47-
}
4847

4948
def parse(using Context): Unit = monitor("parsing") {
5049
val unit = ctx.compilationUnit
@@ -84,17 +83,23 @@ class FrontEnd extends Phase {
8483
case ex: CompilationUnit.SuspendException =>
8584
}
8685

87-
private def firstTopLevelDef(trees: List[tpd.Tree])(using Context): Symbol = trees match {
86+
def javaCheck(using Context): Unit = monitor("checking java") {
87+
val unit = ctx.compilationUnit
88+
if unit.isJava then
89+
JavaChecks.check(unit.tpdTree)
90+
}
91+
92+
93+
private def firstTopLevelDef(trees: List[tpd.Tree])(using Context): Symbol = trees match
8894
case PackageDef(_, defs) :: _ => firstTopLevelDef(defs)
8995
case Import(_, _) :: defs => firstTopLevelDef(defs)
9096
case (tree @ TypeDef(_, _)) :: _ => tree.symbol
9197
case _ => NoSymbol
92-
}
9398

9499
protected def discardAfterTyper(unit: CompilationUnit)(using Context): Boolean =
95100
unit.isJava || unit.suspended
96101

97-
override def runOn(units: List[CompilationUnit])(using Context): List[CompilationUnit] = {
102+
override def runOn(units: List[CompilationUnit])(using Context): List[CompilationUnit] =
98103
val unitContexts =
99104
for unit <- units yield
100105
report.inform(s"compiling ${unit.source}")
@@ -106,13 +111,15 @@ class FrontEnd extends Phase {
106111
enterSyms(using remaining.head)
107112
remaining = remaining.tail
108113

109-
if (firstXmlPos.exists && !defn.ScalaXmlPackageClass.exists)
114+
if firstXmlPos.exists && !defn.ScalaXmlPackageClass.exists then
110115
report.error("""To support XML literals, your project must depend on scala-xml.
111116
|See https://github.com/scala/scala-xml for more information.""".stripMargin,
112117
firstXmlPos)
113118

114119
unitContexts.foreach(typeCheck(using _))
115120
record("total trees after typer", ast.Trees.ntrees)
121+
unitContexts.foreach(javaCheck(using _)) // after typechecking to avoid cycles
122+
116123
val newUnits = unitContexts.map(_.compilationUnit).filterNot(discardAfterTyper)
117124
val suspendedUnits = ctx.run.suspendedUnits
118125
if newUnits.isEmpty && suspendedUnits.nonEmpty && !ctx.reporter.errorsReported then
@@ -123,14 +130,13 @@ class FrontEnd extends Phase {
123130
| ${suspendedUnits.toList}%, %
124131
|"""
125132
val enableXprintSuspensionHint =
126-
if (ctx.settings.XprintSuspension.value) ""
133+
if ctx.settings.XprintSuspension.value then ""
127134
else "\n\nCompiling with -Xprint-suspension gives more information."
128135
report.error(em"""Cyclic macro dependencies $where
129136
|Compilation stopped since no further progress can be made.
130137
|
131138
|To fix this, place macros in one set of files and their callers in another.$enableXprintSuspensionHint""")
132139
newUnits
133-
}
134140

135141
def run(using Context): Unit = unsupported("run")
136142
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package dotty.tools.dotc
2+
package typer
3+
4+
import core.Contexts._
5+
import ast.tpd._
6+
7+
/** PostTyper doesn't run on java sources,
8+
* but some checks still need to be applied.
9+
*/
10+
object JavaChecks {
11+
/** Check the bounds of AppliedTypeTrees. */
12+
private object AppliedTypeChecker extends TreeTraverser {
13+
def traverse(tree: Tree)(using Context): Unit = tree match
14+
case tpt: TypeTree =>
15+
Checking.checkAppliedTypesIn(tpt)
16+
case tree: AppliedTypeTree =>
17+
Checking.checkAppliedType(tree)
18+
case _ =>
19+
traverseChildren(tree)
20+
}
21+
22+
/** Scan a tree and check it. */
23+
def check(tree: Tree)(using Context): Unit =
24+
report.debuglog("checking type bounds in " + ctx.compilationUnit.source.name)
25+
AppliedTypeChecker.traverse(tree)
26+
}

compiler/test/dotty/tools/vulpix/ParallelTesting.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,10 @@ trait ParallelTesting extends RunnerOrchestration { self =>
229229
*/
230230
final def checkFile(testSource: TestSource): Option[JFile] = (testSource match {
231231
case ts: JointCompilationSource =>
232-
ts.files.collectFirst { case f if !f.isDirectory => new JFile(f.getPath.replaceFirst("\\.scala$", ".check")) }
233-
232+
ts.files.collectFirst {
233+
case f if !f.isDirectory =>
234+
new JFile(f.getPath.replaceFirst("\\.(scala|java)$", ".check"))
235+
}
234236
case ts: SeparateCompilationSource =>
235237
Option(new JFile(ts.dir.getPath + ".check"))
236238
}).filter(_.exists)
@@ -679,7 +681,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
679681
def getErrorMapAndExpectedCount(files: Seq[JFile]): (HashMap[String, Integer], Int) = {
680682
val errorMap = new HashMap[String, Integer]()
681683
var expectedErrors = 0
682-
files.filter(_.getName.endsWith(".scala")).foreach { file =>
684+
files.filter(isSourceFile).foreach { file =>
683685
Using(Source.fromFile(file, "UTF-8")) { source =>
684686
source.getLines.zipWithIndex.foreach { case (line, lineNbr) =>
685687
val errors = line.toSeq.sliding("// error".length).count(_.unwrap == "// error")

tests/neg/WrongBounds.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import java.util.*;
2+
3+
class WrongBounds {
4+
class LL<T> extends ArrayList<List<T>> {}
5+
class Wrap<T extends List<List<?>>> extends ArrayList<T> {}
6+
class Wrong<T extends LL<?>> extends Wrap<T> {} // error
7+
}

tests/neg/java-wrong-bounds/D_1.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class A
2+
3+
class D[T >: A](v: T) {
4+
def getV(): T = v
5+
}

tests/neg/java-wrong-bounds/J_2.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
public class J_2 extends D<String> { // error
2+
3+
public J_2() {
4+
super(null);
5+
}
6+
7+
public static D<String> getDS() { // error
8+
return new D<String>("DS");
9+
}
10+
11+
public static final D<String> fieldDS = new D<String>("DS"); // error
12+
13+
public static void useDS(D<String> ds) {} // error
14+
15+
public static <A extends D<String>> void genericDS() {} // error
16+
17+
public static void useOK(D<?> ds) {}
18+
19+
public static D<?> getOK() {return null;}
20+
21+
public static <A extends D<?>> D<?> genericOK(A a) {return a;}
22+
23+
}

0 commit comments

Comments
 (0)