From 7546867b97cc3a52e9e57224b13f85a8a6bc610d Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 7 Nov 2022 15:33:31 +0000 Subject: [PATCH] Skip caching provisional OrType atoms 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. --- .../src/dotty/tools/dotc/core/Types.scala | 28 +++++++++++-------- .../tools/dotc/printing/PlainPrinter.scala | 5 ++-- .../dotty/tools/dotc/printing/Printer.scala | 5 ++-- ...onstructortag-error-in-prepjsinterop.check | 4 +-- tests/pos/i15813.scala | 3 ++ 5 files changed, 26 insertions(+), 19 deletions(-) create mode 100644 tests/pos/i15813.scala diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 61a8760e6c93..c4f4c4a63015 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -3423,25 +3423,29 @@ object Types { private var myAtoms: Atoms = _ private var myWidened: Type = _ + private def computeAtoms()(using Context): Atoms = + if tp1.hasClassSymbol(defn.NothingClass) then tp2.atoms + else if tp2.hasClassSymbol(defn.NothingClass) then tp1.atoms + else tp1.atoms | tp2.atoms + + private def computeWidenSingletons()(using Context): Type = + val tp1w = tp1.widenSingletons + val tp2w = tp2.widenSingletons + if ((tp1 eq tp1w) && (tp2 eq tp2w)) this else TypeComparer.lub(tp1w, tp2w, isSoft = isSoft) + private def ensureAtomsComputed()(using Context): Unit = - if atomsRunId != ctx.runId then - myAtoms = - if tp1.hasClassSymbol(defn.NothingClass) then tp2.atoms - else if tp2.hasClassSymbol(defn.NothingClass) then tp1.atoms - else tp1.atoms | tp2.atoms - val tp1w = tp1.widenSingletons - val tp2w = tp2.widenSingletons - myWidened = if ((tp1 eq tp1w) && (tp2 eq tp2w)) this else TypeComparer.lub(tp1w, tp2w, isSoft = isSoft) + if atomsRunId != ctx.runId && !isProvisional then + myAtoms = computeAtoms() + myWidened = computeWidenSingletons() atomsRunId = ctx.runId override def atoms(using Context): Atoms = ensureAtomsComputed() - myAtoms + if isProvisional then computeAtoms() else myAtoms - override def widenSingletons(using Context): Type = { + override def widenSingletons(using Context): Type = ensureAtomsComputed() - myWidened - } + if isProvisional then computeWidenSingletons() else myWidened def derivedOrType(tp1: Type, tp2: Type, soft: Boolean = isSoft)(using Context): Type = if ((tp1 eq this.tp1) && (tp2 eq this.tp2) && soft == isSoft) this diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 6c4891ff2b18..56bb71e696d6 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -258,8 +258,9 @@ class PlainPrinter(_ctx: Context) extends Printer { if annot.symbol == defn.InlineParamAnnot || annot.symbol == defn.ErasedParamAnnot then toText(tpe) else toTextLocal(tpe) ~ " " ~ toText(annot) case tp: TypeVar => + def toTextCaret(tp: Type) = if printDebug then toTextLocal(tp) ~ Str("^") else toText(tp) if (tp.isInstantiated) - toTextLocal(tp.instanceOpt) ~ (Str("^") provided printDebug) + toTextCaret(tp.instanceOpt) else { val constr = ctx.typerState.constraint val bounds = @@ -267,7 +268,7 @@ class PlainPrinter(_ctx: Context) extends Printer { withMode(Mode.Printing)(TypeComparer.fullBounds(tp.origin)) else TypeBounds.empty - if (bounds.isTypeAlias) toText(bounds.lo) ~ (Str("^") provided printDebug) + if (bounds.isTypeAlias) toTextCaret(bounds.lo) else if (ctx.settings.YshowVarBounds.value) "(" ~ toText(tp.origin) ~ "?" ~ toText(bounds) ~ ")" else toText(tp.origin) } diff --git a/compiler/src/dotty/tools/dotc/printing/Printer.scala b/compiler/src/dotty/tools/dotc/printing/Printer.scala index f06c70f56905..6eae008a0e90 100644 --- a/compiler/src/dotty/tools/dotc/printing/Printer.scala +++ b/compiler/src/dotty/tools/dotc/printing/Printer.scala @@ -31,7 +31,7 @@ abstract class Printer { * ### `atPrec` vs `changePrec` * * This is to be used when changing precedence inside some sort of parentheses: - * for instance, to print T[A]` use + * for instance, to print `T[A]` use * `toText(T) ~ '[' ~ atPrec(GlobalPrec) { toText(A) } ~ ']'`. * * If the presence of the parentheses depends on precedence, inserting them manually is most certainly a bug. @@ -60,8 +60,7 @@ abstract class Printer { * A op B op' C parses as (A op B) op' C if op and op' are left-associative, and as * A op (B op' C) if they're right-associative, so we need respectively * ```scala - * val isType = ??? // is this a term or type operator? - * val prec = parsing.precedence(op, isType) + * val prec = parsing.precedence(op) * // either: * changePrec(prec) { toText(a) ~ op ~ atPrec(prec + 1) { toText(b) } } // for left-associative op and op' * // or: diff --git a/tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.check b/tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.check index c4ce18b2e57c..e1f5a038f2c1 100644 --- a/tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.check +++ b/tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.check @@ -9,7 +9,7 @@ -- [E170] Type Error: tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.scala:16:61 ---------------------------- 16 | val c = js.constructorTag[NativeJSClass with NativeJSTrait] // error | ^ - | (NativeJSClass & NativeJSTrait) is not a class type + | NativeJSClass & NativeJSTrait is not a class type -- [E170] Type Error: tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.scala:17:59 ---------------------------- 17 | val d = js.constructorTag[NativeJSClass { def bar: Int }] // error | ^ @@ -25,7 +25,7 @@ -- [E170] Type Error: tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.scala:22:49 ---------------------------- 22 | val g = js.constructorTag[JSClass with JSTrait] // error | ^ - | (JSClass & JSTrait) is not a class type + | JSClass & JSTrait is not a class type -- [E170] Type Error: tests/neg-scalajs/jsconstructortag-error-in-prepjsinterop.scala:23:53 ---------------------------- 23 | val h = js.constructorTag[JSClass { def bar: Int }] // error | ^ diff --git a/tests/pos/i15813.scala b/tests/pos/i15813.scala new file mode 100644 index 000000000000..9fd63dce7a9e --- /dev/null +++ b/tests/pos/i15813.scala @@ -0,0 +1,3 @@ +class Box[T] +def dep1[T1 <: Singleton, T2 <: T1](t1: T1)(t2: T2): Box[T1] = ??? +val d1 = dep1(1)(2)