Skip to content

Make suggestions of missing implicits imports on type errors #7862

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Jan 5, 2020
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
7cea875
Make "did you mean hints" less chatty
odersky Dec 28, 2019
9a3c33a
Make suggestions of missing implicits imports on type errors
odersky Dec 28, 2019
53a6098
Sort suggestions alphabetically
odersky Dec 29, 2019
b848c57
Don't treat package object's <init> methods as package members
odersky Dec 30, 2019
13c1839
Refine search and reporting criteria
odersky Dec 30, 2019
e1360eb
Don't suggest imports for conversions from Null or Nothing
odersky Dec 30, 2019
5e3f11c
Implement cancellation
odersky Dec 31, 2019
540f69a
Subject implicit suggestion searches to timeouts
odersky Dec 31, 2019
2ccec1f
Streamline suggestion printing
odersky Jan 1, 2020
51f19ec
Use java.util.Timer
odersky Jan 1, 2020
55b1a31
Drop Scheduler
odersky Jan 2, 2020
9c67ee4
Revise search logic
odersky Jan 2, 2020
b3a4966
Some refinements
odersky Jan 2, 2020
717cb7d
Refine implicit search criterion and prioritization
odersky Jan 4, 2020
ad5055b
Further refinement of "did you mean" hints
odersky Jan 4, 2020
848dd0a
Print package symbols always under their full names
odersky Jan 4, 2020
72df855
Fix repl test
odersky Jan 4, 2020
0501bfa
Refactorings and comments for better clarity
odersky Jan 4, 2020
1124b35
Fix two more repl tests
odersky Jan 4, 2020
c601a72
Issue a "did you mean" hint only if there's nothing else to say
odersky Jan 5, 2020
02d7594
Remove dead code and data in "did you mean" hints
odersky Jan 5, 2020
9e72e6c
Better explanation for missing members that have extension methods
odersky Jan 5, 2020
aabcd81
Also suggest imports of extension methods
odersky Jan 5, 2020
427da51
Factor out suggestions logic into its own trait
odersky Jan 5, 2020
5ac8b80
Also suggest partial matches for missing implicit arguments
odersky Jan 5, 2020
8289d51
Don't mention evidence$n parameters in error message
odersky Jan 5, 2020
6f94a83
Fix unrelated test
odersky Jan 5, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions compiler/src/dotty/tools/dotc/Run.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ import scala.util.control.NonFatal
/** A compiler run. Exports various methods to compile source files */
class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with ConstraintRunInfo {

/** If this variable is set to `true`, some core typer operations will
* return immediately. Currently these early abort operations are
* `Typer.typed` and `Implicits.typedImplicit`.
*/
@volatile var isCancelled = false

/** Produces the following contexts, from outermost to innermost
*
* bootStrap: A context with next available runId and a scope consisting of
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,9 @@ class Definitions {
}
@tu lazy val ScalaPackageObject: Symbol = ctx.requiredModule("scala.package")
@tu lazy val JavaPackageVal: TermSymbol = ctx.requiredPackage(nme.java)
@tu lazy val JavaPackageClass: ClassSymbol = JavaPackageVal.moduleClass.asClass
@tu lazy val JavaLangPackageVal: TermSymbol = ctx.requiredPackage(jnme.JavaLang)
@tu lazy val JavaLangPackageClass: ClassSymbol = JavaLangPackageVal.moduleClass.asClass

// fundamental modules
@tu lazy val SysPackage : Symbol = ctx.requiredModule("scala.sys.package")
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2205,7 +2205,7 @@ object SymDenotations {

if (symbol `eq` defn.ScalaPackageClass) {
val denots = super.computeNPMembersNamed(name)
if (denots.exists) denots
if (denots.exists || name == nme.CONSTRUCTOR) denots
else recur(packageObjs, NoDenotation)
}
else recur(packageObjs, NoDenotation)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/TypeErrors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ object CyclicReference {
def apply(denot: SymDenotation)(implicit ctx: Context): CyclicReference = {
val ex = new CyclicReference(denot)
if (!(ctx.mode is Mode.CheckCyclic)) {
cyclicErrors.println(ex.getMessage)
cyclicErrors.println(s"Cyclic reference involving $denot")
for (elem <- ex.getStackTrace take 200)
cyclicErrors.println(elem.toString)
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ class PlainPrinter(_ctx: Context) extends Printer {
}

/** The string representation of this type used as a prefix */
protected def toTextRef(tp: SingletonType): Text = controlled {
def toTextRef(tp: SingletonType): Text = controlled {
tp match {
case tp: TermRef =>
toTextPrefix(tp.prefix) ~ selectionString(tp)
Expand Down Expand Up @@ -438,6 +438,7 @@ class PlainPrinter(_ctx: Context) extends Printer {
(kindString(sym) ~~ {
if (sym.isAnonymousClass) toTextParents(sym.info.parents) ~~ "{...}"
else if (hasMeaninglessName(sym) && !printDebug) simpleNameString(sym.owner) + idString(sym)
else if sym.is(Package) then fullNameString(sym)
else nameString(sym)
}).close

Expand Down
5 changes: 4 additions & 1 deletion compiler/src/dotty/tools/dotc/printing/Printer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package printing

import core._
import Texts._, ast.Trees._
import Types.Type, Symbols.Symbol, Scopes.Scope, Constants.Constant,
import Types.{Type, SingletonType}, Symbols.Symbol, Scopes.Scope, Constants.Constant,
Names.Name, Denotations._, Annotations.Annotation
import typer.Implicits.SearchResult
import util.SourcePosition
Expand Down Expand Up @@ -97,6 +97,9 @@ abstract class Printer {
*/
def toText(sym: Symbol): Text

/** Textual representation of singeton type reference */
def toTextRef(tp: SingletonType): Text

/** Textual representation of symbol's declaration */
def dclText(sym: Symbol): Text

Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
def name =
if (printDebug)
nameString(sym)
else if sym.is(Package) then
fullNameString(sym)
else if (sym.is(ModuleClass) && sym.isPackageObject && sym.name.stripModuleClassSuffix == tpnme.PACKAGE)
nameString(sym.owner.name)
else if (sym.is(ModuleClass))
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/reporting/Reporter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import diagnostic.messages._
import diagnostic._
import ast.{tpd, Trees}
import Message._
import core.Decorators._

import java.lang.System.currentTimeMillis
import java.io.{ BufferedReader, PrintWriter }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,12 @@ object messages {
// Get closest match in `site`
val closest =
decls
.map { case (n, sym) => (n, distance(n, name.show), sym) }
.collect { case (n, dist, sym) if dist <= maxDist => (n, dist, sym) }
.map { (n, sym) => (n, distance(n, name.show), sym) }
.collect {
case (n, dist, sym)
if dist <= maxDist && dist < (name.toString.length min n.length) =>
(n, dist, sym)
}
.groupBy(_._2).toList
.sortBy(_._1)
.headOption.map(_._2).getOrElse(Nil)
Expand Down
10 changes: 9 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,15 @@ object ErrorReporting {
val expected1 = reported(expected)
val (found2, expected2) =
if (found1 frozen_<:< expected1) (found, expected) else (found1, expected1)
TypeMismatch(found2, expected2, whyNoMatchStr(found, expected), postScript)
val postScript1 =
if !postScript.isEmpty
|| expected.isRef(defn.AnyClass)
|| expected.isRef(defn.AnyValClass)
|| expected.isRef(defn.ObjectClass)
|| defn.isBottomType(found)
then postScript
else ctx.typer.implicitSuggestionAddendum(ViewProto(found.widen, expected))
TypeMismatch(found2, expected2, whyNoMatchStr(found, expected), postScript1)
}

/** Format `raw` implicitNotFound or implicitAmbiguous argument, replacing
Expand Down
Loading