diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index b595336a3ce1..6e55be500bf2 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -534,6 +534,15 @@ class ClassfileParser( */ def parseAnnotation(attrNameIndex: Char, skip: Boolean = false)(implicit ctx: Context): Option[Annotation] = try { val attrType = pool.getType(attrNameIndex) + attrType match + case tp: TypeRef => + // Silently ignore missing annotation classes like javac + if tp.denot.infoOrCompleter.isInstanceOf[StubInfo] then + if ctx.debug then + ctx.warning(i"Error while parsing annotations in ${in.file}: annotation class $tp not present on classpath") + return None + case _ => + val nargs = in.nextChar val argbuf = new ListBuffer[untpd.Tree] var hasError = false diff --git a/compiler/test/dotty/tools/AnnotationsTests.scala b/compiler/test/dotty/tools/AnnotationsTests.scala index 0e49b4b8af63..2a25025c2848 100644 --- a/compiler/test/dotty/tools/AnnotationsTests.scala +++ b/compiler/test/dotty/tools/AnnotationsTests.scala @@ -37,3 +37,20 @@ class AnnotationsTest: } } } + + @Test def surviveMissingAnnot: Unit = + withJavaCompiled( + VirtualJavaSource("Annot.java", + "public @interface Annot {}"), + VirtualJavaSource("A.java", + "@Annot() public class A {}")) { javaOutputDir => + Files.delete(javaOutputDir.resolve("Annot.class")) + inCompilerContext(javaOutputDir.toString + File.pathSeparator + TestConfiguration.basicClasspath) { + val cls = ctx.requiredClass("A") + val annots = cls.annotations.map(_.tree) + assert(annots == Nil, + s"class A should have no visible annotations since Annot is not on the classpath, but found: $annots") + assert(!ctx.reporter.hasErrors && !ctx.reporter.hasWarnings, + s"A missing annotation while parsing a Java class should be silently ignored but: ${ctx.reporter.summary}") + } + }