Skip to content

Commit db23c08

Browse files
authored
fix: map name position to desugared version of named context bound (#22374)
resolves: #22335 This PR changes the positions so context bound name position is correctly mapped in the desugaring: ```scala def aa[T : Numeric as num]() = ??? // original code def aa[T >: Nothing <: Any]()(using num: Numeric[T]): Nothing = ??? // desugared code, where position of `num` points to `num` in the original code ``` This also affects the cases where context bound is not named. The definition position of `evidence$0` changed: ```scala def aa[T : Numeric]() = ??? // original code def aa[T >: Nothing <: Any]()(using evidence$0: Numeric[T]): Nothing = ??? // desugared code // previously position of evidence$0 in original code def aa[T : <<>>Numeric]() = ??? // after this PR def aa[T : Numeric<<>>]() = ??? ``` Which I think makes sense since if the was a name it would go after the context bound
2 parents 08442e8 + 942d752 commit db23c08

File tree

8 files changed

+39
-12
lines changed

8 files changed

+39
-12
lines changed

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

+7-5
Original file line numberDiff line numberDiff line change
@@ -272,18 +272,20 @@ object desugar {
272272
case ContextBounds(tbounds, ctxbounds) =>
273273
val isMember = evidenceFlags.isAllOf(DeferredGivenFlags)
274274
for bound <- ctxbounds do
275-
val evidenceName = bound match
275+
val (evidenceName, spanPoint) = bound match
276276
case ContextBoundTypeTree(_, _, ownName) if !ownName.isEmpty =>
277-
ownName // if there is an explicitly given name, use it.
277+
val realName = ownName.stripModuleClassSuffix.lastPart
278+
(ownName, bound.span.end - realName.length) // if there is an explicitly given name, use it.
278279
case _ =>
279280
if Config.nameSingleContextBounds
280281
&& !isMember
281282
&& ctxbounds.tail.isEmpty
282283
&& Feature.enabled(Feature.modularity)
283-
then tdef.name.toTermName
284-
else freshName(bound)
284+
then (tdef.name.toTermName, bound.span.point)
285+
else (freshName(bound), bound.span.point)
285286
evidenceNames += evidenceName
286-
val evidenceParam = ValDef(evidenceName, bound, EmptyTree).withFlags(evidenceFlags)
287+
val evidenceParam =
288+
ValDef(evidenceName, bound, EmptyTree).withFlags(evidenceFlags).withSpan(bound.span.withPoint(spanPoint))
287289
evidenceParam.pushAttachment(ContextBoundParam, ())
288290
evidenceBuf += evidenceParam
289291
tbounds

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -2265,7 +2265,8 @@ object Parsers {
22652265
in.nextToken()
22662266
ident()
22672267
else EmptyTermName
2268-
ContextBoundTypeTree(t, pname, ownName)
2268+
val newSpan = t.span.withPoint(t.span.end).withEnd(in.lastOffset)
2269+
ContextBoundTypeTree(t, pname, ownName).withSpan(newSpan)
22692270

22702271
/** ContextBounds ::= ContextBound [`:` ContextBounds]
22712272
* | `{` ContextBound {`,` ContextBound} `}`

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -2466,7 +2466,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
24662466
def typedContextBoundTypeTree(tree: untpd.ContextBoundTypeTree)(using Context): Tree =
24672467
val tycon = typedType(tree.tycon)
24682468
def spliced(tree: Tree) = untpd.TypedSplice(tree)
2469-
val tparam = untpd.Ident(tree.paramName).withSpan(tree.span)
2469+
val tparam = untpd.Ident(tree.paramName).withSpan(tree.span.withEnd(tree.span.point))
24702470
if tycon.tpe.typeParams.nonEmpty then
24712471
val tycon0 = tycon.withType(tycon.tpe.etaCollapse)
24722472
typed(untpd.AppliedTypeTree(spliced(tycon0), tparam :: Nil))

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

+24
Original file line numberDiff line numberDiff line change
@@ -238,3 +238,27 @@ class HoverDefnSuite extends BaseHoverSuite:
238238
|""".stripMargin,
239239
"val foo: Int".hover
240240
)
241+
242+
@Test def `i22335` =
243+
check(
244+
"""|def fromInt[T: Numeric as n@@um](t: Int): T = num.fromInt(t)
245+
|""".stripMargin,
246+
"""|num: Numeric[T]
247+
|""".stripMargin.hover
248+
)
249+
250+
@Test def `i22335-2` =
251+
check(
252+
"""|def showMax[X : {Numeric as nu@@m, Ordered as ord}](x: X, y: X): String = ???
253+
|""".stripMargin,
254+
"""|num: Numeric[X]
255+
|""".stripMargin.hover
256+
)
257+
258+
@Test def `i22335-3` =
259+
check(
260+
"""|def showMax[X : {Nu@@meric as num, Ordered as ord}](x: X, y: X): String = ???
261+
|""".stripMargin,
262+
"""|type Numeric: Numeric
263+
|""".stripMargin.hover
264+
)

presentation-compiler/test/dotty/tools/pc/tests/inlayHints/InlayHintsSuite.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -898,7 +898,7 @@ class InlayHintsSuite extends BaseInlayHintsSuite {
898898
| import quotes.reflect.*
899899
| Type.of[T] match
900900
| case '[f] =>
901-
| val fr/*: TypeRepr<<scala/quoted/Quotes#reflectModule#TypeRepr#>>*/ = TypeRepr.of[T]/*(using evidence$1<<(3:23)>>)*/
901+
| val fr/*: TypeRepr<<scala/quoted/Quotes#reflectModule#TypeRepr#>>*/ = TypeRepr.of[T]/*(using evidence$1<<(3:27)>>)*/
902902
|""".stripMargin
903903
)
904904

tests/pos/i20901/Foo.tastycheck

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ Trees (98 bytes, starting from <elided base index>):
9292
96: STRINGconst 32 [<elided source file name>]
9393
98:
9494

95-
Positions (73 bytes, starting from <elided base index>):
95+
Positions (75 bytes, starting from <elided base index>):
9696
lines: 7
9797
line sizes:
9898
38, 0, 23, 0, 10, 41, 0

tests/semanticdb/expect/Synthetic.expect.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class Synthetic/*<-example::Synthetic#*/ {
3030
null.asInstanceOf/*->scala::Any#asInstanceOf().*/[Int/*->scala::Int#*/ => Int/*->scala::Int#*/](2)
3131
}
3232

33-
class J/*<-example::Synthetic#J#*/[T/*<-example::Synthetic#J#[T]*/: /*<-example::Synthetic#J#evidence$1.*/Manifest/*->scala::Predef.Manifest#*//*->example::Synthetic#J#[T]*/] { val arr/*<-example::Synthetic#J#arr.*/ = Array/*->scala::Array.*/.empty/*->scala::Array.empty().*/[T/*->example::Synthetic#J#[T]*/] }
33+
class J/*<-example::Synthetic#J#*/[T/*<-example::Synthetic#J#[T]*/: Manifest/*->scala::Predef.Manifest#*//*->example::Synthetic#J#[T]*//*<-example::Synthetic#J#evidence$1.*/] { val arr/*<-example::Synthetic#J#arr.*/ = Array/*->scala::Array.*/.empty/*->scala::Array.empty().*/[T/*->example::Synthetic#J#[T]*/] }
3434

3535
class F/*<-example::Synthetic#F#*/
3636
implicit val ordering/*<-example::Synthetic#ordering.*/: Ordering/*->scala::package.Ordering#*/[F/*->example::Synthetic#F#*/] = ???/*->scala::Predef.`???`().*/

tests/semanticdb/metac.expect

+2-2
Original file line numberDiff line numberDiff line change
@@ -2734,7 +2734,7 @@ Occurrences:
27342734
[17:9..17:10): U <- example/Methods#m7().[U]
27352735
[17:12..17:20): Ordering -> scala/math/Ordering#
27362736
[17:12..17:20): Ordering -> example/Methods#m7().[U]
2737-
[17:12..17:12): <- example/Methods#m7().(evidence$1)
2737+
[17:20..17:20): <- example/Methods#m7().(evidence$1)
27382738
[17:22..17:23): c <- example/Methods#m7().(c)
27392739
[17:25..17:32): Methods -> example/Methods#
27402740
[17:33..17:34): T -> example/Methods#[T]
@@ -3668,9 +3668,9 @@ Occurrences:
36683668
[32:8..32:9): J <- example/Synthetic#J#
36693669
[32:9..32:9): <- example/Synthetic#J#`<init>`().
36703670
[32:10..32:11): T <- example/Synthetic#J#[T]
3671-
[32:13..32:13): <- example/Synthetic#J#evidence$1.
36723671
[32:13..32:21): Manifest -> scala/Predef.Manifest#
36733672
[32:13..32:21): Manifest -> example/Synthetic#J#[T]
3673+
[32:21..32:21): <- example/Synthetic#J#evidence$1.
36743674
[32:29..32:32): arr <- example/Synthetic#J#arr.
36753675
[32:35..32:40): Array -> scala/Array.
36763676
[32:41..32:46): empty -> scala/Array.empty().

0 commit comments

Comments
 (0)