Skip to content

Commit 0610f9f

Browse files
committed
Change position of dynamic selections
When checking whether non-member value refinements could cause unsoundness problems, I noted that the end position of a dynamic select got lost; the dynamic selection would have the same position as its qualifier. I.e. if `z.x` is a dynamic selection, the indicated position would be just `z`. Fixed now. The correct position can be seen when inspecting the error message of i4098.scala. Ideally, this would be a scripting test. I let someone else add one.
1 parent 2b606ae commit 0610f9f

File tree

2 files changed

+35
-18
lines changed

2 files changed

+35
-18
lines changed

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

+19-18
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import dotty.tools.dotc.core.Names.{Name, TermName}
1111
import dotty.tools.dotc.core.StdNames._
1212
import dotty.tools.dotc.core.Types._
1313
import dotty.tools.dotc.core.Decorators._
14+
import util.Positions._
1415
import core.Symbols._
1516
import core.Definitions
1617
import Inferencing._
@@ -49,7 +50,7 @@ trait Dynamic { self: Typer with Applications =>
4950
* foo.bar[T0, ...](x = bazX, y = bazY, baz, ...) ~~> foo.applyDynamicNamed[T0, ...]("bar")(("x", bazX), ("y", bazY), ("", baz), ...)
5051
*/
5152
def typedDynamicApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = {
52-
def typedDynamicApply(qual: untpd.Tree, name: Name, targs: List[untpd.Tree]): Tree = {
53+
def typedDynamicApply(qual: untpd.Tree, name: Name, selPos: Position, targs: List[untpd.Tree]): Tree = {
5354
def isNamedArg(arg: untpd.Tree): Boolean = arg match { case NamedArg(_, _) => true; case _ => false }
5455
val args = tree.args
5556
val dynName = if (args.exists(isNamedArg)) nme.applyDynamicNamed else nme.applyDynamic
@@ -62,19 +63,19 @@ trait Dynamic { self: Typer with Applications =>
6263
case arg => namedArgTuple("", arg)
6364
}
6465
val args1 = if (dynName == nme.applyDynamic) args else namedArgs
65-
typedApply(untpd.Apply(coreDynamic(qual, dynName, name, targs), args1), pt)
66+
typedApply(untpd.Apply(coreDynamic(qual, dynName, name, selPos, targs), args1), pt)
6667
}
6768
}
6869

6970
tree.fun match {
70-
case Select(qual, name) if !isDynamicMethod(name) =>
71-
typedDynamicApply(qual, name, Nil)
72-
case TypeApply(Select(qual, name), targs) if !isDynamicMethod(name) =>
73-
typedDynamicApply(qual, name, targs)
71+
case sel @ Select(qual, name) if !isDynamicMethod(name) =>
72+
typedDynamicApply(qual, name, sel.pos, Nil)
73+
case TypeApply(sel @ Select(qual, name), targs) if !isDynamicMethod(name) =>
74+
typedDynamicApply(qual, name, sel.pos, targs)
7475
case TypeApply(fun, targs) =>
75-
typedDynamicApply(fun, nme.apply, targs)
76+
typedDynamicApply(fun, nme.apply, fun.pos, targs)
7677
case fun =>
77-
typedDynamicApply(fun, nme.apply, Nil)
78+
typedDynamicApply(fun, nme.apply, fun.pos, Nil)
7879
}
7980
}
8081

@@ -86,26 +87,26 @@ trait Dynamic { self: Typer with Applications =>
8687
* through an existing transformation of in typedAssign [foo.bar(baz) = quux ~~> foo.bar.update(baz, quux)].
8788
*/
8889
def typedDynamicSelect(tree: untpd.Select, targs: List[Tree], pt: Type)(implicit ctx: Context): Tree =
89-
typedApply(coreDynamic(tree.qualifier, nme.selectDynamic, tree.name, targs), pt)
90+
typedApply(coreDynamic(tree.qualifier, nme.selectDynamic, tree.name, tree.pos, targs), pt)
9091

9192
/** Translate selection that does not typecheck according to the normal rules into a updateDynamic.
9293
* foo.bar = baz ~~> foo.updateDynamic(bar)(baz)
9394
*/
9495
def typedDynamicAssign(tree: untpd.Assign, pt: Type)(implicit ctx: Context): Tree = {
95-
def typedDynamicAssign(qual: untpd.Tree, name: Name, targs: List[untpd.Tree]): Tree =
96-
typedApply(untpd.Apply(coreDynamic(qual, nme.updateDynamic, name, targs), tree.rhs), pt)
96+
def typedDynamicAssign(qual: untpd.Tree, name: Name, selPos: Position, targs: List[untpd.Tree]): Tree =
97+
typedApply(untpd.Apply(coreDynamic(qual, nme.updateDynamic, name, selPos, targs), tree.rhs), pt)
9798
tree.lhs match {
98-
case Select(qual, name) if !isDynamicMethod(name) =>
99-
typedDynamicAssign(qual, name, Nil)
100-
case TypeApply(Select(qual, name), targs) if !isDynamicMethod(name) =>
101-
typedDynamicAssign(qual, name, targs)
99+
case sel @ Select(qual, name) if !isDynamicMethod(name) =>
100+
typedDynamicAssign(qual, name, sel.pos, Nil)
101+
case TypeApply(sel @ Select(qual, name), targs) if !isDynamicMethod(name) =>
102+
typedDynamicAssign(qual, name, sel.pos, targs)
102103
case _ =>
103104
errorTree(tree, ReassignmentToVal(tree.lhs.symbol.name))
104105
}
105106
}
106107

107-
private def coreDynamic(qual: untpd.Tree, dynName: Name, name: Name, targs: List[untpd.Tree])(implicit ctx: Context): untpd.Apply = {
108-
val select = untpd.Select(qual, dynName)
108+
private def coreDynamic(qual: untpd.Tree, dynName: Name, name: Name, selPos: Position, targs: List[untpd.Tree])(implicit ctx: Context): untpd.Apply = {
109+
val select = untpd.Select(qual, dynName).withPos(selPos)
109110
val selectWithTypes =
110111
if (targs.isEmpty) select
111112
else untpd.TypeApply(select, targs)
@@ -134,7 +135,7 @@ trait Dynamic { self: Typer with Applications =>
134135
def structuralCall(selectorName: TermName, formals: List[Tree]) = {
135136
val selectable = adapt(qual, defn.SelectableType)
136137
val scall = untpd.Apply(
137-
untpd.TypedSplice(selectable.select(selectorName)),
138+
untpd.TypedSplice(selectable.select(selectorName)).withPos(tree.pos),
138139
(Literal(Constant(name.toString)) :: formals).map(untpd.TypedSplice(_)))
139140
typed(scall)
140141
}

tests/neg/i4098a.scala

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
object App {
2+
import scala.reflect.Selectable.reflectiveSelectable
3+
4+
def coerce[U, V](u: U): V = {
5+
type X = { val x: { type R >: U } }
6+
type Y = { val x: { type R = V } }
7+
lazy val z: X & Y = z
8+
val u1: z.x.R = u // error: Object { type R >: U | V <: V } is not stable (with arrows under z.x)
9+
u1
10+
}
11+
12+
def main(args: Array[String]): Unit = {
13+
val x: Int = coerce[String, Int]("a")
14+
println(x + 1)
15+
}
16+
}

0 commit comments

Comments
 (0)