From 3324a7215c87c61791f3e4afb49bc63cf9c80f12 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 13 Apr 2012 15:46:40 -0700 Subject: Fine-tuning of isRepresentableWithWildcards and wildcard printing. --- src/compiler/scala/reflect/internal/Types.scala | 41 +++++++++++----------- .../scala/tools/nsc/typechecker/Typers.scala | 2 +- 2 files changed, 22 insertions(+), 21 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index c13a33a6fc..b3d425f0c5 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -2517,34 +2517,35 @@ trait Types extends api.Types { self: SymbolTable => override def skolemizeExistential(owner: Symbol, origin: AnyRef) = deriveType(quantified, tparam => (owner orElse tparam.owner).newExistentialSkolem(tparam, origin))(underlying) - private def wildcardArgsString(available: Set[Symbol], args: List[Type]): List[String] = args match { - case TypeRef(_, sym, _) :: args1 if (available contains sym) => - ("_"+sym.infoString(sym.info)) :: wildcardArgsString(available - sym, args1) - case arg :: args1 if !(quantified exists (arg contains _)) => - arg.toString :: wildcardArgsString(available, args1) - case _ => - List() + private def wildcardArgsString(qset: Set[Symbol], args: List[Type]): List[String] = args map { + case TypeRef(_, sym, _) if (qset contains sym) => + "_"+sym.infoString(sym.info) + case arg => + arg.toString } + /** An existential can only be printed with wildcards if: * - the underlying type is a typeref - * - where there is a 1-to-1 correspondence between underlying's typeargs and quantified - * - and none of the existential parameters is referenced from anywhere else in the type - * - and none of the existential parameters are singleton types - * - @param checkBounds if set returns false for situations like - * (S, T) forSome { type S; type T <: S } - * If not set returns true. The reason for this mode is to - * avoid cyclic reference errors when the method is called - * early (e.g. from Typers # checkExistentialsFeature) + * - every quantified variable appears at most once as a type argument and + * nowhere inside a type argument + * - no quantified type argument contains a quantified variable in its bound + * - the typeref's symbol is not itself quantified + * - the prefix is not quanitified */ - def isRepresentableWithWildcards(checkBounds: Boolean) = { + def isRepresentableWithWildcards = { val qset = quantified.toSet underlying match { - case TypeRef(_, sym, args) => - def isQuantified(tpe: Type) = tpe exists (t => quantified contains t.typeSymbol) + case TypeRef(pre, sym, args) => + def isQuantified(tpe: Type): Boolean = { + (tpe exists (t => qset contains t.typeSymbol)) || + tpe.typeSymbol.isRefinementClass && (tpe.parents exists isQuantified) + } val (wildcardArgs, otherArgs) = args partition (arg => qset contains arg.typeSymbol) wildcardArgs.distinct == wildcardArgs && !(otherArgs exists (arg => isQuantified(arg))) && - !(wildcardArgs exists (arg => isQuantified(arg.typeSymbol.info.bounds))) + !(wildcardArgs exists (arg => isQuantified(arg.typeSymbol.info.bounds))) && + !(qset contains sym) && + !isQuantified(pre) case _ => false } } @@ -2555,7 +2556,7 @@ trait Types extends api.Types { self: SymbolTable => if (settings.explaintypes.value) "(" + str + ")" else str } underlying match { - case TypeRef(pre, sym, args) if !settings.debug.value && isRepresentableWithWildcards(checkBounds = true) => + case TypeRef(pre, sym, args) if !settings.debug.value && isRepresentableWithWildcards => "" + TypeRef(pre, sym, Nil) + wildcardArgsString(quantified.toSet, args).mkString("[", ", ", "]") case MethodType(_, _) | NullaryMethodType(_) | PolyType(_, _) => "(" + underlying + ")" + clauses diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 1425cd4755..9431c6f5e5 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -761,7 +761,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } def checkExistentialsFeature(pos: Position, tpe: Type, prefix: String) = tpe match { - case extp: ExistentialType if !extp.isRepresentableWithWildcards(checkBounds = false) => + case extp: ExistentialType if !extp.isRepresentableWithWildcards => checkFeature(pos, ExistentialsFeature, prefix+" "+tpe) case _ => } -- cgit v1.2.3