From 4073d2432b6c4d2cec9b51faa1bc155f3db4dc5c Mon Sep 17 00:00:00 2001 From: bjornregnell Date: Tue, 24 Aug 2021 19:05:42 +0200 Subject: [PATCH 1/2] fix #13320 add .type to modules in messages co-authored by: Anatolii Kmetiuk anatoliykmetyuk@gmail.com --- .../dotty/tools/dotc/reporting/messages.scala | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index 04c345b9d790..fa49776bad85 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -280,12 +280,12 @@ import transform.SymUtils._ val (foundStr, expectedStr) = Formatting.typeDiff(found2, expected2)(using printCtx) s"""|Found: $foundStr |Required: $expectedStr""".stripMargin - + whereSuffix + postScript + + whereSuffix + postScript - override def explain = + override def explain = val treeStr = inTree.map(x => s"\nTree: ${x.show}").getOrElse("") treeStr + "\n" + super.explain - + end TypeMismatch @@ -300,14 +300,14 @@ import transform.SymUtils._ // The names of all non-synthetic, non-private members of `site` // that are of the same type/term kind as the missing member. - def candidates: Set[String] = + def candidates: Set[Symbol] = for bc <- site.widen.baseClasses.toSet sym <- bc.info.decls.filter(sym => sym.isType == name.isTypeName && !sym.isConstructor && !sym.flagsUNSAFE.isOneOf(Synthetic | Private)) - yield sym.name.show + yield sym // Calculate Levenshtein distance def distance(s1: String, s2: String): Int = @@ -325,11 +325,11 @@ import transform.SymUtils._ // A list of possible candidate strings with their Levenstein distances // to the name of the missing member - def closest: List[(Int, String)] = candidates + def closest: List[(Int, Symbol)] = candidates .toList - .map(n => (distance(n, missing), n)) - .filter((d, n) => d <= maxDist && d < missing.length && d < n.length) - .sorted // sort by distance first, alphabetically second + .map(n => (distance(n.name.show, missing), n)) + .filter((d, n) => d <= maxDist && d < missing.length && d < n.name.show.length) + .sortBy((d, n) => (d, n.name.show)) // sort by distance first, alphabetically second val enumClause = if ((name eq nme.values) || (name eq nme.valueOf)) && site.classSymbol.companionClass.isEnumClass then @@ -352,7 +352,11 @@ import transform.SymUtils._ val siteName = site match case site: NamedType => site.name.show case site => i"$site" - s" - did you mean $siteName.$n?$enumClause" + val showName = + // Add .type to the name if it is a module + if n.isClass && n.is(Module) then s"${n.name.show}.type" + else n.name.show + s" - did you mean $siteName.$showName?$enumClause" case Nil => prefixEnumClause("") ex"$selected $name is not a member of ${site.widen}$finalAddendum" From 5400724fcb86d5912ed90d88cf032751d22f5ab3 Mon Sep 17 00:00:00 2001 From: bjornregnell Date: Tue, 14 Sep 2021 17:51:59 +0200 Subject: [PATCH 2/2] add test, fix review comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michał Pałka --- .../dotty/tools/dotc/reporting/messages.scala | 16 ++++++++-------- tests/neg/i13320.check | 12 ++++++++++++ tests/neg/i13320.scala | 8 ++++++++ 3 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 tests/neg/i13320.check create mode 100644 tests/neg/i13320.scala diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index fa49776bad85..063ba96410c8 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -298,7 +298,7 @@ import transform.SymUtils._ val maxDist = 3 // maximal number of differences to be considered for a hint val missing = name.show - // The names of all non-synthetic, non-private members of `site` + // The symbols of all non-synthetic, non-private members of `site` // that are of the same type/term kind as the missing member. def candidates: Set[Symbol] = for @@ -323,13 +323,13 @@ import transform.SymUtils._ else (dist(j - 1)(i) min dist(j)(i - 1) min dist(j - 1)(i - 1)) + 1 dist(s2.length)(s1.length) - // A list of possible candidate strings with their Levenstein distances + // A list of possible candidate symbols with their Levenstein distances // to the name of the missing member def closest: List[(Int, Symbol)] = candidates .toList - .map(n => (distance(n.name.show, missing), n)) - .filter((d, n) => d <= maxDist && d < missing.length && d < n.name.show.length) - .sortBy((d, n) => (d, n.name.show)) // sort by distance first, alphabetically second + .map(sym => (distance(sym.name.show, missing), sym)) + .filter((d, sym) => d <= maxDist && d < missing.length && d < sym.name.show.length) + .sortBy((d, sym) => (d, sym.name.show)) // sort by distance first, alphabetically second val enumClause = if ((name eq nme.values) || (name eq nme.valueOf)) && site.classSymbol.companionClass.isEnumClass then @@ -348,14 +348,14 @@ import transform.SymUtils._ val finalAddendum = if addendum.nonEmpty then prefixEnumClause(addendum) else closest match - case (d, n) :: _ => + case (d, sym) :: _ => val siteName = site match case site: NamedType => site.name.show case site => i"$site" val showName = // Add .type to the name if it is a module - if n.isClass && n.is(Module) then s"${n.name.show}.type" - else n.name.show + if sym.is(ModuleClass) then s"${sym.name.show}.type" + else sym.name.show s" - did you mean $siteName.$showName?$enumClause" case Nil => prefixEnumClause("") diff --git a/tests/neg/i13320.check b/tests/neg/i13320.check new file mode 100644 index 000000000000..1e336d8fa7bf --- /dev/null +++ b/tests/neg/i13320.check @@ -0,0 +1,12 @@ +-- [E008] Not Found Error: tests/neg/i13320.scala:8:24 ----------------------------------------------------------------- +8 | type t = Option[Foo.Boo] // error + | ^^^^^^^ + | type Boo is not a member of object Foo - did you mean Foo.Boo.type? +-- [E008] Not Found Error: tests/neg/i13320.scala:4:11 ----------------------------------------------------------------- +4 |var x: Foo.Booo = Foo.Booo // error // error + | ^^^^^^^^ + | type Booo is not a member of object Foo - did you mean Foo.Boo.type? +-- [E008] Not Found Error: tests/neg/i13320.scala:4:22 ----------------------------------------------------------------- +4 |var x: Foo.Booo = Foo.Booo // error // error + | ^^^^^^^^ + | value Booo is not a member of object Foo - did you mean Foo.Boo? \ No newline at end of file diff --git a/tests/neg/i13320.scala b/tests/neg/i13320.scala new file mode 100644 index 000000000000..05edd7e17008 --- /dev/null +++ b/tests/neg/i13320.scala @@ -0,0 +1,8 @@ +object Foo: + case object Boo + +var x: Foo.Booo = Foo.Booo // error // error + +object Main: + def main(args: Array[String]) = + type t = Option[Foo.Boo] // error