Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 8 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4498,7 +4498,14 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
if isAcceptedSpuriousApply(tree, pt.args) then tree
else
tryInsertApplyOrImplicit(tree, pt, locked):
errorTree(tree, MethodDoesNotTakeParameters(tree))
val pos =
if pt.args.isEmpty then tree.srcPos
else
val union = tree.sourcePos.withSpan:
tree.srcPos.span.union(pt.args.last.srcPos.span)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if tree.sourcePos is remapped (e.g. code has a magic header), while the union uses raw srcPos spans? Could that shift reported locations?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll look at how that is done. On Scala 2, the "underlying" position was a function of the source. Otherwise, how could one do any position calculation? However, I endorse my comment about using API to request more context instead of touching position.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously, shifting for funky headers was positionInUltimateSource, which may still be used in two places.

sourcePos.withSpan is the same as tree.source.atSpan or

val union = tree.sourcePos.copy(span = tree.srcPos.span.union(pt.args.last.srcPos.span))

Here we don't have a Positioned, we just want a SrcPos for reporting. Normally, reporting creates a Diagnostic and its SourcePosition together.

I won't push it further here, but it would be nice if reporting had a channel for extra pos info like inlined outers (currently a field in SourcePosition but really belongs to the diagnostic) and for this kludge a pos to say "rendering context should include this line".

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. To be sure I tested it, and it doesn't seem to affect the case I mentioned.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what IDEs do with multiline squiggles, however. Also, one could not do this trick and also emit a rewrite suggestion.

if union.startLine != union.endLine then union // if multiline, show more context
else tree.srcPos
errorTree(tree, MethodDoesNotTakeParameters(tree), pos)
}

def adaptNoArgsImplicitMethod(wtp: MethodType): Tree = {
Expand Down
4 changes: 3 additions & 1 deletion tests/neg/19087.check
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
| Declaration of method foo not allowed here: only classes can have declared but undefined members
-- [E050] Type Error: tests/neg/19087.scala:13:22 ----------------------------------------------------------------------
13 | foo(state.copy(x = 5): // Missing ")" // error: method copy in class State does not take more parameters
| ^^^^^^^^^^^^^^^^^
| ^
| method copy in class State does not take more parameters
|
14 | println("a")
|
| longer explanation available when compiling with `-explain`
53 changes: 53 additions & 0 deletions tests/neg/i9434.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
-- [E018] Syntax Error: tests/neg/i9434.scala:10:18 --------------------------------------------------------------------
10 | Vector(1) ++ // error
| ^
| expression expected but unindent found
|
| longer explanation available when compiling with `-explain`
-- [E050] Type Error: tests/neg/i9434.scala:4:14 -----------------------------------------------------------------------
4 | val bar = foo // error
| ^
| value foo does not take parameters
|
5 | (1, 1)
|
| longer explanation available when compiling with `-explain`
-- [E007] Type Mismatch Error: tests/neg/i9434.scala:6:3 ---------------------------------------------------------------
6 | } // error
| ^
| Found: Unit
| Required: (Int, Int)
|
| Maybe the enclosing block is missing a final expression after the definition of `bar`?
|
| longer explanation available when compiling with `-explain`
-- [E050] Type Error: tests/neg/i9434.scala:26:29 ----------------------------------------------------------------------
26 | def f[A](as: List[A]) = as headOption // error
| ^
| method headOption in trait LinearSeqOps does not take parameters
|
27 | 42
|
| longer explanation available when compiling with `-explain`
-- [E050] Type Error: tests/neg/i9434.scala:30:29 ----------------------------------------------------------------------
30 | def f[A](as: List[A]) = as headOption // error
| ^
| method headOption in trait LinearSeqOps does not take parameters
|
31 | 42
|
| longer explanation available when compiling with `-explain`
-- [E050] Type Error: tests/neg/i9434.scala:35:10 ----------------------------------------------------------------------
35 | def f = g // error
| ^
| method g in object Y does not take parameters
|
36 | (42)
|
| longer explanation available when compiling with `-explain`
-- [E129] Potential Issue Warning: tests/neg/i9434.scala:41:2 ----------------------------------------------------------
41 | (42) // warn
| ^^^^
| A pure expression does nothing in statement position
|
| longer explanation available when compiling with `-explain`
41 changes: 41 additions & 0 deletions tests/neg/i9434.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
object Foo {
def bar1: (Int, Int) = {
val foo = 1.0
val bar = foo // error
(1, 1)
} // error

def bar2: Vector[Int] = {
val foo =
Vector(1) ++ // error
Vector(2) ++
Vector(3)
foo
}
}
/* Now the diagnostic is multiline, to show more context (the args), and only one caret for the point.
-- [E050] Type Error: i9434.scala:5:14 ---------------------------------------------------------------------------------
5 | val bar = foo
| ^^^
| value foo does not take parameters
|
| longer explanation available when compiling with `-explain`
*/

object X:
def f[A](as: List[A]) = as headOption // error
42

object X2:
def f[A](as: List[A]) = as headOption // error
42

object Y:
def g = 42
def f = g // error
(42)

object Z:
def g = 42
def f = g
(42) // warn
Loading