aboutsummaryrefslogtreecommitdiff
path: root/compiler/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2017-02-27 09:34:57 +0100
committerMartin Odersky <odersky@gmail.com>2017-02-28 19:34:42 +0100
commitc3a90a4a9a9827d199ec436fcfda7c5447731542 (patch)
treeafd58a3d48660387ef3e976e731f7b5d2d15697c /compiler/src
parente4775b87c2b5e8f55bb32da9160cd37322a18f2c (diff)
downloaddotty-c3a90a4a9a9827d199ec436fcfda7c5447731542.tar.gz
dotty-c3a90a4a9a9827d199ec436fcfda7c5447731542.tar.bz2
dotty-c3a90a4a9a9827d199ec436fcfda7c5447731542.zip
Systematic treatment of result types of dependent methods
We approximate dependencies to parameters by Wildcards. This was already done in one place, is now done in other places as well, instead of doing nothing for dependent methods.
Diffstat (limited to 'compiler/src')
-rw-r--r--compiler/src/dotty/tools/dotc/core/Types.scala11
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Applications.scala24
-rw-r--r--compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala28
3 files changed, 32 insertions, 31 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala
index 200e94a1e..8bd729472 100644
--- a/compiler/src/dotty/tools/dotc/core/Types.scala
+++ b/compiler/src/dotty/tools/dotc/core/Types.scala
@@ -1686,7 +1686,10 @@ object Types {
}
else newLikeThis(prefix)
}
- else newLikeThis(prefix)
+ else prefix match {
+ case _: WildcardType => WildcardType
+ case _ => newLikeThis(prefix)
+ }
/** Create a NamedType of the same kind as this type, but with a new prefix.
*/
@@ -2391,6 +2394,12 @@ object Types {
*/
def isDependent(implicit ctx: Context): Boolean = dependencyStatus == TrueDeps
+ /** The result type where every reference to a parameter is replaced by a Wildcard
+ */
+ def resultTypeApprox(implicit ctx: Context): Type =
+ if (isDependent) resultType.substParams(this, paramTypes.map(Function.const(WildcardType)))
+ else resultType
+
protected def computeSignature(implicit ctx: Context): Signature =
resultSignature.prepend(paramTypes, isJava)
diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala
index e9df12b42..bca44997d 100644
--- a/compiler/src/dotty/tools/dotc/typer/Applications.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala
@@ -213,16 +213,14 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
protected def init() = methType match {
case methType: MethodType =>
// apply the result type constraint, unless method type is dependent
- if (!methType.isDependent) {
- val savedConstraint = ctx.typerState.constraint
- if (!constrainResult(methType.resultType, resultType))
- if (ctx.typerState.isCommittable)
- // defer the problem until after the application;
- // it might be healed by an implicit conversion
- assert(ctx.typerState.constraint eq savedConstraint)
- else
- fail(err.typeMismatchMsg(methType.resultType, resultType))
- }
+ val savedConstraint = ctx.typerState.constraint
+ if (!constrainResult(methType.resultTypeApprox, resultType))
+ if (ctx.typerState.isCommittable)
+ // defer the problem until after the application;
+ // it might be healed by an implicit conversion
+ assert(ctx.typerState.constraint eq savedConstraint)
+ else
+ fail(err.typeMismatchMsg(methType.resultType, resultType))
// match all arguments with corresponding formal parameters
matchArgs(orderedArgs, methType.paramTypes, 0)
case _ =>
@@ -1100,10 +1098,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
/** Drop any implicit parameter section */
def stripImplicit(tp: Type): Type = tp match {
- case mt: ImplicitMethodType if !mt.isDependent =>
- mt.resultType
- // todo: make sure implicit method types are not dependent?
- // but check test case in /tests/pos/depmet_implicit_chaining_zw.scala
+ case mt: ImplicitMethodType =>
+ mt.resultTypeApprox
case pt: PolyType =>
pt.derivedPolyType(pt.paramNames, pt.paramBounds, stripImplicit(pt.resultType))
case _ =>
diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
index 48f79d147..4d88fc4f5 100644
--- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
+++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
@@ -57,7 +57,7 @@ object ProtoTypes {
case pt: FunProto =>
mt match {
case mt: MethodType =>
- mt.isDependent || constrainResult(mt.resultType, pt.resultType)
+ constrainResult(mt.resultTypeApprox, pt.resultType)
case _ =>
true
}
@@ -408,22 +408,18 @@ object ProtoTypes {
tp.widenSingleton match {
case poly: PolyType => normalize(constrained(poly).resultType, pt)
case mt: MethodType =>
- if (mt.isImplicit)
- if (mt.isDependent)
- mt.resultType.substParams(mt, mt.paramTypes.map(Function.const(WildcardType)))
- else mt.resultType
- else
- if (mt.isDependent) tp
- else {
- val rt = normalize(mt.resultType, pt)
- pt match {
- case pt: IgnoredProto => mt
- case pt: ApplyingProto => mt.derivedMethodType(mt.paramNames, mt.paramTypes, rt)
- case _ =>
- val ft = defn.FunctionOf(mt.paramTypes, rt)
- if (mt.paramTypes.nonEmpty || ft <:< pt) ft else rt
- }
+ if (mt.isImplicit) mt.resultTypeApprox
+ else if (mt.isDependent) tp
+ else {
+ val rt = normalize(mt.resultType, pt)
+ pt match {
+ case pt: IgnoredProto => mt
+ case pt: ApplyingProto => mt.derivedMethodType(mt.paramNames, mt.paramTypes, rt)
+ case _ =>
+ val ft = defn.FunctionOf(mt.paramTypes, rt)
+ if (mt.paramTypes.nonEmpty || ft <:< pt) ft else rt
}
+ }
case et: ExprType => et.resultType
case _ => tp
}