@@ -21,6 +21,7 @@ import CCState.*
2121import dotty .tools .dotc .util .NoSourcePosition
2222import CheckCaptures .CheckerAPI
2323import NamerOps .methodType
24+ import NameKinds .{CanThrowEvidenceName , TryOwnerName }
2425
2526/** Operations accessed from CheckCaptures */
2627trait SetupAPI :
@@ -51,6 +52,15 @@ object Setup:
5152 Some ((res, exc))
5253 case _ =>
5354 None
55+
56+ def firstCanThrowEvidence (body : Tree )(using Context ): Option [Tree ] = body match
57+ case Block (stats, expr) =>
58+ if stats.isEmpty then firstCanThrowEvidence(expr)
59+ else stats.find:
60+ case vd : ValDef => vd.symbol.name.is(CanThrowEvidenceName )
61+ case _ => false
62+ case _ => None
63+
5464end Setup
5565import Setup .*
5666
@@ -480,9 +490,9 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
480490 end transformExplicitType
481491
482492 /** Update info of `sym` for CheckCaptures phase only */
483- private def updateInfo (sym : Symbol , info : Type )(using Context ) =
493+ private def updateInfo (sym : Symbol , info : Type , owner : Symbol )(using Context ) =
484494 toBeUpdated += sym
485- sym.updateInfo(thisPhase, info, newFlagsFor(sym))
495+ sym.updateInfo(thisPhase, info, newFlagsFor(sym), owner )
486496 toBeUpdated -= sym
487497
488498 /** The info of `sym` at the CheckCaptures phase */
@@ -590,6 +600,17 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
590600 traverse(elems)
591601 tpt.setNuType(box(transformInferredType(tpt.tpe)))
592602
603+ case tree @ Try (body, catches, finalizer) =>
604+ val tryOwner = firstCanThrowEvidence(body) match
605+ case Some (vd) =>
606+ newSymbol(ctx.owner, TryOwnerName .fresh(),
607+ Method | Synthetic , ExprType (defn.NothingType ), coord = tree.span)
608+ case _ =>
609+ ctx.owner
610+ inContext(ctx.withOwner(tryOwner)):
611+ traverse(body)
612+ catches.foreach(traverse)
613+ traverse(finalizer)
593614 case _ =>
594615 traverseChildren(tree)
595616 postProcess(tree)
@@ -634,6 +655,8 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
634655 // have a new type installed here (meaning hasRememberedType is true)
635656 def signatureChanges =
636657 tree.tpt.hasNuType || paramSignatureChanges
658+ def ownerChanges =
659+ ctx.owner.name.is(TryOwnerName )
637660
638661 def paramsToCap (mt : Type )(using Context ): Type = mt match
639662 case mt : MethodType =>
@@ -644,38 +667,40 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
644667 mt.derivedLambdaType(resType = paramsToCap(mt.resType))
645668 case _ => mt
646669
647- // If there's a change in the signature, update the info of `sym`
648- if sym.exists && signatureChanges then
670+ // If there's a change in the signature or owner , update the info of `sym`
671+ if sym.exists && ( signatureChanges || ownerChanges) then
649672 val updatedInfo =
650-
651- val paramSymss = sym.paramSymss
652- def newInfo (using Context ) = // will be run in this or next phase
653- root.toResultInResults(sym, report.error(_, tree.srcPos)):
654- if sym.is(Method ) then
655- paramsToCap(methodType(paramSymss, localReturnType))
656- else tree.tpt.nuType
657- if tree.tpt.isInstanceOf [InferredTypeTree ]
658- && ! sym.is(Param ) && ! sym.is(ParamAccessor )
659- then
660- val prevInfo = sym.info
661- new LazyType :
662- def complete (denot : SymDenotation )(using Context ) =
663- assert(ctx.phase == thisPhase.next, i " $sym" )
664- sym.info = prevInfo // set info provisionally so we can analyze the symbol in recheck
665- completeDef(tree, sym, this )
666- sym.info = newInfo
667- .showing(i " new info of $sym = $result" , capt)
668- else if sym.is(Method ) then
669- new LazyType :
670- def complete (denot : SymDenotation )(using Context ) =
671- sym.info = newInfo
672- .showing(i " new info of $sym = $result" , capt)
673- else newInfo
674- updateInfo(sym, updatedInfo)
673+ if signatureChanges then
674+ val paramSymss = sym.paramSymss
675+ def newInfo (using Context ) = // will be run in this or next phase
676+ root.toResultInResults(sym, report.error(_, tree.srcPos)):
677+ if sym.is(Method ) then
678+ paramsToCap(methodType(paramSymss, localReturnType))
679+ else tree.tpt.nuType
680+ if tree.tpt.isInstanceOf [InferredTypeTree ]
681+ && ! sym.is(Param ) && ! sym.is(ParamAccessor )
682+ then
683+ val prevInfo = sym.info
684+ new LazyType :
685+ def complete (denot : SymDenotation )(using Context ) =
686+ assert(ctx.phase == thisPhase.next, i " $sym" )
687+ sym.info = prevInfo // set info provisionally so we can analyze the symbol in recheck
688+ completeDef(tree, sym, this )
689+ sym.info = newInfo
690+ .showing(i " new info of $sym = $result" , capt)
691+ else if sym.is(Method ) then
692+ new LazyType :
693+ def complete (denot : SymDenotation )(using Context ) =
694+ sym.info = newInfo
695+ .showing(i " new info of $sym = $result" , capt)
696+ else newInfo
697+ else sym.info
698+ val updatedOwner = if ownerChanges then ctx.owner else sym.owner
699+ updateInfo(sym, updatedInfo, updatedOwner)
675700
676701 case tree : Bind =>
677702 val sym = tree.symbol
678- updateInfo(sym, transformInferredType(sym.info))
703+ updateInfo(sym, transformInferredType(sym.info), sym.owner )
679704 case tree : TypeDef =>
680705 tree.symbol match
681706 case cls : ClassSymbol =>
@@ -708,7 +733,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
708733 // Install new types and if it is a module class also update module object
709734 if (selfInfo1 ne selfInfo) || (ps1 ne ps) then
710735 val newInfo = ClassInfo (prefix, cls, ps1, decls, selfInfo1)
711- updateInfo(cls, newInfo)
736+ updateInfo(cls, newInfo, cls.owner )
712737 capt.println(i " update class info of $cls with parents $ps selfinfo $selfInfo to $newInfo" )
713738 cls.thisType.asInstanceOf [ThisType ].invalidateCaches()
714739 if cls.is(ModuleClass ) then
@@ -721,7 +746,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
721746 // This would potentially give stackoverflows when setup is run repeatedly.
722747 // One test case is pos-custom-args/captures/checkbounds.scala under
723748 // ccConfig.alwaysRepeatRun = true.
724- updateInfo(modul, CapturingType (modul.info, selfCaptures))
749+ updateInfo(modul, CapturingType (modul.info, selfCaptures), modul.owner )
725750 modul.termRef.invalidateCaches()
726751 case _ =>
727752 case _ =>
0 commit comments