@@ -212,7 +212,7 @@ object ProtoTypes {
212
212
private [this ] var evalState : SimpleIdentityMap [untpd.Tree , (TyperState , Constraint )] = SimpleIdentityMap .Empty
213
213
214
214
def isMatchedBy (tp : Type )(implicit ctx : Context ) =
215
- typer.isApplicable(tp, Nil , typedArgs , resultType)
215
+ typer.isApplicable(tp, Nil , unforcedTypedArgs , resultType)
216
216
217
217
def derivedFunProto (args : List [untpd.Tree ] = this .args, resultType : Type , typer : Typer = this .typer) =
218
218
if ((args eq this .args) && (resultType eq this .resultType) && (typer eq this .typer)) this
@@ -240,33 +240,45 @@ object ProtoTypes {
240
240
myTypedArg.size == args.length
241
241
}
242
242
243
- private def cacheTypedArg (arg : untpd.Tree , typerFn : untpd.Tree => Tree )(implicit ctx : Context ): Tree = {
243
+ private def cacheTypedArg (arg : untpd.Tree , typerFn : untpd.Tree => Tree , force : Boolean )(implicit ctx : Context ): Tree = {
244
244
var targ = myTypedArg(arg)
245
245
if (targ == null ) {
246
- targ = typerFn(arg)
247
- if (! ctx.reporter.hasPending) {
248
- myTypedArg = myTypedArg.updated(arg, targ)
249
- evalState = evalState.updated(arg, (ctx.typerState, ctx.typerState.constraint))
246
+ if (! force && untpd.functionWithUnknownParamType(arg).isDefined)
247
+ // If force = false, assume ? rather than reporting an error.
248
+ // That way we don't cause a "missing parameter" error in `typerFn(arg)`
249
+ targ = arg.withType(WildcardType )
250
+ else {
251
+ targ = typerFn(arg)
252
+ if (! ctx.reporter.hasPending) {
253
+ myTypedArg = myTypedArg.updated(arg, targ)
254
+ evalState = evalState.updated(arg, (ctx.typerState, ctx.typerState.constraint))
255
+ }
250
256
}
251
257
}
252
258
targ
253
259
}
254
260
255
261
/** The typed arguments. This takes any arguments already typed using
256
262
* `typedArg` into account.
263
+ * @param force if true try to typecheck arguments even if they are functions
264
+ * with unknown parameter types - this will then cause a
265
+ * "missing parameter type" error
257
266
*/
258
- def typedArgs : List [Tree ] = {
267
+ private def typedArgs ( force : Boolean ) : List [Tree ] = {
259
268
if (myTypedArgs.size != args.length)
260
- myTypedArgs = args.mapconserve(cacheTypedArg(_, typer.typed(_)))
269
+ myTypedArgs = args.mapconserve(cacheTypedArg(_, typer.typed(_), force ))
261
270
myTypedArgs
262
271
}
263
272
273
+ def typedArgs : List [Tree ] = typedArgs(force = true )
274
+ def unforcedTypedArgs : List [Tree ] = typedArgs(force = false )
275
+
264
276
/** Type single argument and remember the unadapted result in `myTypedArg`.
265
277
* used to avoid repeated typings of trees when backtracking.
266
278
*/
267
279
def typedArg (arg : untpd.Tree , formal : Type )(implicit ctx : Context ): Tree = {
268
280
val locked = ctx.typerState.ownedVars
269
- val targ = cacheTypedArg(arg, typer.typedUnadapted(_, formal, locked))
281
+ val targ = cacheTypedArg(arg, typer.typedUnadapted(_, formal, locked), force = true )
270
282
typer.adapt(targ, formal, locked)
271
283
}
272
284
0 commit comments