From 360406dab1e680ace143a14ee1ea38ebbdacda3c Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Mon, 20 Feb 2017 11:41:04 +0100 Subject: 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. --- compiler/src/dotty/tools/dotc/typer/Namer.scala | 26 ++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'compiler/src/dotty/tools/dotc/typer/Namer.scala') 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 -- cgit v1.2.3