From 721b57e8197699cb6d8bcc4920f32e084c9310f5 Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 24 Jun 2023 17:05:55 +0200 Subject: [PATCH] Fix variance checking in refinements Do variance checks for parameters in method types and poly types of refinements. Fixes #18035 --- .../dotty/tools/dotc/typer/VarianceChecker.scala | 10 +++++++--- tests/neg/i18035.scala | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 tests/neg/i18035.scala diff --git a/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala b/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala index bcfc9288d862..a5e0b62094ef 100644 --- a/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala +++ b/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala @@ -130,8 +130,6 @@ class VarianceChecker(using Context) { case TypeAlias(alias) => this(status, alias) case _ => foldOver(status, tp) } - case tp: MethodOrPoly => - this(status, tp.resultType) // params will be checked in their TypeDef or ValDef nodes. case AnnotatedType(_, annot) if annot.symbol == defn.UncheckedVarianceAnnot => status case tp: ClassInfo => @@ -144,10 +142,16 @@ class VarianceChecker(using Context) { } } + def checkInfo(info: Type): Option[VarianceError] = info match + case info: MethodOrPoly => + checkInfo(info.resultType) // params will be checked in their TypeDef or ValDef nodes. + case _ => + apply(None, info) + def validateDefinition(base: Symbol): Option[VarianceError] = { val saved = this.base this.base = base - try apply(None, base.info) + try checkInfo(base.info) finally this.base = saved } } diff --git a/tests/neg/i18035.scala b/tests/neg/i18035.scala new file mode 100644 index 000000000000..ba2373481c85 --- /dev/null +++ b/tests/neg/i18035.scala @@ -0,0 +1,15 @@ +import reflect.Selectable.reflectiveSelectable + +class A[+Cov](f: Cov => Unit) { + def foo: { def apply(c: Cov): Unit } = // error + f +} + +val aForString = new A[String](_.length) +// => val aForString: A[String] + +val aForStringIsAForAny: A[Any] = aForString +// => val aForStringIsAForAny: A[Any] + +val _ = aForStringIsAForAny.foo(123) +// => java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String (java.lang.Integer and java.lang.String are in module java.base of loader 'bootstrap')