Skip to content

Commit bb63e31

Browse files
committed
Rename InlineCopier to ConservativeTreeCopier, use it in TypeMaps
1 parent bed0e86 commit bb63e31

File tree

5 files changed

+58
-11
lines changed

5 files changed

+58
-11
lines changed

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

+8
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,14 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
827827
Closure(tree: Tree)(env, meth, tpt)
828828
}
829829

830+
// This is a more fault-tolerant copier that does not cause errors when
831+
// function types in applications are undefined.
832+
// This was called `Inliner.InlineCopier` before 3.6.3.
833+
class ConservativeTreeCopier() extends TypedTreeCopier:
834+
override def Apply(tree: Tree)(fun: Tree, args: List[Tree])(using Context): Apply =
835+
if fun.tpe.widen.exists then super.Apply(tree)(fun, args)
836+
else untpd.cpy.Apply(tree)(fun, args).withTypeUnchecked(tree.tpe)
837+
830838
override def skipTransform(tree: Tree)(using Context): Boolean = tree.tpe.isError
831839

832840
implicit class TreeOps[ThisTree <: tpd.Tree](private val tree: ThisTree) extends AnyVal {

compiler/src/dotty/tools/dotc/core/Types.scala

+8-1
Original file line numberDiff line numberDiff line change
@@ -6291,7 +6291,14 @@ object Types extends TypeUtils {
62916291
}
62926292
}
62936293

6294-
private def treeTypeMap = new TreeTypeMap(typeMap = this)
6294+
private def treeTypeMap = new TreeTypeMap(
6295+
typeMap = this,
6296+
// Using `ConservativeTreeCopier` is needed when copying dependent annoted
6297+
// types, where we can refer to a previous parameter represented as
6298+
// `TermParamRef` that has no underlying type yet.
6299+
// See tests/pos/annot-17242.scala.
6300+
cpy = ConservativeTreeCopier()
6301+
)
62956302

62966303
def mapOver(syms: List[Symbol]): List[Symbol] = mapSymbols(syms, treeTypeMap)
62976304

compiler/src/dotty/tools/dotc/inlines/Inliner.scala

+7-10
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,6 @@ object Inliner:
9696
}
9797
end isElideableExpr
9898

99-
// InlineCopier is a more fault-tolerant copier that does not cause errors when
100-
// function types in applications are undefined. This is necessary since we copy at
101-
// the same time as establishing the proper context in which the copied tree should
102-
// be evaluated. This matters for opaque types, see neg/i14653.scala.
103-
private class InlineCopier() extends TypedTreeCopier:
104-
override def Apply(tree: Tree)(fun: Tree, args: List[Tree])(using Context): Apply =
105-
if fun.tpe.widen.exists then super.Apply(tree)(fun, args)
106-
else untpd.cpy.Apply(tree)(fun, args).withTypeUnchecked(tree.tpe)
107-
10899
// InlinerMap is a TreeTypeMap with special treatment for inlined arguments:
109100
// They are generally left alone (not mapped further, and if they wrap a type
110101
// the type Inlined wrapper gets dropped
@@ -116,7 +107,13 @@ object Inliner:
116107
substFrom: List[Symbol],
117108
substTo: List[Symbol])(using Context)
118109
extends TreeTypeMap(
119-
typeMap, treeMap, oldOwners, newOwners, substFrom, substTo, InlineCopier()):
110+
typeMap, treeMap, oldOwners, newOwners, substFrom, substTo,
111+
// It is necessary to use the `ConservativeTreeCopier` since we copy at
112+
// the same time as establishing the proper context in which the copied
113+
// tree should be evaluated. This matters for opaque types, see
114+
// neg/i14653.scala.
115+
ConservativeTreeCopier()
116+
):
120117

121118
override def copy(
122119
typeMap: Type => Type,

tests/pos/annot-17242.scala

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// See also tests/pos/annot-21595.scala
2+
3+
class local(predicate: Int) extends annotation.StaticAnnotation
4+
5+
def failing1(x: Int, z: Int @local(x + x)) = ()

tests/pos/dependent-annot2.scala

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
class dummy(b: Any) extends annotation.StaticAnnotation
2+
3+
class X:
4+
def foo() = 1
5+
def bar() = 2
6+
def eq(x: X) = true
7+
def id(): this.type = this
8+
9+
class Y extends X:
10+
override def bar() = 2
11+
override def eq(x: X) = true
12+
13+
def f(x: Int) = x
14+
def g(x: String) = x
15+
def g(x: Int) = x
16+
17+
object AnnotationTests:
18+
def foo1(elem: Int, bla: Int @dummy(Array(elem))) = bla
19+
def foo2(elem: X, bla: Int @dummy(elem.foo())) = bla
20+
def foo3(elem: Y, bla: Int @dummy(elem.foo())) = bla
21+
def foo4(elem: X, bla: Int @dummy(elem.bar())) = bla
22+
def foo5(elem: Y, bla: Int @dummy(elem.bar())) = bla
23+
def foo6(elem: X, bla: Int @dummy(elem.eq(X()))) = bla
24+
def foo7(elem: Y, bla: Int @dummy(elem.eq(Y()))) = bla
25+
def foo8(elem: X, bla: Int @dummy(elem.id().foo())) = bla
26+
def foo9(elem: Y, bla: Int @dummy(elem.id().foo())) = bla
27+
def foo10(elem: Int, bla: Int @dummy(f(elem))) = bla
28+
def foo11(elem: Int, bla: Int @dummy(g(elem))) = bla
29+
def foo12(elem: Int, bla: Int @dummy(0 == elem)) = bla
30+
def foo13(elem: Int, bla: Int @dummy(elem == 0)) = bla

0 commit comments

Comments
 (0)