@@ -986,61 +986,67 @@ class CheckCaptures extends Recheck, SymTransformer:
986986 * - Heal ill-formed capture sets of type parameters. See `healTypeParam`.
987987 */
988988 def postCheck (unit : tpd.Tree )(using Context ): Unit =
989- unit.foreachSubTree {
990- case _ : InferredTypeTree =>
991- case tree : TypeTree if ! tree.span.isZeroExtent =>
992- tree.knownType.foreachPart { tp =>
993- checkWellformedPost(tp, tree.srcPos)
994- tp match
995- case AnnotatedType (_, annot) if annot.symbol == defn.RetainsAnnot =>
996- warnIfRedundantCaptureSet(annot.tree)
997- case _ =>
998- }
999- case t : ValOrDefDef
1000- if t.tpt.isInstanceOf [InferredTypeTree ] && ! Synthetics .isExcluded(t.symbol) =>
1001- val sym = t.symbol
1002- val isLocal =
1003- sym.owner.ownersIterator.exists(_.isTerm)
1004- || sym.accessBoundary(defn.RootClass ).isContainedIn(sym.topLevelClass)
1005- def canUseInferred = // If canUseInferred is false, all capturing types in the type of `sym` need to be given explicitly
1006- sym.is(Private ) // private symbols can always have inferred types
1007- || sym.name.is(DefaultGetterName ) // default getters are exempted since otherwise it would be
1008- // too annoying. This is a hole since a defualt getter's result type
1009- // might leak into a type variable.
1010- || // non-local symbols cannot have inferred types since external capture types are not inferred
1011- isLocal // local symbols still need explicit types if
1012- && ! sym.owner.is(Trait ) // they are defined in a trait, since we do OverridingPairs checking before capture inference
1013- def isNotPureThis (ref : CaptureRef ) = ref match {
1014- case ref : ThisType => ! ref.cls.isPureClass
1015- case _ => true
1016- }
1017- if ! canUseInferred then
1018- val inferred = t.tpt.knownType
1019- def checkPure (tp : Type ) = tp match
1020- case CapturingType (_, refs)
1021- if ! refs.elems.filter(isNotPureThis).isEmpty =>
1022- val resultStr = if t.isInstanceOf [DefDef ] then " result" else " "
1023- report.error(
1024- em """ Non-local $sym cannot have an inferred $resultStr type
1025- | $inferred
1026- |with non-empty capture set $refs.
1027- |The type needs to be declared explicitly. """ .withoutDisambiguation(),
1028- t.srcPos)
989+ val checker = new TreeTraverser :
990+ def traverse (tree : Tree )(using Context ): Unit =
991+ traverseChildren(tree)
992+ check(tree)
993+ def check (tree : Tree ) = tree match
994+ case _ : InferredTypeTree =>
995+ case tree : TypeTree if ! tree.span.isZeroExtent =>
996+ tree.knownType.foreachPart { tp =>
997+ checkWellformedPost(tp, tree.srcPos)
998+ tp match
999+ case AnnotatedType (_, annot) if annot.symbol == defn.RetainsAnnot =>
1000+ warnIfRedundantCaptureSet(annot.tree)
1001+ case _ =>
1002+ }
1003+ case t : ValOrDefDef
1004+ if t.tpt.isInstanceOf [InferredTypeTree ] && ! Synthetics .isExcluded(t.symbol) =>
1005+ val sym = t.symbol
1006+ val isLocal =
1007+ sym.owner.ownersIterator.exists(_.isTerm)
1008+ || sym.accessBoundary(defn.RootClass ).isContainedIn(sym.topLevelClass)
1009+ def canUseInferred = // If canUseInferred is false, all capturing types in the type of `sym` need to be given explicitly
1010+ sym.is(Private ) // private symbols can always have inferred types
1011+ || sym.name.is(DefaultGetterName ) // default getters are exempted since otherwise it would be
1012+ // too annoying. This is a hole since a defualt getter's result type
1013+ // might leak into a type variable.
1014+ || // non-local symbols cannot have inferred types since external capture types are not inferred
1015+ isLocal // local symbols still need explicit types if
1016+ && ! sym.owner.is(Trait ) // they are defined in a trait, since we do OverridingPairs checking before capture inference
1017+ def isNotPureThis (ref : CaptureRef ) = ref match {
1018+ case ref : ThisType => ! ref.cls.isPureClass
1019+ case _ => true
1020+ }
1021+ if ! canUseInferred then
1022+ val inferred = t.tpt.knownType
1023+ def checkPure (tp : Type ) = tp match
1024+ case CapturingType (_, refs)
1025+ if ! refs.elems.filter(isNotPureThis).isEmpty =>
1026+ val resultStr = if t.isInstanceOf [DefDef ] then " result" else " "
1027+ report.error(
1028+ em """ Non-local $sym cannot have an inferred $resultStr type
1029+ | $inferred
1030+ |with non-empty capture set $refs.
1031+ |The type needs to be declared explicitly. """ .withoutDisambiguation(),
1032+ t.srcPos)
1033+ case _ =>
1034+ inferred.foreachPart(checkPure, StopAt .Static )
1035+ case t @ TypeApply (fun, args) =>
1036+ fun.knownType.widen match
1037+ case tl : PolyType =>
1038+ val normArgs = args.lazyZip(tl.paramInfos).map { (arg, bounds) =>
1039+ arg.withType(arg.knownType.forceBoxStatus(
1040+ bounds.hi.isBoxedCapturing | bounds.lo.isBoxedCapturing))
1041+ }
1042+ checkBounds(normArgs, tl)
10291043 case _ =>
1030- inferred.foreachPart(checkPure, StopAt .Static )
1031- case t @ TypeApply (fun, args) =>
1032- fun.knownType.widen match
1033- case tl : PolyType =>
1034- val normArgs = args.lazyZip(tl.paramInfos).map { (arg, bounds) =>
1035- arg.withType(arg.knownType.forceBoxStatus(
1036- bounds.hi.isBoxedCapturing | bounds.lo.isBoxedCapturing))
1037- }
1038- checkBounds(normArgs, tl)
1039- case _ =>
10401044
1041- args.foreach(healTypeParam(_))
1042- case _ =>
1043- }
1045+ args.foreach(healTypeParam(_))
1046+ case _ =>
1047+ end check
1048+ end checker
1049+ checker.traverse(unit)
10441050 if ! ctx.reporter.errorsReported then
10451051 // We dont report errors here if previous errors were reported, because other
10461052 // errors often result in bad applied types, but flagging these bad types gives
0 commit comments