@@ -205,57 +205,54 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
205
205
! owner.isEmptyPackage || ctx.owner.enclosingPackageClass.isEmptyPackage
206
206
}
207
207
208
+ import BindingPrec .*
209
+ type Result = (Type , BindingPrec )
210
+ val NoResult = (NoType , NothingBound )
211
+
208
212
/** Find the denotation of enclosing `name` in given context `ctx`.
209
- * @param previous A denotation that was found in a more deeply nested scope,
210
- * or else `NoDenotation` if nothing was found yet.
211
- * @param prevPrec The binding precedence of the previous denotation,
212
- * or else `nothingBound` if nothing was found yet.
213
+ * @param prevResult A type that was found in a more deeply nested scope,
214
+ * and its precedence, or NoResult if nothing was found yet.
213
215
* @param prevCtx The context of the previous denotation,
214
216
* or else `NoContext` if nothing was found yet.
215
217
*/
216
- def findRefRecur (previous : Type , prevPrec : BindingPrec , prevCtx : Context )(using Context ): Type = {
217
- import BindingPrec . *
218
+ def findRefRecur (prevResult : Result , prevCtx : Context )(using Context ): Result = {
219
+ val (previous, prevPrec) = prevResult
218
220
219
221
/** Check that any previously found result from an inner context
220
222
* does properly shadow the new one from an outer context.
221
- * @param found The newly found result
222
- * @param newPrec Its precedence
223
+ * @param newResult The newly found type and its precedence.
223
224
* @param scala2pkg Special mode where we check members of the same package, but defined
224
225
* in different compilation units under Scala2. If set, and the
225
226
* previous and new contexts do not have the same scope, we select
226
227
* the previous (inner) definition. This models what scalac does.
227
228
*/
228
- def checkNewOrShadowed (found : Type , newPrec : BindingPrec , scala2pkg : Boolean = false )(using Context ): Type =
229
+ def checkNewOrShadowed (newResult : Result , scala2pkg : Boolean = false )(using Context ): Result =
230
+ val (found, newPrec) = newResult
229
231
if ! previous.exists || TypeComparer .isSameRef(previous, found) then
230
232
found
231
233
else if (prevCtx.scope eq ctx.scope)
232
234
&& (newPrec == Definition || newPrec == NamedImport && prevPrec == WildImport )
233
235
then
234
236
// special cases: definitions beat imports, and named imports beat
235
237
// wildcard imports, provided both are in contexts with same scope
236
- found
238
+ newResult
237
239
else
238
240
if ! scala2pkg && ! previous.isError && ! found.isError then
239
241
fail(AmbiguousReference (name, newPrec, prevPrec, prevCtx))
240
242
previous
241
-
242
- /** Assemble and check alternatives to an imported reference. This implies:
243
- * - If we expand an extension method (i.e. altImports != null),
244
- * search imports on the same level for other possible resolutions of `name`.
245
- * The result and altImports together then contain all possible imported
246
- * references of the highest possible precedence, where `NamedImport` beats
247
243
* `WildImport`.
248
244
* - Find a posssibly shadowing reference in an outer context.
249
245
* If the result is the same as `previous`, check that it is new or
250
246
* shadowed. This order of checking is necessary since an outer package- level
251
247
* definition might trump two conflicting inner imports, so no error should be
252
248
* issued in that case . See i7876.scala.
253
- * @param previous the previously found reference (which is an import)
254
- * @param prevPrec the precedence of the reference (either NamedImport or WildImport)
249
+ * @ param prevResult the previously found reference (which is an import), and
250
+ * the precedence of the reference (either NamedImport or WildImport )
255
251
* @ param prevCtx the context in which the reference was found
256
252
* @ param using_Context the outer context of `precCtx`
257
253
*/
258
- def checkImportAlternatives (previous : Type , prevPrec : BindingPrec , prevCtx : Context )(using Context ): Type =
254
+ def checkImportAlternatives (prevResult : Result , prevCtx : Context )(using Context ): Result =
255
+ val (previous, prevPrec) = prevResult
259
256
260
257
def addAltImport (altImp : TermRef ) =
261
258
if ! TypeComparer .isSameRef(previous, altImp)
@@ -270,20 +267,20 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
270
267
if prevPrec == WildImport then
271
268
// Discard all previously found references and continue with `altImp`
272
269
altImports.clear()
273
- checkImportAlternatives(altImp, NamedImport , ctx)(using ctx.outer)
270
+ checkImportAlternatives(( altImp, NamedImport ) , ctx)(using ctx.outer)
274
271
else
275
272
addAltImport(altImp)
276
- checkImportAlternatives(previous, prevPrec , prevCtx)(using ctx.outer)
273
+ checkImportAlternatives(prevResult , prevCtx)(using ctx.outer)
277
274
case _ =>
278
275
if prevPrec == WildImport then
279
276
wildImportRef(curImport) match
280
277
case altImp : TermRef => addAltImport(altImp)
281
278
case _ =>
282
- checkImportAlternatives(previous, prevPrec , prevCtx)(using ctx.outer)
279
+ checkImportAlternatives(prevResult , prevCtx)(using ctx.outer)
283
280
else
284
- val found = findRefRecur(previous, prevPrec , prevCtx)
285
- if found eq previous then checkNewOrShadowed(found, prevPrec )(using prevCtx)
286
- else found
281
+ val foundResult = findRefRecur(prevResult , prevCtx)
282
+ if foundResult._1 eq previous then checkNewOrShadowed(foundResult )(using prevCtx)
283
+ else foundResult
287
284
end checkImportAlternatives
288
285
289
286
def selection (imp : ImportInfo , name : Name , checkBounds : Boolean ): Type =
@@ -370,10 +367,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
370
367
! noImports &&
371
368
(prevPrec.ordinal < prec.ordinal || prevPrec == prec && (prevCtx.scope eq ctx.scope))
372
369
373
- @ tailrec def loop (lastCtx : Context )(using Context ): Type =
374
- if (ctx.scope eq EmptyScope ) previous
370
+ @ tailrec def loop (lastCtx : Context )(using Context ): Result =
371
+ if (ctx.scope eq EmptyScope ) prevResult
375
372
else {
376
- var result : Type = NoType
373
+ var result : Result = NoResult
377
374
val curOwner = ctx.owner
378
375
379
376
/** Is curOwner a package object that should be skipped?
@@ -472,37 +469,36 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
472
469
effectiveOwner.thisType.select(name, defDenot)
473
470
}
474
471
if ! curOwner.is(Package ) || isDefinedInCurrentUnit(defDenot) then
475
- result = checkNewOrShadowed(found, Definition ) // no need to go further out, we found highest prec entry
472
+ result = checkNewOrShadowed(( found, Definition ) ) // no need to go further out, we found highest prec entry
476
473
found match
477
474
case found : NamedType
478
475
if curOwner.isClass && isInherited(found.denot) && ! ctx.compilationUnit.isJava =>
479
476
checkNoOuterDefs(found.denot, ctx, ctx)
480
477
case _ =>
481
478
else
482
479
if migrateTo3 && ! foundUnderScala2.exists then
483
- foundUnderScala2 = checkNewOrShadowed(found, Definition , scala2pkg = true )
480
+ foundUnderScala2 = checkNewOrShadowed(( found, Definition ) , scala2pkg = true )._1
484
481
if (defDenot.symbol.is(Package ))
485
- result = checkNewOrShadowed(previous orElse found, PackageClause )
482
+ result = checkNewOrShadowed(( previous orElse found, PackageClause ) )
486
483
else if (prevPrec.ordinal < PackageClause .ordinal)
487
- result = findRefRecur(found, PackageClause , ctx)(using ctx.outer)
484
+ result = findRefRecur(( found, PackageClause ) , ctx)(using ctx.outer)
488
485
}
489
486
490
- if result.exists then result
487
+ if result._1. exists then result
491
488
else { // find import
492
489
val outer = ctx.outer
493
490
val curImport = ctx.importInfo
494
- def updateUnimported () =
495
- if (curImport.nn.unimported ne NoSymbol ) unimported += curImport.nn.unimported
496
491
if (curOwner.is(Package ) && curImport != null && curImport.isRootImport && previous.exists)
497
- previous // no more conflicts possible in this case
498
- else if (isPossibleImport(NamedImport ) && (curImport nen outer.importInfo)) {
499
- val namedImp = namedImportRef(curImport.uncheckedNN)
492
+ prevResult // no more conflicts possible in this case
493
+ else if (isPossibleImport(NamedImport ) && curImport != null && (curImport ne outer.importInfo)) {
494
+ def updateUnimported () = if curImport.unimported ne NoSymbol then unimported += curImport.unimported
495
+ val namedImp = namedImportRef(curImport)
500
496
if (namedImp.exists)
501
- checkImportAlternatives(namedImp, NamedImport , ctx)(using outer)
502
- else if (isPossibleImport(WildImport ) && ! curImport.nn. importSym.isCompleting) {
503
- val wildImp = wildImportRef(curImport.uncheckedNN )
497
+ checkImportAlternatives(( namedImp, NamedImport ) , ctx)(using outer)
498
+ else if (isPossibleImport(WildImport ) && ! curImport.importSym.isCompleting) {
499
+ val wildImp = wildImportRef(curImport)
504
500
if (wildImp.exists)
505
- checkImportAlternatives(wildImp, WildImport , ctx)(using outer)
501
+ checkImportAlternatives(( wildImp, WildImport ) , ctx)(using outer)
506
502
else {
507
503
updateUnimported()
508
504
loop(ctx)(using outer)
@@ -521,7 +517,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
521
517
loop(NoContext )
522
518
}
523
519
524
- findRefRecur(NoType , BindingPrec .NothingBound , NoContext )
520
+ val (foundRef, foundPrec) = findRefRecur(NoResult , NoContext )
521
+ foundRef
525
522
}
526
523
527
524
/** If `tree`'s type is a `TermRef` identified by flow typing to be non-null, then
0 commit comments