Skip to content

Make sure arguments are evaluated in the correct typer state. #1460

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 26, 2016

Conversation

odersky
Copy link
Contributor

@odersky odersky commented Aug 21, 2016

There's a tricky interaction with caching of typed arguments in FunProto types
and backtracking using different typer states. We might end up with a typed
argument that is evaluated in one typer state and that is used in another. The
problem is that the argument typing might have inserted type variables (maybe
by adding polymorphic implicit views) that are not registered in the typer
state in which the application is finally typed. In that case we will see
an "orphan poly parameter" in pickling.

The fix is to discard argument types if their typerstate is not committed
to the one in which the application is finally typed. To apply the fix we
need to track

  • for typer states: whether or not it was committed, and what its parent is.
  • for function prototypes: the typer state in which an argument with cached type
    was evaluated.

Test case is t1756.scala, which produced an "orphan poly parameter CI" before.

Based on #1459. First new commit is "Don't force in isErroneous check".

Review by @smarter.

def parent: Option[TyperState] = None

/** The closest ancestor of this typer state (including possible this typer state itself)
* which is not yet committed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation should state what is returned when this state and all of its ancestors are committed, or this method should return an Option

@@ -546,7 +546,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
val fun1 = typedExpr(tree.fun, originalProto)

// Warning: The following lines are dirty and fragile. We record that auto-tupling was demanded as
// a side effect in adapt. If it was, we assume the tupled proto-type in the rest of the application.
// a side effect in adapt. If it was, we assume the tupled proto-type in the rest of the application,
// until, possibly, we have to fall back to insert an implicit on thq qualifier.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So why does the code do tryWithImplicitOnQualifier(fun1, originalProto) and then fallbacks to tryWithImplicitOnQualifier(fun1, proto), isn't originalProto the non-tupled one?

Copy link
Contributor Author

@odersky odersky Aug 21, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have to try with both tupled and untupled. I'll add a comment.

isErroneous forced LazyRefs through the `existsPart` combinator. This
might prompt further errors or infinite recursions, so should be avoided.

Seen in the wild when trying to trace t1756.scala with -Ylog:front and typr printer on.
There's a tricky interaction with caching of typed arguments in FunProto types
and backtracking using different typer states. We might end up with a typed
argument that is evaluated in one typer state and that is used in another. The
problem is that the argument typing might have inserted type variables (maybe
by adding polymorphic implicit views) that are not registered in the typer
state in which the application is finally typed. In that case we will see
an "orphan poly parameter" in pickling.

The fix is to discard argument types is their typerstate is not committed
to the one in which the application is finally typed. To apply the fix we
need to track

 - for typer states: whether or not it was committed, and what its parent is.
 - for function prototypes: the typer state in which an argument with cached type
   was evaluated.

Test case is t1756.scala, which produced an "orphan poly parameter CI" before.
@odersky
Copy link
Contributor Author

odersky commented Aug 21, 2016

Rebased to master. The test failures are all OOM, btw.

new ApplyToTyped(tree, fun1, funRef, proto.typedArgs, pt)
else
new ApplyToUntyped(tree, fun1, funRef, proto, pt)(argCtx(tree))
convertNewGenericArray(ConstFold(app.result))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of this code is duplicated from typedApply and this line is especially non-obvious, it would be better to have simpleApply and typedApply call into a common method

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I can see, the code was moved out of typedApply, not duplicated.

/** The closest ancestor of this typer state (including possibly this typer state itself)
* which is not yet committed, or which does not have a parent.
*/
def uncommittedAncestor: TyperState =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

proposal: instead of storing the direct parent, lazily-cache uncommittedAncestor and test-update it every time it's updated:

private var lastUncommittedAncestor = parent

def uncommittedAncestor: TyperState = {
  if (lastUncommittedAncestor.isCommited && lastUncommittedAncestor.isDefined) { 
    lastUncommittedAncestor = lastUncommittedAncestor.lastUncommittedAncestor
  }
  lastUncommittedAncestor
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I'll roll that into the next PR.

@odersky odersky merged commit b300542 into scala:master Aug 26, 2016
@allanrenucci allanrenucci deleted the fix-t1756 branch December 14, 2017 19:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants