diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 739a06abb7f3..5a6b373561f1 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -209,7 +209,7 @@ object TypeOps: /** Approximate union type by intersection of its dominators. * That is, replace a union type Tn | ... | Tn - * by the smallest intersection type of base-class instances of T1,...,Tn. + * by the smallest intersection type of accessible base-class instances of T1,...,Tn. * Example: Given * * trait C[+T] @@ -370,8 +370,14 @@ object TypeOps: } } + def isAccessible(cls: ClassSymbol) = + if cls.isOneOf(AccessFlags) || cls.privateWithin.exists then + cls.isAccessibleFrom(tp.baseType(cls).normalizedPrefix) + else true + // Step 3: Intersect base classes of both sides - val commonBaseClasses = orBaseClasses(tp) + val commonBaseClasses = orBaseClasses(tp).filterConserve(isAccessible) + val doms = dominators(commonBaseClasses, Nil) def baseTp(cls: ClassSymbol): Type = tp.baseType(cls).mapReduceOr(identity)(mergeRefinedOrApplied) diff --git a/tests/pos/i16474.scala b/tests/pos/i16474.scala new file mode 100644 index 000000000000..834b22c7691f --- /dev/null +++ b/tests/pos/i16474.scala @@ -0,0 +1,13 @@ +object o: + + private[o] trait A + trait B + class C extends A, B + class D extends A, B + +def test = + def f[T](x: T): T => T = identity + val g = f(if ??? then o.C() else o.D()) + g(new o.B{}) + + diff --git a/tests/run/i16474/BaseProvider.java b/tests/run/i16474/BaseProvider.java new file mode 100644 index 000000000000..29346bcf7730 --- /dev/null +++ b/tests/run/i16474/BaseProvider.java @@ -0,0 +1,6 @@ +// BaseProvider.java +package repro.impl; + +import repro.*; +abstract class BaseProvider{} + diff --git a/tests/run/i16474/Case1.java b/tests/run/i16474/Case1.java new file mode 100644 index 000000000000..9d05a2abb6d6 --- /dev/null +++ b/tests/run/i16474/Case1.java @@ -0,0 +1,9 @@ +// Case1.java +package repro; + +import repro.impl.*; + +public class Case1 extends Case1Provider implements Encrypter { + public Case1(){} +} + diff --git a/tests/run/i16474/Case1Provider.java b/tests/run/i16474/Case1Provider.java new file mode 100644 index 000000000000..0b6c63d3bb3d --- /dev/null +++ b/tests/run/i16474/Case1Provider.java @@ -0,0 +1,5 @@ +// Case1Provider.java +package repro.impl; + +public abstract class Case1Provider extends BaseProvider {} + diff --git a/tests/run/i16474/Case2.java b/tests/run/i16474/Case2.java new file mode 100644 index 000000000000..37804d3b84eb --- /dev/null +++ b/tests/run/i16474/Case2.java @@ -0,0 +1,8 @@ +// Case2.java +package repro; + +import repro.impl.*; + +public class Case2 extends Case2Provider implements Encrypter { + public Case2(){} +} diff --git a/tests/run/i16474/Case2Provider.java b/tests/run/i16474/Case2Provider.java new file mode 100644 index 000000000000..e860964e59c3 --- /dev/null +++ b/tests/run/i16474/Case2Provider.java @@ -0,0 +1,5 @@ +// Case2Provider.java +package repro.impl; + +public abstract class Case2Provider extends BaseProvider {} + diff --git a/tests/run/i16474/Encrypter.java b/tests/run/i16474/Encrypter.java new file mode 100644 index 000000000000..ec721d27af9d --- /dev/null +++ b/tests/run/i16474/Encrypter.java @@ -0,0 +1,4 @@ +// Encrypter.java +package repro; +public interface Encrypter{} + diff --git a/tests/run/i16474/test.scala b/tests/run/i16474/test.scala new file mode 100644 index 000000000000..2dc2900dd2a8 --- /dev/null +++ b/tests/run/i16474/test.scala @@ -0,0 +1,15 @@ +// scalajs: --skip +// test.scala +import repro.* +import scala.util.Try + +def get(arg: Any): Try[Encrypter] = Try { + val x: Any = 1 + arg match + case 1 => new Case1() + case 2 => new Case2() + case _ => throw new RuntimeException(s"Unsupported got $arg") +} + +@main def Test = + val result = get(null)