- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Converting method types to "reflectable" types
Mon, 2011-12-26, 23:56
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@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher
Tue, 2011-12-27, 16:51
#2
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@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher
Tue, 2011-12-27, 17:51
#3
Re: Converting method types to "reflectable" types
On Tue, Dec 27, 2011 at 7:44 AM, Paul Butcher <paul@paulbutcher.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.
Wed, 2011-12-28, 02:11
#4
Re: Converting method types to "reflectable" types
On 27 Dec 2011, at 16:50, Paul Phillips 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 :-/
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@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher
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@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher
Tue, 2012-01-03, 18:41
#5
Re: Converting method types to "reflectable" types
On Tue, Dec 27, 2011 at 5:06 PM, Paul Butcher <paul@paulbutcher.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.
Sun, 2012-01-08, 12:21
#6
Re: Converting method types to "reflectable" types
On Wed, Dec 28, 2011 at 2:06 AM, Paul Butcher <paul@paulbutcher.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
On Mon, Dec 26, 2011 at 2:56 PM, Paul Butcher <paul@paulbutcher.com> wrote:
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)