From 1975856c9350cf56e88b392e2d74b6dfd13601a7 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 7 Mar 2021 20:04:04 +0100 Subject: [PATCH 1/7] Merge -explain-types behavior into -explain behavior Eliminate -explain-types option. Error messages that can show subtype traces now do so under the -explain mechanism. --- .../tools/dotc/config/ScalaSettings.scala | 1 - .../dotty/tools/dotc/core/Constraint.scala | 3 ++ .../tools/dotc/core/OrderingConstraint.scala | 22 +++++---- .../dotty/tools/dotc/core/TypeComparer.scala | 41 ++++++++--------- .../dotc/reporting/ConsoleReporter.scala | 2 +- .../tools/dotc/reporting/Diagnostic.scala | 2 +- .../tools/dotc/reporting/ErrorMessageID.scala | 4 +- .../dotty/tools/dotc/reporting/Message.scala | 28 +++++++---- .../dotty/tools/dotc/reporting/messages.scala | 46 ++++++++----------- .../tools/dotc/typer/ErrorReporting.scala | 27 +++++++---- .../dotty/tools/dotc/typer/RefChecks.scala | 25 +++++----- 11 files changed, 111 insertions(+), 90 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 19e5a4cea229..0ae53a46ff82 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -103,7 +103,6 @@ class ScalaSettings extends Settings.SettingGroup with CommonScalaSettings { val semanticdbTarget: Setting[String] = PathSetting("-semanticdb-target", "Specify an alternative output directory for SemanticDB files.", "") val deprecation: Setting[Boolean] = BooleanSetting("-deprecation", "Emit warning and location for usages of deprecated APIs.", aliases = List("--deprecation")) - val explainTypes: Setting[Boolean] = BooleanSetting("-explain-types", "Explain type errors in more detail.", aliases = List("--explain-types")) val explain: Setting[Boolean] = BooleanSetting("-explain", "Explain errors in more detail.", aliases = List("--explain")) val feature: Setting[Boolean] = BooleanSetting("-feature", "Emit warning and location for usages of features that should be imported explicitly.", aliases = List("--feature")) val release: Setting[String] = ChoiceSetting("-release", "release", "Compile code with classes specific to the given version of the Java platform available on the classpath and emit bytecode for this version.", supportedReleaseVersions, "", aliases = List("--release")) diff --git a/compiler/src/dotty/tools/dotc/core/Constraint.scala b/compiler/src/dotty/tools/dotc/core/Constraint.scala index e3ed4ea53f8c..81c108bc1241 100644 --- a/compiler/src/dotty/tools/dotc/core/Constraint.scala +++ b/compiler/src/dotty/tools/dotc/core/Constraint.scala @@ -168,4 +168,7 @@ abstract class Constraint extends Showable { /** Check that constraint only refers to TypeParamRefs bound by itself */ def checkClosed()(using Context): Unit + + /** A string describing the constraint's contents without a header or trailer */ + def contentsToString(using Context): String } diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala index baa5a791eb95..3fb2497ba65d 100644 --- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -648,7 +648,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, // ---------- toText ----------------------------------------------------- - override def toText(printer: Printer): Text = { + private def contentsToText(printer: Printer): Text = //Printer.debugPrintUnique = true def entryText(tp: Type) = tp match { case tp: TypeBounds => @@ -657,20 +657,19 @@ class OrderingConstraint(private val boundsMap: ParamBounds, " := " ~ tp.toText(printer) } val indent = 3 - val header: Text = "Constraint(" - val uninstVarsText = " uninstVars = " ~ - Text(uninstVars map (_.toText(printer)), ", ") ~ ";" + val uninstVarsText = " uninstantiated variables: " ~ + Text(uninstVars.map(_.toText(printer)), ", ") val constrainedText = - " constrained types = " ~ Text(domainLambdas map (_.toText(printer)), ", ") + " constrained types: " ~ Text(domainLambdas map (_.toText(printer)), ", ") val boundsText = - " bounds = " ~ { + " bounds: " ~ { val assocs = for (param <- domainParams) yield (" " * indent) ~ param.toText(printer) ~ entryText(entry(param)) Text(assocs, "\n") } val orderingText = - " ordering = " ~ { + " ordering: " ~ { val deps = for { param <- domainParams @@ -683,8 +682,13 @@ class OrderingConstraint(private val boundsMap: ParamBounds, Text(deps, "\n") } //Printer.debugPrintUnique = false - Text.lines(List(header, uninstVarsText, constrainedText, boundsText, orderingText, ")")) - } + Text.lines(List(uninstVarsText, constrainedText, boundsText, orderingText)) + + override def toText(printer: Printer): Text = + Text.lines(List("Constraint(", contentsToText(printer), ")")) + + def contentsToString(using Context): String = + contentsToText(ctx.printer).show override def toString: String = { def entryText(tp: Type): String = tp match { diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index c1b74a59bcbc..86c964e7d7b8 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -206,7 +206,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling * code would have two extra parameters for each of the many calls that go from * one sub-part of isSubType to another. */ - protected def recur(tp1: Type, tp2: Type): Boolean = trace(s"isSubType ${traceInfo(tp1, tp2)} ${approx.show}", subtyping) { + protected def recur(tp1: Type, tp2: Type): Boolean = trace(s"isSubType ${traceInfo(tp1, tp2)}${approx.show}", subtyping) { def monitoredIsSubType = { if (pendingSubTypes == null) { @@ -2276,13 +2276,6 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling NoType } - /** Show type, handling type types better than the default */ - private def showType(tp: Type)(using Context) = tp match { - case ClassInfo(_, cls, _, _, _) => cls.showLocated - case bounds: TypeBounds => "type bounds" + bounds.show - case _ => tp.show - } - /** A comparison function to pick a winner in case of a merge conflict */ private def isAsGood(tp1: Type, tp2: Type): Boolean = tp1 match { case tp1: ClassInfo => @@ -2546,10 +2539,10 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling finally myInstance = saved /** The trace of comparison operations when performing `op` */ - def explained[T](op: ExplainingTypeComparer => T)(using Context): String = + def explained[T](op: ExplainingTypeComparer => T, header: String = "Subtype trace:")(using Context): String = val cmp = explainingTypeComparer inSubComparer(cmp)(op) - cmp.lastTrace() + cmp.lastTrace(header) def tracked[T](op: TrackingTypeComparer => T)(using Context): T = inSubComparer(trackingTypeComparer)(op) @@ -2565,10 +2558,13 @@ object TypeComparer { var tpe: Type = NoType } - private[core] def show(res: Any)(using Context): String = res match { - case res: printing.Showable if !ctx.settings.YexplainLowlevel.value => res.show - case _ => String.valueOf(res) - } + private[core] def show(res: Any)(using Context): String = + if ctx.settings.YexplainLowlevel.value then String.valueOf(res) + else res match + case ClassInfo(_, cls, _, _, _) => cls.showLocated + case bounds: TypeBounds => i"type bounds [$bounds]" + case res: printing.Showable => res.show + case _ => String.valueOf(res) /** The approximation state indicates how the pair of types currently compared * relates to the types compared originally. @@ -2595,8 +2591,8 @@ object TypeComparer { def addLow: Repr = approx | LoApprox def addHigh: Repr = approx | HiApprox def show: String = - val lo = if low then "LoApprox" else "" - val hi = if high then "HiApprox" else "" + val lo = if low then " (left is tightened)" else "" + val hi = if high then " (right is tigthened)" else "" lo ++ hi end ApproxState type ApproxState = ApproxState.Repr @@ -2698,8 +2694,8 @@ object TypeComparer { def constrainPatternType(pat: Type, scrut: Type)(using Context): Boolean = comparing(_.constrainPatternType(pat, scrut)) - def explained[T](op: ExplainingTypeComparer => T)(using Context): String = - comparing(_.explained(op)) + def explained[T](op: ExplainingTypeComparer => T, header: String = "Subtype trace:")(using Context): String = + comparing(_.explained(op, header)) def tracked[T](op: TrackingTypeComparer => T)(using Context): T = comparing(_.tracked(op)) @@ -2848,17 +2844,20 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) { res } + private def frozenNotice: String = + if frozenConstraint then " in frozen constraint" else "" + override def isSubType(tp1: Type, tp2: Type, approx: ApproxState): Boolean = def moreInfo = if Config.verboseExplainSubtype || ctx.settings.verbose.value then s" ${tp1.getClass} ${tp2.getClass}" else "" - traceIndented(s"${show(tp1)} <:< ${show(tp2)}$moreInfo ${approx.show} ${if (frozenConstraint) " frozen" else ""}") { + traceIndented(s"${show(tp1)} <: ${show(tp2)}$moreInfo${approx.show}$frozenNotice") { super.isSubType(tp1, tp2, approx) } override def recur(tp1: Type, tp2: Type): Boolean = - traceIndented(s"${show(tp1)} <:< ${show(tp2)} recur ${if (frozenConstraint) " frozen" else ""}") { + traceIndented(s"${show(tp1)} <: ${show(tp2)} (recurring)$frozenNotice") { super.recur(tp1, tp2) } @@ -2882,5 +2881,5 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) { super.addConstraint(param, bound, fromBelow) } - def lastTrace(): String = "Subtype trace:" + { try b.toString finally b.clear() } + def lastTrace(header: String): String = header + { try b.toString finally b.clear() } } diff --git a/compiler/src/dotty/tools/dotc/reporting/ConsoleReporter.scala b/compiler/src/dotty/tools/dotc/reporting/ConsoleReporter.scala index 8d74e06b7d49..c3d6d042e379 100644 --- a/compiler/src/dotty/tools/dotc/reporting/ConsoleReporter.scala +++ b/compiler/src/dotty/tools/dotc/reporting/ConsoleReporter.scala @@ -35,7 +35,7 @@ class ConsoleReporter( if (didPrint && shouldExplain(dia)) printMessage(explanation(dia.msg)) - else if (didPrint && dia.msg.explanation.nonEmpty) + else if (didPrint && dia.msg.canExplain) printMessage("\nlonger explanation available when compiling with `-explain`") } diff --git a/compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala b/compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala index f31b0af14c5f..49c71ca33a81 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala @@ -12,7 +12,7 @@ import java.util.Optional object Diagnostic: def shouldExplain(dia: Diagnostic)(using Context): Boolean = - dia.msg.explanation.nonEmpty && ctx.settings.explain.value + ctx.settings.explain.value && dia.msg.canExplain // `Diagnostics to be consumed by `Reporter` ---------------------- // class Error( diff --git a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala index c4839a4c3550..2fba7ef447b5 100644 --- a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala +++ b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala @@ -170,7 +170,9 @@ enum ErrorMessageID extends java.lang.Enum[ErrorMessageID] { TraitMayNotDefineNativeMethodID, JavaEnumParentArgsID, AlreadyDefinedID, - CaseClassInInlinedCodeID + CaseClassInInlinedCodeID, + OverrideTypeMismatchErrorID, + OverrideErrorID def errorNumber = ordinal - 2 } diff --git a/compiler/src/dotty/tools/dotc/reporting/Message.scala b/compiler/src/dotty/tools/dotc/reporting/Message.scala index be711d060d47..03dc0426c582 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Message.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Message.scala @@ -58,6 +58,13 @@ abstract class Message(val errorId: ErrorMessageID) { self => */ protected def explain: String + /** Does this message have an explanation? + * This is normally the same as `explain.nonEmpty` but can be overridden + * if we need a way to return `true` without actually calling the + * `explain` method. + */ + def canExplain: Boolean = explain.nonEmpty + private var myMsg: String | Null = null private var myIsNonSensical: Boolean = false @@ -95,22 +102,25 @@ abstract class Message(val errorId: ErrorMessageID) { self => * that was captured in the original message. */ def persist: Message = new Message(errorId) { - val kind = self.kind - val msg = self.msg - val explain = self.explain + val kind = self.kind + val msg = self.msg + val explain = self.explain + override val canExplain = self.canExplain } def append(suffix: => String): Message = mapMsg(_ ++ suffix) def mapMsg(f: String => String): Message = new Message(errorId): - val kind = self.kind - def msg = f(self.msg) - def explain = self.explain + val kind = self.kind + def msg = f(self.msg) + def explain = self.explain + override def canExplain = self.canExplain def appendExplanation(suffix: => String): Message = new Message(errorId): - val kind = self.kind - def msg = self.msg - def explain = self.explain ++ suffix + val kind = self.kind + def msg = self.msg + def explain = self.explain ++ suffix + override def canExplain = true override def toString = msg } diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index eed9490ee3c1..346baa9405d2 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -44,8 +44,10 @@ import transform.SymUtils._ abstract class TypeMsg(errorId: ErrorMessageID) extends Message(errorId): def kind = "Type" - abstract class TypeMismatchMsg(errorId: ErrorMessageID) extends Message(errorId): + abstract class TypeMismatchMsg(found: Type, expected: Type)(errorId: ErrorMessageID)(using Context) extends Message(errorId): def kind = "Type Mismatch" + def explain = err.whyNoMatchStr(found, expected) + override def canExplain = true abstract class NamingMsg(errorId: ErrorMessageID) extends Message(errorId): def kind = "Naming" @@ -236,7 +238,7 @@ import transform.SymUtils._ } class TypeMismatch(found: Type, expected: Type, addenda: => String*)(using Context) - extends TypeMismatchMsg(TypeMismatchID): + extends TypeMismatchMsg(found, expected)(TypeMismatchID): // replace constrained TypeParamRefs and their typevars by their bounds where possible // the idea is that if the bounds are also not-subtypes of each other to report @@ -274,9 +276,7 @@ import transform.SymUtils._ val (foundStr, expectedStr) = Formatting.typeDiff(found2, expected2)(using printCtx) s"""|Found: $foundStr |Required: $expectedStr""".stripMargin - + whereSuffix + err.whyNoMatchStr(found, expected) + postScript - - def explain = "" + + whereSuffix + postScript end TypeMismatch class NotAMember(site: Type, val name: Name, selected: String, addendum: => String = "")(using Context) @@ -1074,6 +1074,14 @@ import transform.SymUtils._ |""" } + class OverrideError(override val msg: String) extends DeclarationMsg(OverrideErrorID): + def explain = "" + + class OverrideTypeMismatchError(override val msg: String, memberTp: Type, otherTp: Type)(using Context) + extends DeclarationMsg(OverrideTypeMismatchErrorID): + def explain = err.whyNoMatchStr(memberTp, otherTp) + override def canExplain = true + class ForwardReferenceExtendsOverDefinition(value: Symbol, definition: Symbol)(using Context) extends ReferenceMsg(ForwardReferenceExtendsOverDefinitionID) { def msg = em"${definition.name} is a forward reference extending over the definition of ${value.name}" @@ -1324,7 +1332,7 @@ import transform.SymUtils._ if (isNullary) "\nNullary methods may not be called with parenthesis" else "" - "You have specified more parameter lists as defined in the method definition(s)." + addendum + "You have specified more parameter lists than defined in the method definition(s)." + addendum } } @@ -1414,36 +1422,22 @@ import transform.SymUtils._ } class DoesNotConformToBound(tpe: Type, which: String, bound: Type)(using Context) - extends TypeMismatchMsg(DoesNotConformToBoundID) { - def msg = em"Type argument ${tpe} does not conform to $which bound $bound${err.whyNoMatchStr(tpe, bound)}" - def explain = "" + extends TypeMismatchMsg(tpe, bound)(DoesNotConformToBoundID) { + def msg = em"Type argument ${tpe} does not conform to $which bound $bound" } class DoesNotConformToSelfType(category: String, selfType: Type, cls: Symbol, - otherSelf: Type, relation: String, other: Symbol)( + otherSelf: Type, relation: String, other: Symbol)( implicit ctx: Context) - extends TypeMismatchMsg(DoesNotConformToSelfTypeID) { + extends TypeMismatchMsg(selfType, otherSelf)(DoesNotConformToSelfTypeID) { def msg = em"""$category: self type $selfType of $cls does not conform to self type $otherSelf |of $relation $other""" - def explain = - em"""You mixed in $other which requires self type $otherSelf, but $cls has self type - |$selfType and does not inherit from $otherSelf. - | - |Note: Self types are indicated with the notation - | ${s"class "}$other ${hl("{ this: ")}$otherSelf${hl(" => ")} - """ } class DoesNotConformToSelfTypeCantBeInstantiated(tp: Type, selfType: Type)( implicit ctx: Context) - extends TypeMismatchMsg(DoesNotConformToSelfTypeCantBeInstantiatedID) { + extends TypeMismatchMsg(tp, selfType)(DoesNotConformToSelfTypeCantBeInstantiatedID) { def msg = em"""$tp does not conform to its self type $selfType; cannot be instantiated""" - def explain = - em"""To create an instance of $tp it needs to inherit $selfType in some way. - | - |Note: Self types are indicated with the notation - | ${s"class "}$tp ${hl("{ this: ")}$selfType${hl(" => ")} - |""" } class AbstractMemberMayNotHaveModifier(sym: Symbol, flag: FlagSet)( @@ -2207,7 +2201,7 @@ import transform.SymUtils._ } class NoMatchingOverload(val alternatives: List[SingleDenotation], pt: Type)(using Context) - extends TypeMismatchMsg(NoMatchingOverloadID) { + extends TypeMsg(NoMatchingOverloadID) { def msg = em"""None of the ${err.overloadedAltsStr(alternatives)} |match ${err.expectedTypeStr(pt)}""" diff --git a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala index ffac54960578..48baa1e00a64 100644 --- a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala +++ b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala @@ -117,14 +117,25 @@ object ErrorReporting { } /** A subtype log explaining why `found` does not conform to `expected` */ - def whyNoMatchStr(found: Type, expected: Type): String = { - if (ctx.settings.explainTypes.value) - i""" - |${ctx.typerState.constraint} - |${TypeComparer.explained(_.isSubType(found, expected))}""" - else - "" - } + def whyNoMatchStr(found: Type, expected: Type): String = + val header = + i"""I tried to show that + | $found + |conforms to + | $expected + |but the comparison trace ended with `false`: + """ + val c = ctx.typerState.constraint + val constraintText = + if c.domainLambdas.isEmpty then + "empty constraint" + else + i"""following constraint: + |${c.contentsToString}""" + i""" + |${TypeComparer.explained(_.isSubType(found, expected), header)} + | + |The tests were made under the $constraintText""" /** Format `raw` implicitNotFound or implicitAmbiguous argument, replacing * all occurrences of `${X}` where `X` is in `paramNames` with the diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 566891903344..0c9af3bd36e2 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -201,7 +201,7 @@ object RefChecks { val upwardsSelf = upwardsThisType(clazz) var hasErrors = false - case class MixinOverrideError(member: Symbol, msg: String) + case class MixinOverrideError(member: Symbol, msg: Message) val mixinOverrideErrors = new mutable.ListBuffer[MixinOverrideError]() @@ -219,7 +219,7 @@ object RefChecks { if (others1.isEmpty) "" else i";\nother members with override errors are:: $others1%, %" } - report.error(msg + othersMsg, clazz.srcPos) + report.error(msg.append(othersMsg), clazz.srcPos) } def infoString(sym: Symbol) = infoString0(sym, sym.owner != clazz) @@ -270,20 +270,19 @@ object RefChecks { def noErrorType = !memberTp(self).isErroneous && !otherTp(self).isErroneous - def overrideErrorMsg(msg: String): String = { + def overrideErrorMsg(msg: String, compareTypes: Boolean = false): Message = { val isConcreteOverAbstract = (other.owner isSubClass member.owner) && other.is(Deferred) && !member.is(Deferred) val addendum = - if (isConcreteOverAbstract) + if isConcreteOverAbstract then ";\n (Note that %s is abstract,\n and is therefore overridden by concrete %s)".format( infoStringWithLocation(other), infoStringWithLocation(member)) - else if (ctx.settings.Ydebug.value) - TypeMismatch(memberTp(self), otherTp(self)) else "" - - "error overriding %s;\n %s %s%s".format( - infoStringWithLocation(other), infoString(member), msg, addendum) + val fullMsg = + s"error overriding ${infoStringWithLocation(other)};\n ${infoString(member)} $msg$addendum" + if compareTypes then OverrideTypeMismatchError(fullMsg, memberTp(self), otherTp(self)) + else OverrideError(fullMsg) } def compatTypes(memberTp: Type, otherTp: Type): Boolean = @@ -292,7 +291,7 @@ object RefChecks { overrideErrorMsg("no longer has compatible type"), (if (member.owner == clazz) member else clazz).srcPos)) - def emitOverrideError(fullmsg: String) = + def emitOverrideError(fullmsg: Message) = if (!(hasErrors && member.is(Synthetic) && member.is(Module))) { // suppress errors relating toi synthetic companion objects if other override // errors (e.g. relating to the companion class) have already been reported. @@ -301,9 +300,9 @@ object RefChecks { hasErrors = true } - def overrideError(msg: String) = + def overrideError(msg: String, compareTypes: Boolean = false) = if (noErrorType) - emitOverrideError(overrideErrorMsg(msg)) + emitOverrideError(overrideErrorMsg(msg, compareTypes)) def autoOverride(sym: Symbol) = sym.is(Synthetic) && ( @@ -442,7 +441,7 @@ object RefChecks { overrideError("cannot be used here - only Scala-2 macros can override Scala-2 macros") else if (!compatTypes(memberTp(self), otherTp(self)) && !compatTypes(memberTp(upwardsSelf), otherTp(upwardsSelf))) - overrideError("has incompatible type" + err.whyNoMatchStr(memberTp(self), otherTp(self))) + overrideError("has incompatible type", compareTypes = true) else if (member.targetName != other.targetName) if (other.targetName != other.name) overrideError(i"needs to be declared with @targetName(${"\""}${other.targetName}${"\""}) so that external names match") From de6bf431a337676d544a17a3c94abf8d4fd3b178 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 7 Mar 2021 21:46:11 +0100 Subject: [PATCH 2/7] Tweaks in wording of error messages --- compiler/src/dotty/tools/dotc/core/TypeComparer.scala | 4 ++-- compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 86c964e7d7b8..4a1164dff9e7 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -2591,8 +2591,8 @@ object TypeComparer { def addLow: Repr = approx | LoApprox def addHigh: Repr = approx | HiApprox def show: String = - val lo = if low then " (left is tightened)" else "" - val hi = if high then " (right is tigthened)" else "" + val lo = if low then " (left is approximated)" else "" + val hi = if high then " (right is approximated)" else "" lo ++ hi end ApproxState type ApproxState = ApproxState.Repr diff --git a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala index 48baa1e00a64..915f467f6897 100644 --- a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala +++ b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala @@ -128,14 +128,14 @@ object ErrorReporting { val c = ctx.typerState.constraint val constraintText = if c.domainLambdas.isEmpty then - "empty constraint" + "the empty constraint" else - i"""following constraint: + i"""a constraint with: |${c.contentsToString}""" i""" |${TypeComparer.explained(_.isSubType(found, expected), header)} | - |The tests were made under the $constraintText""" + |The tests were made under $constraintText""" /** Format `raw` implicitNotFound or implicitAmbiguous argument, replacing * all occurrences of `${X}` where `X` is in `paramNames` with the From 5a6055eded68be4fae7e1c1248a87c2fc9fe4a68 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 7 Mar 2021 21:47:10 +0100 Subject: [PATCH 3/7] Update check files of tests --- .../explicit-nulls/byname-nullables.check | 4 +++- tests/neg-custom-args/explicit-nulls/i7883.check | 2 +- tests/neg-custom-args/ovlazy.check | 2 +- tests/neg-macros/beta-reduce-inline-result.check | 2 ++ tests/neg/abstract-givens.check | 6 ++++-- tests/neg/exports2.check | 2 +- tests/neg/i11637.check | 12 ++++++++++++ tests/neg/i11637.scala | 12 ++++++++++++ tests/neg/i2033.check | 2 ++ tests/neg/i5311.check | 2 ++ tests/neg/i6762b.check | 2 ++ tests/neg/i6779.check | 4 ++++ tests/neg/i7195.check | 2 ++ tests/neg/i7359-g.check | 2 ++ tests/neg/i7359.check | 2 +- tests/neg/i8736.check | 4 ++++ tests/neg/i8988.check | 2 ++ tests/neg/i9958.check | 2 ++ tests/neg/if-error.check | 2 ++ tests/neg/leading-infix-miss.check | 2 ++ tests/neg/missing-implicit-2.check | 2 ++ tests/neg/missing-implicit-3.check | 2 ++ tests/neg/module-class-name.check | 8 ++++++++ tests/neg/override-scala2-macro.check | 2 +- tests/neg/singleton-ops-any.check | 8 ++++++++ tests/neg/t6663.check | 2 ++ tests/neg/targetName-override.check | 6 +++--- 27 files changed, 89 insertions(+), 11 deletions(-) create mode 100644 tests/neg/i11637.check create mode 100644 tests/neg/i11637.scala diff --git a/tests/neg-custom-args/explicit-nulls/byname-nullables.check b/tests/neg-custom-args/explicit-nulls/byname-nullables.check index bb8969474289..efe94a496c19 100644 --- a/tests/neg-custom-args/explicit-nulls/byname-nullables.check +++ b/tests/neg-custom-args/explicit-nulls/byname-nullables.check @@ -3,6 +3,8 @@ | ^ | Found: (x : String | Null) | Required: String + +longer explanation available when compiling with `-explain` -- Error: tests/neg-custom-args/explicit-nulls/byname-nullables.scala:43:32 -------------------------------------------- 43 | if x != null then f(identity(x), 1) // error: dropping not null check fails typing | ^^^^^^^^^^^ @@ -19,7 +21,7 @@ | Wrapping the argument in `byName(...)` fixes the problem by disabling the flow assumptions. | | `byName` needs to be imported from the `scala.compiletime` package. --- [E134] Type Mismatch Error: tests/neg-custom-args/explicit-nulls/byname-nullables.scala:81:22 ----------------------- +-- [E134] Type Error: tests/neg-custom-args/explicit-nulls/byname-nullables.scala:81:22 -------------------------------- 81 | if x != null then f(byName(x), 1) // error: none of the overloaded methods match argument types | ^ | None of the overloaded alternatives of method f in object Test7 with types diff --git a/tests/neg-custom-args/explicit-nulls/i7883.check b/tests/neg-custom-args/explicit-nulls/i7883.check index 57775b962f3f..4e3660809c86 100644 --- a/tests/neg-custom-args/explicit-nulls/i7883.check +++ b/tests/neg-custom-args/explicit-nulls/i7883.check @@ -1,4 +1,4 @@ --- [E134] Type Mismatch Error: tests/neg-custom-args/explicit-nulls/i7883.scala:6:11 ----------------------------------- +-- [E134] Type Error: tests/neg-custom-args/explicit-nulls/i7883.scala:6:11 -------------------------------------------- 6 | case r(hd, tl) => Some((hd, tl)) // error // error // error | ^ | None of the overloaded alternatives of method unapplySeq in class Regex with types diff --git a/tests/neg-custom-args/ovlazy.check b/tests/neg-custom-args/ovlazy.check index 9dab32c76bfb..c8ee2b99b437 100644 --- a/tests/neg-custom-args/ovlazy.check +++ b/tests/neg-custom-args/ovlazy.check @@ -1,4 +1,4 @@ --- Error: tests/neg-custom-args/ovlazy.scala:5:20 ---------------------------------------------------------------------- +-- [E164] Declaration Error: tests/neg-custom-args/ovlazy.scala:5:20 --------------------------------------------------- 5 | override lazy val x: Int = 2 // error | ^ | error overriding value x in class A of type Int; diff --git a/tests/neg-macros/beta-reduce-inline-result.check b/tests/neg-macros/beta-reduce-inline-result.check index 08672b15d3a8..0dd6098fb820 100644 --- a/tests/neg-macros/beta-reduce-inline-result.check +++ b/tests/neg-macros/beta-reduce-inline-result.check @@ -4,3 +4,5 @@ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | Found: Int | Required: (4 : Int) + +longer explanation available when compiling with `-explain` diff --git a/tests/neg/abstract-givens.check b/tests/neg/abstract-givens.check index 03a5f718f86b..e51e3bded95f 100644 --- a/tests/neg/abstract-givens.check +++ b/tests/neg/abstract-givens.check @@ -2,13 +2,15 @@ 11 | given s[T](using T): Seq[T] with // error | ^ |instance cannot be created, since def iterator: => Iterator[A] in trait IterableOnce in package scala.collection is not defined --- Error: tests/neg/abstract-givens.scala:8:8 -------------------------------------------------------------------------- +-- [E164] Declaration Error: tests/neg/abstract-givens.scala:8:8 ------------------------------------------------------- 8 | given y(using Int): String = summon[Int].toString * 22 // error | ^ | error overriding given instance y in trait T of type (using x$1: Int): String; | given instance y of type (using x$1: Int): String cannot override final member given instance y in trait T --- Error: tests/neg/abstract-givens.scala:9:8 -------------------------------------------------------------------------- +-- [E163] Declaration Error: tests/neg/abstract-givens.scala:9:8 ------------------------------------------------------- 9 | given z[T](using T): Seq[T] = List(summon[T]) // error | ^ | error overriding given instance z in trait T of type [T](using x$1: T): List[T]; | given instance z of type [T](using x$1: T): Seq[T] has incompatible type + +longer explanation available when compiling with `-explain` diff --git a/tests/neg/exports2.check b/tests/neg/exports2.check index 6b35b1fe4621..245538b12abb 100644 --- a/tests/neg/exports2.check +++ b/tests/neg/exports2.check @@ -1,4 +1,4 @@ --- Error: tests/neg/exports2.scala:8:11 -------------------------------------------------------------------------------- +-- [E164] Declaration Error: tests/neg/exports2.scala:8:11 ------------------------------------------------------------- 8 | export A._ // error | ^ | error overriding method f in trait B of type => String; diff --git a/tests/neg/i11637.check b/tests/neg/i11637.check new file mode 100644 index 000000000000..7f9e261b75d7 --- /dev/null +++ b/tests/neg/i11637.check @@ -0,0 +1,12 @@ +-- [E057] Type Mismatch Error: tests/neg/i11637.scala:11:33 ------------------------------------------------------------ +11 | var h = new HKT3_1[FunctorImpl](); // error // error + | ^ + | Type argument test2.FunctorImpl does not conform to upper bound [Generic2[T] <: Set[T]] =>> Any + +longer explanation available when compiling with `-explain` +-- [E057] Type Mismatch Error: tests/neg/i11637.scala:11:21 ------------------------------------------------------------ +11 | var h = new HKT3_1[FunctorImpl](); // error // error + | ^ + | Type argument test2.FunctorImpl does not conform to upper bound [Generic2[T] <: Set[T]] =>> Any + +longer explanation available when compiling with `-explain` diff --git a/tests/neg/i11637.scala b/tests/neg/i11637.scala new file mode 100644 index 000000000000..0b566ecd4328 --- /dev/null +++ b/tests/neg/i11637.scala @@ -0,0 +1,12 @@ +// This is OK +object test1: + class FunctorImpl[Generic1[T] <: Iterable[T]]{} + class HKT3_1[Functor[Generic2[T]<:Set[T]]]{} + var h = new HKT3_1[FunctorImpl](); + +// This is has error +object test2: + class FunctorImpl[Generic1[T] <: Iterable[T]]{} + class HKT3_1[Functor[Generic2[T<:String]<:Set[T]]]{} + var h = new HKT3_1[FunctorImpl](); // error // error + diff --git a/tests/neg/i2033.check b/tests/neg/i2033.check index 5727dbd0c49e..4878ad153a47 100644 --- a/tests/neg/i2033.check +++ b/tests/neg/i2033.check @@ -7,3 +7,5 @@ | ^^^^^^^ | Found: Unit | Required: String + +longer explanation available when compiling with `-explain` diff --git a/tests/neg/i5311.check b/tests/neg/i5311.check index 19b160fd61f5..cc877b020d5e 100644 --- a/tests/neg/i5311.check +++ b/tests/neg/i5311.check @@ -3,3 +3,5 @@ | ^^^^^^^^^^^^^^^^^^ | Found: s.T[Int] => s.T[Int] | Required: m.Foo + +longer explanation available when compiling with `-explain` diff --git a/tests/neg/i6762b.check b/tests/neg/i6762b.check index 7311f21adb33..9c0d571dd77b 100644 --- a/tests/neg/i6762b.check +++ b/tests/neg/i6762b.check @@ -3,3 +3,5 @@ | ^^^^^^^^^^^ | Found: Expr[String] | Required: Expr[G[String]] + +longer explanation available when compiling with `-explain` diff --git a/tests/neg/i6779.check b/tests/neg/i6779.check index b4e12d34b8aa..d2953c80f2b4 100644 --- a/tests/neg/i6779.check +++ b/tests/neg/i6779.check @@ -3,6 +3,8 @@ | ^^^^^^^^^^^^^^^^^^^^^^^^ | Found: F[T] | Required: F[G[T]] + +longer explanation available when compiling with `-explain` -- [E008] Not Found Error: tests/neg/i6779.scala:12:31 ----------------------------------------------------------------- 12 | def g2[T](x: T): F[G[T]] = x.f // error | ^^^ @@ -18,3 +20,5 @@ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | Found: F[T] | Required: F[G[T]] + +longer explanation available when compiling with `-explain` diff --git a/tests/neg/i7195.check b/tests/neg/i7195.check index 72a85faa1378..0d393ca0e979 100644 --- a/tests/neg/i7195.check +++ b/tests/neg/i7195.check @@ -6,3 +6,5 @@ | | where: T is a type in object B | T² is a type in object A + +longer explanation available when compiling with `-explain` diff --git a/tests/neg/i7359-g.check b/tests/neg/i7359-g.check index 9c579c57186b..f750b024c016 100644 --- a/tests/neg/i7359-g.check +++ b/tests/neg/i7359-g.check @@ -3,3 +3,5 @@ | ^^^^^^^ | Found: () => String | Required: SAMTrait + +longer explanation available when compiling with `-explain` diff --git a/tests/neg/i7359.check b/tests/neg/i7359.check index 5376a904e671..6c177e895aba 100644 --- a/tests/neg/i7359.check +++ b/tests/neg/i7359.check @@ -1,4 +1,4 @@ --- Error: tests/neg/i7359.scala:3:6 ------------------------------------------------------------------------------------ +-- [E164] Declaration Error: tests/neg/i7359.scala:3:6 ----------------------------------------------------------------- 3 | def notify(): Unit // error | ^ | error overriding method notify in class Object of type (): Unit; diff --git a/tests/neg/i8736.check b/tests/neg/i8736.check index d99c7ca34c09..80986464d035 100644 --- a/tests/neg/i8736.check +++ b/tests/neg/i8736.check @@ -3,11 +3,15 @@ | ^^^^^^^^^^^^ | Found: Any | Required: String + +longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg/i8736.scala:30:29 ------------------------------------------------------------- 30 | def res2: Int = rec.get("v") // error: type mismatch | ^^^^^^^^^^^^ | Found: Any | Required: Int + +longer explanation available when compiling with `-explain` -- [E051] Reference Error: tests/neg/i8736.scala:31:26 ----------------------------------------------------------------- 31 | def res3: Boolean = rec.get("z") // error: ambiguous | ^^^^^^^ diff --git a/tests/neg/i8988.check b/tests/neg/i8988.check index 8b14c32a3497..6952837128ed 100644 --- a/tests/neg/i8988.check +++ b/tests/neg/i8988.check @@ -3,3 +3,5 @@ | ^^ | Found: (ys : List[Int]) | Required: String + +longer explanation available when compiling with `-explain` diff --git a/tests/neg/i9958.check b/tests/neg/i9958.check index 92de7faae086..3657c466dc8b 100644 --- a/tests/neg/i9958.check +++ b/tests/neg/i9958.check @@ -7,3 +7,5 @@ | ^ | Found: G[[A <: Int] =>> List[A]] | Required: G[List] + +longer explanation available when compiling with `-explain` diff --git a/tests/neg/if-error.check b/tests/neg/if-error.check index 18ba78de6139..c2f1b02b2067 100644 --- a/tests/neg/if-error.check +++ b/tests/neg/if-error.check @@ -4,3 +4,5 @@ | Found: Unit | Required: Int | Maybe you are missing an else part for the conditional? + +longer explanation available when compiling with `-explain` diff --git a/tests/neg/leading-infix-miss.check b/tests/neg/leading-infix-miss.check index 1817290f8065..df9c4d8dd3e0 100644 --- a/tests/neg/leading-infix-miss.check +++ b/tests/neg/leading-infix-miss.check @@ -11,3 +11,5 @@ | ^ | Found: Unit | Required: Boolean + +longer explanation available when compiling with `-explain` diff --git a/tests/neg/missing-implicit-2.check b/tests/neg/missing-implicit-2.check index edc200b6dec2..4ec525f4a34e 100644 --- a/tests/neg/missing-implicit-2.check +++ b/tests/neg/missing-implicit-2.check @@ -26,3 +26,5 @@ | | where: Byte is a class in package scala | Byte² is a class in package java.lang + +longer explanation available when compiling with `-explain` diff --git a/tests/neg/missing-implicit-3.check b/tests/neg/missing-implicit-3.check index abb3b083ab6f..206f97866186 100644 --- a/tests/neg/missing-implicit-3.check +++ b/tests/neg/missing-implicit-3.check @@ -12,6 +12,8 @@ | | import concurrent.duration.pairIntToDuration | + +longer explanation available when compiling with `-explain` -- [E008] Not Found Error: tests/neg/missing-implicit-3.scala:8:48 ----------------------------------------------------- 8 |val d2: scala.concurrent.duration.Duration = 10.days // error | ^^^^^^^ diff --git a/tests/neg/module-class-name.check b/tests/neg/module-class-name.check index 70d944ee4330..0888689553fb 100644 --- a/tests/neg/module-class-name.check +++ b/tests/neg/module-class-name.check @@ -3,21 +3,29 @@ | ^ | Found: Test.C.type | Required: Test.C + +longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg/module-class-name.scala:9:15 -------------------------------------------------- 9 | val y: C = f(C) // error | ^ | Found: Test.C.type | Required: Test.C + +longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg/module-class-name.scala:12:14 ------------------------------------------------- 12 | val z1: C = z // error | ^ | Found: Test.C.type | Required: Test.C + +longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg/module-class-name.scala:13:16 ------------------------------------------------- 13 | val z2: Int = z // error | ^ | Found: Test.C.type | Required: Int + +longer explanation available when compiling with `-explain` -- [E008] Not Found Error: tests/neg/module-class-name.scala:15:4 ------------------------------------------------------ 15 | C.foo // error: value foo is not a member of object Test.C | ^^^^^ diff --git a/tests/neg/override-scala2-macro.check b/tests/neg/override-scala2-macro.check index fcef6e87677c..ff5e478342dd 100644 --- a/tests/neg/override-scala2-macro.check +++ b/tests/neg/override-scala2-macro.check @@ -1,4 +1,4 @@ --- Error: tests/neg/override-scala2-macro.scala:2:22 ------------------------------------------------------------------- +-- [E164] Declaration Error: tests/neg/override-scala2-macro.scala:2:22 ------------------------------------------------ 2 | override inline def f[A >: Any](args: A*): String = ??? // error | ^ |error overriding method f in class StringContext of type [A >: Any](args: Seq[A]): String; diff --git a/tests/neg/singleton-ops-any.check b/tests/neg/singleton-ops-any.check index a497686284af..6de768fa0b2e 100644 --- a/tests/neg/singleton-ops-any.check +++ b/tests/neg/singleton-ops-any.check @@ -3,18 +3,26 @@ | ^^^^ | Found: (true : Boolean) | Required: (false : Boolean) + +longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg/singleton-ops-any.scala:7:22 -------------------------------------------------- 7 | val t35: 10 == 10 = false // error | ^^^^^ | Found: (false : Boolean) | Required: (true : Boolean) + +longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg/singleton-ops-any.scala:12:24 ------------------------------------------------- 12 | val t38: false != 5 = false // error | ^^^^^ | Found: (false : Boolean) | Required: (true : Boolean) + +longer explanation available when compiling with `-explain` -- [E007] Type Mismatch Error: tests/neg/singleton-ops-any.scala:13:22 ------------------------------------------------- 13 | val t39: 10 != 10 = true // error | ^^^^ | Found: (true : Boolean) | Required: (false : Boolean) + +longer explanation available when compiling with `-explain` diff --git a/tests/neg/t6663.check b/tests/neg/t6663.check index 96f8609c2593..806f3357a0f6 100644 --- a/tests/neg/t6663.check +++ b/tests/neg/t6663.check @@ -3,3 +3,5 @@ | ^^^^^^^^^^^^^^^^^^^^^^^^^ | Found: String | Required: Int + +longer explanation available when compiling with `-explain` diff --git a/tests/neg/targetName-override.check b/tests/neg/targetName-override.check index 912f7debc247..2d21e8cbfbd4 100644 --- a/tests/neg/targetName-override.check +++ b/tests/neg/targetName-override.check @@ -1,14 +1,14 @@ --- Error: tests/neg/targetName-override.scala:16:35 -------------------------------------------------------------------- +-- [E164] Declaration Error: tests/neg/targetName-override.scala:16:35 ------------------------------------------------- 16 | @targetName("foo1") override def foo() = 1 // error: should not have a target name | ^ |error overriding method foo in class Alpha of type (): Int; | method foo of type (): Int should not have a @targetName annotation since the overridden member hasn't one either --- Error: tests/neg/targetName-override.scala:18:25 -------------------------------------------------------------------- +-- [E164] Declaration Error: tests/neg/targetName-override.scala:18:25 ------------------------------------------------- 18 | @targetName("baz") def foo(x: String): String = x ++ x // error: has a different target name annotation | ^ | error overriding method foo in class Alpha of type (x: String): String; | method foo of type (x: String): String has a different target name annotation; it should be @targetName(foo1) --- Error: tests/neg/targetName-override.scala:20:15 -------------------------------------------------------------------- +-- [E164] Declaration Error: tests/neg/targetName-override.scala:20:15 ------------------------------------------------- 20 | override def ++ (xs: Alpha[String]): Alpha[String] = this // error: misses a targetname annotation | ^ | error overriding method ++ in class Alpha of type (xs: Alpha[String]): Alpha[String]; From dad48ad10a0d43a8840ece764357aeb5bd01be3e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 7 Mar 2021 21:51:55 +0100 Subject: [PATCH 4/7] Check file for -explain output --- .../dotty/tools/dotc/CompilationTests.scala | 1 + tests/neg-custom-args/i11637.check | 77 +++++++++++++++++++ tests/{neg => neg-custom-args}/i11637.scala | 0 tests/neg/i11637.check | 12 --- 4 files changed, 78 insertions(+), 12 deletions(-) create mode 100644 tests/neg-custom-args/i11637.check rename tests/{neg => neg-custom-args}/i11637.scala (100%) delete mode 100644 tests/neg/i11637.check diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 67a45a3a9703..6a807bbb4d91 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -145,6 +145,7 @@ class CompilationTests { compileFile("tests/neg-custom-args/i4372.scala", allowDeepSubtypes), compileFile("tests/neg-custom-args/i1754.scala", allowDeepSubtypes), compileFile("tests/neg-custom-args/i9517.scala", defaultOptions.and("-Xprint-types")), + compileFile("tests/neg-custom-args/i11637.scala", defaultOptions.and("-explain")), compileFile("tests/neg-custom-args/interop-polytypes.scala", allowDeepSubtypes.and("-Yexplicit-nulls")), compileFile("tests/neg-custom-args/conditionalWarnings.scala", allowDeepSubtypes.and("-deprecation").and("-Xfatal-warnings")), compileFilesInDir("tests/neg-custom-args/isInstanceOf", allowDeepSubtypes and "-Xfatal-warnings"), diff --git a/tests/neg-custom-args/i11637.check b/tests/neg-custom-args/i11637.check new file mode 100644 index 000000000000..b0479b633efc --- /dev/null +++ b/tests/neg-custom-args/i11637.check @@ -0,0 +1,77 @@ +-- [E057] Type Mismatch Error: tests/neg-custom-args/i11637.scala:11:33 ------------------------------------------------ +11 | var h = new HKT3_1[FunctorImpl](); // error // error + | ^ + | Type argument test2.FunctorImpl does not conform to upper bound [Generic2[T] <: Set[T]] =>> Any + +Explanation +=========== + +I tried to show that + test2.FunctorImpl +conforms to + [Generic2[T] <: Set[T]] =>> Any +but the comparison trace ended with `false`: + + ==> test2.FunctorImpl <: [Generic2[T] <: Set[T]] =>> Any + ==> test2.FunctorImpl <: [Generic2[T] <: Set[T]] =>> Any (recurring) + ==> type bounds [[T] <: Set[T]] <: type bounds [[T] <: Iterable[T]] + ==> type bounds [[T] <: Set[T]] <: type bounds [[T] <: Iterable[T]] (recurring) + ==> [T <: String] =>> Set[T] <: Iterable + ==> [T <: String] =>> Set[T] <: Iterable (recurring) + ==> type bounds [] <: type bounds [ <: String] + ==> type bounds [] <: type bounds [ <: String] (recurring) + ==> Any <: String + ==> Any <: String (recurring) + ==> Any <: String (recurring) + <== Any <: String (recurring) = false + <== Any <: String (recurring) = false + <== Any <: String = false + <== type bounds [] <: type bounds [ <: String] (recurring) = false + <== type bounds [] <: type bounds [ <: String] = false + <== [T <: String] =>> Set[T] <: Iterable (recurring) = false + <== [T <: String] =>> Set[T] <: Iterable = false + <== type bounds [[T] <: Set[T]] <: type bounds [[T] <: Iterable[T]] (recurring) = false + <== type bounds [[T] <: Set[T]] <: type bounds [[T] <: Iterable[T]] = false + <== test2.FunctorImpl <: [Generic2[T] <: Set[T]] =>> Any (recurring) = false + <== test2.FunctorImpl <: [Generic2[T] <: Set[T]] =>> Any = false + +The tests were made under the empty constraint + +-- [E057] Type Mismatch Error: tests/neg-custom-args/i11637.scala:11:21 ------------------------------------------------ +11 | var h = new HKT3_1[FunctorImpl](); // error // error + | ^ + | Type argument test2.FunctorImpl does not conform to upper bound [Generic2[T] <: Set[T]] =>> Any + +Explanation +=========== + +I tried to show that + test2.FunctorImpl +conforms to + [Generic2[T] <: Set[T]] =>> Any +but the comparison trace ended with `false`: + + ==> test2.FunctorImpl <: [Generic2[T] <: Set[T]] =>> Any + ==> test2.FunctorImpl <: [Generic2[T] <: Set[T]] =>> Any (recurring) + ==> type bounds [[T] <: Set[T]] <: type bounds [[T] <: Iterable[T]] + ==> type bounds [[T] <: Set[T]] <: type bounds [[T] <: Iterable[T]] (recurring) + ==> [T <: String] =>> Set[T] <: Iterable + ==> [T <: String] =>> Set[T] <: Iterable (recurring) + ==> type bounds [] <: type bounds [ <: String] + ==> type bounds [] <: type bounds [ <: String] (recurring) + ==> Any <: String + ==> Any <: String (recurring) + ==> Any <: String (recurring) + <== Any <: String (recurring) = false + <== Any <: String (recurring) = false + <== Any <: String = false + <== type bounds [] <: type bounds [ <: String] (recurring) = false + <== type bounds [] <: type bounds [ <: String] = false + <== [T <: String] =>> Set[T] <: Iterable (recurring) = false + <== [T <: String] =>> Set[T] <: Iterable = false + <== type bounds [[T] <: Set[T]] <: type bounds [[T] <: Iterable[T]] (recurring) = false + <== type bounds [[T] <: Set[T]] <: type bounds [[T] <: Iterable[T]] = false + <== test2.FunctorImpl <: [Generic2[T] <: Set[T]] =>> Any (recurring) = false + <== test2.FunctorImpl <: [Generic2[T] <: Set[T]] =>> Any = false + +The tests were made under the empty constraint diff --git a/tests/neg/i11637.scala b/tests/neg-custom-args/i11637.scala similarity index 100% rename from tests/neg/i11637.scala rename to tests/neg-custom-args/i11637.scala diff --git a/tests/neg/i11637.check b/tests/neg/i11637.check deleted file mode 100644 index 7f9e261b75d7..000000000000 --- a/tests/neg/i11637.check +++ /dev/null @@ -1,12 +0,0 @@ --- [E057] Type Mismatch Error: tests/neg/i11637.scala:11:33 ------------------------------------------------------------ -11 | var h = new HKT3_1[FunctorImpl](); // error // error - | ^ - | Type argument test2.FunctorImpl does not conform to upper bound [Generic2[T] <: Set[T]] =>> Any - -longer explanation available when compiling with `-explain` --- [E057] Type Mismatch Error: tests/neg/i11637.scala:11:21 ------------------------------------------------------------ -11 | var h = new HKT3_1[FunctorImpl](); // error // error - | ^ - | Type argument test2.FunctorImpl does not conform to upper bound [Generic2[T] <: Set[T]] =>> Any - -longer explanation available when compiling with `-explain` From 39c84d9c0086f15930796f9b9b6af4df6aa00df2 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 7 Mar 2021 22:09:31 +0100 Subject: [PATCH 5/7] More check file updates --- tests/neg-scalajs/jsconstructorof-error-in-typer.check | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/neg-scalajs/jsconstructorof-error-in-typer.check b/tests/neg-scalajs/jsconstructorof-error-in-typer.check index bca385d021f3..391ffa4c6933 100644 --- a/tests/neg-scalajs/jsconstructorof-error-in-typer.check +++ b/tests/neg-scalajs/jsconstructorof-error-in-typer.check @@ -2,11 +2,17 @@ 9 | val a = js.constructorOf[ScalaClass] // error | ^ | Type argument ScalaClass does not conform to upper bound scala.scalajs.js.Any + +longer explanation available when compiling with `-explain` -- [E057] Type Mismatch Error: tests/neg-scalajs/jsconstructorof-error-in-typer.scala:10:27 ---------------------------- 10 | val b = js.constructorOf[ScalaTrait] // error | ^ | Type argument ScalaTrait does not conform to upper bound scala.scalajs.js.Any + +longer explanation available when compiling with `-explain` -- [E057] Type Mismatch Error: tests/neg-scalajs/jsconstructorof-error-in-typer.scala:11:27 ---------------------------- 11 | val c = js.constructorOf[ScalaObject.type] // error | ^ | Type argument ScalaObject.type does not conform to upper bound scala.scalajs.js.Any + +longer explanation available when compiling with `-explain` From b501cbe38bbc4fa89c9e39ffe164903289ccc53e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 8 Mar 2021 11:38:15 +0100 Subject: [PATCH 6/7] Make -explain-types an alias of -explain --- compiler/src/dotty/tools/dotc/config/ScalaSettings.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 0ae53a46ff82..a977aca8570d 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -103,7 +103,7 @@ class ScalaSettings extends Settings.SettingGroup with CommonScalaSettings { val semanticdbTarget: Setting[String] = PathSetting("-semanticdb-target", "Specify an alternative output directory for SemanticDB files.", "") val deprecation: Setting[Boolean] = BooleanSetting("-deprecation", "Emit warning and location for usages of deprecated APIs.", aliases = List("--deprecation")) - val explain: Setting[Boolean] = BooleanSetting("-explain", "Explain errors in more detail.", aliases = List("--explain")) + val explain: Setting[Boolean] = BooleanSetting("-explain", "Explain errors in more detail.", aliases = List("--explain", "-explain-types", "--explain-types")) val feature: Setting[Boolean] = BooleanSetting("-feature", "Emit warning and location for usages of features that should be imported explicitly.", aliases = List("--feature")) val release: Setting[String] = ChoiceSetting("-release", "release", "Compile code with classes specific to the given version of the Java platform available on the classpath and emit bytecode for this version.", supportedReleaseVersions, "", aliases = List("--release")) val source: Setting[String] = ChoiceSetting("-source", "source version", "source version", List("3.0", "future", "3.0-migration", "future-migration"), "3.0", aliases = List("--source")) From 9b45f99a124032ca1a9aa0d926481ddaacaac68b Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 9 Mar 2021 10:42:58 +0100 Subject: [PATCH 7/7] Bring back -exlain-types Need to keep it for cross compilation. --- compiler/src/dotty/tools/dotc/config/ScalaSettings.scala | 5 ++++- compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index a977aca8570d..dc292c0db573 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -103,7 +103,10 @@ class ScalaSettings extends Settings.SettingGroup with CommonScalaSettings { val semanticdbTarget: Setting[String] = PathSetting("-semanticdb-target", "Specify an alternative output directory for SemanticDB files.", "") val deprecation: Setting[Boolean] = BooleanSetting("-deprecation", "Emit warning and location for usages of deprecated APIs.", aliases = List("--deprecation")) - val explain: Setting[Boolean] = BooleanSetting("-explain", "Explain errors in more detail.", aliases = List("--explain", "-explain-types", "--explain-types")) + val explainTypes: Setting[Boolean] = BooleanSetting("-explain-types", "Explain type errors in more detail (deprecated, use -explain instead).", aliases = List("--explain-types")) + // this setting is necessary for cross compilation, since it is mentioned in sbt-tpolecat, for instance + // it is otherwise subsumed by -explain, and should be dropped as soon as we can. + val explain: Setting[Boolean] = BooleanSetting("-explain", "Explain errors in more detail.", aliases = List("--explain")) val feature: Setting[Boolean] = BooleanSetting("-feature", "Emit warning and location for usages of features that should be imported explicitly.", aliases = List("--feature")) val release: Setting[String] = ChoiceSetting("-release", "release", "Compile code with classes specific to the given version of the Java platform available on the classpath and emit bytecode for this version.", supportedReleaseVersions, "", aliases = List("--release")) val source: Setting[String] = ChoiceSetting("-source", "source version", "source version", List("3.0", "future", "3.0-migration", "future-migration"), "3.0", aliases = List("--source")) diff --git a/compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala b/compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala index 49c71ca33a81..fbb7145152d6 100644 --- a/compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala +++ b/compiler/src/dotty/tools/dotc/reporting/Diagnostic.scala @@ -13,6 +13,8 @@ object Diagnostic: def shouldExplain(dia: Diagnostic)(using Context): Boolean = ctx.settings.explain.value && dia.msg.canExplain + || ctx.settings.explainTypes.value && dia.msg.isInstanceOf[TypeMismatchMsg] + // keep old explain-types behavior for backwards compatibility and cross-compilation // `Diagnostics to be consumed by `Reporter` ---------------------- // class Error(