diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 59 |
1 files changed, 30 insertions, 29 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 837ccf7e06..2cbd9475fc 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3333,15 +3333,15 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper def handleOverloaded = { val undetparams = context.undetparams - def funArgTypes(tps: List[Type]) = tps.map { tp => - val relTp = tp.asSeenFrom(pre, fun.symbol.owner) + def funArgTypes(tpAlts: List[(Type, Symbol)]) = tpAlts.map { case (tp, alt) => + val relTp = tp.asSeenFrom(pre, alt.owner) val argTps = functionOrSamArgTypes(relTp) //println(s"funArgTypes $argTps from $relTp") argTps.map(approximateAbstracts) } - def functionProto(argTps: List[Type]): Type = - try functionType(funArgTypes(argTps).transpose.map(lub), WildcardType) + def functionProto(argTpWithAlt: List[(Type, Symbol)]): Type = + try functionType(funArgTypes(argTpWithAlt).transpose.map(lub), WildcardType) catch { case _: IllegalArgumentException => WildcardType } // To propagate as much information as possible to typedFunction, which uses the expected type to @@ -3355,21 +3355,21 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper // do not receive special treatment: they are typed under WildcardType.) val altArgPts = if (settings.isScala212 && args.exists(treeInfo.isFunctionMissingParamType)) - try alts.map(alt => formalTypes(alt.info.paramTypes, argslen)).transpose // do least amount of work up front + try alts.map(alt => formalTypes(alt.info.paramTypes, argslen).map(ft => (ft, alt))).transpose // do least amount of work up front catch { case _: IllegalArgumentException => args.map(_ => Nil) } // fail safe in case formalTypes fails to align to argslen else args.map(_ => Nil) // will type under argPt == WildcardType val (args1, argTpes) = context.savingUndeterminedTypeParams() { val amode = forArgMode(fun, mode) - map2(args, altArgPts) { (arg, argPts) => + map2(args, altArgPts) { (arg, argPtAlts) => def typedArg0(tree: Tree) = { // if we have an overloaded HOF such as `(f: Int => Int)Int <and> (f: Char => Char)Char`, // and we're typing a function like `x => x` for the argument, try to collapse // the overloaded type into a single function type from which `typedFunction` // can derive the argument type for `x` in the function literal above val argPt = - if (argPts.nonEmpty && treeInfo.isFunctionMissingParamType(tree)) functionProto(argPts) + if (argPtAlts.nonEmpty && treeInfo.isFunctionMissingParamType(tree)) functionProto(argPtAlts) else WildcardType val argTyped = typedArg(tree, amode, BYVALmode, argPt) @@ -3426,29 +3426,29 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper // repeat vararg as often as needed, remove by-name val formals = formalTypes(paramTypes, argslen) - /* Try packing all arguments into a Tuple and apply `fun` - * to that. This is the last thing which is tried (after - * default arguments) + /* Try packing all arguments into a Tuple and apply `fun` to that. + * This is the last thing which is tried (after default arguments). */ - def tryTupleApply: Tree = { - if (eligibleForTupleConversion(paramTypes, argslen) && !phase.erasedTypes) { + def tryTupleApply: Tree = + if (phase.erasedTypes || !eligibleForTupleConversion(paramTypes, argslen)) EmptyTree + else { val tupleArgs = List(atPos(tree.pos.makeTransparent)(gen.mkTuple(args))) // expected one argument, but got 0 or >1 ==> try applying to tuple // the inner "doTypedApply" does "extractUndetparams" => restore when it fails val savedUndetparams = context.undetparams - silent(_.doTypedApply(tree, fun, tupleArgs, mode, pt)) map { t => - // Depending on user options, may warn or error here if - // a Unit or tuple was inserted. - val keepTree = ( - !mode.typingExprNotFun // why? introduced in 4e488a60, doc welcome - || t.symbol == null // ditto - || checkValidAdaptation(t, args) - ) - if (keepTree) t else EmptyTree - } orElse { _ => context.undetparams = savedUndetparams ; EmptyTree } + // May warn or error if a Unit or tuple was inserted. + def validate(t: Tree): Tree = { + // regardless of typer's mode + val invalidAdaptation = t.symbol != null && !checkValidAdaptation(t, args) + // only bail if we're typing an expression (and not inside another application) + if (invalidAdaptation && mode.typingExprNotFun) EmptyTree else t + } + def reset(errors: Seq[AbsTypeError]): Tree = { + context.undetparams = savedUndetparams + EmptyTree + } + silent(_.doTypedApply(tree, fun, tupleArgs, mode, pt)).map(validate).orElse(reset) } - else EmptyTree - } /* Treats an application which uses named or default arguments. * Also works if names + a vararg used: when names are used, the vararg @@ -4666,19 +4666,20 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper val qual1 = typedQualifier(qual) if (treeInfo.isVariableOrGetter(qual1)) { if (Statistics.canEnable) Statistics.stopTimer(failedOpEqNanos, opeqStart) - val erred = qual1.isErroneous || args.exists(_.isErroneous) + val erred = qual1.exists(_.isErroneous) || args.exists(_.isErroneous) if (erred) reportError(error) else { val convo = convertToAssignment(fun, qual1, name, args) silent(op = _.typed1(convo, mode, pt)) match { case SilentResultValue(t) => t - case err: SilentTypeError => reportError(SilentTypeError(advice1(convo, error.errors, err), error.warnings)) + case err: SilentTypeError => reportError( + SilentTypeError(advice1(convo, error.errors, err), error.warnings) + ) } } - } - else { + } else { if (Statistics.canEnable) Statistics.stopTimer(failedApplyNanos, appStart) val Apply(Select(qual2, _), args2) = tree - val erred = qual2.isErroneous || args2.exists(_.isErroneous) + val erred = qual2.exists(_.isErroneous) || args2.exists(_.isErroneous) reportError { if (erred) error else SilentTypeError(advice2(error.errors), error.warnings) } |