This page is no longer maintained — Please continue to the home page at www.scala-lang.org

[scala-language] Compiler plugin: how to check method return values

6 replies
Olivier Pernet 2
Joined: 2010-12-03,
User offline. Last seen 42 years 45 weeks ago.

Hi all,

I'm working on a compiler plugin, and need to do additional checks on
the return values of some methods. I want to see all possible return
values of the methods of interest:
that means going through all branches and return statements.

This sounds complicated and error-prone. Is there some code I could
reuse in the compiler? The compiler must be doing something very
similar to checks that all return values are of the expected type or
subtypes. I haven't found it so far.
Olivier Pernet

We are the knights who say
echo '16i[q]sa[ln0=aln100%Pln100/snlbx]sbA0D4D465452snlbxq'|dc

rytz
Joined: 2008-07-01,
User offline. Last seen 45 weeks 5 days ago.
Re: [scala-language] Compiler plugin: how to check method return
It's all in "Typers.scala". Look for "typedDefDef". The compiler computesthe type of the righthand-side and verifies that it's a subtype of the annotatedreturn type.
In case the return type is inferred, there's no check.
Scala doesn't allow "return" statements in methods without explicit return type(see "typedReturn").
Cheers: Lukas
On Fri, Jan 28, 2011 at 14:01, Olivier Pernet <o.pernet@gmail.com> wrote:
Hi all,

I'm working on a compiler plugin, and need to do additional checks on
the return values of some methods. I want to see all possible return
values of the methods of interest:
that means going through all branches and return statements.

This sounds complicated and error-prone. Is there some code I could
reuse in the compiler? The compiler must be doing something very
similar to checks that all return values are of the expected type or
subtypes. I haven't found it so far.
Olivier Pernet

We are the knights who say
echo '16i[q]sa[ln0=aln100%Pln100/snlbx]sbA0D4D465452snlbxq'|dc

Olivier Pernet
Joined: 2010-03-13,
User offline. Last seen 42 years 45 weeks ago.
Re: [scala-language] Compiler plugin: how to check method return

On Fri, Jan 28, 2011 at 13:13, Lukas Rytz wrote:
> It's all in "Typers.scala". Look for "typedDefDef". The compiler computes
> the type of the righthand-side and verifies that it's a subtype of the
> annotated
> return type.
> In case the return type is inferred, there's no check.
> Scala doesn't allow "return" statements in methods without explicit return
> type
> (see "typedReturn").
> Cheers: Lukas

Thanks! I'm looking at Typers now, and what I'm interested in seems to be in
the scary, scary method
protected def typed1(tree: Tree, mode: Int, pt: Type): Tree.

Do you think I can reuse some of this code for my purpose? I want to
see all return values of some methods and verify that they are tuples
with components in a consistent order.

So I need a pattern-matching block that will go down all branches and
match their final expressions, but only for branches whose value is
not bound to a val or var.

How would you go about that?

Cheers,
Olivier

rytz
Joined: 2008-07-01,
User offline. Last seen 45 weeks 5 days ago.
Re: [scala-language] Compiler plugin: how to check method return


On Fri, Jan 28, 2011 at 14:53, Olivier Pernet <omp08@doc.ic.ac.uk> wrote:
On Fri, Jan 28, 2011 at 13:13, Lukas Rytz <lukas.rytz@epfl.ch> wrote:
> It's all in "Typers.scala". Look for "typedDefDef". The compiler computes
> the type of the righthand-side and verifies that it's a subtype of the
> annotated
> return type.
> In case the return type is inferred, there's no check.
> Scala doesn't allow "return" statements in methods without explicit return
> type
> (see "typedReturn").
> Cheers: Lukas

Thanks! I'm looking at Typers now, and what I'm interested in seems to be in
the scary, scary method
protected def typed1(tree: Tree, mode: Int, pt: Type): Tree.

Do you think I can reuse some of this code for my purpose? I want to
see all return values of some methods and verify that they are tuples
with components in a consistent order.

How do you decide if a value matches or not, by looking at the type?Then you only need to look at the type of the expression and the types of all "Return" trees.
class MyTrav extends Traverser {  val enclMethods: Stack[Symbol]
  override def traverse(tree: Tree) {    tree match {       case DefDef(_, _, _, _, _, rhs) =>        verify-type(rhs.tpe, tree.symbol.tpe)        enclMethods push tree.symbol        traverse(rhs)         enclMethods.pop()
      case Return(expr) =>        verify-type(expr.tpe, enclMethods.top.tpe)        traverse(expr)
      case _=> super.traverse(tree)   }}
 

So I need a pattern-matching block that will go down all branches and
match their final expressions, but only for branches whose value is
not bound to a val or var.

Please elaborate. 

How would you go about that?

Cheers,
Olivier

Olivier Pernet
Joined: 2010-03-13,
User offline. Last seen 42 years 45 weeks ago.
Re: [scala-language] Compiler plugin: how to check method return

On Fri, Jan 28, 2011 at 14:21, Lukas Rytz wrote:
>
>
> On Fri, Jan 28, 2011 at 14:53, Olivier Pernet wrote:
>>
>> On Fri, Jan 28, 2011 at 13:13, Lukas Rytz wrote:
>> > It's all in "Typers.scala". Look for "typedDefDef". The compiler
>> > computes
>> > the type of the righthand-side and verifies that it's a subtype of the
>> > annotated
>> > return type.
>> > In case the return type is inferred, there's no check.
>> > Scala doesn't allow "return" statements in methods without explicit
>> > return
>> > type
>> > (see "typedReturn").
>> > Cheers: Lukas
>>
>> Thanks! I'm looking at Typers now, and what I'm interested in seems to be
>> in
>> the scary, scary method
>> protected def typed1(tree: Tree, mode: Int, pt: Type): Tree.
>>
>> Do you think I can reuse some of this code for my purpose? I want to
>> see all return values of some methods and verify that they are tuples
>> with components in a consistent order.
>
> How do you decide if a value matches or not, by looking at the type?
> Then you only need to look at the type of the expression and the types
> of all "Return" trees.
> class MyTrav extends Traverser {
>   val enclMethods: Stack[Symbol]
>   override def traverse(tree: Tree) {
>     tree match {
>       case DefDef(_, _, _, _, _, rhs) =>
>         verify-type(rhs.tpe, tree.symbol.tpe)
>         enclMethods push tree.symbol
>         traverse(rhs)
>         enclMethods.pop()
>       case Return(expr) =>
>         verify-type(expr.tpe, enclMethods.top.tpe)
>         traverse(expr)
>       case _=> super.traverse(tree)
>   }
> }
>
>>
>> So I need a pattern-matching block that will go down all branches and
>> match their final expressions, but only for branches whose value is
>> not bound to a val or var.
>
> Please elaborate.

Ok, that was unclear. More details:

My compiler plugin implements a flavour of session types, which are
about using typing to enforce communication protocols.
Session type checking is only concerned with communication channels (I
have a library class that represents them).

Session typing is a specific kind of linear typing: communication
channels cannot be duplicated, otherwise static checking of the
protocol becomes impossible.

I allow communication channels to be passed to methods, which
implement part of a protocol. A method can take more than one channel
as a parameter, and implement parts of several interleaved protocols.

To allow the caller of such a method to implement the rest of the
protocol, I allow methods to return the communication channels they
got as parameters. When there are more than one, they should be
wrapped in a tuple.

We get here to the reason for my email: I need to check that channels
returned in a tuple are always returned in the same order, otherwise
static checking is impossible. Example:

def mymethod(s1: SessionChannel, s2: SessionChannel): (SessionChannel,
SessionChannel) = {
s1 ! 42
s2 ! "foo"
if (condition) (s1, s2) // this...
else (s2, s1) // ...should be a compile error
}

How could I enforce this? Alternatively I could mandate that channels
always be returned at the top-level of the method, but then I still
have to check all branches to make sure there is only one return
point, so it's basically the same amount of work.

Thanks a lot,
Olivier

rytz
Joined: 2008-07-01,
User offline. Last seen 45 weeks 5 days ago.
Re: [scala-language] Compiler plugin: how to check method return
You can do something ad-hoc, pattern match on some trees that you allow andreject all other methods, but then I don't think there's a "better" way to do it, thetype checker can't help you.
However, you might be interested in Philipp Haller's extension of the Scalatype system to track unique references.See here: http://lamp.epfl.ch/~phaller/capabilities.html
Cheers: Lukas

Olivier Pernet
Joined: 2010-03-13,
User offline. Last seen 42 years 45 weeks ago.
Re: [scala-language] Compiler plugin: how to check method return

On Fri, Jan 28, 2011 at 19:18, Lukas Rytz wrote:
> You can do something ad-hoc, pattern match on some trees that you allow and
> reject all other methods, but then I don't think there's a "better" way to
> do it, the
> type checker can't help you.
> However, you might be interested in Philipp Haller's extension of the Scala
> type system to track unique references.
> See here: http://lamp.epfl.ch/~phaller/capabilities.html
> Cheers: Lukas

Thanks, I read about Philipp's work in his ECOOP'10 paper (someone
from our group actually presented just after or before him). Linearity
checking is actually a small part of what I'm doing, and doesn't need
to be as fine-grained as in Philipp's work, so I'm doing it myself.
I'll have a look at his code for ideas about how to structure my
plugin, though.

I ended up doing ad-hoc pattern matching, which turned out a lot
easier than I expected:
http://code.google.com/p/session-scala/source/diff?spec=svn45a93d93b470f...

Thanks for your help!

Olivier

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland