diff options
author | Martin Odersky <odersky@gmail.com> | 2006-10-30 17:29:19 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2006-10-30 17:29:19 +0000 |
commit | 7ebc41cda22ee26d4242e305782a14f7e6bf63aa (patch) | |
tree | 2ead03fe1fae2466677cdcddcbb5ac2e7c4778ed /src | |
parent | 640ecf38b7125ff0d2c926a9a634593640cd95b1 (diff) | |
download | scala-7ebc41cda22ee26d4242e305782a14f7e6bf63aa.tar.gz scala-7ebc41cda22ee26d4242e305782a14f7e6bf63aa.tar.bz2 scala-7ebc41cda22ee26d4242e305782a14f7e6bf63aa.zip |
fixed bugs 54, 415
Improved avoidance of MalformedType's
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Types.scala | 69 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 11 |
2 files changed, 53 insertions, 27 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index ef8796b3f8..d0ee84fd58 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -1107,18 +1107,26 @@ trait Types requires SymbolTable { if (phase.erasedTypes) sym.tpe else unique(new ThisType(sym) with UniqueType) /** The canonical creator for single-types */ - def singleType(pre: Type, sym: Symbol): Type = { + def singleType(pre: Type, sym: Symbol): Type = singleType(pre, sym, 0) + + /** The canonical creator for single-types, + * with possibility of approximating in case of malformed types */ + def singleType(pre: Type, sym: Symbol, variance: int): Type = { if (phase.erasedTypes) sym.tpe.resultType - else if (checkMalformedSwitch && !pre.isStable && !pre.isError) - throw new MalformedType(pre, sym.name.toString()) else if (sym.isRootPackage) ThisType(RootClass) else { var sym1 = rebind(pre, sym) val pre1 = removeSuper(pre, sym1) if (pre1 ne pre) sym1 = rebind(pre1, sym1) - unique(new SingleType(pre1, sym1) with UniqueType) + if (checkMalformedSwitch && !pre1.isStable && !pre1.isError) { + if (variance == 1) pre.memberType(sym).resultType + else if (variance == -1) AllClass.tpe + else throw new MalformedType(pre, sym.nameString) + } else { + unique(new SingleType(pre1, sym1) with UniqueType) + } } } @@ -1173,17 +1181,14 @@ trait Types requires SymbolTable { def ConstantType(value: Constant): ConstantType = unique(new ConstantType(value) with UniqueType) - /** The canonical creator for typerefs. - * - * @param pre ... - * @param sym ... - * @param args ... - * @return ... - */ - def typeRef(pre: Type, sym: Symbol, args: List[Type]): Type = { + + /** The canonical creator for typerefs. */ + def typeRef(pre: Type, sym: Symbol, args: List[Type]): Type = typeRef(pre, sym, args, 0) + + /** The canonical creator for typerefs, + * with possibility of approximating in case of malformed types */ + def typeRef(pre: Type, sym: Symbol, args: List[Type], variance: int): Type = { var sym1 = if (sym.isAbstractType) rebind(pre, sym) else sym - if (checkMalformedSwitch && sym1.isAbstractType && !pre.isStable && !pre.isError) - throw new MalformedType(pre, sym.nameString) if (sym1.isAliasType && sym1.info.typeParams.length == args.length) { // note: we require that object is initialized, // that's why we use info.typeParams instead of typeParams. @@ -1197,7 +1202,13 @@ trait Types requires SymbolTable { val pre1 = removeSuper(pre, sym1) if (pre1 ne pre) { if (sym1.isAbstractType) sym1 = rebind(pre1, sym1) - typeRef(pre1, sym1, args) + typeRef(pre1, sym1, args, variance) + } else if (checkMalformedSwitch && sym1.isAbstractType && !pre.isStable && !pre.isError) { + def transform(tp: Type): Type = + tp.asSeenFrom(pre, sym1.owner).subst(sym1.typeParams, args) + if (variance == 1 && !(sym1.info.bounds.hi contains sym1)) transform(sym1.info.bounds.hi) + else if (variance == -1 && !(sym1.info.bounds.lo contains sym1)) transform(sym1.info.bounds.lo) + else throw new MalformedType(pre, sym1.nameString) } else { rawTypeRef(pre, sym1, args) } @@ -1321,7 +1332,7 @@ trait Types requires SymbolTable { val pre1 = this(pre) variance = v if (pre1 eq pre) tp - else singleType(pre1, sym) + else singleType(pre1, sym, variance) } case SuperType(thistp, supertp) => val thistp1 = this(thistp) @@ -1338,7 +1349,7 @@ trait Types requires SymbolTable { else mapOverArgs(args, tparams) } if ((pre1 eq pre) && (args1 eq args)) tp - else typeRef(pre1, sym, args1) + else typeRef(pre1, sym, args1, variance) case TypeBounds(lo, hi) => variance = -variance val lo1 = this(lo) @@ -1435,6 +1446,12 @@ trait Types requires SymbolTable { /** A map to compute the asSeenFrom method */ class AsSeenFromMap(pre: Type, clazz: Symbol) extends TypeMap { + /** Return pre.baseType(clazz), or if that's NoType and clazz is a refinement, pre itself. + * See bug397.scala for an example where the second alternative is needed. + * The problem is that when forming the closure of an abstract type, + * any refinements in the base type list might be regenerated, and thus acquire + * new class symbols. However, since refinements always have non-interesting prefixes + * it looks OK to me to just take the prefix directly. */ def base(pre: Type, clazz: Symbol) = { val b = pre.baseType(clazz) if (b == NoType && clazz.isRefinementClass) pre @@ -1522,8 +1539,8 @@ trait Types requires SymbolTable { class SubstSymMap(from: List[Symbol], to: List[Symbol]) extends SubstMap(from, to) { protected def toType(fromtp: Type, sym: Symbol) = fromtp match { - case TypeRef(pre, _, args) => typeRef(pre, sym, args) - case SingleType(pre, _) => singleType(pre, sym) + case TypeRef(pre, _, args) => typeRef(pre, sym, args, variance) + case SingleType(pre, _) => singleType(pre, sym, variance) } override def apply(tp: Type): Type = { def subst(sym: Symbol, from: List[Symbol], to: List[Symbol]): Symbol = @@ -1532,9 +1549,9 @@ trait Types requires SymbolTable { else subst(sym, from.tail, to.tail) tp match { case TypeRef(pre, sym, args) if !(pre eq NoPrefix) => - mapOver(typeRef(pre, subst(sym, from, to), args)) + mapOver(typeRef(pre, subst(sym, from, to), args, variance)) case SingleType(pre, sym) if !(pre eq NoPrefix) => - mapOver(singleType(pre, subst(sym, from, to))) + mapOver(singleType(pre, subst(sym, from, to), variance)) case _ => super.apply(tp) } @@ -1648,7 +1665,7 @@ trait Types requires SymbolTable { val rebind = rebind0.suchThat(sym => sym.isType || sym.isStable) if (rebind == NoSymbol) { if (settings.debug.value) Console.println("" + phase + " " + phase.flatClasses+sym.owner+sym.name) - throw new MalformedType(pre, sym.name.toString()) + throw new MalformedType(pre, sym.nameString) } rebind } @@ -1663,7 +1680,7 @@ trait Types requires SymbolTable { val pre1 = this(pre) val sym1 = adaptToNewRun(pre1, sym) if ((pre1 eq pre) && (sym1 eq sym)) tp - else singleType(pre1, sym1) + else singleType(pre1, sym1, variance) } case TypeRef(pre, sym, args) => if (sym.isPackageClass) tp @@ -1672,7 +1689,7 @@ trait Types requires SymbolTable { val args1 = List.mapConserve(args)(this) val sym1 = adaptToNewRun(pre1, sym) if ((pre1 eq pre) && (sym1 eq sym) && (args1 eq args)/* && sym.isExternal*/) tp - else typeRef(pre1, sym1, args1) + else typeRef(pre1, sym1, args1, variance) } case PolyType(tparams, restp) => val restp1 = this(restp) @@ -2347,7 +2364,7 @@ trait Types requires SymbolTable { else NoType)) try { if (args contains NoType) None - else Some(typeRef(pre, sym, args)) + else Some(typeRef(pre, sym, args, variance)) } catch { case ex: MalformedType => None } @@ -2355,7 +2372,7 @@ trait Types requires SymbolTable { val pres = tps map (.prefix) val pre = if (variance == 1) lub(pres) else glb(pres) try { - Some(singleType(pre, sym)) + Some(singleType(pre, sym, variance)) } catch { case ex: MalformedType => None } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index f8461e52ef..3e3193f964 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -186,6 +186,8 @@ trait Typers requires Analyzer { } if (context.retyping) context.error(pos, msg) else context.unit.error(pos, msg) + if (sym == ObjectClass) + throw new FatalError("cannot redefine root "+sym) case _ => context.error(pos, ex) } @@ -291,7 +293,14 @@ trait Typers requires Analyzer { if (badSymbol == NoSymbol) tree else if (badSymbol.isErroneous) setError(tree) else { - val tp1 = heal(tree.tpe) + val tp1 = try { + heal(tree.tpe) + } catch { + case ex: MalformedType => + tree.tpe + // revert to `tree.tpe', because the healing widening operation would introduce + // a malformed type + } if (tp1 eq tree.tpe) { error(tree.pos, (if (badSymbol hasFlag PRIVATE) "private " else "") + badSymbol + |