Skip to content

Commit 360406d

Browse files
committed
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.
1 parent 2245ffd commit 360406d

File tree

1 file changed

+15
-11
lines changed

1 file changed

+15
-11
lines changed

compiler/src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import language.implicitConversions
2424
import reporting.diagnostic.messages._
2525

2626
trait NamerContextOps { this: Context =>
27+
import NamerContextOps._
2728

2829
/** Enter symbol into current class, if current class is owner of current context,
2930
* or into current scope, if not. Should always be called instead of scope.enter
@@ -119,22 +120,25 @@ trait NamerContextOps { this: Context =>
119120
else monotpe
120121
}
121122

122-
/** Find moduleClass/sourceModule in effective scope */
123-
private def findModuleBuddy(name: Name)(implicit ctx: Context) = {
124-
val scope = effectiveScope
125-
val it = scope.lookupAll(name).filter(_ is Module)
126-
assert(it.hasNext, s"no companion $name in $scope")
127-
it.next
128-
}
129-
130123
/** Add moduleClass or sourceModule functionality to completer
131124
* for a module or module class
132125
*/
133-
def adjustModuleCompleter(completer: LazyType, name: Name) =
126+
def adjustModuleCompleter(completer: LazyType, name: Name) = {
127+
val scope = this.effectiveScope
134128
if (name.isTermName)
135-
completer withModuleClass (_ => findModuleBuddy(name.moduleClassName))
129+
completer withModuleClass (implicit ctx => findModuleBuddy(name.moduleClassName, scope))
136130
else
137-
completer withSourceModule (_ => findModuleBuddy(name.sourceModuleName))
131+
completer withSourceModule (implicit ctx => findModuleBuddy(name.sourceModuleName, scope))
132+
}
133+
}
134+
135+
object NamerContextOps {
136+
/** Find moduleClass/sourceModule in effective scope */
137+
private def findModuleBuddy(name: Name, scope: Scope)(implicit ctx: Context) = {
138+
val it = scope.lookupAll(name).filter(_ is Module)
139+
assert(it.hasNext, s"no companion $name in $scope")
140+
it.next
141+
}
138142
}
139143

140144
/** This class creates symbols from definitions and imports and gives them

0 commit comments

Comments
 (0)