diff options
author | Martin Odersky <odersky@gmail.com> | 2016-08-26 16:38:37 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-08-26 17:57:09 +0200 |
commit | 36648547105bc8ac53dd63a03821a27243af13cd (patch) | |
tree | 87aa262b01aa983088e7f3349da2cc380308f15b /src | |
parent | eef9be9817f5c0516e221aab1d14d748a12b386c (diff) | |
download | dotty-36648547105bc8ac53dd63a03821a27243af13cd.tar.gz dotty-36648547105bc8ac53dd63a03821a27243af13cd.tar.bz2 dotty-36648547105bc8ac53dd63a03821a27243af13cd.zip |
Handle complex context merging cases
Test case in isApplicableSafe.scala. It turns out that this
requires a context merge using the new `&' operator. Sequence of actions:
1) Typecheck argument in typerstate 1.
2) Cache argument.
3) Evolve same typer state (to typecheck other arguments, say)
leading to a different constraint.
4) Take typechecked argument in same state.
It turns out that the merge in TyperState is needed not just for
isApplicableSafe but also for (e.g. erased-lubs.scala) as well as
many parts of dotty itself.
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/core/TyperState.scala | 8 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Inferencing.scala | 3 |
2 files changed, 7 insertions, 4 deletions
diff --git a/src/dotty/tools/dotc/core/TyperState.scala b/src/dotty/tools/dotc/core/TyperState.scala index 4b3c1554d..a7ad6824f 100644 --- a/src/dotty/tools/dotc/core/TyperState.scala +++ b/src/dotty/tools/dotc/core/TyperState.scala @@ -96,7 +96,8 @@ extends TyperState(r) { override def reporter = myReporter - private var myConstraint: Constraint = previous.constraint + private val previousConstraint = previous.constraint + private var myConstraint: Constraint = previousConstraint override def constraint = myConstraint override def constraint_=(c: Constraint)(implicit ctx: Context) = { @@ -129,8 +130,9 @@ extends TyperState(r) { override def commit()(implicit ctx: Context) = { val targetState = ctx.typerState assert(isCommittable) - if (targetState eq previous) targetState.constraint = constraint - else targetState.constraint &= constraint + targetState.constraint = + if (targetState.constraint eq previousConstraint) constraint + else targetState.constraint & constraint constraint foreachTypeVar { tvar => if (tvar.owningState eq this) tvar.owningState = targetState diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala index 7c61f8c23..719e8d7fc 100644 --- a/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/src/dotty/tools/dotc/typer/Inferencing.scala @@ -78,7 +78,8 @@ object Inferencing { def apply(x: Boolean, tp: Type): Boolean = tp.dealias match { case _: WildcardType | _: ProtoType => false - case tvar: TypeVar if !tvar.isInstantiated => + case tvar: TypeVar + if !tvar.isInstantiated && ctx.typerState.constraint.contains(tvar) => force.appliesTo(tvar) && { val direction = instDirection(tvar.origin) if (direction != 0) { |