Skip to content

Commit 11e2986

Browse files
committed
Fixes for cleanup retains scheme
- Cleanup all inferred types, not just result types of ValDefs and DefDefs. - To compensate, map overriding ValDefs and DefDefs to have declared result types. - Make type trees generated for varargs inferred.
1 parent 618bbc5 commit 11e2986

File tree

7 files changed

+30
-26
lines changed

7 files changed

+30
-26
lines changed

compiler/src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,7 @@ object Trees {
778778
override def isEmpty: Boolean = !hasType
779779
override def toString: String =
780780
s"TypeTree${if (hasType) s"[$typeOpt]" else ""}"
781+
def isInferred = false
781782
}
782783

783784
/** Tree that replaces a level 1 splices in pickled (level 0) quotes.
@@ -800,6 +801,7 @@ object Trees {
800801
*/
801802
class InferredTypeTree[+T <: Untyped](implicit @constructorOnly src: SourceFile) extends TypeTree[T]:
802803
type ThisTree[+T <: Untyped] <: InferredTypeTree[T]
804+
override def isInferred = true
803805

804806
/** ref.type */
805807
case class SingletonTypeTree[+T <: Untyped] private[ast] (ref: Tree[T])(implicit @constructorOnly src: SourceFile)

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -806,10 +806,10 @@ class TreePickler(pickler: TastyPickler, attributes: Attributes) {
806806
report.error(ex.toMessage, tree.srcPos.focus)
807807
pickleErrorType()
808808
case ex: AssertionError =>
809-
println(i"error when pickling tree $tree")
809+
println(i"error when pickling tree $tree of class ${tree.getClass}")
810810
throw ex
811811
case ex: MatchError =>
812-
println(i"error when pickling tree $tree")
812+
println(i"error when pickling tree $tree of class ${tree.getClass}")
813813
throw ex
814814
}
815815
}

compiler/src/dotty/tools/dotc/transform/PostTyper.scala

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -303,20 +303,19 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
303303
if !tree.symbol.is(Package) then tree
304304
else errorTree(tree, em"${tree.symbol} cannot be used as a type")
305305

306-
// Cleans up retains annotations in inferred type trees. This is needed because
307-
// during the typer, it is infeasible to correctly infer the capture sets in most
308-
// cases, resulting ill-formed capture sets that could crash the pickler later on.
309-
// See #20035.
310-
private def cleanupRetainsAnnot(symbol: Symbol, tpt: Tree)(using Context): Tree =
306+
/** Make result types of ValDefs and DefDefs that override some other definitions
307+
* declared types rather than InferredTypes. This is necessary since we otherwise
308+
* clean retains annotations from such types. But for an overriding symbol the
309+
* retains annotations come from the explicitly declared parent types, so should
310+
* be kept.
311+
*/
312+
private def makeOverrideTypeDeclared(symbol: Symbol, tpt: Tree)(using Context): Tree =
311313
tpt match
312314
case tpt: InferredTypeTree
313-
if !symbol.allOverriddenSymbols.hasNext =>
314-
// if there are overridden symbols, the annotation comes from an explicit type of the overridden symbol
315-
// and should be retained.
316-
val tm = new CleanupRetains
317-
val tpe1 = tm(tpt.tpe)
318-
tpt.withType(tpe1)
319-
case _ => tpt
315+
if symbol.allOverriddenSymbols.hasNext =>
316+
TypeTree(tpt.tpe, inferred = false).withSpan(tpt.span).withAttachmentsFrom(tpt)
317+
case _ =>
318+
tpt
320319

321320
override def transform(tree: Tree)(using Context): Tree =
322321
try tree match {
@@ -432,7 +431,7 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
432431
registerIfHasMacroAnnotations(tree)
433432
checkErasedDef(tree)
434433
Checking.checkPolyFunctionType(tree.tpt)
435-
val tree1 = cpy.ValDef(tree)(tpt = cleanupRetainsAnnot(tree.symbol, tree.tpt), rhs = normalizeErasedRhs(tree.rhs, tree.symbol))
434+
val tree1 = cpy.ValDef(tree)(tpt = makeOverrideTypeDeclared(tree.symbol, tree.tpt), rhs = normalizeErasedRhs(tree.rhs, tree.symbol))
436435
if tree1.removeAttachment(desugar.UntupledParam).isDefined then
437436
checkStableSelection(tree.rhs)
438437
processValOrDefDef(super.transform(tree1))
@@ -441,7 +440,7 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
441440
checkErasedDef(tree)
442441
Checking.checkPolyFunctionType(tree.tpt)
443442
annotateContextResults(tree)
444-
val tree1 = cpy.DefDef(tree)(tpt = cleanupRetainsAnnot(tree.symbol, tree.tpt), rhs = normalizeErasedRhs(tree.rhs, tree.symbol))
443+
val tree1 = cpy.DefDef(tree)(tpt = makeOverrideTypeDeclared(tree.symbol, tree.tpt), rhs = normalizeErasedRhs(tree.rhs, tree.symbol))
445444
processValOrDefDef(superAcc.wrapDefDef(tree1)(super.transform(tree1).asInstanceOf[DefDef]))
446445
case tree: TypeDef =>
447446
registerIfHasMacroAnnotations(tree)
@@ -524,12 +523,12 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
524523
report.error(em"type ${alias.tpe} outside bounds $bounds", tree.srcPos)
525524
super.transform(tree)
526525
case tree: TypeTree =>
527-
tree.withType(
528-
tree.tpe match {
529-
case AnnotatedType(tpe, annot) => AnnotatedType(tpe, transformAnnot(annot))
530-
case tpe => tpe
531-
}
532-
)
526+
val tpe = if tree.isInferred then CleanupRetains()(tree.tpe) else tree.tpe
527+
tree.withType:
528+
tpe match
529+
case AnnotatedType(parent, annot) =>
530+
AnnotatedType(parent, transformAnnot(annot)) // TODO: Also map annotations embedded in type?
531+
case _ => tpe
533532
case Typed(Ident(nme.WILDCARD), _) =>
534533
withMode(Mode.Pattern)(super.transform(tree))
535534
// The added mode signals that bounds in a pattern need not

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,7 @@ trait Applications extends Compatibility {
883883
def makeVarArg(n: Int, elemFormal: Type): Unit = {
884884
val args = typedArgBuf.takeRight(n).toList
885885
typedArgBuf.dropRightInPlace(n)
886-
val elemtpt = TypeTree(elemFormal)
886+
val elemtpt = TypeTree(elemFormal, inferred = true)
887887
typedArgBuf += seqToRepeated(SeqLiteral(args, elemtpt))
888888
}
889889

compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ trait TypeAssigner {
5151
else sym.info
5252

5353
private def toRepeated(tree: Tree, from: ClassSymbol)(using Context): Tree =
54-
Typed(tree, TypeTree(tree.tpe.widen.translateToRepeated(from)))
54+
Typed(tree, TypeTree(tree.tpe.widen.translateToRepeated(from), inferred = true))
5555

5656
def seqToRepeated(tree: Tree)(using Context): Tree = toRepeated(tree, defn.SeqClass)
5757

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,7 +1457,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
14571457
cpy.Block(block)(stats, expr1) withType expr1.tpe // no assignType here because avoid is redundant
14581458
case _ =>
14591459
val target = pt.simplified
1460-
val targetTpt = InferredTypeTree().withType(target)
1460+
val targetTpt = TypeTree(target, inferred = true)
14611461
if tree.tpe <:< target then Typed(tree, targetTpt)
14621462
else
14631463
// This case should not normally arise. It currently does arise in test cases
@@ -2092,7 +2092,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
20922092
// TODO: move the check above to patternMatcher phase
20932093
val uncheckedTpe = AnnotatedType(sel.tpe.widen, Annotation(defn.UncheckedAnnot, tree.selector.span))
20942094
tpd.cpy.Match(result)(
2095-
selector = tpd.Typed(sel, new tpd.InferredTypeTree().withType(uncheckedTpe)),
2095+
selector = tpd.Typed(sel, tpd.TypeTree(uncheckedTpe, inferred = true)),
20962096
cases = result.cases
20972097
)
20982098
case _ =>

library/src/scala/caps.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ import annotation.{experimental, compileTimeOnly, retainsCap}
2929
*/
3030
given containsImpl[C <: CapSet @retainsCap, R <: Singleton]: Contains[C, R]()
3131

32+
/** A wrapper indicating a type variable in a capture argument list of a
33+
* @retains annotation. E.g. `^{x, Y^}` is represented as `@retains(x, capsOf[Y])`.
34+
*/
3235
@compileTimeOnly("Should be be used only internally by the Scala compiler")
3336
def capsOf[CS]: Any = ???
3437

0 commit comments

Comments
 (0)