summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Typers.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala59
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)
}