diff options
author | Adriaan Moors <adriaan.moors@epfl.ch> | 2010-09-14 12:37:50 +0000 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2010-09-14 12:37:50 +0000 |
commit | ce755fb08dbd3bdfe202d3ea52a8e599d846b4c1 (patch) | |
tree | 5f07ea16f293ec578aea6347dd9393fc0a85e17c | |
parent | c0f03d837c9af04f404e800ce6fbeb65d1eac38a (diff) | |
download | scala-ce755fb08dbd3bdfe202d3ea52a8e599d846b4c1.tar.gz scala-ce755fb08dbd3bdfe202d3ea52a8e599d846b4c1.tar.bz2 scala-ce755fb08dbd3bdfe202d3ea52a8e599d846b4c1.zip |
closes #3612.
given the definitions below (for full context, see test file), before,
O0 would work but O would not, now both are accepted:
{{{
object O0 extends C {}
object O extends C { self => }
}}}
review by odersky
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 60 | ||||
-rw-r--r-- | test/files/pos/t3612.scala | 6 |
2 files changed, 36 insertions, 30 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 8248c5c950..461ed8b2cc 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3206,44 +3206,44 @@ trait Typers { self: Analyzer => } def typedNew(tpt: Tree) = { - var tpt1 = typedTypeConstructor(tpt) - checkClassType(tpt1, false, true) - if (tpt1.hasSymbol && !tpt1.symbol.typeParams.isEmpty) { - context.undetparams = cloneSymbols(tpt1.symbol.typeParams) - tpt1 = TypeTree() - .setOriginal(tpt1) - .setType(appliedType(tpt1.tpe, context.undetparams map (_.tpe))) + val tpt1 = { + val tpt0 = typedTypeConstructor(tpt) + checkClassType(tpt0, false, true) + if (tpt0.hasSymbol && !tpt0.symbol.typeParams.isEmpty) { + context.undetparams = cloneSymbols(tpt0.symbol.typeParams) + TypeTree().setOriginal(tpt0) + .setType(appliedType(tpt0.tpe, context.undetparams map (_.tpe))) + } else tpt0 } /** If current tree <tree> appears in <val x(: T)? = <tree>> * return `tp with x.type' else return `tp'. */ - def narrowRhs(tp: Type) = { - var sym = context.tree.symbol - if (sym != null && sym != NoSymbol) - if (sym.owner.isClass) { - if (sym.getter(sym.owner) != NoSymbol) sym = sym.getter(sym.owner) - } else if (sym hasFlag LAZY) { - if (sym.lazyAccessor != NoSymbol) sym = sym.lazyAccessor - } + def narrowRhs(tp: Type) = { val sym = context.tree.symbol context.tree match { - case ValDef(mods, _, _, Apply(Select(`tree`, _), _)) if !(mods hasFlag MUTABLE) => - val pre = if (sym.owner.isClass) sym.owner.thisType else NoPrefix - intersectionType(List(tp, singleType(pre, sym))) - case _ => - tp - } - } - if (tpt1.tpe.typeSymbol.isAbstractType || (tpt1.tpe.typeSymbol hasFlag ABSTRACT)) - error(tree.pos, tpt1.tpe.typeSymbol + " is abstract; cannot be instantiated") - else if (tpt1.tpe.typeSymbol.initialize.thisSym != tpt1.tpe.typeSymbol && - !(narrowRhs(tpt1.tpe) <:< tpt1.tpe.typeOfThis) && - !phase.erasedTypes) { - error(tree.pos, tpt1.tpe.typeSymbol + + case ValDef(mods, _, _, Apply(Select(`tree`, _), _)) if !(mods hasFlag MUTABLE) && sym != null && sym != NoSymbol => + val sym1 = if (sym.owner.isClass && sym.getter(sym.owner) != NoSymbol) sym.getter(sym.owner) + else if ((sym hasFlag LAZY) && sym.lazyAccessor != NoSymbol) sym.lazyAccessor + else sym + val pre = if (sym1.owner.isClass) sym1.owner.thisType else NoPrefix + intersectionType(List(tp, singleType(pre, sym1))) + case _ => tp + }} + + val tp = tpt1.tpe + val sym = tp.typeSymbol + if (sym.isAbstractType || (sym hasFlag ABSTRACT)) + error(tree.pos, sym + " is abstract; cannot be instantiated") + else if (!( tp == sym.initialize.thisSym.tpe // when there's no explicit self type -- with (#3612) or without self variable + // sym.thisSym.tpe == tp.typeOfThis (except for objects) + || narrowRhs(tp) <:< tp.typeOfThis + || phase.erasedTypes + )) { + error(tree.pos, sym + " cannot be instantiated because it does not conform to its self-type "+ - tpt1.tpe.typeOfThis) + tp.typeOfThis) } - treeCopy.New(tree, tpt1).setType(tpt1.tpe) + treeCopy.New(tree, tpt1).setType(tp) } def typedEta(expr1: Tree): Tree = expr1.tpe match { diff --git a/test/files/pos/t3612.scala b/test/files/pos/t3612.scala new file mode 100644 index 0000000000..d3bcc373e3 --- /dev/null +++ b/test/files/pos/t3612.scala @@ -0,0 +1,6 @@ +trait C + +class Outer { + object O0 extends C {} + object O extends C { self => } +}
\ No newline at end of file |