Skip to content

Avoid "missing parameter type" error when checking isMatchedBy #4165

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

Merged
merged 2 commits into from
Mar 24, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 21 additions & 9 deletions compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ object ProtoTypes {
private[this] var evalState: SimpleIdentityMap[untpd.Tree, (TyperState, Constraint)] = SimpleIdentityMap.Empty

def isMatchedBy(tp: Type)(implicit ctx: Context) =
typer.isApplicable(tp, Nil, typedArgs, resultType)
typer.isApplicable(tp, Nil, unforcedTypedArgs, resultType)

def derivedFunProto(args: List[untpd.Tree] = this.args, resultType: Type, typer: Typer = this.typer) =
if ((args eq this.args) && (resultType eq this.resultType) && (typer eq this.typer)) this
Expand Down Expand Up @@ -240,33 +240,45 @@ object ProtoTypes {
myTypedArg.size == args.length
}

private def cacheTypedArg(arg: untpd.Tree, typerFn: untpd.Tree => Tree)(implicit ctx: Context): Tree = {
private def cacheTypedArg(arg: untpd.Tree, typerFn: untpd.Tree => Tree, force: Boolean)(implicit ctx: Context): Tree = {
var targ = myTypedArg(arg)
if (targ == null) {
targ = typerFn(arg)
if (!ctx.reporter.hasPending) {
myTypedArg = myTypedArg.updated(arg, targ)
evalState = evalState.updated(arg, (ctx.typerState, ctx.typerState.constraint))
if (!force && untpd.functionWithUnknownParamType(arg).isDefined)
// If force = false, assume ? rather than reporting an error.
// That way we don't cause a "missing parameter" error in `typerFn(arg)`
targ = arg.withType(WildcardType)
else {
targ = typerFn(arg)
if (!ctx.reporter.hasPending) {
myTypedArg = myTypedArg.updated(arg, targ)
evalState = evalState.updated(arg, (ctx.typerState, ctx.typerState.constraint))
}
}
}
targ
}

/** The typed arguments. This takes any arguments already typed using
* `typedArg` into account.
* @param force if true try to typecheck arguments even if they are functions
* with unknown parameter types - this will then cause a
* "missing parameter type" error
*/
def typedArgs: List[Tree] = {
private def typedArgs(force: Boolean): List[Tree] = {
if (myTypedArgs.size != args.length)
myTypedArgs = args.mapconserve(cacheTypedArg(_, typer.typed(_)))
myTypedArgs = args.mapconserve(cacheTypedArg(_, typer.typed(_), force))
myTypedArgs
}

def typedArgs: List[Tree] = typedArgs(force = true)
def unforcedTypedArgs: List[Tree] = typedArgs(force = false)

/** Type single argument and remember the unadapted result in `myTypedArg`.
* used to avoid repeated typings of trees when backtracking.
*/
def typedArg(arg: untpd.Tree, formal: Type)(implicit ctx: Context): Tree = {
val locked = ctx.typerState.ownedVars
val targ = cacheTypedArg(arg, typer.typedUnadapted(_, formal, locked))
val targ = cacheTypedArg(arg, typer.typedUnadapted(_, formal, locked), force = true)
typer.adapt(targ, formal, locked)
}

Expand Down