Skip to content

Restructure Try node. #202

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 16 commits into from
Nov 3, 2014
Merged

Conversation

DarkDimius
Copy link
Contributor

Now Try node always has cases as handlers. In case handler is an Ident of
type Throwable => T than it's desugared to a CaseDef during parsing.

@DarkDimius
Copy link
Contributor Author

@odersky please review

@retronym
Copy link
Member

In Scala2, handlers of Throwable => T are not allowed:

scala> try { ??? } catch { case F }
<console>:1: error: '=>' expected but '}' found.
       try { ??? } catch { case F }
                                  ^

scala> try { ??? } catch F
<console>:9: error: value isDefinedAt is not a member of Throwable => Unit
              try { ??? } catch F
                                ^

Only PartialFunction-s are supported:

scala> val F: PartialFunction[Throwable, Unit] = { case _ => }
F: PartialFunction[Throwable,Unit] = <function1>

scala> try { ??? } catch F

Perhaps this is a conscious generalisation of the existing facility, though.

@retronym
Copy link
Member

I also notice that we allow an expression that is implicit convertible to that type.

scala> try { ??? } catch ""

scala> try { ??? } catch "".reverse

The spec says:

The handler h is expected conform to type scala.PartialFunction[scala.Throwable, pt]

The implementation wrongly appears to assume s/conform to/be compatible with/.

I have lodged this as https://issues.scala-lang.org/browse/SI-8945.

List(CaseDef(Ident(nme.DEFAULT_EXCEPTION_NAME), EmptyTree, Apply(handler, Ident(nme.DEFAULT_EXCEPTION_NAME)))),
finalizer)
}

Copy link
Member

Choose a reason for hiding this comment

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

Isn't the dotty parser designed as a desugaring-free zone?

@odersky
Copy link
Contributor

odersky commented Oct 29, 2014

I proposed the representation in the PR, but Jason is right. It is not good that the parser does this desugaring. The parser represents naked case blocks

 { case P1 => E1 ... case Pn => En }

as Match nodes with EmptyTree as the selector. How about we use the same representation for catch blocks? I.e. a Try would be represented as follows:

 case class Try(body: Tree, handler: Tree, finalizer: Tree)

and after desugaring we would make sure that the handler is always of the form

 Match(EmptyTree, cases)

What do people think about this?

@odersky odersky mentioned this pull request Oct 29, 2014
@retronym
Copy link
Member

SGTM

@DarkDimius
Copy link
Contributor Author

@odersky In case Try after desugaring(and typeing) should always have handlers as cases, I believe it would be better to have this enforced by types.
We already have a untyped trees that are parsed but are gone after typechecking&desugaring. I propose to have a different tree representing Try nodes before and after desugaring. See my last commit.

What do you think?

Simplifies a lot handling of Try blocks in patmat and in tailrec.
Box& unbox methods are defined in companion objects.
It doesn't exist.
Also use symbol with 'ex' name as selector for exceptions
After erasure was always wrong(didn't include the type of handler).
Now it's able to use both Closures and desugared Math nodes.
Now Try node always has cases as handlers.
In case handler is an Ident of type Throwable => T
than it's desugared to a CaseDef during parsing.
It's not used anymore as superseded by previous commit.
Instead of desugaring in parser desugaring is now done during desugaring.
@DarkDimius
Copy link
Contributor Author

@odersky should be ready for review. #206 Conflicts with this as both change typer and I would prefer to get this in first.

@@ -60,7 +61,10 @@ class Run(comp: Compiler)(implicit ctx: Context) {

private def printTree(ctx: Context) = {
val unit = ctx.compilationUnit
println(s"result of $unit after ${ctx.phase.prev}:")
val prevPhase = ctx.phase.prev // can be a mini-phase
val squahsedPhase = ctx.squashed(prevPhase)
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo

@odersky
Copy link
Contributor

odersky commented Oct 31, 2014

Otherwise LGTM.

DarkDimius added a commit that referenced this pull request Nov 3, 2014
@DarkDimius DarkDimius merged commit 97a3732 into scala:master Nov 3, 2014
@DarkDimius DarkDimius deleted the no-closure-try branch November 3, 2014 10:18
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