aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/core/Signature.scala20
-rw-r--r--src/dotty/tools/dotc/core/StdNames.scala2
-rw-r--r--src/dotty/tools/dotc/core/TypeErasure.scala3
-rw-r--r--src/dotty/tools/dotc/core/Types.scala12
-rw-r--r--src/dotty/tools/dotc/transform/PostTyper.scala15
5 files changed, 40 insertions, 12 deletions
diff --git a/src/dotty/tools/dotc/core/Signature.scala b/src/dotty/tools/dotc/core/Signature.scala
index 54771bae5..984315f18 100644
--- a/src/dotty/tools/dotc/core/Signature.scala
+++ b/src/dotty/tools/dotc/core/Signature.scala
@@ -29,6 +29,19 @@ case class Signature(paramsSig: List[TypeName], resSig: TypeName) {
/** Does this signature coincide with that signature on their parameter parts? */
final def sameParams(that: Signature): Boolean = this.paramsSig == that.paramsSig
+ /** Does this signature coincide with that signature on their parameter parts?
+ * This is the case if all parameter names are _consistent_, i.e. they are either
+ * equal or on of them is tpnme.Uninstantiated.
+ */
+ final def consistentParams(that: Signature): Boolean = {
+ def consistent(name1: TypeName, name2: TypeName) =
+ name1 == name2 || name1 == tpnme.Uninstantiated || name2 == tpnme.Uninstantiated
+ def loop(names1: List[TypeName], names2: List[TypeName]): Boolean =
+ if (names1.isEmpty) names2.isEmpty
+ else names2.nonEmpty && consistent(names1.head, names2.head) && loop(names1.tail, names2.tail)
+ loop(this.paramsSig, that.paramsSig)
+ }
+
/** The degree to which this signature matches `that`.
* If both parameter and result type names match (i.e. they are the same
* or one is a wildcard), the result is `FullMatch`.
@@ -52,6 +65,13 @@ case class Signature(paramsSig: List[TypeName], resSig: TypeName) {
def prepend(params: List[Type], isJava: Boolean)(implicit ctx: Context) =
Signature((params.map(sigName(_, isJava))) ++ paramsSig, resSig)
+ /** A signature is under-defined if its paramsSig part contains at least one
+ * `tpnme.Uninstantited`. Under-defined signatures arise when taking a signature
+ * of a type that still contains uninstantiated type variables. They are eliminated
+ * by `fixSignature` in `PostTyper`.
+ */
+ def isUnderDefined(implicit ctx: Context) =
+ paramsSig.contains(tpnme.Uninstantiated) || resSig == tpnme.Uninstantiated
}
object Signature {
diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala
index 778d13cab..f9ede23c5 100644
--- a/src/dotty/tools/dotc/core/StdNames.scala
+++ b/src/dotty/tools/dotc/core/StdNames.scala
@@ -743,6 +743,8 @@ object StdNames {
(0 until num).map(syntheticLambdaParamName)(breakOut)
final val Conforms = encode("<:<")
+
+ final val Uninstantiated: TypeName = "?$"
}
abstract class JavaNames[N <: Name] extends DefinedNames[N] {
diff --git a/src/dotty/tools/dotc/core/TypeErasure.scala b/src/dotty/tools/dotc/core/TypeErasure.scala
index c71726a3e..74d2d193f 100644
--- a/src/dotty/tools/dotc/core/TypeErasure.scala
+++ b/src/dotty/tools/dotc/core/TypeErasure.scala
@@ -476,6 +476,9 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
sigName(tp.widen)
case ExprType(rt) =>
sigName(defn.FunctionOf(Nil, rt))
+ case tp: TypeVar =>
+ val inst = tp.instanceOpt
+ if (inst.exists) sigName(inst) else tpnme.Uninstantiated
case tp: TypeProxy =>
sigName(tp.underlying)
case ErrorType | WildcardType =>
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 9150925ff..d78bbd49e 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -2108,15 +2108,7 @@ object Types {
def derivedRefinedType(parent: Type, refinedName: Name, refinedInfo: Type)(implicit ctx: Context): Type =
if ((parent eq this.parent) && (refinedName eq this.refinedName) && (refinedInfo eq this.refinedInfo)) this
- else {
- // `normalizedRefinedInfo` is `refinedInfo` reduced everywhere via `reduceProjection`.
- // (this is achieved as a secondary effect of substRecThis).
- // It turns out this normalization is now needed; without it there's
- // A Y-check error (incompatible types involving hk lambdas) for dotty itself.
- // TODO: investigate and, if possible, drop after revision.
- val normalizedRefinedInfo = refinedInfo.substRecThis(dummyRec, dummyRec)
- RefinedType(parent, refinedName, normalizedRefinedInfo)
- }
+ else RefinedType(parent, refinedName, refinedInfo)
/** Add this refinement to `parent`, provided If `refinedName` is a member of `parent`. */
def wrapIfMember(parent: Type)(implicit ctx: Context): Type =
@@ -2338,7 +2330,7 @@ object Types {
final override def signature(implicit ctx: Context): Signature = {
if (ctx.runId != mySignatureRunId) {
mySignature = computeSignature
- mySignatureRunId = ctx.runId
+ if (!mySignature.isUnderDefined) mySignatureRunId = ctx.runId
}
mySignature
}
diff --git a/src/dotty/tools/dotc/transform/PostTyper.scala b/src/dotty/tools/dotc/transform/PostTyper.scala
index 6b0b2b073..057026a67 100644
--- a/src/dotty/tools/dotc/transform/PostTyper.scala
+++ b/src/dotty/tools/dotc/transform/PostTyper.scala
@@ -115,6 +115,17 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
}
}
+ /** If the type of `tree` is a TermRefWithSignature with an underdefined
+ * signature, narrow the type by re-computing the signature (which should
+ * be fully-defined by now).
+ */
+ private def fixSignature[T <: Tree](tree: T)(implicit ctx: Context): T = tree.tpe match {
+ case tpe: TermRefWithSignature if tpe.signature.isUnderDefined =>
+ println(i"fixing $tree with type ${tree.tpe.widen.toString} with sig ${tpe.signature} to ${tpe.widen.signature}")
+ tree.withType(TermRef.withSig(tpe.prefix, tpe.name, tpe.widen.signature)).asInstanceOf[T]
+ case _ => tree
+ }
+
class PostTyperTransformer extends Transformer {
private var inJavaAnnot: Boolean = false
@@ -192,10 +203,10 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
case tree: Ident =>
tree.tpe match {
case tpe: ThisType => This(tpe.cls).withPos(tree.pos)
- case _ => paramFwd.adaptRef(tree)
+ case _ => paramFwd.adaptRef(fixSignature(tree))
}
case tree: Select =>
- transformSelect(paramFwd.adaptRef(tree), Nil)
+ transformSelect(paramFwd.adaptRef(fixSignature(tree)), Nil)
case tree: TypeApply =>
val tree1 @ TypeApply(fn, args) = normalizeTypeArgs(tree)
Checking.checkBounds(args, fn.tpe.widen.asInstanceOf[PolyType])