diff options
Diffstat (limited to 'src')
5 files changed, 47 insertions, 24 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index c90ea60b12..6bc136e976 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -208,13 +208,20 @@ abstract class TreeGen { ValDef(mvar, if (mvar.owner.isClass) EmptyTree else Literal(Constant(null))) } - // def m: T = { if (m$ eq null) m$ = new m$class; m$ } - def mkModuleAccessDef(accessor: Symbol, mvar: Symbol) = - DefDef(accessor, vparamss => - mkCached(mvar, - New(TypeTree(mvar.tpe), - List(for (pt <- mvar.tpe.typeSymbol.primaryConstructor.info.paramTypes) - yield This(accessor.owner.enclClass))))) + // def m: T = { if (m$ eq null) m$ = new m$class(...) m$ } + // where (...) are eventual outer accessors + def mkCachedModuleAccessDef(accessor: Symbol, mvar: Symbol) = + DefDef(accessor, vparamss => mkCached(mvar, newModule(accessor, mvar.tpe))) + + // def m: T = new tpe(...) + // where (...) are eventual outer accessors + def mkModuleAccessDef(accessor: Symbol, tpe: Type) = + DefDef(accessor, vparamss => newModule(accessor, tpe)) + + private def newModule(accessor: Symbol, tpe: Type) = + New(TypeTree(tpe), + List(for (pt <- tpe.typeSymbol.primaryConstructor.info.paramTypes) + yield This(accessor.owner.enclClass))) // def m: T; def mkModuleAccessDcl(accessor: Symbol) = diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index 0b801fca89..c735c953bf 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -611,6 +611,18 @@ trait Symbols { def getAttributes(clazz: Symbol): List[AnnotationInfo] = attributes.filter(_.atp.typeSymbol.isNonBottomSubClass(clazz)) + /** The least proper supertype of a class; includes all parent types + * and refinement where needed */ + def classBound: Type = { + val tp = refinedType(info.parents, owner) + val thistp = tp.typeSymbol.thisType + for (sym <- info.decls.toList) { + if (sym.isPublic && !sym.isClass && !sym.isConstructor) + addMember(thistp, tp, sym.cloneSymbol(tp.typeSymbol).setInfo(sym.info)) + } + tp + } + /** Reset symbol to initial state */ def reset(completer: Type) { diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 7289468406..9803294ae9 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -630,7 +630,7 @@ abstract class Mixin extends InfoTransform { // add modules val vdef = gen.mkModuleVarDef(sym) addDef(position(sym), vdef) - addDef(position(sym), gen.mkModuleAccessDef(sym, vdef.symbol)) + addDef(position(sym), gen.mkCachedModuleAccessDef(sym, vdef.symbol)) } else if (!sym.isMethod) { // add fields addDef(position(sym), ValDef(sym)) diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index fb10d2b1b2..ffecaf5a39 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -598,8 +598,23 @@ abstract class RefChecks extends InfoTransform { .setPos(tree.pos) .setSymbol(sym.moduleClass) .setType(NoType); - if (sym.isStatic) List(transform(cdef)) - else { + if (sym.isStatic) { + if (!sym.allOverriddenSymbols.isEmpty) { + val factory = sym.owner.newMethod(sym.pos, sym.name) + .setFlag(sym.flags | STABLE).resetFlag(MODULE) + .setInfo(PolyType(List(), sym.moduleClass.tpe)) + sym.owner.info.decls.enter(factory) + val ddef = + atPhase(phase.next) { + localTyper.typed { + gen.mkModuleAccessDef(factory, sym.tpe) + } + } + transformTrees(List(cdef, ddef)) + } else { + List(transform(cdef)) + } + } else { val vdef = localTyper.typed { atPos(tree.pos) { @@ -611,7 +626,7 @@ abstract class RefChecks extends InfoTransform { atPhase(phase.next) { localTyper.typed { if (sym.owner.isTrait) gen.mkModuleAccessDcl(sym) - else gen.mkModuleAccessDef(sym, vdef.symbol) + else gen.mkCachedModuleAccessDef(sym, vdef.symbol) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index ab07c52a07..ef56d827c4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -358,7 +358,7 @@ trait Typers { self: Analyzer => else if (hiddenSymbols exists (_.isErroneous)) setError(tree) else if (isFullyDefined(pt)) tree setType pt //todo: eliminate else if (tp1.typeSymbol.isAnonymousClass) // todo: eliminate - check(owner, scope, pt, tree setType classBound(tp1.typeSymbol)) + check(owner, scope, pt, tree setType tp1.typeSymbol.classBound) else if (owner == NoSymbol) tree setType packSymbols(hiddenSymbols.reverse, tp1) else { // privates @@ -1331,16 +1331,6 @@ trait Typers { self: Analyzer => copy.LabelDef(ldef, ldef.name, ldef.params, rhs1) setType restpe } - def classBound(clazz: Symbol): Type = { - val tp = refinedType(clazz.info.parents, clazz.owner) - val thistp = tp.typeSymbol.thisType - for (sym <- clazz.info.decls.toList) { - if (sym.isPublic && !sym.isClass && !sym.isConstructor) - addMember(thistp, tp, sym.cloneSymbol(tp.typeSymbol).setInfo(sym.info)) - } - tp - } - protected def typedFunctionIDE(fun : Function, txt : Context) = {} /** @@ -1857,8 +1847,7 @@ trait Typers { self: Analyzer => protected def existentialBound(sym: Symbol): Type = if (sym.isClass) - parameterizedType( - sym.typeParams, mkTypeBounds(AllClass.tpe, classBound(sym))) + parameterizedType(sym.typeParams, mkTypeBounds(AllClass.tpe, sym.classBound)) else if (sym.isAbstractType) sym.info else if (sym.isTerm) |