diff options
author | Martin Odersky <odersky@gmail.com> | 2015-03-02 14:52:16 +0100 |
---|---|---|
committer | Dmitry Petrashko <dmitry.petrashko@gmail.com> | 2015-03-18 11:14:13 +0100 |
commit | 8f3e32781e9112e1567b9a5a78c52acd55b3506a (patch) | |
tree | 777bc08384b3564099abac25482b9076d1afdb68 | |
parent | fb72eaf1ebcdb4e562f98df239465421e862c42f (diff) | |
download | dotty-8f3e32781e9112e1567b9a5a78c52acd55b3506a.tar.gz dotty-8f3e32781e9112e1567b9a5a78c52acd55b3506a.tar.bz2 dotty-8f3e32781e9112e1567b9a5a78c52acd55b3506a.zip |
Avoiding dependent method types in closures
The previous logic for avoiding dependent method types in closures had a hole.
The problem arose when the expected return type of a closure was a type variable.
Then, the that type variable would be taken as the declared result type of the
closure without (at first) checking the body. The type variable would not yet
be bounded and therefore would not represent a dependent method type. Afterwards
when typechecking the closure the type variable woul dbe bounded and instantiated.
But at that time, all checking and possibly avoiding of depenencies has already
happened.
We solve the problem by typing the body of a closure during Namer whenever the expected
type is not fully defined.
Doing so uncovered a problem that anonymus function were seen as the target of returns
(tehy shoul be skipped instead). Thsi problem is fixed by a patch to SymDenotations#isSourceMethod.
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 5 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 19 |
2 files changed, 16 insertions, 8 deletions
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index e1254322e..4ededf796 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -456,8 +456,9 @@ object SymDenotations { } } - /** Is this a user defined "def" method? Excluded are accessors. */ - final def isSourceMethod(implicit ctx: Context) = this is (Method, butNot = AccessorOrLabel) + /** Is this a user defined "def" method? Excluded are accessors and anonymous functions. */ + final def isSourceMethod(implicit ctx: Context) = + this.is(Method, butNot = AccessorOrLabel) && !isAnonymousFunction /** Is this a setter? */ final def isGetter(implicit ctx: Context) = diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index 8293b0239..947d46ee0 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -653,13 +653,20 @@ class Namer { typer: Typer => lhsType orElse WildcardType } } - - val pt = mdef.tpt match { - case _: untpd.DerivedTypeTree => WildcardType - case TypeTree(untpd.EmptyTree) => inferredType - case _ => WildcardType + + val tptProto = mdef.tpt match { + case _: untpd.DerivedTypeTree => + WildcardType + case TypeTree(untpd.EmptyTree) => + inferredType + case TypedSplice(tpt: TypeTree) if !isFullyDefined(tpt.tpe, ForceDegree.none) => + typedAheadExpr(mdef.rhs, tpt.tpe) + typr.println(i"determine closure result type to be ${tpt.tpe}") + WildcardType + case _ => + WildcardType } - paramFn(typedAheadType(mdef.tpt, pt).tpe) + paramFn(typedAheadType(mdef.tpt, tptProto).tpe) } /** The type signature of a DefDef with given symbol */ |