Skip to content

Commit b5941e4

Browse files
authored
Skip caching provisional OrType atoms (#16295)
Also, fix printing TypeVars when not using -Yprint-debug so that it doesn't add redudant and misleading parentheses, which can lead to the perception that a tuple was inferred.
2 parents b3f870f + 7546867 commit b5941e4

File tree

5 files changed

+26
-19
lines changed

5 files changed

+26
-19
lines changed

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

+16-12
Original file line numberDiff line numberDiff line change
@@ -3413,25 +3413,29 @@ object Types {
34133413
private var myAtoms: Atoms = _
34143414
private var myWidened: Type = _
34153415

3416+
private def computeAtoms()(using Context): Atoms =
3417+
if tp1.hasClassSymbol(defn.NothingClass) then tp2.atoms
3418+
else if tp2.hasClassSymbol(defn.NothingClass) then tp1.atoms
3419+
else tp1.atoms | tp2.atoms
3420+
3421+
private def computeWidenSingletons()(using Context): Type =
3422+
val tp1w = tp1.widenSingletons
3423+
val tp2w = tp2.widenSingletons
3424+
if ((tp1 eq tp1w) && (tp2 eq tp2w)) this else TypeComparer.lub(tp1w, tp2w, isSoft = isSoft)
3425+
34163426
private def ensureAtomsComputed()(using Context): Unit =
3417-
if atomsRunId != ctx.runId then
3418-
myAtoms =
3419-
if tp1.hasClassSymbol(defn.NothingClass) then tp2.atoms
3420-
else if tp2.hasClassSymbol(defn.NothingClass) then tp1.atoms
3421-
else tp1.atoms | tp2.atoms
3422-
val tp1w = tp1.widenSingletons
3423-
val tp2w = tp2.widenSingletons
3424-
myWidened = if ((tp1 eq tp1w) && (tp2 eq tp2w)) this else TypeComparer.lub(tp1w, tp2w, isSoft = isSoft)
3427+
if atomsRunId != ctx.runId && !isProvisional then
3428+
myAtoms = computeAtoms()
3429+
myWidened = computeWidenSingletons()
34253430
atomsRunId = ctx.runId
34263431

34273432
override def atoms(using Context): Atoms =
34283433
ensureAtomsComputed()
3429-
myAtoms
3434+
if isProvisional then computeAtoms() else myAtoms
34303435

3431-
override def widenSingletons(using Context): Type = {
3436+
override def widenSingletons(using Context): Type =
34323437
ensureAtomsComputed()
3433-
myWidened
3434-
}
3438+
if isProvisional then computeWidenSingletons() else myWidened
34353439

34363440
def derivedOrType(tp1: Type, tp2: Type, soft: Boolean = isSoft)(using Context): Type =
34373441
if ((tp1 eq this.tp1) && (tp2 eq this.tp2) && soft == isSoft) this

compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala

+3-2
Original file line numberDiff line numberDiff line change
@@ -258,16 +258,17 @@ class PlainPrinter(_ctx: Context) extends Printer {
258258
if annot.symbol == defn.InlineParamAnnot || annot.symbol == defn.ErasedParamAnnot then toText(tpe)
259259
else toTextLocal(tpe) ~ " " ~ toText(annot)
260260
case tp: TypeVar =>
261+
def toTextCaret(tp: Type) = if printDebug then toTextLocal(tp) ~ Str("^") else toText(tp)
261262
if (tp.isInstantiated)
262-
toTextLocal(tp.instanceOpt) ~ (Str("^") provided printDebug)
263+
toTextCaret(tp.instanceOpt)
263264
else {
264265
val constr = ctx.typerState.constraint
265266
val bounds =
266267
if constr.contains(tp) then
267268
withMode(Mode.Printing)(TypeComparer.fullBounds(tp.origin))
268269
else
269270
TypeBounds.empty
270-
if (bounds.isTypeAlias) toText(bounds.lo) ~ (Str("^") provided printDebug)
271+
if (bounds.isTypeAlias) toTextCaret(bounds.lo)
271272
else if (ctx.settings.YshowVarBounds.value) "(" ~ toText(tp.origin) ~ "?" ~ toText(bounds) ~ ")"
272273
else toText(tp.origin)
273274
}

compiler/src/dotty/tools/dotc/printing/Printer.scala

+2-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ abstract class Printer {
3131
* ### `atPrec` vs `changePrec`
3232
*
3333
* This is to be used when changing precedence inside some sort of parentheses:
34-
* for instance, to print T[A]` use
34+
* for instance, to print `T[A]` use
3535
* `toText(T) ~ '[' ~ atPrec(GlobalPrec) { toText(A) } ~ ']'`.
3636
*
3737
* If the presence of the parentheses depends on precedence, inserting them manually is most certainly a bug.
@@ -60,8 +60,7 @@ abstract class Printer {
6060
* A op B op' C parses as (A op B) op' C if op and op' are left-associative, and as
6161
* A op (B op' C) if they're right-associative, so we need respectively
6262
* ```scala
63-
* val isType = ??? // is this a term or type operator?
64-
* val prec = parsing.precedence(op, isType)
63+
* val prec = parsing.precedence(op)
6564
* // either:
6665
* changePrec(prec) { toText(a) ~ op ~ atPrec(prec + 1) { toText(b) } } // for left-associative op and op'
6766
* // or:

tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.check

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
-- [E170] Type Error: tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.scala:16:61 ----------------------------
1010
16 | val c = js.constructorTag[NativeJSClass with NativeJSTrait] // error
1111
| ^
12-
| (NativeJSClass & NativeJSTrait) is not a class type
12+
| NativeJSClass & NativeJSTrait is not a class type
1313
-- [E170] Type Error: tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.scala:17:59 ----------------------------
1414
17 | val d = js.constructorTag[NativeJSClass { def bar: Int }] // error
1515
| ^
@@ -25,7 +25,7 @@
2525
-- [E170] Type Error: tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.scala:22:49 ----------------------------
2626
22 | val g = js.constructorTag[JSClass with JSTrait] // error
2727
| ^
28-
| (JSClass & JSTrait) is not a class type
28+
| JSClass & JSTrait is not a class type
2929
-- [E170] Type Error: tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.scala:23:53 ----------------------------
3030
23 | val h = js.constructorTag[JSClass { def bar: Int }] // error
3131
| ^

tests/pos/i15813.scala

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
class Box[T]
2+
def dep1[T1 <: Singleton, T2 <: T1](t1: T1)(t2: T2): Box[T1] = ???
3+
val d1 = dep1(1)(2)

0 commit comments

Comments
 (0)