Skip to content

Commit 1c8cfa4

Browse files
committed
Always widen or-types when inferring types
The idea is that or-types should never be inferred, so we widen them - when instantiating type variables - when computing the type of valdef or defdefs from the rhs. This is already done in harmonizeUnion. However, harmonizeUnion had the restrictions that it joined or-types only in Scala2 mode. This restriction is now dropped.
1 parent 54dd50c commit 1c8cfa4

File tree

10 files changed

+40
-20
lines changed

10 files changed

+40
-20
lines changed

compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ trait ConstraintHandling {
271271
// 2. If instance is from below and is a fully-defined union type, yet upper bound
272272
// is not a union type, approximate the union type from above by an intersection
273273
// of all common base types.
274-
if (fromBelow && isOrType(inst) && isFullyDefined(inst) && !isOrType(upperBound))
274+
if (fromBelow && isOrType(inst) && /*isFullyDefined(inst) &&*/ !isOrType(upperBound))
275275
inst = ctx.harmonizeUnion(inst)
276276

277277
inst

compiler/src/dotty/tools/dotc/core/TypeOps.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
300300

301301
/** Under -language:Scala2: Replace or-types with their joins */
302302
private def joinIfScala2(tp: Type) = tp match {
303-
case tp: OrType if scala2Mode => tp.join
303+
case tp: OrType => tp.join
304304
case _ => tp
305305
}
306306

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -830,23 +830,23 @@ object Types {
830830
* def o: Outer
831831
* <o.x.type>.widen = o.C
832832
*/
833-
@tailrec final def widen(implicit ctx: Context): Type = widenSingleton match {
833+
final def widen(implicit ctx: Context): Type = widenSingleton match {
834834
case tp: ExprType => tp.resultType.widen
835835
case tp => tp
836836
}
837837

838838
/** Widen from singleton type to its underlying non-singleton
839839
* base type by applying one or more `underlying` dereferences.
840840
*/
841-
@tailrec final def widenSingleton(implicit ctx: Context): Type = stripTypeVar match {
841+
final def widenSingleton(implicit ctx: Context): Type = stripTypeVar match {
842842
case tp: SingletonType if !tp.isOverloaded => tp.underlying.widenSingleton
843843
case _ => this
844844
}
845845

846846
/** Widen from TermRef to its underlying non-termref
847847
* base type, while also skipping Expr types.
848848
*/
849-
@tailrec final def widenTermRefExpr(implicit ctx: Context): Type = stripTypeVar match {
849+
final def widenTermRefExpr(implicit ctx: Context): Type = stripTypeVar match {
850850
case tp: TermRef if !tp.isOverloaded => tp.underlying.widenExpr.widenTermRefExpr
851851
case _ => this
852852
}
@@ -860,7 +860,7 @@ object Types {
860860
}
861861

862862
/** Widen type if it is unstable (i.e. an ExprType, or TermRef to unstable symbol */
863-
@tailrec final def widenIfUnstable(implicit ctx: Context): Type = stripTypeVar match {
863+
final def widenIfUnstable(implicit ctx: Context): Type = stripTypeVar match {
864864
case tp: ExprType => tp.resultType.widenIfUnstable
865865
case tp: TermRef if !tp.symbol.isStable => tp.underlying.widenIfUnstable
866866
case _ => this

compiler/test/dotc/tests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ class tests extends CompilerTest {
167167
@Test def rewrites = compileFile(posScala2Dir, "rewrites", "-rewrite" :: scala2mode)
168168

169169
@Test def pos_t8146a = compileFile(posSpecialDir, "t8146a")(allowDeepSubtypes)
170+
@Test def pos_jon = compileFile(posSpecialDir, "jon")(allowDeepSubtypes)
170171

171172
@Test def pos_t5545 = {
172173
// compile by hand in two batches, since junit lacks the infrastructure to

tests/neg/union.scala

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
object Test {
2+
3+
class A
4+
class B extends A
5+
class C extends A
6+
class D extends A
7+
8+
val b = true
9+
val x = if (b) new B else new C
10+
val y: B | C = x // error
11+
}
12+
13+
object O {
14+
class A
15+
class B
16+
def f[T](x: T, y: T): T = x
17+
18+
val x: A = f(new A { }, new A)
19+
20+
val y1: A | B = f(new A { }, new B) // error
21+
val y2: A | B = f[A | B](new A { }, new B) // ok
22+
23+
val z = if (???) new A{} else new B
24+
25+
val z1: A | B = z // error
26+
27+
val z2: A | B = if (???) new A else new B // ok
28+
}
File renamed without changes.

tests/pos/anonClassSubtyping.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ object O {
55

66
val x: A = f(new A { }, new A)
77

8-
val y: A | B = f(new A { }, new B)
8+
val z: A | B = if (???) new A{} else new A
99
}

tests/pos/constraining-lub.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ object Test {
1717

1818
val x: Inv[Int] = inv(true)
1919

20-
def inv2(cond: Boolean) =
20+
def inv2(cond: Boolean): Inv[Int] | Inv2[Int] =
2121
if (cond) {
2222
if (cond)
2323
new Inv(1)

tests/pos/intersection.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ object intersection {
99
val z = if (???) x else y
1010

1111
val a: A & B => Unit = z
12-
val b: (A => Unit) | (B => Unit) = z
12+
//val b: (A => Unit) | (B => Unit) = z // error under new or-type rules
13+
14+
val c: (A => Unit) | (B => Unit) = if (???) x else y // ok
1315

1416
type needsA = A => Nothing
1517
type needsB = B => Nothing

tests/pos/union.scala

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)