@@ -241,38 +241,40 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
241
241
! owner.isEmptyPackage || ctx.owner.enclosingPackageClass.isEmptyPackage
242
242
}
243
243
244
+ import BindingPrec .*
245
+ type Result = (Type , BindingPrec )
246
+ val NoResult = (NoType , NothingBound )
247
+
244
248
/** Find the denotation of enclosing `name` in given context `ctx`.
245
- * @param previous A denotation that was found in a more deeply nested scope,
246
- * or else `NoDenotation` if nothing was found yet.
247
- * @param prevPrec The binding precedence of the previous denotation,
248
- * or else `nothingBound` if nothing was found yet.
249
+ * @param prevResult A type that was found in a more deeply nested scope,
250
+ * and its precedence, or NoResult if nothing was found yet.
249
251
* @param prevCtx The context of the previous denotation,
250
252
* or else `NoContext` if nothing was found yet.
251
253
*/
252
- def findRefRecur (previous : Type , prevPrec : BindingPrec , prevCtx : Context )(using Context ): Type = {
253
- import BindingPrec . *
254
+ def findRefRecur (prevResult : Result , prevCtx : Context )(using Context ): Result = {
255
+ val (previous, prevPrec) = prevResult
254
256
255
257
/** Check that any previously found result from an inner context
256
258
* does properly shadow the new one from an outer context.
257
- * @param found The newly found result
258
- * @param newPrec Its precedence
259
+ * @param newResult The newly found type and its precedence.
259
260
* @param scala2pkg Special mode where we check members of the same package, but defined
260
261
* in different compilation units under Scala2. If set, and the
261
262
* previous and new contexts do not have the same scope, we select
262
263
* the previous (inner) definition. This models what scalac does.
263
264
*/
264
- def checkNewOrShadowed (found : Type , newPrec : BindingPrec , scala2pkg : Boolean = false )(using Context ): Type =
265
+ def checkNewOrShadowed (newResult : Result , scala2pkg : Boolean = false )(using Context ): Result =
266
+ val (found, newPrec) = newResult
265
267
if ! previous.exists || TypeComparer .isSameRef(previous, found) then
266
- found
268
+ newResult
267
269
else if (prevCtx.scope eq ctx.scope) && newPrec.beats(prevPrec) then
268
270
// special cases: definitions beat imports, and named imports beat
269
271
// wildcard imports, provided both are in contexts with same scope
270
- found
272
+ newResult
271
273
else
272
274
if ! scala2pkg && ! previous.isError && ! found.isError then
273
275
fail(AmbiguousReference (name, newPrec, prevPrec, prevCtx,
274
276
isExtension = previous.termSymbol.is(ExtensionMethod ) && found.termSymbol.is(ExtensionMethod )))
275
- previous
277
+ prevResult
276
278
277
279
/** Assemble and check alternatives to an imported reference. This implies:
278
280
* - If we expand an extension method (i.e. altImports != null),
@@ -285,12 +287,13 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
285
287
* shadowed. This order of checking is necessary since an outer package-level
286
288
* definition might trump two conflicting inner imports, so no error should be
287
289
* issued in that case. See i7876.scala.
288
- * @param previous the previously found reference (which is an import)
289
- * @param prevPrec the precedence of the reference (either NamedImport or WildImport)
290
+ * @param prevResult the previously found reference (which is an import), and
291
+ * the precedence of the reference (either NamedImport or WildImport)
290
292
* @param prevCtx the context in which the reference was found
291
293
* @param using_Context the outer context of `precCtx`
292
294
*/
293
- def checkImportAlternatives (previous : Type , prevPrec : BindingPrec , prevCtx : Context )(using Context ): Type =
295
+ def checkImportAlternatives (prevResult : Result , prevCtx : Context )(using Context ): Result =
296
+ val (previous, prevPrec) = prevResult
294
297
295
298
def addAltImport (altImp : TermRef ) =
296
299
if ! TypeComparer .isSameRef(previous, altImp)
@@ -305,20 +308,20 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
305
308
if prevPrec == WildImport then
306
309
// Discard all previously found references and continue with `altImp`
307
310
altImports.clear()
308
- checkImportAlternatives(altImp, NamedImport , ctx)(using ctx.outer)
311
+ checkImportAlternatives(( altImp, NamedImport ) , ctx)(using ctx.outer)
309
312
else
310
313
addAltImport(altImp)
311
- checkImportAlternatives(previous, prevPrec , prevCtx)(using ctx.outer)
314
+ checkImportAlternatives(prevResult , prevCtx)(using ctx.outer)
312
315
case _ =>
313
316
if prevPrec == WildImport then
314
317
wildImportRef(curImport) match
315
318
case altImp : TermRef => addAltImport(altImp)
316
319
case _ =>
317
- checkImportAlternatives(previous, prevPrec , prevCtx)(using ctx.outer)
320
+ checkImportAlternatives(prevResult , prevCtx)(using ctx.outer)
318
321
else
319
- val found = findRefRecur(previous, prevPrec , prevCtx)
320
- if found eq previous then checkNewOrShadowed(found, prevPrec )(using prevCtx)
321
- else found
322
+ val foundResult = findRefRecur(prevResult , prevCtx)
323
+ if foundResult._1 eq previous then checkNewOrShadowed(foundResult )(using prevCtx)
324
+ else foundResult
322
325
end checkImportAlternatives
323
326
324
327
def selection (imp : ImportInfo , name : Name , checkBounds : Boolean ): Type =
@@ -408,10 +411,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
408
411
! noImports &&
409
412
(prevPrec.ordinal < prec.ordinal || prevPrec == prec && (prevCtx.scope eq ctx.scope))
410
413
411
- @ tailrec def loop (lastCtx : Context )(using Context ): Type =
412
- if (ctx.scope eq EmptyScope ) previous
414
+ @ tailrec def loop (lastCtx : Context )(using Context ): Result =
415
+ if (ctx.scope eq EmptyScope ) prevResult
413
416
else {
414
- var result : Type = NoType
417
+ var result : Result = NoResult
415
418
val curOwner = ctx.owner
416
419
417
420
/** Is curOwner a package object that should be skipped?
@@ -510,37 +513,36 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
510
513
effectiveOwner.thisType.select(name, defDenot).makePackageObjPrefixExplicit
511
514
}
512
515
if ! curOwner.is(Package ) || isDefinedInCurrentUnit(defDenot) then
513
- result = checkNewOrShadowed(found, Definition ) // no need to go further out, we found highest prec entry
516
+ result = checkNewOrShadowed(( found, Definition ) ) // no need to go further out, we found highest prec entry
514
517
found match
515
518
case found : NamedType
516
519
if curOwner.isClass && isInherited(found.denot) && ! ctx.compilationUnit.isJava =>
517
520
checkNoOuterDefs(found.denot, ctx, ctx)
518
521
case _ =>
519
522
else
520
523
if migrateTo3 && ! foundUnderScala2.exists then
521
- foundUnderScala2 = checkNewOrShadowed(found, Definition , scala2pkg = true )
524
+ foundUnderScala2 = checkNewOrShadowed(( found, Definition ) , scala2pkg = true )._1
522
525
if (defDenot.symbol.is(Package ))
523
- result = checkNewOrShadowed(previous orElse found, PackageClause )
526
+ result = checkNewOrShadowed(( previous orElse found, PackageClause ) )
524
527
else if (prevPrec.ordinal < PackageClause .ordinal)
525
- result = findRefRecur(found, PackageClause , ctx)(using ctx.outer)
528
+ result = findRefRecur(( found, PackageClause ) , ctx)(using ctx.outer)
526
529
}
527
530
528
- if result.exists then result
531
+ if result._1. exists then result
529
532
else { // find import
530
533
val outer = ctx.outer
531
534
val curImport = ctx.importInfo
532
- def updateUnimported () =
533
- if (curImport.nn.unimported ne NoSymbol ) unimported += curImport.nn.unimported
534
535
if (curOwner.is(Package ) && curImport != null && curImport.isRootImport && previous.exists)
535
- previous // no more conflicts possible in this case
536
- else if (isPossibleImport(NamedImport ) && (curImport nen outer.importInfo)) {
537
- val namedImp = namedImportRef(curImport.uncheckedNN)
536
+ prevResult // no more conflicts possible in this case
537
+ else if (isPossibleImport(NamedImport ) && curImport != null && (curImport ne outer.importInfo)) {
538
+ def updateUnimported () = if curImport.unimported ne NoSymbol then unimported += curImport.unimported
539
+ val namedImp = namedImportRef(curImport)
538
540
if (namedImp.exists)
539
- checkImportAlternatives(namedImp, NamedImport , ctx)(using outer)
540
- else if (isPossibleImport(WildImport ) && ! curImport.nn. importSym.isCompleting) {
541
- val wildImp = wildImportRef(curImport.uncheckedNN )
541
+ checkImportAlternatives(( namedImp, NamedImport ) , ctx)(using outer)
542
+ else if (isPossibleImport(WildImport ) && ! curImport.importSym.isCompleting) {
543
+ val wildImp = wildImportRef(curImport)
542
544
if (wildImp.exists)
543
- checkImportAlternatives(wildImp, WildImport , ctx)(using outer)
545
+ checkImportAlternatives(( wildImp, WildImport ) , ctx)(using outer)
544
546
else {
545
547
updateUnimported()
546
548
loop(ctx)(using outer)
@@ -559,7 +561,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
559
561
loop(NoContext )
560
562
}
561
563
562
- findRefRecur(NoType , BindingPrec .NothingBound , NoContext )
564
+ val (foundRef, foundPrec) = findRefRecur(NoResult , NoContext )
565
+ foundRef
563
566
}
564
567
565
568
/** If `tree`'s type is a `TermRef` identified by flow typing to be non-null, then
0 commit comments