-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Drop retains annotations in inferred type trees #20057
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -454,7 +454,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI: | |
case _ => false | ||
|
||
def signatureChanges = | ||
tree.tpt.hasRememberedType && !sym.isConstructor || paramSignatureChanges | ||
(tree.tpt.hasRememberedType || tree.tpt.isInstanceOf[InferredTypeTree]) && !sym.isConstructor || paramSignatureChanges | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is the added condition needed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After a second thought this feels like a hack. The actual problem this tries to solve is that, for instance, given a ValDef Later on |
||
|
||
// Replace an existing symbol info with inferred types where capture sets of | ||
// TypeParamRefs and TermParamRefs put in correspondence by BiTypeMaps with the | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ import config.Feature | |
import util.SrcPos | ||
import reporting.* | ||
import NameKinds.WildcardParamName | ||
import cc.* | ||
|
||
object PostTyper { | ||
val name: String = "posttyper" | ||
|
@@ -279,6 +280,17 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase => | |
if !tree.symbol.is(Package) then tree | ||
else errorTree(tree, em"${tree.symbol} cannot be used as a type") | ||
|
||
// Cleans up retains annotations in inferred type trees. This is needed because | ||
// during the typer, it is infeasible to correctly infer the capture sets in most | ||
// cases, resulting ill-formed capture sets that could crash the pickler later on. | ||
// See #20035. | ||
private def cleanupRetainsAnnot(symbol: Symbol, tpt: Tree)(using Context): Tree = | ||
tpt match | ||
case tpt: InferredTypeTree if !symbol.allOverriddenSymbols.hasNext => | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be good to explain the condition. Something like: // if there are overridden symbols, the annotation comes from an explicit type of the overridden symbol, and should be retained. |
||
val tpe1 = cleanupRetains(tpt.tpe) | ||
tpt.withType(tpe1) | ||
case _ => tpt | ||
|
||
override def transform(tree: Tree)(using Context): Tree = | ||
try tree match { | ||
// TODO move CaseDef case lower: keep most probable trees first for performance | ||
|
@@ -388,7 +400,7 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase => | |
registerIfHasMacroAnnotations(tree) | ||
checkErasedDef(tree) | ||
Checking.checkPolyFunctionType(tree.tpt) | ||
val tree1 = cpy.ValDef(tree)(rhs = normalizeErasedRhs(tree.rhs, tree.symbol)) | ||
val tree1 = cpy.ValDef(tree)(tpt = cleanupRetainsAnnot(tree.symbol, tree.tpt), rhs = normalizeErasedRhs(tree.rhs, tree.symbol)) | ||
if tree1.removeAttachment(desugar.UntupledParam).isDefined then | ||
checkStableSelection(tree.rhs) | ||
processValOrDefDef(super.transform(tree1)) | ||
|
@@ -398,7 +410,7 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase => | |
checkErasedDef(tree) | ||
Checking.checkPolyFunctionType(tree.tpt) | ||
annotateContextResults(tree) | ||
val tree1 = cpy.DefDef(tree)(rhs = normalizeErasedRhs(tree.rhs, tree.symbol)) | ||
val tree1 = cpy.DefDef(tree)(tpt = cleanupRetainsAnnot(tree.symbol, tree.tpt), rhs = normalizeErasedRhs(tree.rhs, tree.symbol)) | ||
processValOrDefDef(superAcc.wrapDefDef(tree1)(super.transform(tree1).asInstanceOf[DefDef])) | ||
case tree: TypeDef => | ||
registerIfHasMacroAnnotations(tree) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,7 +48,7 @@ import staging.StagingLevel | |
import reporting.* | ||
import Nullables.* | ||
import NullOpsDecorator.* | ||
import cc.{CheckCaptures, isRetainsLike} | ||
import cc.{CheckCaptures, isRetainsLike, cleanupRetains} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like this import is not needed |
||
import config.Config | ||
import config.MigrationVersion | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import language.experimental.captureChecking | ||
|
||
trait Seq[+A]: | ||
def zipAll[A1 >: A, B](that: Seq[B]^, thisElem: A1, thatElem: B): Seq[(A1, B)]^{this, that} | ||
def map[B](f: A => B): Seq[B]^{this, f} | ||
|
||
def zipAllOption[X](left: Seq[X], right: Seq[X]) = | ||
left.map(Option(_)).zipAll(right.map(Option(_)), None, None) | ||
|
||
def fillRow[T](headRow: Seq[T], tailRow: Seq[T]) = | ||
val paddedZip = zipAllOption(headRow, tailRow) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need the
theMap
trick. Just define a normal typemap like:and use that instead of the
cleanupRetains
method in PostTyper.The
theMap
trick is used if we want to avoid creating the type map for simple types because the operation is very hot. But to pay off, you then need to actually handle simple types in the associated methods. Here, cleanupRetains is fairly warm but not as hot as methods that use the theMap trick such as substitutions.