@@ -2,14 +2,23 @@ package dotty.tools
2
2
3
3
import vulpix .TestConfiguration
4
4
5
+ import org .junit .Assert ._
5
6
import org .junit .Test
6
7
7
- import dotc .ast .Trees . _
8
+ import dotc .ast .untpd
8
9
import dotc .core .Decorators ._
9
10
import dotc .core .Contexts ._
11
+ import dotc .core .Flags ._
10
12
import dotc .core .Phases ._
13
+ import dotc .core .Names ._
11
14
import dotc .core .Types ._
12
15
import dotc .core .Symbols ._
16
+ import dotc .core .StdNames ._
17
+ import dotc .core .Signature
18
+ import dotc .typer .ProtoTypes .constrained
19
+ import dotc .typer .Inferencing .isFullyDefined
20
+ import dotc .typer .ForceDegree
21
+ import dotc .util .NoSourcePosition
13
22
14
23
import java .io .File
15
24
import java .nio .file ._
@@ -38,3 +47,69 @@ class SignatureTest:
38
47
| ${ref.denot.signature}""" .stripMargin)
39
48
}
40
49
}
50
+
51
+ /** Ensure that signature computation returns an underdefined signature when
52
+ * the signature depends on uninstantiated type variables.
53
+ */
54
+ @ Test def underdefined : Unit =
55
+ inCompilerContext(TestConfiguration .basicClasspath, separateRun = false ,
56
+ """ trait Foo
57
+ |trait Bar
58
+ |class A[T <: Tuple]:
59
+ | def and(x: T & Foo): Unit = {}
60
+ | def andor(x: (T | Bar) & Foo): Unit = {}
61
+ | def array(x: Array[(T | Bar) & Foo]): Unit = {}
62
+ | def tuple(x: Foo *: T): Unit = {}
63
+ | def tuple2(x: Foo *: (T | Tuple) & Foo): Unit = {}
64
+ |""" .stripMargin):
65
+ val cls = requiredClass(" A" )
66
+ val tvar = constrained(cls.requiredMethod(nme.CONSTRUCTOR ).info.asInstanceOf [TypeLambda ], untpd.EmptyTree , alwaysAddTypeVars = true )._2.head.tpe
67
+ tvar <:< defn.TupleTypeRef
68
+ val prefix = cls.typeRef.appliedTo(tvar)
69
+
70
+ def checkSignatures (expectedIsUnderDefined : Boolean )(using Context ): Unit =
71
+ for decl <- cls.info.decls.toList if decl.is(Method ) && ! decl.isConstructor do
72
+ val meth = decl.asSeenFrom(prefix)
73
+ val sig = meth.info.signature
74
+ val what = if expectedIsUnderDefined then " underdefined" else " fully-defined"
75
+ assert(sig.isUnderDefined == expectedIsUnderDefined, i " Signature of ` $meth` with prefix ` $prefix` and type ` ${meth.info}` should be $what but is ` $sig` " )
76
+
77
+ checkSignatures(expectedIsUnderDefined = true )
78
+ assert(isFullyDefined(tvar, force = ForceDegree .all), s " Could not instantiate $tvar" )
79
+ checkSignatures(expectedIsUnderDefined = false )
80
+
81
+ /** Check that signature caching behaves correctly with respect to retracted
82
+ * instantiations of type variables.
83
+ */
84
+ @ Test def cachingWithRetraction : Unit =
85
+ inCompilerContext(TestConfiguration .basicClasspath, separateRun = false ,
86
+ """ trait Foo
87
+ |trait Bar
88
+ |class A[T]:
89
+ | def and(x: T & Foo): Unit = {}
90
+ |""" .stripMargin):
91
+ val cls = requiredClass(" A" )
92
+ val tvar = constrained(cls.requiredMethod(nme.CONSTRUCTOR ).info.asInstanceOf [TypeLambda ], untpd.EmptyTree , alwaysAddTypeVars = true )._2.head.tpe
93
+ val prefix = cls.typeRef.appliedTo(tvar)
94
+ val ref = prefix.select(cls.requiredMethod(" and" )).asInstanceOf [TermRef ]
95
+
96
+ /** Check that the signature of the first parameter of `ref` is equal to `expectedParamSig`. */
97
+ def checkParamSig (ref : TermRef , expectedParamSig : TypeName )(using Context ): Unit =
98
+ assertEquals(i " Check failed for param signature of $ref" ,
99
+ expectedParamSig, ref.signature.paramsSig.head)
100
+ // Both NamedType and MethodOrPoly cache signatures, so check both caches.
101
+ assertEquals(i " Check failed for param signature of ${ref.info} (but not for $ref itself) " ,
102
+ expectedParamSig, ref.info.signature.paramsSig.head)
103
+
104
+
105
+ // Initially, the param signature is Uninstantiated since it depends on an uninstantiated type variable
106
+ checkParamSig(ref, tpnme.Uninstantiated )
107
+
108
+ // In this context, the signature is the erasure of `Bar & Foo`.
109
+ inContext(ctx.fresh.setNewTyperState()):
110
+ tvar =:= requiredClass(" Bar" ).typeRef
111
+ assert(isFullyDefined(tvar, force = ForceDegree .all), s " Could not instantiate $tvar" )
112
+ checkParamSig(ref, " Bar" .toTypeName)
113
+
114
+ // If our caching logic is working correctly, we should get the original signature here.
115
+ checkParamSig(ref, tpnme.Uninstantiated )
0 commit comments