Skip to content

Commit 12c88bc

Browse files
committed
Add missing span to extension method select
1 parent a37dac6 commit 12c88bc

File tree

6 files changed

+68
-13
lines changed

6 files changed

+68
-13
lines changed

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

+12-10
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,7 @@ trait Implicits:
860860
/** Find an implicit conversion to apply to given tree `from` so that the
861861
* result is compatible with type `to`.
862862
*/
863-
def inferView(from: Tree, to: Type)(using Context): SearchResult = {
863+
def inferView(from: Tree, to: Type, nameSpan: Span = NoSpan)(using Context): SearchResult = {
864864
record("inferView")
865865
if !ctx.mode.is(Mode.ImplicitsEnabled) || from.isInstanceOf[Super] then
866866
NoMatchingImplicitsFailure
@@ -878,7 +878,7 @@ trait Implicits:
878878
}
879879

880880
try
881-
val inferred = inferImplicit(adjust(to), from, from.span)
881+
val inferred = inferImplicit(adjust(to), from, from.span, nameSpan)
882882

883883
inferred match {
884884
case SearchSuccess(_, ref, _, false) if isOldStyleFunctionConversion(ref.underlying) =>
@@ -1059,7 +1059,7 @@ trait Implicits:
10591059
* it should be applied, EmptyTree otherwise.
10601060
* @param span The position where errors should be reported.
10611061
*/
1062-
def inferImplicit(pt: Type, argument: Tree, span: Span)(using Context): SearchResult =
1062+
def inferImplicit(pt: Type, argument: Tree, span: Span, nameSpan: Span = NoSpan)(using Context): SearchResult =
10631063
trace(s"search implicit ${pt.show}, arg = ${argument.show}: ${argument.tpe.show}", implicits, show = true) {
10641064
record("inferImplicit")
10651065
assert(ctx.phase.allowsImplicitSearch,
@@ -1082,7 +1082,7 @@ trait Implicits:
10821082
(searchCtx.scope eq ctx.scope) && (searchCtx.owner eq ctx.owner.owner)
10831083
do ()
10841084

1085-
try ImplicitSearch(pt, argument, span)(using searchCtx).bestImplicit
1085+
try ImplicitSearch(pt, argument, span, nameSpan)(using searchCtx).bestImplicit
10861086
catch case ce: CyclicReference =>
10871087
ce.inImplicitSearch = true
10881088
throw ce
@@ -1102,9 +1102,9 @@ trait Implicits:
11021102
result
11031103
case result: SearchFailure if result.isAmbiguous =>
11041104
val deepPt = pt.deepenProto
1105-
if (deepPt ne pt) inferImplicit(deepPt, argument, span)
1105+
if (deepPt ne pt) inferImplicit(deepPt, argument, span, nameSpan)
11061106
else if (migrateTo3 && !ctx.mode.is(Mode.OldOverloadingResolution))
1107-
withMode(Mode.OldOverloadingResolution)(inferImplicit(pt, argument, span)) match {
1107+
withMode(Mode.OldOverloadingResolution)(inferImplicit(pt, argument, span, nameSpan)) match {
11081108
case altResult: SearchSuccess =>
11091109
report.migrationWarning(
11101110
result.reason.msg
@@ -1125,7 +1125,7 @@ trait Implicits:
11251125
}
11261126

11271127
/** Try to typecheck an implicit reference */
1128-
def typedImplicit(cand: Candidate, pt: Type, argument: Tree, span: Span)(using Context): SearchResult = trace(i"typed implicit ${cand.ref}, pt = $pt, implicitsEnabled == ${ctx.mode is ImplicitsEnabled}", implicits, show = true) {
1128+
def typedImplicit(cand: Candidate, pt: Type, argument: Tree, span: Span, nameSpan: Span = NoSpan)(using Context): SearchResult = trace(i"typed implicit ${cand.ref}, pt = $pt, implicitsEnabled == ${ctx.mode is ImplicitsEnabled}", implicits, show = true) {
11291129
if ctx.run.nn.isCancelled then NoMatchingImplicitsFailure
11301130
else
11311131
record("typedImplicit")
@@ -1164,7 +1164,9 @@ trait Implicits:
11641164
case selProto @ SelectionProto(selName: TermName, mbrType, _, _) =>
11651165

11661166
def tryExtension(using Context) =
1167-
extMethodApply(untpd.Select(untpdGenerated, selName), argument, mbrType)
1167+
val select0 = untpd.Select(untpdGenerated, selName)
1168+
val select = if nameSpan.exists then select0.withSpan(nameSpan) else select0
1169+
extMethodApply(select, argument, mbrType)
11681170

11691171
def tryConversionForSelection(using Context) =
11701172
val converted = tryConversion
@@ -1215,7 +1217,7 @@ trait Implicits:
12151217
}
12161218

12171219
/** An implicit search; parameters as in `inferImplicit` */
1218-
class ImplicitSearch(protected val pt: Type, protected val argument: Tree, span: Span)(using Context):
1220+
class ImplicitSearch(protected val pt: Type, protected val argument: Tree, span: Span, nameSpan: Span = NoSpan)(using Context):
12191221
assert(argument.isEmpty || argument.tpe.isValueType || argument.tpe.isInstanceOf[ExprType],
12201222
em"found: $argument: ${argument.tpe}, expected: $pt")
12211223

@@ -1264,7 +1266,7 @@ trait Implicits:
12641266
val history = ctx.searchHistory.nest(cand, pt)
12651267
val typingCtx =
12661268
nestedContext().setNewTyperState().setFreshGADTBounds.setSearchHistory(history)
1267-
val result = typedImplicit(cand, pt, argument, span)(using typingCtx)
1269+
val result = typedImplicit(cand, pt, argument, span, nameSpan)(using typingCtx)
12681270
result match
12691271
case res: SearchSuccess =>
12701272
ctx.searchHistory.defineBynameImplicit(wideProto, res)

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Decorators._
1010
import typer.ProtoTypes._
1111
import ast.{tpd, untpd}
1212
import scala.util.control.NonFatal
13-
import util.Spans.Span
13+
import util.Spans.{NoSpan, Span}
1414
import Nullables._
1515
import staging.StagingLevel.*
1616

@@ -179,7 +179,7 @@ class ReTyper(nestingLevel: Int = 0) extends Typer(nestingLevel) with ReChecking
179179

180180
override def inlineExpansion(mdef: DefDef)(using Context): List[Tree] = mdef :: Nil
181181

182-
override def inferView(from: Tree, to: Type)(using Context): Implicits.SearchResult =
182+
override def inferView(from: Tree, to: Type, nameSpan: Span = NoSpan)(using Context): Implicits.SearchResult =
183183
Implicits.NoMatchingImplicitsFailure
184184
override def checkCanEqual(ltp: Type, rtp: Type, span: Span)(using Context): Unit = ()
185185

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -3598,7 +3598,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
35983598
if ctx.mode.is(Mode.ImplicitsEnabled) && !tree.name.isConstructorName && qual.tpe.isValueType then
35993599
try
36003600
val selProto = selectionProto
3601-
trace(i"try insert impl on qualifier $tree $pt") { inferView(qual, selProto) } match
3601+
trace(i"try insert impl on qualifier $tree $pt") { inferView(qual, selProto, tree.nameSpan) } match
36023602
case SearchSuccess(found, _, _, isExtension) =>
36033603
if isExtension then return found
36043604
else

presentation-compiler/test/dotty/tools/pc/tests/definition/PcDefinitionSuite.scala

+10
Original file line numberDiff line numberDiff line change
@@ -401,3 +401,13 @@ class PcDefinitionSuite extends BasePcDefinitionSuite:
401401
|
402402
|""".stripMargin
403403
)
404+
405+
@Test def `implicit-extension` =
406+
check(
407+
"""|class MyIntOut(val value: Int)
408+
|object MyIntOut:
409+
| extension (i: MyIntOut) def <<uneven>> = i.value % 2 == 1
410+
|
411+
|val a = MyIntOut(1).un@@even
412+
|""".stripMargin,
413+
)

presentation-compiler/test/dotty/tools/pc/tests/highlight/DocumentHighlightSuite.scala

+31
Original file line numberDiff line numberDiff line change
@@ -1143,3 +1143,34 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite:
11431143
| case MySome[<<AA>>](value: <<A@@A>>) extends MyOption[Int]
11441144
|""".stripMargin,
11451145
)
1146+
1147+
@Test def `implicit-extension` =
1148+
check(
1149+
"""|class MyIntOut(val value: Int)
1150+
|object MyIntOut:
1151+
| extension (i: MyIntOut) def <<uneven>> = i.value % 2 == 1
1152+
|
1153+
|val a = MyIntOut(1)
1154+
|val m = a.<<un@@even>>
1155+
|""".stripMargin,
1156+
)
1157+
1158+
@Test def `implicit-extension-2` =
1159+
check(
1160+
"""|class MyIntOut(val value: Int)
1161+
|object MyIntOut:
1162+
| extension (i: MyIntOut) def <<uneven>>(u: Int) = i.value % 2 == 1
1163+
|
1164+
|val a = MyIntOut(1).<<un@@even>>(3)
1165+
|""".stripMargin,
1166+
)
1167+
1168+
@Test def `implicit-extension-infix` =
1169+
check(
1170+
"""|class MyIntOut(val value: Int)
1171+
|object MyIntOut:
1172+
| extension (i: MyIntOut) def <<++>>(u: Int) = i.value + u
1173+
|
1174+
|val a = MyIntOut(1) <<+@@+>> 3
1175+
|""".stripMargin,
1176+
)

presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTypeSuite.scala

+12
Original file line numberDiff line numberDiff line change
@@ -355,3 +355,15 @@ class HoverTypeSuite extends BaseHoverSuite:
355355
"""|val ddd: Int
356356
|""".stripMargin.hover,
357357
)
358+
359+
@Test def `infix-extension` =
360+
check(
361+
"""|class MyIntOut(val value: Int)
362+
|object MyIntOut:
363+
| extension (i: MyIntOut) def uneven = i.value % 2 == 1
364+
|
365+
|val a = MyIntOut(1).un@@even
366+
|""".stripMargin,
367+
"""|extension (i: MyIntOut) def uneven: Boolean
368+
|""".stripMargin.hover,
369+
)

0 commit comments

Comments
 (0)