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

Type checker problem with transformed AST

2 replies
Lucas Satabin
Joined: 2010-02-23,
User offline. Last seen 2 years 3 weeks ago.

Hi everybody,

In a compiler plugin that I am writing, I generate some elements before
the type checking phase. I wanted to benefit from the type checking
system of the scala compiler to check that my generated code is type
safe (and also because I have to rewrite things that are actually not
type safe as this).
But during type checking the compiler is complaining because a class is
not found in the given package which actually is present in the package.
he re is the original source code

import events.annot._

class Test {

lazy val e = new events.lib.ExplicitEvent[Int]

@observable
def test(i: Int) = println("test")
}

After my transformation phase, the AST is as follows:

[[syntax trees at end of observables]]// Scala source: Test.scala
package {
import events.annot._;
class Test extends scala.ScalaObject {
...
lazy val test$Int$before = new
events.lib.ExplicitEvent[Int].();
lazy val test$Int$after = new
events.lib.ExplicitEvent[Int].();
...
lazy val e = new events.lib.ExplicitEvent[Int].();
...
}
}

The two synthetic values are generated as follows:

val newEv =
Apply(
Select(
New(AppliedTypeTree(
Select(
Select(Ident("events"),
newTermName("lib")),
newTermName("ExplicitEvent")), generics)),
newTermName("")),
Nil)
val modifiers = tree.mods
val flags = modifiers.copy(modifiers.flags,
modifiers.privateWithin,
Nil,
modifiers.positions) | LAZY | SYNTHETIC

val evt = ValDef(flags, name, TypeTree(), newEv)
atPos(pos)(evt)

The type checking phase can not type the synthesized member BUT can type
the lazy val e!

Running the compiler with the -Ydebug option, I get the following message:

/path/to/Test.scala:7: error: value ExplicitEvent is not a member of
package events.this.lib
@observable
^
qual = events.lib:.this.events.lib.type
Symbol=package lib
symbol-info = package events.this.lib
scope-id = 24737685
members = List( [...] , object ExplicitEvent, class ExplicitEvent, [...] )
name = ExplicitEvent
found = object ExplicitEvent
owner = class Test
scala.tools.nsc.symtab.Types$TypeError: value ExplicitEvent is not a
member of package events.this.lib
at
scala.tools.nsc.typechecker.Contexts$Context.error(Contexts.scala:318)
at scala.tools.nsc.typechecker.Infer$Inferencer.error(Infer.scala:273)
at
scala.tools.nsc.typechecker.Typers$Typer.typedSelect$1(Typers.scala:3488)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:3994)
at
scala.tools.nsc.typechecker.Typers$Typer.typedAppliedTypeTree$1(Typers.scala:3682)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4026)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4087)
at
scala.tools.nsc.typechecker.Typers$Typer.typedTypeConstructor(Typers.scala:4207)
at
scala.tools.nsc.typechecker.Typers$Typer.typedTypeConstructor(Typers.scala:4230)
at
scala.tools.nsc.typechecker.Typers$Typer.typedNew$1(Typers.scala:3160)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:3858)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4087)
at
scala.tools.nsc.typechecker.Typers$Typer.typedQualifier(Typers.scala:4162)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:3973)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4087)
at
scala.tools.nsc.typechecker.Typers$Typer$$anonfun$typedApply$1$1.apply(Typers.scala:3304)
at
scala.tools.nsc.typechecker.Typers$Typer$$anonfun$typedApply$1$1.apply(Typers.scala:3304)
at scala.tools.nsc.typechecker.Typers$Typer.silent(Typers.scala:716)
at
scala.tools.nsc.typechecker.Typers$Typer.typedApply$1(Typers.scala:3304)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:3933)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4087)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4153)
at
scala.tools.nsc.typechecker.Typers$Typer.computeType(Typers.scala:4233)
at scala.tools.nsc.typechecker.Namers$Namer.typeSig(Namers.scala:1154)
at
scala.tools.nsc.typechecker.Namers$Namer$$anonfun$typeCompleter$1.apply(Namers.scala:515)
at
scala.tools.nsc.typechecker.Namers$Namer$$anonfun$typeCompleter$1.apply(Namers.scala:513)
at
scala.tools.nsc.typechecker.Namers$$anon$1.complete(Namers.scala:1303)
at scala.tools.nsc.symtab.Symbols$Symbol.info(Symbols.scala:758)
at scala.tools.nsc.symtab.Symbols$Symbol.initialize(Symbols.scala:867)
at scala.tools.nsc.symtab.Symbols$Symbol.annotations(Symbols.scala:114)
at
scala.tools.nsc.typechecker.Typers$Typer.addGetterSetter(Typers.scala:1346)
at
scala.tools.nsc.typechecker.Typers$Typer$$anonfun$9.apply(Typers.scala:1511)
at
scala.tools.nsc.typechecker.Typers$Typer$$anonfun$9.apply(Typers.scala:1511)
at
scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:259)
at
scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:259)
at scala.collection.LinearSeqLike$class.foreach(LinearSeqLike.scala:97)
at scala.collection.immutable.List.foreach(List.scala:46)
at
scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:259)
at scala.collection.immutable.List.flatMap(List.scala:46)
at
scala.tools.nsc.typechecker.Typers$Typer.typedTemplate(Typers.scala:1511)
at
scala.tools.nsc.typechecker.Typers$Typer.typedClassDef(Typers.scala:1296)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:3742)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4087)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4140)
at
scala.tools.nsc.typechecker.Typers$Typer.typedStat$1(Typers.scala:2098)
at
scala.tools.nsc.typechecker.Typers$Typer$$anonfun$20.apply(Typers.scala:2166)
at
scala.tools.nsc.typechecker.Typers$Typer$$anonfun$20.apply(Typers.scala:2166)
at scala.collection.immutable.List.loop$1(List.scala:116)
at scala.collection.immutable.List.mapConserve(List.scala:133)
at
scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:2166)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:3738)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4087)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4140)
at
scala.tools.nsc.typechecker.Analyzer$typerFactory$$anon$3.apply(Analyzer.scala:82)
at
scala.tools.nsc.Global$GlobalPhase$$anonfun$applyPhase$1.apply(Global.scala:281)
at
scala.tools.nsc.Global$GlobalPhase$$anonfun$applyPhase$1.apply(Global.scala:281)
at scala.tools.nsc.reporters.Reporter.withSource(Reporter.scala:48)
at scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:281)
at
scala.tools.nsc.typechecker.Analyzer$typerFactory$$anon$3$$anonfun$run$1.apply(Analyzer.scala:77)
at
scala.tools.nsc.typechecker.Analyzer$typerFactory$$anon$3$$anonfun$run$1.apply(Analyzer.scala:77)
at scala.collection.Iterator$class.foreach(Iterator.scala:582)
at
scala.collection.mutable.ListBuffer$$anon$1.foreach(ListBuffer.scala:285)
at
scala.tools.nsc.typechecker.Analyzer$typerFactory$$anon$3.run(Analyzer.scala:77)
at scala.tools.nsc.Global$Run.compileSources(Global.scala:749)
at scala.tools.nsc.Global$Run.compile(Global.scala:839)
at scala.tools.nsc.Main$.process(Main.scala:110)
at scala.tools.nsc.Main$.main(Main.scala:124)
at scala.tools.nsc.Main.main(Main.scala)

The compiler version that I am using is 2.8.0.Beta1-prerelease (I get
the same error message with the last one from the repository, only with
other line numbers)

I also checked my generated AST tree via the -Ybrowse option and both
generated subtree and the one for the lazy value e are identically
structured. I really do not understand what I am doing wrong.
Has anybody an idea of this problem?

Thanks in advance
Lucas

Lucas Satabin
Joined: 2010-02-23,
User offline. Last seen 2 years 3 weeks ago.
Re: Type checker problem with transformed AST

Lucas Satabin schrieb:
> Hi everybody,
>
> In a compiler plugin that I am writing, I generate some elements
> before the type checking phase. I wanted to benefit from the type
> checking system of the scala compiler to check that my generated code
> is type safe (and also because I have to rewrite things that are
> actually not type safe as this).
> But during type checking the compiler is complaining because a class
> is not found in the given package which actually is present in the
> package.
> he re is the original source code
>
> import events.annot._
>
> class Test {
>
> lazy val e = new events.lib.ExplicitEvent[Int]
>
> @observable
> def test(i: Int) = println("test")
> }
>
> After my transformation phase, the AST is as follows:
>
> [[syntax trees at end of observables]]// Scala source: Test.scala
> package {
> import events.annot._;
> class Test extends scala.ScalaObject {
> ...
> lazy val test$Int$before = new
> events.lib.ExplicitEvent[Int].();
> lazy val test$Int$after = new
> events.lib.ExplicitEvent[Int].();
> ...
> lazy val e = new events.lib.ExplicitEvent[Int].();
> ...
> }
> }
>
> The two synthetic values are generated as follows:
>
> val newEv =
> Apply(
> Select(
> New(AppliedTypeTree(
> Select(
> Select(Ident("events"),
> newTermName("lib")),
> newTermName("ExplicitEvent")), generics)),
> newTermName("")),
> Nil)
> val modifiers = tree.mods
> val flags = modifiers.copy(modifiers.flags,
> modifiers.privateWithin,
> Nil,
> modifiers.positions) | LAZY | SYNTHETIC
> val evt = ValDef(flags, name, TypeTree(), newEv)
> atPos(pos)(evt)
>
> The type checking phase can not type the synthesized member BUT can
> type the lazy val e!
>
> Running the compiler with the -Ydebug option, I get the following
> message:
>
> /path/to/Test.scala:7: error: value ExplicitEvent is not a member of
> package events.this.lib
> @observable
> ^
> qual = events.lib:.this.events.lib.type
> Symbol=package lib
> symbol-info = package events.this.lib
> scope-id = 24737685
> members = List( [...] , object ExplicitEvent, class ExplicitEvent,
> [...] )
> name = ExplicitEvent
> found = object ExplicitEvent
> owner = class Test
> scala.tools.nsc.symtab.Types$TypeError: value ExplicitEvent is not a
> member of package events.this.lib
> at
> scala.tools.nsc.typechecker.Contexts$Context.error(Contexts.scala:318)
> at scala.tools.nsc.typechecker.Infer$Inferencer.error(Infer.scala:273)
> at
> scala.tools.nsc.typechecker.Typers$Typer.typedSelect$1(Typers.scala:3488)
> at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:3994)
> at
> scala.tools.nsc.typechecker.Typers$Typer.typedAppliedTypeTree$1(Typers.scala:3682)
>
> at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4026)
> at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4087)
> at
> scala.tools.nsc.typechecker.Typers$Typer.typedTypeConstructor(Typers.scala:4207)
>
> at
> scala.tools.nsc.typechecker.Typers$Typer.typedTypeConstructor(Typers.scala:4230)
>
> at
> scala.tools.nsc.typechecker.Typers$Typer.typedNew$1(Typers.scala:3160)
> at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:3858)
> at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4087)
> at
> scala.tools.nsc.typechecker.Typers$Typer.typedQualifier(Typers.scala:4162)
>
> at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:3973)
> at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4087)
> at
> scala.tools.nsc.typechecker.Typers$Typer$$anonfun$typedApply$1$1.apply(Typers.scala:3304)
>
> at
> scala.tools.nsc.typechecker.Typers$Typer$$anonfun$typedApply$1$1.apply(Typers.scala:3304)
>
> at scala.tools.nsc.typechecker.Typers$Typer.silent(Typers.scala:716)
> at
> scala.tools.nsc.typechecker.Typers$Typer.typedApply$1(Typers.scala:3304)
> at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:3933)
> at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4087)
> at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4153)
> at
> scala.tools.nsc.typechecker.Typers$Typer.computeType(Typers.scala:4233)
> at scala.tools.nsc.typechecker.Namers$Namer.typeSig(Namers.scala:1154)
> at
> scala.tools.nsc.typechecker.Namers$Namer$$anonfun$typeCompleter$1.apply(Namers.scala:515)
>
> at
> scala.tools.nsc.typechecker.Namers$Namer$$anonfun$typeCompleter$1.apply(Namers.scala:513)
>
> at
> scala.tools.nsc.typechecker.Namers$$anon$1.complete(Namers.scala:1303)
> at scala.tools.nsc.symtab.Symbols$Symbol.info(Symbols.scala:758)
> at scala.tools.nsc.symtab.Symbols$Symbol.initialize(Symbols.scala:867)
> at
> scala.tools.nsc.symtab.Symbols$Symbol.annotations(Symbols.scala:114)
> at
> scala.tools.nsc.typechecker.Typers$Typer.addGetterSetter(Typers.scala:1346)
>
> at
> scala.tools.nsc.typechecker.Typers$Typer$$anonfun$9.apply(Typers.scala:1511)
>
> at
> scala.tools.nsc.typechecker.Typers$Typer$$anonfun$9.apply(Typers.scala:1511)
>
> at
> scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:259)
>
> at
> scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:259)
>
> at
> scala.collection.LinearSeqLike$class.foreach(LinearSeqLike.scala:97)
> at scala.collection.immutable.List.foreach(List.scala:46)
> at
> scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:259)
> at scala.collection.immutable.List.flatMap(List.scala:46)
> at
> scala.tools.nsc.typechecker.Typers$Typer.typedTemplate(Typers.scala:1511)
> at
> scala.tools.nsc.typechecker.Typers$Typer.typedClassDef(Typers.scala:1296)
> at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:3742)
> at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4087)
> at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4140)
> at
> scala.tools.nsc.typechecker.Typers$Typer.typedStat$1(Typers.scala:2098)
> at
> scala.tools.nsc.typechecker.Typers$Typer$$anonfun$20.apply(Typers.scala:2166)
>
> at
> scala.tools.nsc.typechecker.Typers$Typer$$anonfun$20.apply(Typers.scala:2166)
>
> at scala.collection.immutable.List.loop$1(List.scala:116)
> at scala.collection.immutable.List.mapConserve(List.scala:133)
> at
> scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:2166)
> at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:3738)
> at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4087)
> at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4140)
> at
> scala.tools.nsc.typechecker.Analyzer$typerFactory$$anon$3.apply(Analyzer.scala:82)
>
> at
> scala.tools.nsc.Global$GlobalPhase$$anonfun$applyPhase$1.apply(Global.scala:281)
>
> at
> scala.tools.nsc.Global$GlobalPhase$$anonfun$applyPhase$1.apply(Global.scala:281)
>
> at scala.tools.nsc.reporters.Reporter.withSource(Reporter.scala:48)
> at scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:281)
> at
> scala.tools.nsc.typechecker.Analyzer$typerFactory$$anon$3$$anonfun$run$1.apply(Analyzer.scala:77)
>
> at
> scala.tools.nsc.typechecker.Analyzer$typerFactory$$anon$3$$anonfun$run$1.apply(Analyzer.scala:77)
>
> at scala.collection.Iterator$class.foreach(Iterator.scala:582)
> at
> scala.collection.mutable.ListBuffer$$anon$1.foreach(ListBuffer.scala:285)
> at
> scala.tools.nsc.typechecker.Analyzer$typerFactory$$anon$3.run(Analyzer.scala:77)
>
> at scala.tools.nsc.Global$Run.compileSources(Global.scala:749)
> at scala.tools.nsc.Global$Run.compile(Global.scala:839)
> at scala.tools.nsc.Main$.process(Main.scala:110)
> at scala.tools.nsc.Main$.main(Main.scala:124)
> at scala.tools.nsc.Main.main(Main.scala)
>
>
> The compiler version that I am using is 2.8.0.Beta1-prerelease (I get
> the same error message with the last one from the repository, only
> with other line numbers)
>
> I also checked my generated AST tree via the -Ybrowse option and both
> generated subtree and the one for the lazy value e are identically
> structured. I really do not understand what I am doing wrong.
> Has anybody an idea of this problem?
>
> Thanks in advance
> Lucas
>
Hi everybody,

I finally found my (stupid) mistake: I was generating the class Name
with the newTermName method instead of newTypeName. And the type checker
looked for a value instead of a type. If it can help anybody in the future!

Lucas

Johannes Rudolph 2
Joined: 2010-02-12,
User offline. Last seen 42 years 45 weeks ago.
Re: Type checker problem with transformed AST

On Tue, Mar 2, 2010 at 10:44 AM, Lucas Satabin wrote:
> I finally found my (stupid) mistake: I was generating the class Name with
> the newTermName method instead of newTypeName. And the type checker looked
> for a value instead of a type. If it can help anybody in the future!

This is good to know. Thanks for telling us. I think I've struggled
with a similar problem before...

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