diff options
author | Martin Odersky <odersky@gmail.com> | 2008-02-08 18:28:09 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2008-02-08 18:28:09 +0000 |
commit | d3a71dbd88dd98006a893b35d52ad909c8cd10bb (patch) | |
tree | 6d5f7ceec3d52caf80789ad8d61f51ae2f006537 | |
parent | a176556bea2482d4c3c86a3604ec1eaa16d0daf1 (diff) | |
download | scala-d3a71dbd88dd98006a893b35d52ad909c8cd10bb.tar.gz scala-d3a71dbd88dd98006a893b35d52ad909c8cd10bb.tar.bz2 scala-d3a71dbd88dd98006a893b35d52ad909c8cd10bb.zip |
fixed missing deprecated warning on types; fixe...
fixed missing deprecated warning on types; fixed problem with traits in
refinements.
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Symbols.scala | 37 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Types.scala | 16 | ||||
-rwxr-xr-x | src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala.notyet | 409 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | 14 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 16 | ||||
-rw-r--r-- | src/library/scala/Predef.scala | 4 | ||||
-rw-r--r-- | test/files/pos/t0438.scala | 12 |
7 files changed, 483 insertions, 25 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index c50984bac2..03ea3c0b5a 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -6,6 +6,7 @@ package scala.tools.nsc.symtab +import scala.collection.mutable.ListBuffer import scala.tools.nsc.io.AbstractFile import scala.tools.nsc.util.{Position, NoPosition, BatchSourceFile} import Flags._ @@ -637,18 +638,46 @@ trait Symbols { attributes.filter(_.atp.typeSymbol.isNonBottomSubClass(clazz)) /** The least proper supertype of a class; includes all parent types - * and refinement where needed */ + * and refinement where needed + */ def classBound: Type = { val tp = refinedType(info.parents, owner) val thistp = tp.typeSymbol.thisType + val oldsymbuf = new ListBuffer[Symbol] + val newsymbuf = new ListBuffer[Symbol] for (sym <- info.decls.toList) { - if (sym.isPublic && !sym.isClass && !sym.isConstructor) - addMember(thistp, tp, - sym.cloneSymbol(tp.typeSymbol).setInfo(sym.info.substThis(this, thistp))) + // todo: what about public references to private symbols? + if (sym.isPublic && !sym.isConstructor) { + oldsymbuf += sym + newsymbuf += ( + if (sym.isClass) + tp.typeSymbol.newAbstractType(sym.pos, sym.name).setInfo(sym.existentialBound) + else + sym.cloneSymbol(tp.typeSymbol)) + } + } + val oldsyms = oldsymbuf.toList + val newsyms = newsymbuf.toList + for (sym <- newsyms) { + addMember(thistp, tp, sym.setInfo(sym.info.substThis(this, thistp).substSym(oldsyms, newsyms))) } tp } + /** If we quantify existentially over this symbol, + * the bound of the type variable that stands for it + * pre: symbol is a term, a class, or an abstract type (no alias type allowed) + */ + def existentialBound: Type = + if (this.isClass) + polyType(this.typeParams, mkTypeBounds(AllClass.tpe, this.classBound)) + else if (this.isAbstractType) + this.info + else if (this.isTerm) + mkTypeBounds(AllClass.tpe, intersectionType(List(this.tpe, SingletonClass.tpe))) + else + throw new Error("unexpected alias type: "+this) + /** Reset symbol to initial state */ def reset(completer: Type) { diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index ae04027c5f..aca7f823c1 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -435,12 +435,18 @@ trait Types { /** Substitute symbols `to' for occurrences of symbols * `from' in this type. + * !!! NOTE !!!: If you need to do a substThis and a substSym, the substThis has to come + * first, as otherwise symbols will immediately get rebound in typeRef to the old + * symbol. */ def substSym(from: List[Symbol], to: List[Symbol]): Type = if (from eq to) this else new SubstSymMap(from, to) apply this /** Substitute all occurrences of `ThisType(from)' in this type * by `to'. + * !!! NOTE !!!: If you need to do a substThis and a substSym, the substThis has to come + * first, as otherwise symbols will immediately get rebound in typeRef to the old + * symbol. */ def substThis(from: Symbol, to: Type): Type = new SubstThisMap(from, to) apply this @@ -1835,7 +1841,11 @@ A type's typeSymbol should never be inspected directly. if (owner.isClass && owner != pre.typeSymbol && !sym.isFinal && !sym.isClass) { //Console.println("rebind "+pre+" "+sym)//DEBUG val rebind = pre.nonPrivateMember(sym.name).suchThat(sym => sym.isType || sym.isStable) - if (rebind == NoSymbol) sym else rebind + if (rebind == NoSymbol) sym + else { + // Console.println("rebound "+pre+" "+sym+" to "+rebind)//DEBUG + rebind + } } else sym } @@ -1927,7 +1937,7 @@ A type's typeSymbol should never be inspected directly. val syms2 = result.decls.toList val resultThis = result.typeSymbol.thisType for (sym <- syms2) - sym.setInfo(sym.info.substSym(syms1, syms2).substThis(original.typeSymbol, resultThis)) + sym.setInfo(sym.info.substThis(original.typeSymbol, resultThis).substSym(syms1, syms2)) result } @@ -4187,7 +4197,7 @@ A type's typeSymbol should never be inspected directly. */ def addMember(thistp: Type, tp: Type, sym: Symbol) { assert(sym != NoSymbol) - if (settings.debug.value) log("add member " + sym+":"+tp+" to "+thistp) + if (settings.debug.value) log("add member " + sym+":"+sym.info+" to "+thistp) if (!(thistp specializes sym)) { if (sym.isTerm) for (alt <- tp.nonPrivateDecl(sym.name).alternatives) diff --git a/src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala.notyet b/src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala.notyet new file mode 100755 index 0000000000..57215d5b77 --- /dev/null +++ b/src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala.notyet @@ -0,0 +1,409 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2007 LAMP/EPFL + * @author Martin Odersky + */ +// $Id: RefChecks.scala 13735 2008-01-18 17:18:58Z odersky $ + +package scala.tools.nsc.typechecker + +import symtab.Flags._ +import transform.InfoTransform +import scala.tools.nsc.util.{Position, NoPosition} + +abstract class DeVirtualize extends InfoTransform { + + import global._ + import definitions._ + import typer.{typed, typedOperator, atOwner} + import posAssigner.atPos + + /** the following two members override abstract members in Transform */ + val phaseName: String = "devirtualize" + + /** The phase might set the following new flags: */ + override def phaseNewFlags: Long = notOVERRIDE | notFINAL + + def newTransformer(unit: CompilationUnit): DeVirtualizeTransformer = + new DeVirtualizeTransformer(unit) + override def changesBaseClasses = false + + lazy val ownPhase = phaseNamed(phaseName) + + def transformInfo(sym: Symbol, tp: Type): Type = devirtualizeMap(tp) + + /* todo: + check: overriding classes must have same type params + virtual classes cannot have self types + */ + + /** Do the following transformations everywhere in a type: + * + * 1. If a class defines virtual classes VC, add abstract types VA, + * worker traits VT and factories VF instead (@see devirtualize). + * 2. Convert VC.this where VC is a virtual class to WT.this where WT is the worker trait for VC + * (@see workerTrait) + * 3. Convert TypeRef's to VC where VC is a virtual class to TypeRef's to AT, where AT + * is the abstract type corresponding to VC. + * + * Note: If a class inherits vc's from two different paths, a vc in the + * inheriting class has to be created beforehand. This is done in phase ??? + */ + object devirtualizeMap extends TypeMap { + def apply(tp: Type): Type = mapOver(tp) match { + case tp1 @ ClassInfoType(parents, decls, clazz) => + val ds = decls.toList + if (ds exists (_.isVirtualClass)) { + transformOwnerInfo(clazz) + val decls1 = newScope(ds) + for (m <- m.info.decls) + if (m.isVirtualClass) devirtualize(m, decls1) + for (m <- classesInNeedOfFactories(clazz)) + addFactory(m, clazz, decls1) + ClassInfoType(parents, decls1, clazz) + } else tp1 + case ThisType(clazz) if clazz.isVirtualClass => + ThisType(workerTrait(clazz)) + case TypeRef(pre, clazz, args) if sym.isVirtualClass => + TypeRef(pre, abstractType(clazz), args) + case _ => + tp + } + } + + /** Transform owner of given clazz symbol */ + protected def transformOwnerInfo(clazz: Symbol) { atPhase(ownPhase.next) { clazz.owner.info } } + + protected def workerTraitName(clazzName: Name) = newTypeName(clazzName+"$trait") + protected def concreteClassName(clazzName: Name) = newTypeName(clazzName+"$fix") + protected def factoryName(clazzName: Name) = newTermName("new$"+clazzName) + + protected def definedVirtuals(clazz: Symbol) = m.info.decls.toList filter (_.isVirtual) + + protected def classesInNeedOfFactories(clazz: Symbol) = atPhase(ownPhase) { + def isDefinedVirtual(c: Symbol) = c.isVirtualClass && c.owner == clazz + val buf: ListBuffer[Symbol] + for (m <- clazz.info.members) + if (m.isVirtualClass && !(m hasFlag ABSTRACT) && (m.baseClasses exists isDefinedVirtual)) + buf += m + buf.toList + } + + /** The abstract type corresponding to a virtual class. */ + protected def abstractType(clazz: Symbol): Symbol = atPhase(ownPhase.next) { + val tsym = clazz.info.owner.member(clazz.name) + assert(tsym.isAbstractType, clazz) + tsym + } + + /** The worker trait corresponding to a virtual class. */ + protected def workerTrait(clazz: Symbol) = atPhase(ownPhase.next) { + val tsym = clazz.info.owner.member(workerTraitName(clazz.name)) + assert(tsym.isTrait, clazz) + tsym + } + + /** The factory corresponding to a virtual class. */ + protected def factory(clazz: Symbol) = atPhase(ownPhase.next) { + val fsym = clazz.info.owner.member(factoryName(clazz.name.toTermName)) + assert(fsym.isMethod, clazz) + fsym + } + + /** A reference to workertrait VT[Us] as from symbol `base'. Renames type parameters + * Us to those of `base' and also substitutes this to this of base's owner. + */ + protected def workerTypeRef(wtrait: Symbol, base: Symbol): Type = + wtrait.tpe.subst(wtrait.typeParams, base.typeParams).substThis(wtrait.owner, base.owner) + + /** The flags that a worker trait can inherit from its virtual class */ + protected val traitFlagMask = AccessFlags | FINAL + + /** The flags that an abstract type can inherit from its virtual class */ + protected val absTypeFlagMask = AccessFlags | DEFERRED + + /** The flags that a factory method can inherit from its virtual class */ + protected val factoryFlagMask = AccessFlags + + /** Create a polytype with given type parameters and given type, or return just the type + * if type params is empty. */ + protected def mkPolyType(tparams: List[Symbol], tp: Type) = + if (tparams.isEmpty) tp else PolyType(tparams, tp) + + /** Set info of `dst' to `tp', potentially wrapped by copies of any type + * parameters of `src' */ + def setPolyInfo(dst: Symbol, from: Symbol, tp: Type) = { + val tparams = cloneSymbols(from.typeParams, dst) + dst setInfo mkPolyType(tparams, tp subst (from.typeParams, tparams)) + } + + /** The virtual classes overridden by given virtual class `clazz' + * Classes appear in linearization order (with superclasses before subclasses) + */ + protected def overriddenVirtuals(clazz: Symbol): List[Symbol] = atPhase(ownPhase) { + for (bc <- clazz.owner.info.baseClasses + oc <- bc.info.member(clazz.name).alternatives + if oc.isVirtualClass) yield oc + }.reverse + + + /** Replace a virtual class + * + * attrs mods class VC[Ts] <: Ps { decls } + * + * with overridden classes _VC[Us]'s + * + * by the following symbols + * + * attrs mods1 type VC[Ts] <: dvm(Ps) with _VC$trait[Ts]'s with VC$trait[Ts] + * attrs mods2 trait VC$trait[Ts] extends Object with ScalaObject { + * this: VC[Ts] with VC$trait[Ts] => decls1 + * } + * + * Furthermore, for all virtual member classes VC which + * are not abstract and which are or inherit from a virtual class defined +also add a factory: + * + * attrs mods3 def new$VC[Ts](): VC[Ts] = { + * class VC$fix extends VC$trait's[Ts] with VC$trait[Ts] + * + * where + * + * dvm is the devirtalization mapping which converts refs to + * virtual classes to refs to their abstract types (@see devirtualize) + * mods1 are the modifiers inherited from abstract types + * mods2 are the modifiers inherited from worker traits + * mods3 are the modifiers inherited from factories + * decls1 is decls but members that have an override modifier + * lose it and any final modifier as well. + */ + protected def devirtualize(clazz: Symbol, scope: Scope) { + scope.unlink(clazz) + + val cabstype = clazz.owner.newAbstractType(clazz.pos, clazz.name) + .setFlag(clazz.flags & absTypeFlagMask) + scope.enter(cabstype) + + cabstype setInfo new LazyType { + override val typeParams = cloneSymbols(clazz.typeParams, cabstype) + override def complete(sym: Symbol) { + def parentTypeRef(tp: Type) = + devirtualizeMap(tp.subst(clazz.typeParams, typeParams)) + val parents1 = clazz.info.parents map parentTypeRef + val parents2 = overriddenVirtuals(clazz) map (oc => workerTypeRef(workerTrait(oc), cabstype)) + sym.setInfo( + mkPolyType(typeParams, mkTypeBounds(AllClass.tpe, intersectionType(parents1 ::: parents2)))) + } + } + + val wtrait = clazz.owner.newClass(clazz.pos, workerTraitName(clazz.name)) + .setFlag(clazz.flags & traitFlagMask | TRAIT) + .setAttributes(clazz.atttributes) + scope.enter(wtrait) + + val decls1 = clazz.info.decls.toList + for (val m <- decls1) + if (m hasFlag OVERRIDE) m serFlag (notOVERRIDE | notFINAL) + setPolyInfo( + wtrait, clazz, + ClassInfoType(List(ObjectClass.tpe, ScalaObjectClass.tpe), new Scope(decls1), wtrait)) + wtrait.setTypeOfThis(intersectionType(List(cabstype.tpe, wtrait.tpe)), clazz) + } + + def addFactory(clazz: Symbol, owner: Symbol, scope: Scope) { + val pos = if (clazz.owner == owner) clazz.pos else owner.pos + val factory = owner.newMethod(pos, factoryName(clazz)) + .setFlag(clazz.flags & factoryFlagMask) + scope.enter(factory) + val cabstype = abstractType(clazz) + setPolyInfo(factory, cabstype, MethodType(List(), cabstype.tpe)) + } + + protected def concreteClassSym(clazz: Symbol, factory: Symbol) = { + val cclazz = factory.newClass(clazz.pos, concreteClassName(clazz)) + .setFlag(clazz.flags) + .setAttributes(clazz.atttributes) + + cclazz setInfo new LazyType { + override def complete(sym: Symbol) { + sym setInfo ClassInfoType( + overriddenVirtuals(clazz) map (oc => workerTypeRef(workerTrait(oc), factory)) + new Scope(), + cclazz) + } + } + + cclazz + } + + /** (new VC).init() => new$VC + * add stuff to onwing class + * transform types + */ + class DeVirtualizeTransformer(unit: CompilationUnit) extends TypingTransformer { + + override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = { + val stats1 = for (stat <- stats; stat1 <- transformStat(stat)) yield transform(stat1) + val newDefs = new ListBuffer[Tree] + if (currentOwner.isClass && currentOwner.info.decls.toList exists (_.isVirtualClass)) { + for (m <- classesInNeedOfFactories(currentOwner)) + newDefs += factoryDef(m) + } + if (newDefs.isEmpty) stats1 + else stats1 ::: newDefs.toList + } + + protected def transformStat(tree: Tree): List[Tree] = tree match { + case ClassDef(mods, name, tparams, Template(parents, self, body)) if (tree.symbol.isVirtualClass) => + val clazz = tree.symbol + val absTypeSym = abstractType(clazz) + val workerTraitSym = workerTrait(clazz) + val abstypeDef = TypeDef(abstractType(clazz)) + val selfDef = ValDef(Modifiers(PRIVATE), nme.WILDCARD, TypeTree(clazz.tpe), EmptyTree) + val traitTemplate = atPos(templ.pos) { + Template( + List.map2(workerTraitSym.parents, parents) ((ptpe, ptree) => TypeTree(ptpe) setPos ptree.pos), + selfDef, Modifiers(), List(List()), List(List()), + body) + } + new ChangeOwnerTraverser(templ.symbol.owner, workerTrait)( + new ChangeOwnerTraverser(templ.symbol, traitTemplate.symbol)(traitTemplate)) + var newdefs = List(abstypeDef, traitTemplate) + if (!clazz.hasFlag(ABSTRACT)) { + val factorySym = factory(clazz) + val cclazzSym = concreteClassSym(clazz, factorySym) + def overrideBridge(m: Symbol) = atPos(m.pos) { + val bridge = m.cloneSymbol(cclazzSym) + .resetFlag(notOVERRIDE | notFINAL) + val superRef = Select(Super(cclazzSym, nme.EMPTY.toTypeName), m) + DefDef(bridge, vparamss => (superRef /: vparamss)((fn, vparams) => + Apply(fn, vparams map (param => Ident(param.symbol) setPos param.pos)))) + } + val overrideBridges = + for (m <- workerTraitSym.info.decls.toList if m hasFlag notOVERRIDE) + yield overrideBridge(m) + val cclazzDef = ClassDef(cclazzSym, Modifiers(), List(List()), List(List()), overrideBridges) + val factoryExpr = atPos(templ.pos) { + Block(cclazzDef, New(TypeTree(cclazzSym.tpe), List(List()))) + } + val factoryDef = DefDef(factorySym, vparamss => factoryExpr) + newdefs = newdefs ::: List(factoryDef) + } + newdefs map localTyper.typed + case _ => + List(tree) + } + + override def transform(tree: Tree): Tree = tree match { + case ClassDef(mods, name, tparams, Template(parents, self, body)) => + + case This(_) | Super(_, _) if tree.symbol.isVirtualClass => + tree setSymbol workerTrait(tree.symbol) + case Select(New(tpt), name) if (tree.symbol.isConstructor && tree.symbol.owner.isVirtualClass) => + val clazz = tpt.tpe.typeSymbol + val fn = mkAttributedRef(factory(clazz)) + val targs = tpt.tpe.typeArgs + atPos(tree.pos) { + if (targs.isEmpty) fn else TypeApply(fn, targs map TypeTree) setType tpt.tpe + } + case _ => + super.transform(tree) + } setType devirtualizeMap(tree.tpe) + + override def transformUnit(unit: CompilationUnit) = atPhase(ownPhase.next) { + super.transformUnit(unit) + } + } +} + + + + + scope.enter(wtrait) + + .setInfo + scope.enter(cabstype) + + setPolyType(wtrait, ClassInfoType( + List(ObjectClass.tpe, ScalaObjectClass.tpe), + new Scope(clazz.info.decls), + wtrait)) + + setPolyType(cabstype, mkTypeBounds( + AllClass.tpe, + (overridden map (workerTrait(_).tpe)) ::: (clazz.parents map devirtualizeMap))) + + + + + + + val cfix = ... + val cfactory = ... + val virBound = { + mkTypeBounds( + AllClass.tpe, + c.info.parents ::: overridden.map(oc => virTrait(oc).tpe)) + + c.setInfo(mkTypeBounds(AllClass.tpe, intersectionType( + ).tpe), c.owner))) + } + +/* + class A { + class C[X, Y](x: X) <: { var y = x ; def f(z: Y): X } + class D[Y](z) extends C[Int, Y](f(z)) { override def f(z:Int) = 3 } + } + class B extends A { + class C[X, Y](x: X) <: { def g = 2 } + } + +maps to: + + class A { + type C[X, Y] <: CT[X, Y] + + trait CT[X, Y] { self: C => protected[this] val x: Int; val y = x; def f(z:Int) = z + 1 } + + type D <: C with DT + + trait DT extends { self: D => def f(z:Int) = z + 2 } + + trait preDT extends { self: D => val z: Int; val x = f(z) } + + def newC(x: Int): C + def newD(x: Int): D + + //type C = CT + //type D = C with DT + + class CC(_x:Int) extends { val x = _x } with CT + + def newC[X, Y](x:Int): C = + new CC(x).asInstanceOf[C] + + class DC(_z:Int) extends { val z = _z } with preDT with CT with DT { + override def f(z:Int) = super.f(z) + } + + def newD(z:Int):D = new DC(z).asInstanceOf[D] + } + + class B extends A { + type C <: CT with CT2 + + trait CT2 { self : C => def g = 2 } + + //type C = CT with CT2 + //type D = C with DT + + class CC2(_x:Int) extends { val x = _x } with CT with CT2 + + def newC(x:Int): C = new CC2(x).asInstanceOf[C] + + class DC2(_z:Int) extends { val z = _z } with preDT with CT with CT2 + with DT { override def f(z:Int) = super.f(z) } + + def newD(z:Int): D = new DC2(z).asInstanceOf[D] + } + +*/ diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index bc8a15297e..fa37dd5786 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -684,6 +684,15 @@ abstract class RefChecks extends InfoTransform { result } + /** If symbol is deprecated and is not contained in a depreceated definition, + * issue a deprecated warning + */ + def checkDeprecated(sym: Symbol, pos: Position) { + if (sym.isDeprecated && !currentOwner.ownerChain.exists(_.isDeprecated)) { + unit.deprecationWarning(pos, sym+sym.locationString+" is deprecated") + } + } + /** Check that a deprecated val or def does not override a * concrete, non-deprecated method. If it does, then * deprecation is meaningless. @@ -736,6 +745,7 @@ abstract class RefChecks extends InfoTransform { new TypeTraverser { def traverse(tp: Type): TypeTraverser = tp match { case TypeRef(pre, sym, args) => + checkDeprecated(sym, tree.pos) if (!tp.isHigherKinded) checkBounds(pre, sym.owner, sym.typeParams, args) this case _ => @@ -785,9 +795,7 @@ abstract class RefChecks extends InfoTransform { } case Select(qual, name) => - if (sym.isDeprecated && !currentOwner.ownerChain.exists(_.isDeprecated)) { - unit.deprecationWarning(tree.pos, sym+sym.locationString+" is deprecated") - } + checkDeprecated(sym, tree.pos) if (currentClass != sym.owner && (sym hasFlag LOCAL)) { var o = currentClass var hidden = false diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 8f0efd5819..915a6a159e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1914,16 +1914,6 @@ trait Typers { self: Analyzer => } } - protected def existentialBound(sym: Symbol): Type = - if (sym.isClass) - polyType(sym.typeParams, mkTypeBounds(AllClass.tpe, sym.classBound)) - else if (sym.isAbstractType) - sym.info - else if (sym.isTerm) - mkTypeBounds(AllClass.tpe, intersectionType(List(sym.tpe, SingletonClass.tpe))) - else - throw new Error("unexpected alias type: "+sym) - /** Given a set `rawSyms' of term- and type-symbols, and a type `tp'. * produce a set of fresh type parameters and a type so that it can be * abstracted to an existential type. @@ -1943,7 +1933,7 @@ trait Typers { self: Analyzer => protected def existentialTransform(rawSyms: List[Symbol], tp: Type) = { val typeParams: List[Symbol] = rawSyms map { sym => val name = if (sym.isType) sym.name else newTypeName(sym.name+".type") - val bound = existentialBound(sym) + val bound = sym.existentialBound val quantified: Symbol = recycle(sym.owner.newAbstractType(sym.pos, name)) trackSetInfo(quantified setFlag EXISTENTIAL)(bound.cloneInfo(quantified)) @@ -2016,14 +2006,14 @@ trait Typers { self: Analyzer => !(localSyms contains sym) && !(boundSyms contains sym) ) { if (sym.typeParams.isEmpty) { localSyms += sym - addLocals(existentialBound(sym)) + addLocals(sym.existentialBound) } else if (tp.typeArgs.isEmpty) { unit.error(tree.pos, "implementation restriction: can't existentially abstract over higher-kinded type" + tp) } else { val inst = new SymInstance(sym, tp) if (!(localInstances contains inst)) { - val bound = existentialBound(sym) match { + val bound = sym.existentialBound match { case PolyType(tparams, restpe) => restpe.subst(tparams, tp.typeArgs) case t => diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index 5950a999fe..f196aafa8a 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -35,9 +35,9 @@ object Predef { type boolean = scala.Boolean type unit = scala.Unit - /** @deprecated use <code>Int</code> instead */ + /** @deprecated use <code>java.lang.Integer</code> instead */ @deprecated type Integer = java.lang.Integer - /** @deprecated use <code>Char</code> instead */ + /** @deprecated use <code>java.lang.Character</code> instead */ @deprecated type Character = java.lang.Character type String = java.lang.String diff --git a/test/files/pos/t0438.scala b/test/files/pos/t0438.scala new file mode 100644 index 0000000000..fa5b7711ff --- /dev/null +++ b/test/files/pos/t0438.scala @@ -0,0 +1,12 @@ +class Foo { + implicit def pair2fun2[A, B, C](f: (A, B) => C) = + {p: (A, B) => f(p._1, p._2) } + + def foo(f: ((Int, Int)) => Int) = f + def bar(x: Int, y: Int) = x + y + + foo({ (x: Int, y: Int) => x + y }) // works + foo(pair2fun2(bar _)) // works + foo(bar _) // error + foo(bar) // same error +} |