@@ -986,61 +986,67 @@ class CheckCaptures extends Recheck, SymTransformer:
986
986
* - Heal ill-formed capture sets of type parameters. See `healTypeParam`.
987
987
*/
988
988
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)
1029
1043
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 _ =>
1040
1044
1041
- args.foreach(healTypeParam(_))
1042
- case _ =>
1043
- }
1045
+ args.foreach(healTypeParam(_))
1046
+ case _ =>
1047
+ end check
1048
+ end checker
1049
+ checker.traverse(unit)
1044
1050
if ! ctx.reporter.errorsReported then
1045
1051
// We dont report errors here if previous errors were reported, because other
1046
1052
// errors often result in bad applied types, but flagging these bad types gives
0 commit comments