Skip to content

Fix #2566: Ycheck that New node is always enclosed in a Select #2639

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 1 commit into from
Jun 4, 2017

Conversation

abeln
Copy link
Contributor

@abeln abeln commented May 31, 2017

Tested:
Verified that the test case in #2564
triggers the assert.
Verified that the check doesn't run when we ycheck a phase before frontend.

@@ -122,6 +122,10 @@ class TreeChecker extends Phase with SymTransformer {
val squahsedPhase = ctx.squashed(prevPhase)
ctx.echo(s"checking ${ctx.compilationUnit} after phase ${squahsedPhase}")

if (ctx.isAfterTyper) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@DarkDimius is this the right place to invoke the new check? Do I need to pass a fresh context?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, this is the right place.
TreeChecker is always after typer, no need for the if.

@abeln
Copy link
Contributor Author

abeln commented May 31, 2017

@DarkDimius The regular tests pass, but the legacy and bootstrap suites fail with what looks like unrelated (to this PR) errors. Are those tests flaky?


detect(NotFound(None), tree) match {
case Found(Some(parent), child) =>
assert(assertion = false, i"`New` node must be wrapped in a `Select`:\n parent = ${parent.show}\n child = ${child.show}")
Copy link
Contributor

Choose a reason for hiding this comment

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

I would put the assertion inside of the TreeAccumulator .apply to have it fail with the accumulator stacktrace. This would allow us to attache the debugger at the moment of the assertion failure and navigate back to the trees that contained this malformed New.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a good idea. Will do.

Copy link
Contributor

Choose a reason for hiding this comment

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

If you do this you might not even need the parameter of Found and could make it a case object

// Current state of the search. We return as soon as we see the first improperly wrapped `New`.
sealed trait State
case class NotFound(parent: Option[tpd.Tree]) extends State
case class Found(parent: Option[tpd.Tree], child: tpd.New) extends State
Copy link
Contributor

@nicolasstucki nicolasstucki Jun 1, 2017

Choose a reason for hiding this comment

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

Why not just partent: tpd.Tree?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When I invoke the accumulator on the root of the tree, there's no parent node. But I guess I could also pass an empty Thicket?

Copy link
Contributor

Choose a reason for hiding this comment

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

But on the root you use NotFound. My comment is only for Found.

For NotFound you could maybe simplify it using some trick like the Ticket or defining a case object Root extends State

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, when we construct the Found object,we use the optional parent from the NotFound, so the optionality trickles through the hierarchy. We can get rid of it everywhere with the Thicket.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Applied your suggestion and the code is now simpler. Thanks.

@abeln
Copy link
Contributor Author

abeln commented Jun 1, 2017

@DarkDimius @nicolasstucki
The test failures are because sometimes annotations violate the invariant:

e.g. this test https://github.com/lampepfl/dotty/blob/master/tests/pos/functions1.scala
after tailrec ends up with this node

Annotated(Ident(x),New(TypeTree[TypeRef(ThisType(TypeRef(NoPrefix,scala)),unchecked)]))

So should we relax the invariant? Is it ok for Annotated nodes to wrap New? (if so, which constructor gets chosen?)

Xprint:tailrec shows

val y: PartialFunction[String, String] = 
        {
          def $anonfun(x: String): String = 
            x match 
              {
                case "abc" => ""
                case _ => 
                  x
              }
          def isDefinedAt(x: String): Boolean = 
            x @unchecked match 
              {
                case "abc" => true
                case _ => true
                case _ @ _ => false
              }
          {
            class $anonfun() extends Object() with PartialFunction { 
              def apply(x: String): String = $anonfun(x)
              def isDefinedAt(x: String): Boolean = isDefinedAt(x)
            }
            new Object with PartialFunction[String, String]{...}()
          }
        }

@DarkDimius
Copy link
Contributor

Is it ok for Annotated nodes to wrap New?

Annotations aren't systematically transformed in the pipeline and they also can contain some-what invalid trees. I think you shouldn't recurse into annotations at all.

Tested:
Verified that the test case in scala#2564
triggers the assert.
Verified that the check doesn't run when we ycheck a phase before frontend.
@abeln
Copy link
Contributor Author

abeln commented Jun 2, 2017

@DarkDimius We no longer check inside annotations. PTAL.

@abeln
Copy link
Contributor Author

abeln commented Jun 4, 2017

Friendly ping.

@DarkDimius DarkDimius merged commit 92b2561 into scala:master Jun 4, 2017
@DarkDimius
Copy link
Contributor

Looks good to me!
@abeln, thanks for making Ycheck better!

@abeln abeln deleted the new-select branch June 7, 2017 22:31
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