diff options
author | Adriaan Moors <adriaan.moors@epfl.ch> | 2009-09-11 10:34:02 +0000 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2009-09-11 10:34:02 +0000 |
commit | 57ed4ca11459b48f2310c81beef1d31476494d25 (patch) | |
tree | f310b1456553557c67a6baae9b7d095436a6a144 /src | |
parent | 10cf73815b04d3d3d214adc1d5176daa81916e8f (diff) | |
download | scala-57ed4ca11459b48f2310c81beef1d31476494d25.tar.gz scala-57ed4ca11459b48f2310c81beef1d31476494d25.tar.bz2 scala-57ed4ca11459b48f2310c81beef1d31476494d25.zip |
Fixed #2201 (slight rewrite of paulp's patch at...
Fixed #2201 (slight rewrite of paulp's patch at
http://github.com/paulp/scala/commit/24419959b4d6c93716c216bbf276948a830
4b4e6)
ImplicitSearch::cacheResult now clones symbols that represent bound
variables (more specifically, parameters of anonymous functions that
are used as implicit values) to ensure that different bound variables
are represented by different symbols (otherwise lambda lifting gets
confused).
updated check file for bug692: error-reporting got more complete because
TypeRef::transform has been relaxed slightly
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Types.scala | 12 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 24 |
2 files changed, 27 insertions, 9 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index 707137dd78..5705399428 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -1410,15 +1410,11 @@ trait Types { sym.isModuleClass || sym == NothingClass || isValueClass(sym) || super.isNotNull // @M: propagate actual type params (args) to `tp', by replacing formal type parameters with actual ones + // if tp is higher kinded, the "actual" type arguments are types that simply reference the corresponding type parameters (unbound type variables) def transform(tp: Type): Type = { - val args = typeArgsOrDummies - if (args.length == sym.typeParams.length) - tp.asSeenFrom(pre, sym.owner).instantiateTypeParams(sym.typeParams, args) - else { - assert(sym.typeParams.isEmpty || (args exists (_.isError)) || isRaw(sym, args)/*#2266/2305*/, tp) - tp - } - // @M TODO maybe we shouldn't instantiate type params if isHigherKinded -- probably needed for partial type application though + val res = tp.asSeenFrom(pre, sym.owner) + if (sym.typeParams.isEmpty || (args exists (_.isError)) || isRaw(sym, args)/*#2266/2305*/) res + else res.instantiateTypeParams(sym.typeParams, typeArgsOrDummies) } //@M! use appliedType on the polytype that represents the bounds (or if aliastype, the rhs) diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 7ebaa27872..96670ab131 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -671,6 +671,28 @@ self: Analyzer => } } + /** Construct a fresh symbol tree for an implicit parameter + because of caching, must clone symbols that represent bound variables, + or we will end up with different bound variables that are represented by the same symbol */ + def freshenFunctionParameters(tree : Tree) : Tree = new Transformer { + currentOwner = context.owner + override val treeCopy = new LazyTreeCopier + override def transform(tr : Tree) = super.transform(tr match { + case Function(vparams, body) => { + // New tree + val sym = tr.symbol cloneSymbol currentOwner + val res = tr.duplicate setSymbol sym + // New parameter symbols + var oldsyms = vparams map (_.symbol) + var newsyms = cloneSymbols(oldsyms, sym) + // Fix all symbols + new TreeSymSubstituter(oldsyms, newsyms) traverse res + res + } + case x => x + }) + } transform tree + /** Return cached search result if found. Otherwise update cache * but keep within sizeLimit entries */ @@ -679,7 +701,7 @@ self: Analyzer => hits += 1 if (sr == SearchFailure) sr else { - val result = new SearchResult(sr.tree.duplicate, sr.subst) + val result = new SearchResult(freshenFunctionParameters(sr.tree.duplicate), sr.subst) // #2201: generate fresh symbols for parameters for (t <- result.tree) t.setPos(tree.pos.focus) result } |