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

Converting method types to "reflectable" types

6 replies
paulbutcher
Joined: 2010-03-08,
User offline. Last seen 10 weeks 5 days ago.

In my compiler plugin, given a method, I want to find that method's "reflectable" type (i.e. the types to be passed to Class.getMethod to find an instance of that method). This boils down to replacing every type-parameterised parameter type with Any.

Consider, for example, the following class:

> package com.example
>
> class C[T] {
> def m1(x: Int, y: Double) = (x, y)
> def m2[A, B](x: Int, y: A, z: B) = (x, y, z)
> def m3(x: Int, y: T) = (x, y)
> }

I have no problem with m1 (the types I'm after are just the parameter types) and m2 (I just use appliedType to instantiate both A and B to Any), but I'm struggling with m3. I thought that I could use appliedType on C to instantiate T to Any, but that doesn't seem to work - see below:

> Welcome to Scala version 2.9.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_29).
> Type in expressions to have them evaluated.
> Type :help for more information.
>
> scala> :power
> ** Power User mode enabled - BEEP BOOP SPIZ **
> ** :phase has been set to 'typer'. **
> ** scala.tools.nsc._ has been imported **
> ** global._ and definitions._ also imported **
> ** Try :help, vals., power. **
>
> scala> import com.example._
> import com.example._
>
> scala> getClassIfDefined("com.example.C")
> res0: $r.global.Symbol = class C
>
> scala> res0.info.member("m1").info.params map (_.tpe)
> res1: List[$r.global.Type] = List(Int, Double)
>
> scala> res0.info.member("m2").info.params map (_.tpe)
> res2: List[$r.global.Type] = List(Int, A, B)
>
> scala> appliedType(res0.info.member("m2").info, List(AnyClass.tpe, AnyClass.tpe)).params map (_.tpe)
> res3: List[$r.global.Type] = List(Int, Any, Any)
>
> scala> res0.info.member("m3").info.params map (_.tpe)
> res4: List[$r.global.Type] = List(Int, T)
>
> scala> appliedType(res0.info, List(AnyClass.tpe))
> res5: $r.global.Type = java.lang.Object with ScalaObject{def this: <?>; def m1(x: Int,y: Double): (Int, Double); def m2[A,B](x: Int,y: A,z: B): (Int, A, B); def m3(x: Int,y: T): (Int, T)}
>
> scala> res5.member("m3").info.params map (_.tpe)
> res6: List[$r.global.Type] = List(Int, T)

I'd very much welcome a pointer in the right direction.

Thanks!

--
paul.butcher->msgCount++

Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: paul [at] paulbutcher [dot] com
AIM: paulrabutcher
Skype: paulrabutcher

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Converting method types to "reflectable" types


On Mon, Dec 26, 2011 at 2:56 PM, Paul Butcher <paul [at] paulbutcher [dot] com> wrote:
> scala> appliedType(res0.info, List(AnyClass.tpe))
> res5: $r.global.Type = java.lang.Object with ScalaObject{def this: <?>; def m1(x: Int,y: Double): (Int, Double); def m2[A,B](x: Int,y: A,z: B): (Int, A, B); def m3(x: Int,y: T): (Int, T)}

That output is a big warning sign that you didn't do what you meant, because you should see something like "C[Any]" assuming you mean what I take you to mean.  You need to apply Any to the type constructor of C (which is a TypeRef whose symbol has type parameters) not its symbol's info (which is probably a PolyType wrapping a ClassInfoType.)
scala> val c = appliedType(res0.typeConstructor, List(AnyClass.tpe))c: $r.intp.global.Type = com.example.C[Any]
// And the method symbol.scala> val m3 = c.member("m3".toTermName) m3: $r.intp.global.Symbol = method m3
// However m3 itself still has C's type parameters floating around.scala> m3.defStringres0: String = def m3(x: Int,y: T): (Int, T)
// Here and often you need "asSeenFrom" in one form or another,// in this case most easily like this:scala> c.memberType(m3)res1: $r.intp.global.Type = (x: Int, y: Any)(Int, Any)
paulbutcher
Joined: 2010-03-08,
User offline. Last seen 10 weeks 5 days ago.
Re: Converting method types to "reflectable" types

On 27 Dec 2011, at 04:16, Paul Phillips wrote:
> That output is a big warning sign that you didn't do what you meant

I had no doubt that I didn't do what I meant - I just didn't know what I should be doing differently :-)

> to mean. You need to apply Any to the type constructor of C (which is a TypeRef whose symbol has type parameters) not its symbol's info (which is probably a PolyType wrapping a ClassInfoType.)
>
> scala> val c = appliedType(res0.typeConstructor, List(AnyClass.tpe))
> c: $r.intp.global.Type = com.example.C[Any]
>
> // And the method symbol.
> scala> val m3 = c.member("m3".toTermName)
> m3: $r.intp.global.Symbol = method m3
>
> // However m3 itself still has C's type parameters floating around.
> scala> m3.defString
> res0: String = def m3(x: Int,y: T): (Int, T)
>
> // Here and often you need "asSeenFrom" in one form or another,
> // in this case most easily like this:
> scala> c.memberType(m3)
> res1: $r.intp.global.Type = (x: Int, y: Any)(Int, Any)

Thanks Paul - that looks like exactly what I'm after.

Thanks again!

--
paul.butcher->msgCount++

Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: paul [at] paulbutcher [dot] com
AIM: paulrabutcher
Skype: paulrabutcher

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Converting method types to "reflectable" types


On Tue, Dec 27, 2011 at 7:44 AM, Paul Butcher <paul [at] paulbutcher [dot] com> wrote:
Thanks Paul - that looks like exactly what I'm after.

Thanks again!

If you really want to thank me (and this goes for anyone to whom I've given compiler advice) you could take a shot at distilling some of this information into compiler documentation.  It doesn't matter if you don't understand everything and have some inaccuracies; it's easier for me to correct an existing document than to write something from scratch.  I know how hard this knowledge is to come by and it's not something I take any pleasure in, but on any given day the code always seems more important.
paulbutcher
Joined: 2010-03-08,
User offline. Last seen 10 weeks 5 days ago.
Re: Converting method types to "reflectable" types
On 27 Dec 2011, at 16:50, Paul Phillips wrote:
If you really want to thank me (and this goes for anyone to whom I've given compiler advice) you could take a shot at distilling some of this information into compiler documentation.

I'd love to, Paul - but I fear my understanding is still pretty shaky. I'm at that "voodoo" stage where I know a few magic incantations that seem to work, but I'm not sure that I really understand them enough to write anything meaningful :-/
I'll bear it in mind, for the future, however - my understanding is increasing all the time :-)
While we're on the subject of documentation, is there anywhere I should be looking to find existing documentation other than:
http://www.scala-lang.org/node/140http://lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/
--
paul.butcher->msgCount++

Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: paul [at] paulbutcher [dot] com
AIM: paulrabutcher
Skype: paulrabutcher
extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Converting method types to "reflectable" types


On Tue, Dec 27, 2011 at 5:06 PM, Paul Butcher <paul [at] paulbutcher [dot] com> wrote:
While we're on the subject of documentation, is there anywhere I should be looking to find existing documentation other than:
http://www.scala-lang.org/node/140 http://lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/

When I write compiler documentation (admittedly not that often) it's either in the source code or in the commit message.  With git you can always go back and see a commit, which in my experience is a lot more educational than documentation.
vlad.ureche
Joined: 2011-03-17,
User offline. Last seen 1 year 26 weeks ago.
Re: Converting method types to "reflectable" types


On Wed, Dec 28, 2011 at 2:06 AM, Paul Butcher <paul [at] paulbutcher [dot] com> wrote:

I'd love to, Paul - but I fear my understanding is still pretty shaky. I'm at that "voodoo" stage where I know a few magic incantations that seem to work, but I'm not sure that I really understand them enough to write anything meaningful :-/

Hi PaulB,

I found the Scala Compiler Internals presentations by Martin particularly useful for compiler hacking.
Some things might have changed a bit in the meantime, but the basics are there.

HTH
Vlad

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