-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix #4466: Update contexts of FunProto when something else is tried #4871
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
Conversation
Type inference does backtracking over several possibilities, with fresh contexts for each branch. If a FunProto is kept from one branch to the next we have to make sure that it uses the right context in the new branch.
The idea of cloning FunProtos has promise, but we need to make sure that all clones refer to the same core state.
Default arguments in a parameter list of a supercall that follows the first one were sometimes handled incorrectly. In this case, the supercall can a block which contains bindings of earlier arguments that are passed to the default getter.
It seems FromTasty printing has to do the same thing. For the moment the test default-super.scala fails in the printing phase, and is therefpre blacklisted.
@@ -1593,6 +1593,7 @@ object Types { | |||
def isMatchedBy(tp: Type)(implicit ctx: Context): Boolean | |||
def fold[T](x: T, ta: TypeAccumulator[T])(implicit ctx: Context): T | |||
def map(tm: TypeMap)(implicit ctx: Context): ProtoType | |||
def withContext(ctx: Context): ProtoType = this |
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.
Maybe add a documentation comment.
evalState = evalState.remove(arg) | ||
typr.println(i"need to invalidate $arg / ${state.typedArg(arg)}, ${tstateConstr._2}, current = ${ctx.typerState.constraint}") | ||
state.typedArg = state.typedArg.remove(arg) | ||
state.evalState = state.evalState.remove(arg) |
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.
This wasn't done before either, but shouldn't state.typedArgs
be reset to an empty map too?
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.
Maybe. But I only wanted to do the minimum change here. We have to come back to this at some point.
val (callArgs, initArgs) = if (tree.symbol.owner.is(Trait)) (Nil, args) else (args, Nil) | ||
(superRef(tree.symbol, tree.pos).appliedToArgs(callArgs), initArgs) | ||
def transformConstructor(tree: Tree): (Tree, List[Tree]) = tree match { | ||
case Block(stats, expr) => |
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.
Hmm, if this works, doesn't it mean that we could very easily support early initializers (for the Scala 2 mode) ?
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.
There's still a way to go if we want to bring back early initializers. We'd also have to map definitions in the block back to definitions of the class fields.
result.toDrop = toDrop | ||
result | ||
} | ||
else new FunProto(args, resType)(typer, state)(newCtx) |
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.
The idea of cloning FunProtos has promise, but we need to make sure that all clones refer to the same core state.
In what situation are multiple clones of the same FunProto live at the same time, and why is it necessary that they share the same state?
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.
I noted we had problems with auto-tupling otherwise. The other danger is that we have FP1, infer a type argument, then go to FP2, infer another argument, then decide this is a blocker so fall back to FP1 and try something else afterwards. In this case the computed type argument of FP2 is lost.
Type inference does backtracking over several possibilities, with fresh
contexts for each branch. If a FunProto is kept from one branch to the next
we have to make sure that it uses the right context in the new branch.