diff options
author | Guillaume Martres <smarter@ubuntu.com> | 2017-02-20 11:41:04 +0100 |
---|---|---|
committer | Guillaume Martres <smarter@ubuntu.com> | 2017-02-20 11:54:19 +0100 |
commit | 360406dab1e680ace143a14ee1ea38ebbdacda3c (patch) | |
tree | 70aea422c0613a107cd9d92b04ba37c32efa726f | |
parent | 2245ffd076ece27f874e912cca61ee440626dd56 (diff) | |
download | dotty-360406dab1e680ace143a14ee1ea38ebbdacda3c.tar.gz dotty-360406dab1e680ace143a14ee1ea38ebbdacda3c.tar.bz2 dotty-360406dab1e680ace143a14ee1ea38ebbdacda3c.zip |
adjustModuleCompleter: Avoid capturing Context
Previously we computed the scope in `findModuleBuddy` using
`this.effectiveScope`, this means that we captured `this` which has a
self-type of `Context`, replacing it by `ctx.effectiveScope`
would be wrong since we are interested in the scope at the time
`adjustModuleCompleter` was called, not the scope at the time the
completer is called. Therefore, we have to eagerly compute
`this.effectiveScope` so that we don't capture the Context but can use
the right scope in `findModuleBuddy`.
We also move `findModuleBuddy` to a companion object to avoid accidental
captures of `this`.
This capture lead to crashes in the IDE.
-rw-r--r-- | compiler/src/dotty/tools/dotc/typer/Namer.scala | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 9f35a07ab..d5f171fe3 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -24,6 +24,7 @@ import language.implicitConversions import reporting.diagnostic.messages._ trait NamerContextOps { this: Context => + import NamerContextOps._ /** Enter symbol into current class, if current class is owner of current context, * or into current scope, if not. Should always be called instead of scope.enter @@ -119,22 +120,25 @@ trait NamerContextOps { this: Context => else monotpe } - /** Find moduleClass/sourceModule in effective scope */ - private def findModuleBuddy(name: Name)(implicit ctx: Context) = { - val scope = effectiveScope - val it = scope.lookupAll(name).filter(_ is Module) - assert(it.hasNext, s"no companion $name in $scope") - it.next - } - /** Add moduleClass or sourceModule functionality to completer * for a module or module class */ - def adjustModuleCompleter(completer: LazyType, name: Name) = + def adjustModuleCompleter(completer: LazyType, name: Name) = { + val scope = this.effectiveScope if (name.isTermName) - completer withModuleClass (_ => findModuleBuddy(name.moduleClassName)) + completer withModuleClass (implicit ctx => findModuleBuddy(name.moduleClassName, scope)) else - completer withSourceModule (_ => findModuleBuddy(name.sourceModuleName)) + completer withSourceModule (implicit ctx => findModuleBuddy(name.sourceModuleName, scope)) + } +} + +object NamerContextOps { + /** Find moduleClass/sourceModule in effective scope */ + private def findModuleBuddy(name: Name, scope: Scope)(implicit ctx: Context) = { + val it = scope.lookupAll(name).filter(_ is Module) + assert(it.hasNext, s"no companion $name in $scope") + it.next + } } /** This class creates symbols from definitions and imports and gives them |