From 8d4d9a363d90cc24bd79b18ea2ef7cba6a746bef Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 7 Aug 2016 17:29:24 +0200 Subject: New string infterpolators Roll `sm` and `i` into one interpolator (also called `i`) Evolve `d` to `em` interpolator (for error messages) New interpolator `ex` with more explanations, replaces disambiguation. --- src/dotty/tools/dotc/typer/Applications.scala | 10 +-- src/dotty/tools/dotc/typer/Checking.scala | 38 +++++------ src/dotty/tools/dotc/typer/ErrorReporting.scala | 85 ++++++++++--------------- src/dotty/tools/dotc/typer/Implicits.scala | 20 +++--- src/dotty/tools/dotc/typer/Namer.scala | 8 +-- src/dotty/tools/dotc/typer/RefChecks.scala | 6 +- src/dotty/tools/dotc/typer/TypeAssigner.scala | 22 ++++--- src/dotty/tools/dotc/typer/Typer.scala | 52 +++++++-------- 8 files changed, 113 insertions(+), 128 deletions(-) (limited to 'src/dotty/tools/dotc/typer') diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala index f0a514e8c..c8f41b7fa 100644 --- a/src/dotty/tools/dotc/typer/Applications.scala +++ b/src/dotty/tools/dotc/typer/Applications.scala @@ -777,9 +777,9 @@ trait Applications extends Compatibility { self: Typer with Dynamic => maximizeType(unapplyArgType) match { case Some(tvar) => def msg = - d"""There is no best instantiation of pattern type $unapplyArgType - |that makes it a subtype of selector type $selType. - |Non-variant type variable ${tvar.origin} cannot be uniquely instantiated.""".stripMargin + ex"""There is no best instantiation of pattern type $unapplyArgType + |that makes it a subtype of selector type $selType. + |Non-variant type variable ${tvar.origin} cannot be uniquely instantiated.""" if (fromScala2x) { // We can't issue an error here, because in Scala 2, ::[B] is invariant // whereas List[+T] is covariant. According to the strict rule, a pattern @@ -801,7 +801,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => unapp.println("Neither sub nor super") unapp.println(TypeComparer.explained(implicit ctx => unapplyArgType <:< selType)) errorType( - d"Pattern type $unapplyArgType is neither a subtype nor a supertype of selector type $selType", + ex"Pattern type $unapplyArgType is neither a subtype nor a supertype of selector type $selType", tree.pos) } @@ -822,7 +822,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => case _ => args } if (argTypes.length != bunchedArgs.length) { - ctx.error(d"wrong number of argument patterns for $qual; expected: ($argTypes%, %)", tree.pos) + ctx.error(em"wrong number of argument patterns for $qual; expected: ($argTypes%, %)", tree.pos) argTypes = argTypes.take(args.length) ++ List.fill(argTypes.length - args.length)(WildcardType) } diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala index b1cceea88..d77520c77 100644 --- a/src/dotty/tools/dotc/typer/Checking.scala +++ b/src/dotty/tools/dotc/typer/Checking.scala @@ -25,7 +25,7 @@ import util.common._ import transform.SymUtils._ import Decorators._ import Uniques._ -import ErrorReporting.{err, errorType, DiagnosticString} +import ErrorReporting.{err, errorType} import config.Printers._ import collection.mutable import SymDenotations.NoCompleter @@ -40,11 +40,11 @@ object Checking { def checkBounds(args: List[tpd.Tree], boundss: List[TypeBounds], instantiate: (Type, List[Type]) => Type)(implicit ctx: Context) = { (args, boundss).zipped.foreach { (arg, bound) => if (!bound.isHK && arg.tpe.isHK) - ctx.error(d"missing type parameter(s) for $arg", arg.pos) + ctx.error(ex"missing type parameter(s) for $arg", arg.pos) } for ((arg, which, bound) <- ctx.boundsViolations(args, boundss, instantiate)) ctx.error( - d"Type argument ${arg.tpe} does not conform to $which bound $bound ${err.whyNoMatchStr(arg.tpe, bound)}", + ex"Type argument ${arg.tpe} does not conform to $which bound $bound ${err.whyNoMatchStr(arg.tpe, bound)}", arg.pos) } @@ -65,7 +65,7 @@ object Checking { tycon match { case tycon: TypeLambda => ctx.errorOrMigrationWarning( - d"unreducible application of higher-kinded type $tycon to wildcard arguments", + ex"unreducible application of higher-kinded type $tycon to wildcard arguments", pos) case _ => checkWildcardHKApply(tp.superType, pos) @@ -117,14 +117,14 @@ object Checking { case tref: TypeRef => val cls = tref.symbol if (cls.is(AbstractOrTrait)) - ctx.error(d"$cls is abstract; cannot be instantiated", pos) + ctx.error(em"$cls is abstract; cannot be instantiated", pos) if (!cls.is(Module)) { // Create a synthetic singleton type instance, and check whether // it conforms to the self type of the class as seen from that instance. val stp = SkolemType(tp) val selfType = tref.givenSelfType.asSeenFrom(stp, cls) if (selfType.exists && !(stp <:< selfType)) - ctx.error(d"$tp does not conform to its self type $selfType; cannot be instantiated") + ctx.error(ex"$tp does not conform to its self type $selfType; cannot be instantiated") } case _ => } @@ -133,7 +133,7 @@ object Checking { def checkRealizable(tp: Type, pos: Position)(implicit ctx: Context): Unit = { val rstatus = realizability(tp) if (rstatus ne Realizable) { - def msg = d"$tp is not a legal path\n since it${rstatus.msg}" + def msg = em"$tp is not a legal path\n since it${rstatus.msg}" if (ctx.scala2Mode) ctx.migrationWarning(msg, pos) else ctx.error(msg, pos) } } @@ -378,7 +378,7 @@ object Checking { var tp1 = if (tp.symbol.is(Private) && !accessBoundary(sym).isContainedIn(tp.symbol.owner)) { - errors = (d"non-private $sym refers to private ${tp.symbol}\n in its type signature ${sym.info}", + errors = (em"non-private $sym refers to private ${tp.symbol}\n in its type signature ${sym.info}", pos) :: errors tp } @@ -422,20 +422,20 @@ trait Checking { val sym = tree.tpe.termSymbol // The check is avoided inside Java compilation units because it always fails // on the singleton type Module.type. - if ((sym is Package) || ((sym is JavaModule) && !ctx.compilationUnit.isJava)) ctx.error(d"$sym is not a value", tree.pos) + if ((sym is Package) || ((sym is JavaModule) && !ctx.compilationUnit.isJava)) ctx.error(em"$sym is not a value", tree.pos) } tree } /** Check that type `tp` is stable. */ def checkStable(tp: Type, pos: Position)(implicit ctx: Context): Unit = - if (!tp.isStable) ctx.error(d"$tp is not stable", pos) + if (!tp.isStable) ctx.error(ex"$tp is not stable", pos) /** Check that all type members of `tp` have realizable bounds */ def checkRealizableBounds(tp: Type, pos: Position)(implicit ctx: Context): Unit = { val rstatus = boundsRealizability(tp) if (rstatus ne Realizable) - ctx.error(i"$tp cannot be instantiated since it${rstatus.msg}", pos) + ctx.error(ex"$tp cannot be instantiated since it${rstatus.msg}", pos) } /** Check that `tp` is a class type. @@ -447,11 +447,11 @@ trait Checking { def checkClassType(tp: Type, pos: Position, traitReq: Boolean, stablePrefixReq: Boolean)(implicit ctx: Context): Type = tp.underlyingClassRef(refinementOK = false) match { case tref: TypeRef => - if (traitReq && !(tref.symbol is Trait)) ctx.error(d"$tref is not a trait", pos) + if (traitReq && !(tref.symbol is Trait)) ctx.error(ex"$tref is not a trait", pos) if (stablePrefixReq && ctx.phase <= ctx.refchecksPhase) checkStable(tref.prefix, pos) tp case _ => - ctx.error(d"$tp is not a class type", pos) + ctx.error(ex"$tp is not a class type", pos) defn.ObjectType } @@ -475,7 +475,7 @@ trait Checking { case tp: RecType => tp.rebind(tp.parent) case tp @ TypeBounds(lo, hi) if !(lo <:< hi) => - ctx.error(d"no type exists between low bound $lo and high bound $hi$where", pos) + ctx.error(ex"no type exists between low bound $lo and high bound $hi$where", pos) TypeAlias(hi) case _ => tp @@ -493,17 +493,17 @@ trait Checking { typr.println(i"conflict? $decl $other") if (decl.matches(other)) { def doubleDefError(decl: Symbol, other: Symbol): Unit = { - def ofType = if (decl.isType) "" else d": ${other.info}" + def ofType = if (decl.isType) "" else em": ${other.info}" def explanation = if (!decl.isRealMethod) "" else "\n (the definitions have matching type signatures)" - ctx.error(d"$decl is already defined as $other$ofType$explanation", decl.pos) + ctx.error(em"$decl is already defined as $other$ofType$explanation", decl.pos) } if (decl is Synthetic) doubleDefError(other, decl) else doubleDefError(decl, other) } if ((decl is HasDefaultParams) && (other is HasDefaultParams)) { - ctx.error(d"two or more overloaded variants of $decl have default arguments") + ctx.error(em"two or more overloaded variants of $decl have default arguments") decl resetFlag HasDefaultParams } } @@ -524,7 +524,7 @@ trait Checking { ctx.error(i"$caller may not call constructor of $called", call.pos) else if (called.is(Trait) && !caller.mixins.contains(called)) ctx.error(i"""$called is already implemented by super${caller.superClass}, - |its constructor cannot be called again""".stripMargin, call.pos) + |its constructor cannot be called again""", call.pos) } /** Check that `tpt` does not define a higher-kinded type */ @@ -532,7 +532,7 @@ trait Checking { if (tpt.tpe.isHK && !ctx.compilationUnit.isJava) { // be more lenient with missing type params in Java, // needed to make pos/java-interop/t1196 work. - errorTree(tpt, d"missing type parameter for ${tpt.tpe}") + errorTree(tpt, ex"missing type parameter for ${tpt.tpe}") } else tpt } diff --git a/src/dotty/tools/dotc/typer/ErrorReporting.scala b/src/dotty/tools/dotc/typer/ErrorReporting.scala index 6f7d427cb..ad84ff583 100644 --- a/src/dotty/tools/dotc/typer/ErrorReporting.scala +++ b/src/dotty/tools/dotc/typer/ErrorReporting.scala @@ -9,8 +9,8 @@ import Types._, ProtoTypes._, Contexts._, Decorators._, Denotations._, Symbols._ import Applications._, Implicits._, Flags._ import util.Positions._ import reporting.Diagnostic -import printing.Showable -import printing.Disambiguation.disambiguated +import printing.{Showable, RefinedPrinter} +import scala.collection.mutable import java.util.regex.Matcher.quoteReplacement object ErrorReporting { @@ -38,7 +38,7 @@ object ErrorReporting { val treeSym = ctx.symOfContextTree(tree) if (treeSym.exists && treeSym.name == cycleSym.name && treeSym.owner == cycleSym.owner) { val result = if (cycleSym is Method) " result" else "" - d"overloaded or recursive $cycleSym needs$result type" + em"overloaded or recursive $cycleSym needs$result type" } else errorMsg(msg, cx.outer) case _ => @@ -48,6 +48,9 @@ object ErrorReporting { errorMsg(ex.show, ctx) } + def wrongNumberOfArgs(fntpe: Type, kind: String, expected: Int, pos: Position)(implicit ctx: Context) = + errorType(em"wrong number of ${kind}arguments for $fntpe, expected: $expected", pos) + class Errors(implicit ctx: Context) { /** An explanatory note to be added to error messages @@ -59,15 +62,15 @@ object ErrorReporting { def expectedTypeStr(tp: Type): String = tp match { case tp: PolyProto => - d"type arguments [${tp.targs}%, %] and ${expectedTypeStr(tp.resultType)}" + em"type arguments [${tp.targs}%, %] and ${expectedTypeStr(tp.resultType)}" case tp: FunProto => val result = tp.resultType match { case _: WildcardType | _: IgnoredProto => "" - case tp => d" and expected result type $tp" + case tp => em" and expected result type $tp" } - d"arguments (${tp.typedArgs.tpes}%, %)$result" + em"arguments (${tp.typedArgs.tpes}%, %)$result" case _ => - d"expected type $tp" + em"expected type $tp" } def anonymousTypeMemberStr(tpe: Type) = { @@ -76,12 +79,12 @@ object ErrorReporting { case _: PolyType | _: MethodType => "method" case _ => "value of type" } - d"$kind $tpe" + em"$kind $tpe" } def overloadedAltsStr(alts: List[SingleDenotation]) = - d"overloaded alternatives of ${denotStr(alts.head)} with types\n" + - d" ${alts map (_.info)}%\n %" + em"overloaded alternatives of ${denotStr(alts.head)} with types\n" + + em" ${alts map (_.info)}%\n %" def denotStr(denot: Denotation): String = if (denot.isOverloaded) overloadedAltsStr(denot.alternatives) @@ -97,9 +100,8 @@ object ErrorReporting { def patternConstrStr(tree: Tree): String = ??? - def typeMismatch(tree: Tree, pt: Type, implicitFailure: SearchFailure = NoImplicitMatches): Tree = { + def typeMismatch(tree: Tree, pt: Type, implicitFailure: SearchFailure = NoImplicitMatches): Tree = errorTree(tree, typeMismatchStr(normalize(tree.tpe, pt), pt) + implicitFailure.postscript) - } /** A subtype log explaining why `found` does not conform to `expected` */ def whyNoMatchStr(found: Type, expected: Type) = @@ -108,28 +110,31 @@ object ErrorReporting { else "" - def typeMismatchStr(found: Type, expected: Type) = disambiguated { implicit ctx => - def infoStr = found match { // DEBUG - case tp: TypeRef => s"with info ${tp.info} / ${tp.prefix.toString} / ${tp.prefix.dealias.toString}" - case _ => "" - } + def typeMismatchStr(found: Type, expected: Type) = { // replace constrained polyparams and their typevars by their bounds where possible - val reported = new TypeMap { + object reported extends TypeMap { + def setVariance(v: Int) = variance = v + val constraint = ctx.typerState.constraint def apply(tp: Type): Type = tp match { case tp: PolyParam => - val e = ctx.typerState.constraint.entry(tp) - if (e.exists) - if (variance > 0) e.bounds.hi - else if (variance < 0) e.bounds.lo - else tp - else tp + constraint.entry(tp) match { + case bounds: TypeBounds => + if (variance < 0) apply(constraint.fullUpperBound(tp)) + else if (variance > 0) apply(constraint.fullLowerBound(tp)) + else tp + case NoType => tp + case instType => apply(instType) + } case tp: TypeVar => apply(tp.stripTypeVar) case _ => mapOver(tp) } } - d"""type mismatch: - | found : $found - | required: ${reported(expected)}""".stripMargin + whyNoMatchStr(found, expected) + val found1 = reported(found) + reported.setVariance(-1) + val expected1 = reported(expected) + ex"""type mismatch: + | found : $found1 + | required: $expected1""" + whyNoMatchStr(found, expected) } /** Format `raw` implicitNotFound argument, replacing all @@ -139,35 +144,11 @@ object ErrorReporting { def implicitNotFoundString(raw: String, paramNames: List[String], args: List[Type]): String = { def translate(name: String): Option[String] = { val idx = paramNames.indexOf(name) - if (idx >= 0) Some(quoteReplacement(args(idx).show)) else None + if (idx >= 0) Some(quoteReplacement(ex"${args(idx)}")) else None } """\$\{\w*\}""".r.replaceSomeIn(raw, m => translate(m.matched.drop(2).init)) } } def err(implicit ctx: Context): Errors = new Errors - - /** The d string interpolator works like the i string interpolator, but marks nonsensical errors - * using `...` tags. - * Note: Instead of these tags, it would be nicer to return a data structure containing the message string - * and a boolean indicating whether the message is sensical, but then we cannot use string operations - * like concatenation, stripMargin etc on the values returned by d"...", and in the current error - * message composition methods, this is crucial. - */ - implicit class DiagnosticString(val sc: StringContext) extends AnyVal { - def d(args: Any*)(implicit ctx: Context): String = { - def isSensical(arg: Any): Boolean = arg match { - case l: Seq[_] => l.forall(isSensical(_)) - case tpe: Type if tpe.isErroneous => false - case NoType => false - case sym: Symbol if sym.isCompleted => - sym.info != ErrorType && sym.info != TypeAlias(ErrorType) && sym.info != NoType - case _ => true - } - - val s = new StringInterpolators(sc).i(args : _*) - if (args.forall(isSensical(_))) s - else Diagnostic.nonSensicalStartTag + s + Diagnostic.nonSensicalEndTag - } - } } diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala index 1eba64e2e..0a3307140 100644 --- a/src/dotty/tools/dotc/typer/Implicits.scala +++ b/src/dotty/tools/dotc/typer/Implicits.scala @@ -217,8 +217,8 @@ object Implicits { protected def pt: Type protected def argument: tpd.Tree protected def qualify(implicit ctx: Context) = - if (argument.isEmpty) d"match type $pt" - else d"convert from ${argument.tpe} to $pt" + if (argument.isEmpty) em"match type $pt" + else em"convert from ${argument.tpe} to $pt" /** An explanation of the cause of the failure as a string */ def explanation(implicit ctx: Context): String @@ -227,7 +227,7 @@ object Implicits { /** An ambiguous implicits failure */ class AmbiguousImplicits(alt1: TermRef, alt2: TermRef, val pt: Type, val argument: tpd.Tree) extends ExplainedSearchFailure { def explanation(implicit ctx: Context): String = - d"both ${err.refStr(alt1)} and ${err.refStr(alt2)} $qualify" + em"both ${err.refStr(alt1)} and ${err.refStr(alt2)} $qualify" override def postscript(implicit ctx: Context) = "\nNote that implicit conversions cannot be applied because they are ambiguous;" + "\n " + explanation @@ -235,17 +235,17 @@ object Implicits { class NonMatchingImplicit(ref: TermRef, val pt: Type, val argument: tpd.Tree) extends ExplainedSearchFailure { def explanation(implicit ctx: Context): String = - d"${err.refStr(ref)} does not $qualify" + em"${err.refStr(ref)} does not $qualify" } class ShadowedImplicit(ref: TermRef, shadowing: Type, val pt: Type, val argument: tpd.Tree) extends ExplainedSearchFailure { def explanation(implicit ctx: Context): String = - d"${err.refStr(ref)} does $qualify but is shadowed by ${err.refStr(shadowing)}" + em"${err.refStr(ref)} does $qualify but is shadowed by ${err.refStr(shadowing)}" } class DivergingImplicit(ref: TermRef, val pt: Type, val argument: tpd.Tree) extends ExplainedSearchFailure { def explanation(implicit ctx: Context): String = - d"${err.refStr(ref)} produces a diverging implicit search when trying to $qualify" + em"${err.refStr(ref)} produces a diverging implicit search when trying to $qualify" } class FailedImplicit(failures: List[ExplainedSearchFailure], val pt: Type, val argument: tpd.Tree) extends ExplainedSearchFailure { @@ -253,7 +253,9 @@ object Implicits { if (failures.isEmpty) s" No implicit candidates were found that $qualify" else " " + (failures map (_.explanation) mkString "\n ") override def postscript(implicit ctx: Context): String = - "\nImplicit search failure summary:\n" + explanation + i""" + |Implicit search failure summary: + |$explanation""" } } @@ -456,7 +458,7 @@ trait Implicits { self: Typer => if (!arg.isEmpty) arg else { var msgFn = (where: String) => - d"no implicit argument of type $formal found for $where" + failure.postscript + em"no implicit argument of type $formal found for $where" + failure.postscript for { notFound <- formal.typeSymbol.getAnnotation(defn.ImplicitNotFoundAnnot) Trees.Literal(Constant(raw: String)) <- notFound.argument(0) @@ -568,7 +570,7 @@ trait Implicits { self: Typer => // Not clear whether we need to drop the `.widen` here. All tests pass with it in place, though. assert(argument.isEmpty || argument.tpe.isValueType || argument.tpe.isInstanceOf[ExprType], - d"found: $argument: ${argument.tpe}, expected: $pt") + em"found: $argument: ${argument.tpe}, expected: $pt") /** The expected type for the searched implicit */ lazy val fullProto = implicitProto(pt, identity) diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index f917c233f..698f7e9a9 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -646,7 +646,7 @@ class Namer { typer: Typer => val pname = paramAccessor.name def illegal(how: String): Unit = { - ctx.error(d"Illegal override of public type parameter $pname in $parent$how", paramAccessor.pos) + ctx.error(em"Illegal override of public type parameter $pname in $parent$how", paramAccessor.pos) ok = false } @@ -659,7 +659,7 @@ class Namer { typer: Typer => case TypeRef(pre, name1) if name1 == pname && (pre =:= cls.thisType) => // OK, parameter is passed on directly case _ => - illegal(d".\nParameter is both redeclared and instantiated with $alias.") + illegal(em".\nParameter is both redeclared and instantiated with $alias.") } case _ => // OK, argument is not fully defined } @@ -832,7 +832,7 @@ class Namer { typer: Typer => // println(s"final inherited for $sym: ${inherited.toString}") !!! // println(s"owner = ${sym.owner}, decls = ${sym.owner.info.decls.show}") def isInline = sym.is(Final, butNot = Method | Mutable) - + // Widen rhs type and approximate `|' but keep ConstantTypes if // definition is inline (i.e. final in Scala2). def widenRhs(tp: Type): Type = tp.widenTermRefExpr match { @@ -856,7 +856,7 @@ class Namer { typer: Typer => else { if (sym is Implicit) { val resStr = if (mdef.isInstanceOf[DefDef]) "result " else "" - ctx.error(d"${resStr}type of implicit definition needs to be given explicitly", mdef.pos) + ctx.error(s"${resStr}type of implicit definition needs to be given explicitly", mdef.pos) sym.resetFlag(Implicit) } lhsType orElse WildcardType diff --git a/src/dotty/tools/dotc/typer/RefChecks.scala b/src/dotty/tools/dotc/typer/RefChecks.scala index a654bb08f..2838866fd 100644 --- a/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/src/dotty/tools/dotc/typer/RefChecks.scala @@ -81,14 +81,14 @@ object RefChecks { def checkSelfConforms(other: TypeRef, category: String, relation: String) = { val otherSelf = other.givenSelfType.asSeenFrom(cls.thisType, other.classSymbol) if (otherSelf.exists && !(cinfo.selfType <:< otherSelf)) - ctx.error(d"$category: self type ${cinfo.selfType} of $cls does not conform to self type $otherSelf of $relation ${other.classSymbol}", cls.pos) + ctx.error(ex"$category: self type ${cinfo.selfType} of $cls does not conform to self type $otherSelf of $relation ${other.classSymbol}", cls.pos) } for (parent <- cinfo.classParents) { val pclazz = parent.classSymbol if (pclazz.is(Final)) - ctx.error(d"cannot extend final $pclazz", cls.pos) + ctx.error(em"cannot extend final $pclazz", cls.pos) if (pclazz.is(Sealed) && pclazz.associatedFile != cls.associatedFile) - ctx.error(d"cannot extend sealed $pclazz in different compilation unit", cls.pos) + ctx.error(em"cannot extend sealed $pclazz in different compilation unit", cls.pos) checkSelfConforms(parent, "illegal inheritance", "parent") } for (reqd <- cinfo.givenSelfType.classSymbols) diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala index c2b7b7101..ab151fb1d 100644 --- a/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -171,13 +171,13 @@ trait TypeAssigner { case sym :: Nil => if (sym.owner == pre.typeSymbol) sym.show else sym.showLocated case _ => - d"none of the overloaded alternatives named $name" + em"none of the overloaded alternatives named $name" } val where = if (ctx.owner.exists) s" from ${ctx.owner.enclosingClass}" else "" val whyNot = new StringBuffer alts foreach (_.isAccessibleFrom(pre, superAccess, whyNot)) if (!tpe.isError) - ctx.error(d"$what cannot be accessed as a member of $pre$where.$whyNot", pos) + ctx.error(ex"$what cannot be accessed as a member of $pre$where.$whyNot", pos) ErrorType } } @@ -205,10 +205,12 @@ trait TypeAssigner { if (!site.isErroneous) { def notAMember = d"${if (name.isTypeName) "type" else "value"} $name is not a member of $site" ctx.error( - if (name == nme.CONSTRUCTOR) d"$site does not have a constructor" - else if (site.derivesFrom(defn.DynamicClass)) s"$notAMember\npossible cause: maybe a wrong Dynamic method signature?" - else notAMember, - pos) + if (name == nme.CONSTRUCTOR) ex"$site does not have a constructor" + else if (site.derivesFrom(defn.DynamicClass)) { + ex"$name is not a member of $site\n" + + "possible cause: maybe a wrong Dynamic method signature?" + } + else ex"$name is not a member of $site", pos) } ErrorType } @@ -283,7 +285,7 @@ trait TypeAssigner { case p :: Nil => p case Nil => - errorType(d"$mix does not name a parent class of $cls", tree.pos) + errorType(em"$mix does not name a parent class of $cls", tree.pos) case p :: q :: _ => errorType("ambiguous parent class qualifier", tree.pos) } @@ -302,7 +304,7 @@ trait TypeAssigner { val ownType = fn.tpe.widen match { case fntpe @ MethodType(_, ptypes) => if (sameLength(ptypes, args) || ctx.phase.prev.relaxedTyping) fntpe.instantiate(args.tpes) - else errorType(i"wrong number of parameters for ${fn.tpe}; expected: ${ptypes.length}", tree.pos) + else wrongNumberOfArgs(fn.tpe, "", ptypes.length, tree.pos) case t => errorType(i"${err.exprStr(fn)} does not take parameters", tree.pos) } @@ -348,7 +350,7 @@ trait TypeAssigner { else { val argTypes = args.tpes if (sameLength(argTypes, paramNames)|| ctx.phase.prev.relaxedTyping) pt.instantiate(argTypes) - else errorType(d"wrong number of type parameters for ${fn.tpe}; expected: ${pt.paramNames.length}", tree.pos) + else wrongNumberOfArgs(fn.tpe, "type ", pt.paramNames.length, tree.pos) } case _ => errorType(i"${err.exprStr(fn)} does not take type parameters", tree.pos) @@ -429,7 +431,7 @@ trait TypeAssigner { val ownType = if (hasNamedArg(args)) (tycon.tpe /: args)(refineNamed) else if (sameLength(tparams, args)) tycon.tpe.appliedTo(args.tpes) - else errorType(d"wrong number of type arguments for ${tycon.tpe}, should be ${tparams.length}", tree.pos) + else wrongNumberOfArgs(tycon.tpe, "type ", tparams.length, tree.pos) tree.withType(ownType) } diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index e982f9aa9..2b690ef51 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -134,8 +134,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit * or defined in */ def bindingString(prec: Int, whereFound: Context, qualifier: String = "") = - if (prec == wildImport || prec == namedImport) d"imported$qualifier by ${whereFound.importInfo}" - else d"defined$qualifier in ${whereFound.owner}" + if (prec == wildImport || prec == namedImport) ex"imported$qualifier by ${whereFound.importInfo}" + else ex"defined$qualifier in ${whereFound.owner}" /** Check that any previously found result from an inner context * does properly shadow the new one from an outer context. @@ -152,9 +152,9 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit else { if (!previous.isError && !found.isError) { error( - d"""reference to $name is ambiguous; - |it is both ${bindingString(newPrec, ctx, "")} - |and ${bindingString(prevPrec, prevCtx, " subsequently")}""".stripMargin, + ex"""reference to $name is ambiguous; + |it is both ${bindingString(newPrec, ctx, "")} + |and ${bindingString(prevPrec, prevCtx, " subsequently")}""", tree.pos) } previous @@ -167,7 +167,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def checkUnambiguous(found: Type) = { val other = namedImportRef(site, selectors.tail) if (other.exists && found.exists && (found != other)) - error(d"reference to $name is ambiguous; it is imported twice in ${ctx.tree}", + error(em"reference to $name is ambiguous; it is imported twice in ${ctx.tree}", tree.pos) found } @@ -275,7 +275,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit if (rawType.exists) ensureAccessible(rawType, superAccess = false, tree.pos) else { - error(d"not found: $kind$name", tree.pos) + error(em"not found: $kind$name", tree.pos) ErrorType } @@ -304,10 +304,10 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit tree match { case tree @ Select(qual, _) if !qual.tpe.isStable => val alt = typedSelect(tree, pt, Typed(qual, TypeTree(SkolemType(qual.tpe.widen)))) - typr.println(d"healed type: ${tree.tpe} --> $alt") + typr.println(i"healed type: ${tree.tpe} --> $alt") alt.asInstanceOf[T] case _ => - ctx.error(d"unsafe instantiation of type ${tree.tpe}", tree.pos) + ctx.error(ex"unsafe instantiation of type ${tree.tpe}", tree.pos) tree } else tree @@ -342,7 +342,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit convertToSelectFromType(tree.qualifier, tree.name) match { case Some(sftt) => typedSelectFromTypeTree(sftt, pt) - case _ => ctx.error(d"Could not convert $tree to a SelectFromTypeTree"); EmptyTree + case _ => ctx.error(em"Could not convert $tree to a SelectFromTypeTree"); EmptyTree } } @@ -569,7 +569,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit ensureNoLocalRefs(tree1, pt, localSyms, forcedDefined = true) } else errorTree(tree, - d"local definition of ${leaks.head.name} escapes as part of expression's type ${tree.tpe}"/*; full type: ${result.tpe.toString}"*/) + em"local definition of ${leaks.head.name} escapes as part of expression's type ${tree.tpe}"/*; full type: ${result.tpe.toString}"*/) } def typedIf(tree: untpd.If, pt: Type)(implicit ctx: Context) = track("typedIf") { @@ -723,7 +723,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit pt match { case SAMType(meth) if !defn.isFunctionType(pt) && mt <:< meth.info => if (!isFullyDefined(pt, ForceDegree.all)) - ctx.error(d"result type of closure is an underspecified SAM type $pt", tree.pos) + ctx.error(ex"result type of closure is an underspecified SAM type $pt", tree.pos) TypeTree(pt) case _ => if (!mt.isDependent) EmptyTree @@ -802,7 +802,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit super.transform(tree.withType(elimWildcardSym(tree.tpe))) match { case b: Bind => if (ctx.scope.lookup(b.name) == NoSymbol) ctx.enter(b.symbol) - else ctx.error(d"duplicate pattern variable: ${b.name}", b.pos) + else ctx.error(em"duplicate pattern variable: ${b.name}", b.pos) b.symbol.info = elimWildcardSym(b.symbol.info) b case t => t @@ -854,7 +854,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit val proto = returnProto(owner, cx.scope) (from, proto) } - else (EmptyTree, errorType(d"$owner has return statement; needs result type", tree.pos)) + else (EmptyTree, errorType(em"$owner has return statement; needs result type", tree.pos)) } else enclMethInfo(cx.outer) } @@ -973,7 +973,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit val tpt1 = typed(tree.tpt, AnyTypeConstructorProto)(ctx.retractMode(Mode.Pattern)) val tparams = tpt1.tpe.typeParams if (tparams.isEmpty) { - ctx.error(d"${tpt1.tpe} does not take type parameters", tree.pos) + ctx.error(ex"${tpt1.tpe} does not take type parameters", tree.pos) tpt1 } else { @@ -982,7 +982,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit if (hasNamedArg(args)) typedNamedArgs(args) else { if (args.length != tparams.length) { - ctx.error(d"wrong number of type arguments for ${tpt1.tpe}, should be ${tparams.length}", tree.pos) + wrongNumberOfArgs(tpt1.tpe, "type ", tparams.length, tree.pos) args = args.take(tparams.length) } def typedArg(arg: untpd.Tree, tparam: TypeParamInfo) = { @@ -1207,7 +1207,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit case _ => // add synthetic class type val first :: _ = ensureFirstIsClass(parents.tpes) - TypeTree(checkFeasible(first, pos, d"\n in inferred parent $first")).withPos(pos) :: parents + TypeTree(checkFeasible(first, pos, em"\n in inferred parent $first")).withPos(pos) :: parents } /** If this is a real class, make sure its first parent is a @@ -1239,7 +1239,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit val packageContext = if (pkg is Package) ctx.fresh.setOwner(pkg.moduleClass).setTree(tree) else { - ctx.error(d"$pkg is already defined, cannot be a package", tree.pos) + ctx.error(em"$pkg is already defined, cannot be a package", tree.pos) ctx } val stats1 = typedStats(tree.stats, pkg.moduleClass)(packageContext) @@ -1522,8 +1522,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def methodStr = err.refStr(methPart(tree).tpe) def missingArgs = errorTree(tree, - d"""missing arguments for $methodStr - |follow this method with `_' if you want to treat it as a partially applied function""".stripMargin) + em"""missing arguments for $methodStr + |follow this method with `_' if you want to treat it as a partially applied function""") def adaptOverloaded(ref: TermRef) = { val altDenots = ref.denot.alternatives @@ -1537,8 +1537,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit case Nil => def noMatches = errorTree(tree, - d"""none of the ${err.overloadedAltsStr(altDenots)} - |match $expectedStr""".stripMargin) + em"""none of the ${err.overloadedAltsStr(altDenots)} + |match $expectedStr""") def hasEmptyParams(denot: SingleDenotation) = denot.info.paramTypess == ListOfNil pt match { case pt: FunProto => @@ -1553,8 +1553,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit val remainingDenots = alts map (_.denot.asInstanceOf[SingleDenotation]) def all = if (remainingDenots.length == 2) "both" else "all" errorTree(tree, - d"""Ambiguous overload. The ${err.overloadedAltsStr(remainingDenots)} - |$all match $expectedStr""".stripMargin) + em"""Ambiguous overload. The ${err.overloadedAltsStr(remainingDenots)} + |$all match $expectedStr""") } } @@ -1581,7 +1581,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit case Apply(_, _) => " more" case _ => "" } - (_, _) => errorTree(tree, d"$methodStr does not take$more parameters") + (_, _) => errorTree(tree, em"$methodStr does not take$more parameters") } } @@ -1630,7 +1630,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } val args = (wtp.paramNames, wtp.paramTypes).zipped map { (pname, formal) => def implicitArgError(msg: String => String) = - errors += (() => msg(d"parameter $pname of $methodStr")) + errors += (() => msg(em"parameter $pname of $methodStr")) inferImplicitArg(formal, implicitArgError, tree.pos.endPos) } if (errors.nonEmpty) { -- cgit v1.2.3