Skip to content

Commit a32b4b8

Browse files
committed
The great implicits re-org
Refactoring of implicits with the aim of clearer code and better error messages. Here's an example: -- Error: implicitSearch.scala:15:12 ------------------------------------------- 15 | sort(xs) // error (with a partially constructed implicit argument shown) | ^ |no implicit argument of type Test.Ord[scala.collection.immutable.List[scala.collection.immutable.List[T]]] was found for parameter o of method sort in object Test. |I found: | | Test.listOrd[T](Test.listOrd[T](/* missing */implicitly[Test.Ord[T]])) | |But no implicit values were found that match type Test.Ord[T].
1 parent c1c9198 commit a32b4b8

File tree

11 files changed

+261
-262
lines changed

11 files changed

+261
-262
lines changed

compiler/src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,9 @@ object Trees {
145145
}
146146

147147
/** A unique identifier for this tree. Used for debugging, and potentially
148-
* tracking presentation compiler interactions
148+
* tracking presentation compiler interactions.
149149
*/
150-
private var myUniqueId: Int = nxId
150+
@sharable private var myUniqueId: Int = nxId
151151

152152
def uniqueId = myUniqueId
153153

@@ -449,6 +449,11 @@ object Trees {
449449
override def toString = s"BackquotedIdent($name)"
450450
}
451451

452+
class SearchFailureIdent[-T >: Untyped] private[ast] (name: Name)
453+
extends Ident[T](name) {
454+
override def toString = s"SearchFailureIdent($name)"
455+
}
456+
452457
/** qualifier.name, or qualifier#name, if qualifier is a type */
453458
case class Select[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name)
454459
extends RefTree[T] {
@@ -948,6 +953,7 @@ object Trees {
948953

949954
type Ident = Trees.Ident[T]
950955
type BackquotedIdent = Trees.BackquotedIdent[T]
956+
type SearchFailureIdent = Trees.SearchFailureIdent[T]
951957
type Select = Trees.Select[T]
952958
type SelectWithSig = Trees.SelectWithSig[T]
953959
type This = Trees.This[T]

compiler/src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
282282

283283
def Ident(name: Name): Ident = new Ident(name)
284284
def BackquotedIdent(name: Name): BackquotedIdent = new BackquotedIdent(name)
285+
def SearchFailureIdent(name: Name): SearchFailureIdent = new SearchFailureIdent(name)
285286
def Select(qualifier: Tree, name: Name): Select = new Select(qualifier, name)
286287
def SelectWithSig(qualifier: Tree, name: Name, sig: Signature): Select = new SelectWithSig(qualifier, name, sig)
287288
def This(qual: Ident): This = new This(qual)

compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ class ScalaSettings extends Settings.SettingGroup {
2626
val migration = BooleanSetting("-migration", "Emit warning and location for migration issues from Scala 2.")
2727
val encoding = StringSetting("-encoding", "encoding", "Specify character encoding used by source files.", Properties.sourceEncoding)
2828
val explainTypes = BooleanSetting("-explain-types", "Explain type errors in more detail.")
29-
val explainImplicits = BooleanSetting("-explain-implicits", "Explain implicit search errors in more detail.")
3029
val explain = BooleanSetting("-explain", "Explain errors in more detail.")
3130
val feature = BooleanSetting("-feature", "Emit warning and location for usages of features that should be imported explicitly.")
3231
val help = BooleanSetting("-help", "Print a synopsis of standard options")

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

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1981,7 +1981,7 @@ object Types {
19811981
else candidate
19821982

19831983
def withPrefix(prefix: Type)(implicit ctx: Context): NamedType = designator match {
1984-
case designator: TermSymbol =>
1984+
case designator: TermSymbol @unchecked =>
19851985
TermRef(prefix, designator)
19861986
case _ =>
19871987
// If symbol exists, the new signature is the symbol's signature as seen
@@ -3641,22 +3641,25 @@ object Types {
36413641
*/
36423642
abstract class FlexType extends UncachedGroundType with ValueType
36433643

3644-
class ErrorType private[Types] () extends FlexType {
3645-
def msg(implicit ctx: Context): Message =
3646-
ctx.errorTypeMsg.get(this) match {
3647-
case Some(msgFun) => msgFun()
3648-
case None => "error message from previous run no longer available"
3649-
}
3644+
abstract class ErrorType extends FlexType {
3645+
def msg(implicit ctx: Context): Message
36503646
}
3647+
36513648
object ErrorType {
36523649
def apply(msg: => Message)(implicit ctx: Context): ErrorType = {
3653-
val et = new ErrorType
3650+
val et = new ErrorType {
3651+
def msg(implicit ctx: Context): Message =
3652+
ctx.errorTypeMsg.get(this) match {
3653+
case Some(msgFun) => msgFun()
3654+
case None => "error message from previous run no longer available"
3655+
}
3656+
}
36543657
ctx.base.errorTypeMsg(et) = () => msg
36553658
et
36563659
}
36573660
}
36583661

3659-
object UnspecifiedErrorType extends ErrorType() {
3662+
object UnspecifiedErrorType extends ErrorType {
36603663
override def msg(implicit ctx: Context): Message = "unspecified error"
36613664
}
36623665

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

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,8 @@ class PlainPrinter(_ctx: Context) extends Printer {
171171
changePrec(AndPrec) { toText(tp1) ~ " & " ~ toText(tp2) }
172172
case OrType(tp1, tp2) =>
173173
changePrec(OrPrec) { toText(tp1) ~ " | " ~ toText(tp2) }
174-
case _: ErrorType =>
175-
"<error>"
174+
case tp: ErrorType =>
175+
s"<error ${tp.msg.msg}>"
176176
case tp: WildcardType =>
177177
if (tp.optBounds.exists) "(?" ~ toTextRHS(tp.bounds) ~ ")" else "?"
178178
case NoType =>
@@ -202,8 +202,6 @@ class PlainPrinter(_ctx: Context) extends Printer {
202202
ParamRefNameString(tp) ~ ".type"
203203
case AnnotatedType(tpe, annot) =>
204204
toTextLocal(tpe) ~ " " ~ toText(annot)
205-
case AppliedType(tycon, args) =>
206-
toTextLocal(tycon) ~ "[" ~ Text(args.map(argText), ", ") ~ "]"
207205
case tp: TypeVar =>
208206
if (tp.isInstantiated)
209207
toTextLocal(tp.instanceOpt) ~ ("^" provided ctx.settings.YprintDebug.value)
@@ -501,18 +499,16 @@ class PlainPrinter(_ctx: Context) extends Printer {
501499
def toText(result: SearchResult): Text = result match {
502500
case result: SearchSuccess =>
503501
"SearchSuccess: " ~ toText(result.ref) ~ " via " ~ toText(result.tree)
504-
case _: NonMatchingImplicit | NoImplicitMatches =>
505-
"NoImplicitMatches"
506-
case _: DivergingImplicit =>
507-
"Diverging Implicit"
508-
case result: ShadowedImplicit =>
509-
"Shadowed Implicit"
510-
case result: FailedImplicit =>
511-
"Failed Implicit"
512-
case result: AmbiguousImplicits =>
513-
"Ambiguous Implicit: " ~ toText(result.alt1) ~ " and " ~ toText(result.alt2)
514-
case _ =>
515-
"?Unknown Implicit Result?" + result.getClass
502+
case result: SearchFailure =>
503+
result.reason match {
504+
case _: NoMatchingImplicits => "No Matching Implicit"
505+
case _: DivergingImplicit => "Diverging Implicit"
506+
case _: ShadowedImplicit => "Shadowed Implicit"
507+
case result: AmbiguousImplicits =>
508+
"Ambiguous Implicit: " ~ toText(result.alt1) ~ " and " ~ toText(result.alt2)
509+
case _ =>
510+
"?Unknown Implicit Result?" + result.getClass
511+
}
516512
}
517513

518514
def toText(importInfo: ImportInfo): Text = {

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import TypeErasure.ErasedValueType
77
import Contexts.Context, Scopes.Scope, Denotations._, SymDenotations._, Annotations.Annotation
88
import StdNames.{nme, tpnme}
99
import ast.{Trees, untpd, tpd}
10-
import typer.{Namer, Inliner}
10+
import typer.{Namer, Inliner, Implicits}
1111
import typer.ProtoTypes.{SelectionProto, ViewProto, FunProto, IgnoredProto, dummyTreeOfType}
1212
import Trees._
1313
import TypeApplications._
@@ -332,6 +332,13 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
332332
def toTextCore(tree: Tree): Text = tree match {
333333
case id: Trees.BackquotedIdent[_] if !homogenizedView =>
334334
"`" ~ toText(id.name) ~ "`"
335+
case id: Trees.SearchFailureIdent[_] =>
336+
tree.typeOpt match {
337+
case reason: Implicits.SearchFailureType =>
338+
toText(id.name) ~ "implicitly[" ~ toText(reason.expectedType) ~ "]"
339+
case _ =>
340+
toText(id.name)
341+
}
335342
case Ident(name) =>
336343
tree.typeOpt match {
337344
case tp: NamedType if name != nme.WILDCARD =>

compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,11 @@ object ErrorReporting {
104104

105105
def patternConstrStr(tree: Tree): String = ???
106106

107-
def typeMismatch(tree: Tree, pt: Type, implicitFailure: SearchFailure = NoImplicitMatches): Tree = {
107+
def typeMismatch(tree: Tree, pt: Type, implicitFailure: SearchFailureType = NoMatchingImplicits): Tree = {
108108
val normTp = normalize(tree.tpe, pt)
109109
val treeTp = if (normTp <:< pt) tree.tpe else normTp
110110
// use normalized type if that also shows an error, original type otherwise
111-
errorTree(tree, typeMismatchMsg(treeTp, pt, implicitFailure.postscript))
111+
errorTree(tree, typeMismatchMsg(treeTp, pt, implicitFailure.whyNoConversion))
112112
}
113113

114114
/** A subtype log explaining why `found` does not conform to `expected` */

0 commit comments

Comments
 (0)