diff options
-rw-r--r-- | src/dotty/tools/dotc/core/Signature.scala | 20 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/StdNames.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeErasure.scala | 3 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 12 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/PostTyper.scala | 15 |
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]) |