diff options
author | Adriaan Moors <adriaan.moors@epfl.ch> | 2010-09-16 22:26:24 +0000 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2010-09-16 22:26:24 +0000 |
commit | e557acb9a7d672c0635c3eaf9fe385adc41e5c86 (patch) | |
tree | d13db6639464acc57f0e44b4b3ef6f3e607ad403 /src/compiler/scala/tools/nsc/typechecker/Typers.scala | |
parent | ce223fe7abc47af712382a64404604e75f9f4d20 (diff) | |
download | scala-e557acb9a7d672c0635c3eaf9fe385adc41e5c86.tar.gz scala-e557acb9a7d672c0635c3eaf9fe385adc41e5c86.tar.bz2 scala-e557acb9a7d672c0635c3eaf9fe385adc41e5c86.zip |
part 2 of the dependent method refactoring: imp...
part 2 of the dependent method refactoring: improved interaction with
implicit search (needed for oopsla paper)
more to come in this area, see e.g. #3346 (stanford edsl stuff)
reopens #13, which wasn't fixed properly before imo, anyway (have a look at -Xprint:typer output before this commit: a type that's not expressible in surface syntax is inferred -- also removed duplicate test file)
closes #3731: co-evolve type alias type symbols when their rhs is
updated and they are referenced by type selections (see typemap)
review by odersky
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 79 |
1 files changed, 50 insertions, 29 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index e71ad5475c..f793da0c54 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -178,18 +178,12 @@ trait Typers { self: Analyzer => */ def applyImplicitArgs(fun: Tree): Tree = fun.tpe match { case MethodType(params, _) => - var positional = true val argResultsBuff = new ListBuffer[SearchResult]() + val argBuff = new ListBuffer[Tree]() - // apply the substitutions (undet type param -> type) that were determined - // by implicit resolution of implicit arguments on the left of this argument - for(param <- params) { - var paramTp = param.tpe - for(ar <- argResultsBuff) - paramTp = paramTp.subst(ar.subst.from, ar.subst.to) - - argResultsBuff += inferImplicit(fun, paramTp, true, false, context) - } + def mkPositionalArg(argTree: Tree, paramName: Name) = argTree + def mkNamedArg(argTree: Tree, paramName: Name) = atPos(argTree.pos)(new AssignOrNamedArg(Ident(paramName), (argTree))) + var mkArg: (Tree, Name) => Tree = mkPositionalArg def errorMessage(paramName: Name, paramTp: Type) = paramTp.typeSymbol match { @@ -200,23 +194,40 @@ trait Typers { self: Analyzer => else "parameter "+paramName+": ")+paramTp } - val argResults = argResultsBuff.toList - val args = argResults.zip(params) flatMap { - case (arg, param) => - if (arg != SearchFailure) { - if (positional) List(arg.tree) - else List(atPos(arg.tree.pos)(new AssignOrNamedArg(Ident(param.name), (arg.tree)))) - } else { - if (!param.hasFlag(DEFAULTPARAM)) - context.error(fun.pos, errorMessage(param.name, param.tpe)) - positional = false - Nil - } + // DEPMETTODO: instantiate type vars that depend on earlier implicit args (see adapt (4.1)) + // + // apply the substitutions (undet type param -> type) that were determined + // by implicit resolution of implicit arguments on the left of this argument + for(param <- params) { + var paramTp = param.tpe + for(ar <- argResultsBuff) + paramTp = paramTp.subst(ar.subst.from, ar.subst.to) + + val res = inferImplicit(fun, paramTp, true, false, context) + argResultsBuff += res + + if (res != SearchFailure) { + argBuff += mkArg(res.tree, param.name) + } else { + mkArg = mkNamedArg // don't pass the default argument (if any) here, but start emitting named arguments for the following args + if (!param.hasFlag(DEFAULTPARAM)) + context.error(fun.pos, errorMessage(param.name, param.tpe)) + /* else { + TODO: alternative (to expose implicit search failure more) --> + resolve argument, do type inference, keep emitting positional args, infer type params based on default value for arg + for (ar <- argResultsBuff) ar.subst traverse defaultVal + val targs = exprTypeArgs(context.undetparams, defaultVal.tpe, paramTp) + substExpr(tree, tparams, targs, pt) + }*/ + } } - for (s <- argResults map (_.subst)) { - s traverse fun - for (arg <- args) s traverse arg + + val args = argBuff.toList + for (ar <- argResultsBuff) { + ar.subst traverse fun + for (arg <- args) ar.subst traverse arg } + new ApplyToImplicitArgs(fun, args) setPos fun.pos case ErrorType => fun @@ -819,10 +830,20 @@ trait Typers { self: Analyzer => context.undetparams = context.undetparams ::: tparams1 adapt(tree1 setType restpe.substSym(tparams, tparams1), mode, pt, original) case mt: MethodType if mt.isImplicit && ((mode & (EXPRmode | FUNmode | LHSmode)) == EXPRmode) => // (4.1) - if (context.undetparams nonEmpty) // (9) -- should revisit dropped condition `(mode & POLYmode) == 0` - // dropped so that type args of implicit method are inferred even if polymorphic expressions are allowed - // needed for implicits in 2.8 collection library -- maybe once #3346 is fixed, we can reinstate the condition? - context.undetparams = inferExprInstance(tree, context.extractUndetparams(), pt, false) // false: retract Nothing's that indicate failure, ambiguities in manifests are dealt with in manifestOfType + if (context.undetparams nonEmpty) { // (9) -- should revisit dropped condition `(mode & POLYmode) == 0` + // dropped so that type args of implicit method are inferred even if polymorphic expressions are allowed + // needed for implicits in 2.8 collection library -- maybe once #3346 is fixed, we can reinstate the condition? + context.undetparams = + inferExprInstance(tree, context.extractUndetparams(), pt, + // approximate types that depend on arguments since dependency on implicit argument is like dependency on type parameter + if(settings.YdepMethTpes.value) mt.approximate else mt, + // if we are looking for a manifest, instantiate type to Nothing anyway, + // as we would get ambiguity errors otherwise. Example + // Looking for a manifest of Nil: This mas many potential types, + // so we need to instantiate to minimal type List[Nothing]. + false) // false: retract Nothing's that indicate failure, ambiguities in manifests are dealt with in manifestOfType + } + val typer1 = constrTyperIf(treeInfo.isSelfOrSuperConstrCall(tree)) if (original != EmptyTree && pt != WildcardType) typer1.silent(tpr => tpr.typed(tpr.applyImplicitArgs(tree), mode, pt)) match { |