Skip to content

Commit aff1e11

Browse files
authored
Merge pull request #15094 from griggt/fix-13523
Fix #13523: Survive missing Java inner annotation classfiles
2 parents 1f4daea + ccc33ea commit aff1e11

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala

+10-1
Original file line numberDiff line numberDiff line change
@@ -1127,7 +1127,16 @@ class ClassfileParser(
11271127
val outerName = entry.strippedOuter
11281128
val innerName = entry.originalName
11291129
val owner = classNameToSymbol(outerName)
1130-
val result = atPhase(typerPhase)(getMember(owner, innerName.toTypeName))
1130+
val result = owner.denot.infoOrCompleter match
1131+
case _: StubInfo if hasAnnotation(entry.jflags) =>
1132+
requiredClass(innerName.toTypeName)
1133+
// It's okay for the classfiles of Java annotations to be missing
1134+
// from the classpath. If an annotation is defined as an inner class
1135+
// we need to avoid forcing the outer class symbol here, and instead
1136+
// return a new stub symbol for the inner class. This is tested by
1137+
// `surviveMissingInnerClassAnnot` in AnnotationsTests.scala
1138+
case _ =>
1139+
atPhase(typerPhase)(getMember(owner, innerName.toTypeName))
11311140
assert(result ne NoSymbol,
11321141
i"""failure to resolve inner class:
11331142
|externalName = ${entry.externalName},

compiler/test/dotty/tools/AnnotationsTests.scala

+23
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,26 @@ class AnnotationsTest:
6666
s"A missing annotation while parsing a Java class should be silently ignored but: ${ctx.reporter.summary}")
6767
}
6868
}
69+
70+
@Test def surviveMissingInnerClassAnnot: Unit =
71+
withJavaCompiled(
72+
VirtualJavaSource("Outer.java",
73+
"""|package a.b;
74+
|public @interface Outer { public @interface Value { @interface Immutable {} } }
75+
|""".stripMargin),
76+
VirtualJavaSource("Baz.java",
77+
"""|package a.b;
78+
|@Outer.Value.Immutable abstract class Baz {}""".stripMargin)
79+
) { javaOutputDir =>
80+
Files.delete(javaOutputDir.resolve("a/b/Outer.class"))
81+
Files.delete(javaOutputDir.resolve("a/b/Outer$Value.class"))
82+
Files.delete(javaOutputDir.resolve("a/b/Outer$Value$Immutable.class"))
83+
inCompilerContext(javaOutputDir.toString + File.pathSeparator + TestConfiguration.basicClasspath) {
84+
val cls = requiredClass("a.b.Baz")
85+
val annots = cls.annotations.map(_.tree)
86+
assert(annots == Nil,
87+
s"class Baz should have no visible annotations since Outer.Value.Immutable is not on the classpath, but found: $annots")
88+
assert(!ctx.reporter.hasErrors && !ctx.reporter.hasWarnings,
89+
s"A missing annotation while parsing a Java class should be silently ignored but: ${ctx.reporter.summary}")
90+
}
91+
}

0 commit comments

Comments
 (0)