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