Skip to content

Commit

Permalink
Changes many calls to normalize to dealiasWiden.
Browse files Browse the repository at this point in the history
Calling normalize is very aggressive and is usually the wrong
thing. It is one of the leading contributors to non-determinism
in compiler outcomes (often of the form "I gave a debugging or
logging compiler option and it started/stopped working") and
should be used only in very specific circumstances.

Almost without exception, dealiasWiden is what you want; not
widen, not normalize. If possible I will remove normalize from
Type entirely, making it private to those areas of the compiler
which actually require it.
  • Loading branch information
paulp committed Jan 29, 2013
1 parent 0388a7c commit 039b1cb
Show file tree
Hide file tree
Showing 20 changed files with 53 additions and 53 deletions.
2 changes: 1 addition & 1 deletion src/compiler/scala/reflect/reify/package.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ package object reify {
if (concrete) throw new ReificationException(enclosingMacroPosition, "tpe %s is an unresolved spliceable type".format(tpe)) if (concrete) throw new ReificationException(enclosingMacroPosition, "tpe %s is an unresolved spliceable type".format(tpe))
} }


tpe.normalize match { tpe.dealiasWiden match {
case TypeRef(_, ArrayClass, componentTpe :: Nil) => case TypeRef(_, ArrayClass, componentTpe :: Nil) =>
val componentErasure = reifyRuntimeClass(global)(typer0, componentTpe, concrete) val componentErasure = reifyRuntimeClass(global)(typer0, componentTpe, concrete)
gen.mkMethodCall(arrayClassMethod, List(componentErasure)) gen.mkMethodCall(arrayClassMethod, List(componentErasure))
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -368,10 +368,10 @@ trait TypeKinds { self: ICodes =>


/** Return the TypeKind of the given type /** Return the TypeKind of the given type
* *
* Call to .normalize fixes #3003 (follow type aliases). Otherwise, * Call to dealiasWiden fixes #3003 (follow type aliases). Otherwise,
* arrayOrClassType below would return ObjectReference. * arrayOrClassType below would return ObjectReference.
*/ */
def toTypeKind(t: Type): TypeKind = t.normalize match { def toTypeKind(t: Type): TypeKind = t.dealiasWiden match {
case ThisType(ArrayClass) => ObjectReference case ThisType(ArrayClass) => ObjectReference
case ThisType(sym) => REFERENCE(sym) case ThisType(sym) => REFERENCE(sym)
case SingleType(_, sym) => primitiveOrRefType(sym) case SingleType(_, sym) => primitiveOrRefType(sym)
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/nsc/dependencies/Changes.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -90,11 +90,11 @@ abstract class Changes {
} else } else
!sym1.isTypeParameter || !changedTypeParams.contains(sym1.fullName) !sym1.isTypeParameter || !changedTypeParams.contains(sym1.fullName)


// @M! normalize reduces higher-kinded case to PolyType's
testSymbols && sameType(pre1, pre2) && testSymbols && sameType(pre1, pre2) &&
(sym1.variance == sym2.variance) && (sym1.variance == sym2.variance) &&
((tp1.isHigherKinded && tp2.isHigherKinded && tp1.normalize =:= tp2.normalize) || ((tp1.isHigherKinded && tp2.isHigherKinded && tp1.normalize =:= tp2.normalize) ||
sameTypes(args1, args2)) sameTypes(args1, args2))
// @M! normalize reduces higher-kinded case to PolyType's


case (RefinedType(parents1, ref1), RefinedType(parents2, ref2)) => case (RefinedType(parents1, ref1), RefinedType(parents2, ref2)) =>
def isSubScope(s1: Scope, s2: Scope): Boolean = s2.toList.forall { def isSubScope(s1: Scope, s2: Scope): Boolean = s2.toList.forall {
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ trait CompletionOutput {
} }


def methodString() = def methodString() =
method.keyString + " " + method.nameString + (method.info.normalize match { method.keyString + " " + method.nameString + (method.info.dealiasWiden match {
case NullaryMethodType(resType) => ": " + typeToString(resType) case NullaryMethodType(resType) => ": " + typeToString(resType)
case PolyType(tparams, resType) => tparamsString(tparams) + typeToString(resType) case PolyType(tparams, resType) => tparamsString(tparams) + typeToString(resType)
case mt @ MethodType(_, _) => methodTypeToString(mt) case mt @ MethodType(_, _) => methodTypeToString(mt)
Expand Down
10 changes: 5 additions & 5 deletions src/compiler/scala/tools/nsc/transform/Erasure.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ abstract class Erasure extends AddInterfaces
* unboxing some primitive types and further simplifications as they are done in jsig. * unboxing some primitive types and further simplifications as they are done in jsig.
*/ */
val prepareSigMap = new TypeMap { val prepareSigMap = new TypeMap {
def squashBoxed(tp: Type): Type = tp.normalize match { def squashBoxed(tp: Type): Type = tp.dealiasWiden match {
case t @ RefinedType(parents, decls) => case t @ RefinedType(parents, decls) =>
val parents1 = parents mapConserve squashBoxed val parents1 = parents mapConserve squashBoxed
if (parents1 eq parents) tp if (parents1 eq parents) tp
Expand All @@ -114,7 +114,7 @@ abstract class Erasure extends AddInterfaces
if (boxedClass contains t.typeSymbol) ObjectClass.tpe if (boxedClass contains t.typeSymbol) ObjectClass.tpe
else tp else tp
} }
def apply(tp: Type): Type = tp.normalize match { def apply(tp: Type): Type = tp.dealiasWiden match {
case tp1 @ TypeBounds(lo, hi) => case tp1 @ TypeBounds(lo, hi) =>
val lo1 = squashBoxed(apply(lo)) val lo1 = squashBoxed(apply(lo))
val hi1 = squashBoxed(apply(hi)) val hi1 = squashBoxed(apply(hi))
Expand Down Expand Up @@ -145,7 +145,7 @@ abstract class Erasure extends AddInterfaces
} }
case tp1 @ MethodType(params, restpe) => case tp1 @ MethodType(params, restpe) =>
val params1 = mapOver(params) val params1 = mapOver(params)
val restpe1 = if (restpe.normalize.typeSymbol == UnitClass) UnitClass.tpe else apply(restpe) val restpe1 = if (restpe.typeSymbol == UnitClass) UnitClass.tpe else apply(restpe)
if ((params1 eq params) && (restpe1 eq restpe)) tp1 if ((params1 eq params) && (restpe1 eq restpe)) tp1
else MethodType(params1, restpe1) else MethodType(params1, restpe1)
case tp1 @ RefinedType(parents, decls) => case tp1 @ RefinedType(parents, decls) =>
Expand All @@ -163,8 +163,8 @@ abstract class Erasure extends AddInterfaces
} }
} }


private def hiBounds(bounds: TypeBounds): List[Type] = bounds.hi.normalize match { private def hiBounds(bounds: TypeBounds): List[Type] = bounds.hi.dealiasWiden match {
case RefinedType(parents, _) => parents map (_.normalize) case RefinedType(parents, _) => parents map (_.dealiasWiden)
case tp => tp :: Nil case tp => tp :: Nil
} }


Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
def specializedTypeVars(tpe: Type): immutable.Set[Symbol] = tpe match { def specializedTypeVars(tpe: Type): immutable.Set[Symbol] = tpe match {
case TypeRef(pre, sym, args) => case TypeRef(pre, sym, args) =>
if (sym.isAliasType) if (sym.isAliasType)
specializedTypeVars(tpe.normalize) specializedTypeVars(tpe.dealiasWiden)
else if (sym.isTypeParameter && sym.isSpecialized || (sym.isTypeSkolem && sym.deSkolemize.isSpecialized)) else if (sym.isTypeParameter && sym.isSpecialized || (sym.isTypeSkolem && sym.deSkolemize.isSpecialized))
Set(sym) Set(sym)
else if (sym == ArrayClass) else if (sym == ArrayClass)
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ trait ContextErrors {
// members present, then display along with the expected members. This is done here because // members present, then display along with the expected members. This is done here because
// this is the last point where we still have access to the original tree, rather than just // this is the last point where we still have access to the original tree, rather than just
// the found/req types. // the found/req types.
val foundType: Type = req.normalize match { val foundType: Type = req.dealiasWiden match {
case RefinedType(parents, decls) if !decls.isEmpty && found.typeSymbol.isAnonOrRefinementClass => case RefinedType(parents, decls) if !decls.isEmpty && found.typeSymbol.isAnonOrRefinementClass =>
val retyped = typed (tree.duplicate.clearType()) val retyped = typed (tree.duplicate.clearType())
val foundDecls = retyped.tpe.decls filter (sym => !sym.isConstructor && !sym.isSynthetic) val foundDecls = retyped.tpe.decls filter (sym => !sym.isConstructor && !sym.isSynthetic)
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/scala/tools/nsc/typechecker/Implicits.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ trait Implicits {
* if one or both are intersection types with a pair of overlapping parent types. * if one or both are intersection types with a pair of overlapping parent types.
*/ */
private def dominates(dtor: Type, dted: Type): Boolean = { private def dominates(dtor: Type, dted: Type): Boolean = {
def core(tp: Type): Type = tp.normalize match { def core(tp: Type): Type = tp.dealiasWiden match {
case RefinedType(parents, defs) => intersectionType(parents map core, tp.typeSymbol.owner) case RefinedType(parents, defs) => intersectionType(parents map core, tp.typeSymbol.owner)
case AnnotatedType(annots, tp, selfsym) => core(tp) case AnnotatedType(annots, tp, selfsym) => core(tp)
case ExistentialType(tparams, result) => core(result).subst(tparams, tparams map (t => core(t.info.bounds.hi))) case ExistentialType(tparams, result) => core(result).subst(tparams, tparams map (t => core(t.info.bounds.hi)))
Expand All @@ -362,11 +362,11 @@ trait Implicits {
deriveTypeWithWildcards(syms.distinct)(tp) deriveTypeWithWildcards(syms.distinct)(tp)
} }
def sum(xs: List[Int]) = (0 /: xs)(_ + _) def sum(xs: List[Int]) = (0 /: xs)(_ + _)
def complexity(tp: Type): Int = tp.normalize match { def complexity(tp: Type): Int = tp.dealiasWiden match {
case NoPrefix => case NoPrefix =>
0 0
case SingleType(pre, sym) => case SingleType(pre, sym) =>
if (sym.isPackage) 0 else complexity(tp.normalize.widen) if (sym.isPackage) 0 else complexity(tp.dealiasWiden)
case TypeRef(pre, sym, args) => case TypeRef(pre, sym, args) =>
complexity(pre) + sum(args map complexity) + 1 complexity(pre) + sum(args map complexity) + 1
case RefinedType(parents, _) => case RefinedType(parents, _) =>
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
**/ **/
// must treat Typed and Bind together -- we need to know the patBinder of the Bind pattern to get at the actual type // must treat Typed and Bind together -- we need to know the patBinder of the Bind pattern to get at the actual type
case MaybeBoundTyped(subPatBinder, pt) => case MaybeBoundTyped(subPatBinder, pt) =>
val next = glb(List(patBinder.info.widen, pt)).normalize val next = glb(List(patBinder.info.dealiasWiden, pt)).normalize
// a typed pattern never has any subtrees // a typed pattern never has any subtrees
noFurtherSubPats(TypeTestTreeMaker(subPatBinder, patBinder, pt, next)(pos)) noFurtherSubPats(TypeTestTreeMaker(subPatBinder, patBinder, pt, next)(pos))


Expand Down
12 changes: 6 additions & 6 deletions src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
if (sym.hasAccessBoundary) "" + sym.privateWithin.name else "" if (sym.hasAccessBoundary) "" + sym.privateWithin.name else ""
) )


def overridesTypeInPrefix(tp1: Type, tp2: Type, prefix: Type): Boolean = (tp1.normalize, tp2.normalize) match { def overridesTypeInPrefix(tp1: Type, tp2: Type, prefix: Type): Boolean = (tp1.dealiasWiden, tp2.dealiasWiden) match {
case (MethodType(List(), rtp1), NullaryMethodType(rtp2)) => case (MethodType(List(), rtp1), NullaryMethodType(rtp2)) =>
rtp1 <:< rtp2 rtp1 <:< rtp2
case (NullaryMethodType(rtp1), MethodType(List(), rtp2)) => case (NullaryMethodType(rtp1), MethodType(List(), rtp2)) =>
Expand Down Expand Up @@ -472,12 +472,12 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
// check a type alias's RHS corresponds to its declaration // check a type alias's RHS corresponds to its declaration
// this overlaps somewhat with validateVariance // this overlaps somewhat with validateVariance
if(member.isAliasType) { if(member.isAliasType) {
// println("checkKindBounds" + ((List(member), List(memberTp.normalize), self, member.owner))) // println("checkKindBounds" + ((List(member), List(memberTp.dealiasWiden), self, member.owner)))
val kindErrors = typer.infer.checkKindBounds(List(member), List(memberTp.normalize), self, member.owner) val kindErrors = typer.infer.checkKindBounds(List(member), List(memberTp.dealiasWiden), self, member.owner)


if(!kindErrors.isEmpty) if(!kindErrors.isEmpty)
unit.error(member.pos, unit.error(member.pos,
"The kind of the right-hand side "+memberTp.normalize+" of "+member.keyString+" "+ "The kind of the right-hand side "+memberTp.dealiasWiden+" of "+member.keyString+" "+
member.varianceString + member.nameString+ " does not conform to its expected kind."+ member.varianceString + member.nameString+ " does not conform to its expected kind."+
kindErrors.toList.mkString("\n", ", ", "")) kindErrors.toList.mkString("\n", ", ", ""))
} else if (member.isAbstractType) { } else if (member.isAbstractType) {
Expand All @@ -496,7 +496,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
if (member.isStable && !otherTp.isVolatile) { if (member.isStable && !otherTp.isVolatile) {
if (memberTp.isVolatile) if (memberTp.isVolatile)
overrideError("has a volatile type; cannot override a member with non-volatile type") overrideError("has a volatile type; cannot override a member with non-volatile type")
else memberTp.normalize.resultType match { else memberTp.dealiasWiden.resultType match {
case rt: RefinedType if !(rt =:= otherTp) && !(checkedCombinations contains rt.parents) => case rt: RefinedType if !(rt =:= otherTp) && !(checkedCombinations contains rt.parents) =>
// might mask some inconsistencies -- check overrides // might mask some inconsistencies -- check overrides
checkedCombinations += rt.parents checkedCombinations += rt.parents
Expand Down Expand Up @@ -1298,7 +1298,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
// if the unnormalized type is accessible, that's good enough // if the unnormalized type is accessible, that's good enough
if (inaccessible.isEmpty) () if (inaccessible.isEmpty) ()
// or if the normalized type is, that's good too // or if the normalized type is, that's good too
else if ((tpe ne tpe.normalize) && lessAccessibleSymsInType(tpe.normalize, member).isEmpty) () else if ((tpe ne tpe.normalize) && lessAccessibleSymsInType(tpe.dealiasWiden, member).isEmpty) ()
// otherwise warn about the inaccessible syms in the unnormalized type // otherwise warn about the inaccessible syms in the unnormalized type
else inaccessible foreach (sym => warnLessAccessible(sym, member)) else inaccessible foreach (sym => warnLessAccessible(sym, member))
} }
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ trait TypeDiagnostics {
// force measures than comparing normalized Strings were producing error messages // force measures than comparing normalized Strings were producing error messages
// like "and java.util.ArrayList[String] <: java.util.ArrayList[String]" but there // like "and java.util.ArrayList[String] <: java.util.ArrayList[String]" but there
// should be a cleaner way to do this. // should be a cleaner way to do this.
if (found.normalize.toString == tp.normalize.toString) "" if (found.dealiasWiden.toString == tp.dealiasWiden.toString) ""
else " (and %s <: %s)".format(found, tp) else " (and %s <: %s)".format(found, tp)
) )
val explainDef = { val explainDef = {
Expand Down
14 changes: 7 additions & 7 deletions src/compiler/scala/tools/nsc/typechecker/Typers.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2437,7 +2437,7 @@ trait Typers extends Adaptations with Tags {
// but not in real life (i.e., now that's we've reset the method's type skolems' // but not in real life (i.e., now that's we've reset the method's type skolems'
// infos back to their pre-GADT-constraint state) // infos back to their pre-GADT-constraint state)
if (isFullyDefined(pt) && !(body1.tpe <:< pt)) if (isFullyDefined(pt) && !(body1.tpe <:< pt))
body1 = typedPos(body1.pos)(gen.mkCast(body1, pt.normalize)) body1 = typedPos(body1.pos)(gen.mkCast(body1, pt.dealiasWiden))


} }


Expand Down Expand Up @@ -2507,7 +2507,7 @@ trait Typers extends Adaptations with Tags {
*/ */
def synthesizePartialFunction(paramName: TermName, paramPos: Position, tree: Tree, mode: Mode, pt: Type): Tree = { def synthesizePartialFunction(paramName: TermName, paramPos: Position, tree: Tree, mode: Mode, pt: Type): Tree = {
assert(pt.typeSymbol == PartialFunctionClass, s"PartialFunction synthesis for match in $tree requires PartialFunction expected type, but got $pt.") assert(pt.typeSymbol == PartialFunctionClass, s"PartialFunction synthesis for match in $tree requires PartialFunction expected type, but got $pt.")
val targs = pt.normalize.typeArgs val targs = pt.dealiasWiden.typeArgs


// if targs.head isn't fully defined, we can translate --> error // if targs.head isn't fully defined, we can translate --> error
targs match { targs match {
Expand Down Expand Up @@ -2665,10 +2665,10 @@ trait Typers extends Adaptations with Tags {


def decompose(pt: Type): (Symbol, List[Type], Type) = def decompose(pt: Type): (Symbol, List[Type], Type) =
if ((isFunctionType(pt) || (pt.typeSymbol == PartialFunctionClass && numVparams == 1 && fun.body.isInstanceOf[Match])) && // see bug901 for a reason why next conditions are needed if ((isFunctionType(pt) || (pt.typeSymbol == PartialFunctionClass && numVparams == 1 && fun.body.isInstanceOf[Match])) && // see bug901 for a reason why next conditions are needed
( pt.normalize.typeArgs.length - 1 == numVparams ( pt.dealiasWiden.typeArgs.length - 1 == numVparams
|| fun.vparams.exists(_.tpt.isEmpty) || fun.vparams.exists(_.tpt.isEmpty)
)) ))
(pt.typeSymbol, pt.normalize.typeArgs.init, pt.normalize.typeArgs.last) (pt.typeSymbol, pt.dealiasWiden.typeArgs.init, pt.dealiasWiden.typeArgs.last)
else else
(FunctionClass(numVparams), fun.vparams map (x => NoType), WildcardType) (FunctionClass(numVparams), fun.vparams map (x => NoType), WildcardType)


Expand Down Expand Up @@ -3316,7 +3316,7 @@ trait Typers extends Adaptations with Tags {


if (fun1.tpe.isErroneous) duplErrTree if (fun1.tpe.isErroneous) duplErrTree
else { else {
val resTp = fun1.tpe.finalResultType.normalize val resTp = fun1.tpe.finalResultType.dealiasWiden
val nbSubPats = args.length val nbSubPats = args.length


val (formals, formalsExpanded) = extractorFormalTypes(fun0.pos, resTp, nbSubPats, fun1.symbol) val (formals, formalsExpanded) = extractorFormalTypes(fun0.pos, resTp, nbSubPats, fun1.symbol)
Expand Down Expand Up @@ -3364,7 +3364,7 @@ trait Typers extends Adaptations with Tags {
def extractorForUncheckedType(pos: Position, pt: Type): Option[Tree] = if (isPastTyper) None else { def extractorForUncheckedType(pos: Position, pt: Type): Option[Tree] = if (isPastTyper) None else {
// only look at top-level type, can't (reliably) do anything about unchecked type args (in general) // only look at top-level type, can't (reliably) do anything about unchecked type args (in general)
// but at least make a proper type before passing it elsewhere // but at least make a proper type before passing it elsewhere
val pt1 = pt.dealias match { val pt1 = pt.dealiasWiden match {
case tr @ TypeRef(pre, sym, args) if args.nonEmpty => copyTypeRef(tr, pre, sym, sym.typeParams map (_.tpeHK)) // replace actual type args with dummies case tr @ TypeRef(pre, sym, args) if args.nonEmpty => copyTypeRef(tr, pre, sym, sym.typeParams map (_.tpeHK)) // replace actual type args with dummies
case pt1 => pt1 case pt1 => pt1
} }
Expand Down Expand Up @@ -4209,7 +4209,7 @@ trait Typers extends Adaptations with Tags {
if (newPatternMatching && (pt.typeSymbol == PartialFunctionClass)) if (newPatternMatching && (pt.typeSymbol == PartialFunctionClass))
synthesizePartialFunction(newTermName(context.unit.fresh.newName("x")), tree.pos, tree, mode, pt) synthesizePartialFunction(newTermName(context.unit.fresh.newName("x")), tree.pos, tree, mode, pt)
else { else {
val arity = if (isFunctionType(pt)) pt.normalize.typeArgs.length - 1 else 1 val arity = if (isFunctionType(pt)) pt.dealiasWiden.typeArgs.length - 1 else 1
val params = for (i <- List.range(0, arity)) yield val params = for (i <- List.range(0, arity)) yield
atPos(tree.pos.focusStart) { atPos(tree.pos.focusStart) {
ValDef(Modifiers(PARAM | SYNTHETIC), ValDef(Modifiers(PARAM | SYNTHETIC),
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ trait CPSUtils {
// annotation checker // annotation checker


protected def annTypes(ann: AnnotationInfo): (Type, Type) = { protected def annTypes(ann: AnnotationInfo): (Type, Type) = {
val tp0 :: tp1 :: Nil = ann.atp.normalize.typeArgs val tp0 :: tp1 :: Nil = ann.atp.dealiasWiden.typeArgs
((tp0, tp1)) ((tp0, tp1))
} }
protected def hasMinusMarker(tpe: Type) = tpe hasAnnotation MarkerCPSAdaptMinus protected def hasMinusMarker(tpe: Type) = tpe hasAnnotation MarkerCPSAdaptMinus
Expand Down
10 changes: 5 additions & 5 deletions src/reflect/scala/reflect/internal/Definitions.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ trait Definitions extends api.StandardDefinitions {
len <= MaxTupleArity && sym == TupleClass(len) len <= MaxTupleArity && sym == TupleClass(len)
case _ => false case _ => false
} }
def isTupleType(tp: Type) = isTupleTypeDirect(tp.normalize) def isTupleType(tp: Type) = isTupleTypeDirect(tp.dealiasWiden)


lazy val ProductRootClass: ClassSymbol = requiredClass[scala.Product] lazy val ProductRootClass: ClassSymbol = requiredClass[scala.Product]
def Product_productArity = getMemberMethod(ProductRootClass, nme.productArity) def Product_productArity = getMemberMethod(ProductRootClass, nme.productArity)
Expand All @@ -648,16 +648,16 @@ trait Definitions extends api.StandardDefinitions {
case _ => tp case _ => tp
} }


def unapplyUnwrap(tpe:Type) = tpe.finalResultType.normalize match { def unapplyUnwrap(tpe:Type) = tpe.finalResultType.dealiasWiden match {
case RefinedType(p :: _, _) => p.normalize case RefinedType(p :: _, _) => p.dealiasWiden
case tp => tp case tp => tp
} }


def abstractFunctionForFunctionType(tp: Type) = def abstractFunctionForFunctionType(tp: Type) =
if (isFunctionType(tp)) abstractFunctionType(tp.typeArgs.init, tp.typeArgs.last) if (isFunctionType(tp)) abstractFunctionType(tp.typeArgs.init, tp.typeArgs.last)
else NoType else NoType


def isFunctionType(tp: Type): Boolean = tp.normalize match { def isFunctionType(tp: Type): Boolean = tp.dealiasWiden match {
case TypeRef(_, sym, args) if args.nonEmpty => case TypeRef(_, sym, args) if args.nonEmpty =>
val arity = args.length - 1 // -1 is the return type val arity = args.length - 1 // -1 is the return type
arity <= MaxFunctionArity && sym == FunctionClass(arity) arity <= MaxFunctionArity && sym == FunctionClass(arity)
Expand Down Expand Up @@ -1145,7 +1145,7 @@ trait Definitions extends api.StandardDefinitions {
else if (sym.isTopLevel) sym.javaClassName else if (sym.isTopLevel) sym.javaClassName
else flatNameString(sym.owner, separator) + nme.NAME_JOIN_STRING + sym.simpleName else flatNameString(sym.owner, separator) + nme.NAME_JOIN_STRING + sym.simpleName
def signature1(etp: Type): String = { def signature1(etp: Type): String = {
if (etp.typeSymbol == ArrayClass) "[" + signature1(erasure(etp.normalize.typeArgs.head)) if (etp.typeSymbol == ArrayClass) "[" + signature1(erasure(etp.dealiasWiden.typeArgs.head))
else if (isPrimitiveValueClass(etp.typeSymbol)) abbrvTag(etp.typeSymbol).toString() else if (isPrimitiveValueClass(etp.typeSymbol)) abbrvTag(etp.typeSymbol).toString()
else "L" + flatNameString(etp.typeSymbol, '/') + ";" else "L" + flatNameString(etp.typeSymbol, '/') + ";"
} }
Expand Down
2 changes: 1 addition & 1 deletion src/reflect/scala/reflect/internal/Symbols.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -844,7 +844,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Is this class or type defined as a structural refinement type? /** Is this class or type defined as a structural refinement type?
*/ */
final def isStructuralRefinement: Boolean = final def isStructuralRefinement: Boolean =
(isClass || isType || isModule) && info.normalize/*.underlying*/.isStructuralRefinement (isClass || isType || isModule) && info.dealiasWiden/*.underlying*/.isStructuralRefinement


/** Is this a term symbol only defined in a refinement (so that it needs /** Is this a term symbol only defined in a refinement (so that it needs
* to be accessed by reflection)? * to be accessed by reflection)?
Expand Down
2 changes: 1 addition & 1 deletion src/reflect/scala/reflect/internal/TreeGen.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ abstract class TreeGen extends macros.TreeBuilder {
mkTypeApply(mkAttributedSelect(target, method), targs map TypeTree) mkTypeApply(mkAttributedSelect(target, method), targs map TypeTree)


private def mkSingleTypeApply(value: Tree, tpe: Type, what: Symbol, wrapInApply: Boolean) = { private def mkSingleTypeApply(value: Tree, tpe: Type, what: Symbol, wrapInApply: Boolean) = {
val tapp = mkAttributedTypeApply(value, what, tpe.normalize :: Nil) val tapp = mkAttributedTypeApply(value, what, tpe.dealias :: Nil)
if (wrapInApply) Apply(tapp, Nil) else tapp if (wrapInApply) Apply(tapp, Nil) else tapp
} }
private def typeTestSymbol(any: Boolean) = if (any) Any_isInstanceOf else Object_isInstanceOf private def typeTestSymbol(any: Boolean) = if (any) Any_isInstanceOf else Object_isInstanceOf
Expand Down
2 changes: 1 addition & 1 deletion src/reflect/scala/reflect/internal/Types.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2456,7 +2456,7 @@ trait Types extends api.Types { self: SymbolTable =>
case RepeatedParamClass => args.head + "*" case RepeatedParamClass => args.head + "*"
case ByNameParamClass => "=> " + args.head case ByNameParamClass => "=> " + args.head
case _ => case _ =>
def targs = normalize.typeArgs def targs = dealiasWiden.typeArgs


if (isFunctionType(this)) { if (isFunctionType(this)) {
// Aesthetics: printing Function1 as T => R rather than (T) => R // Aesthetics: printing Function1 as T => R rather than (T) => R
Expand Down
6 changes: 3 additions & 3 deletions src/reflect/scala/reflect/internal/transform/Erasure.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ trait Erasure {
/** Is `tp` an unbounded generic type (i.e. which could be instantiated /** Is `tp` an unbounded generic type (i.e. which could be instantiated
* with primitive as well as class types)?. * with primitive as well as class types)?.
*/ */
private def genericCore(tp: Type): Type = tp.normalize match { private def genericCore(tp: Type): Type = tp.dealiasWiden match {
/* A Java Array<T> is erased to Array[Object] (T can only be a reference type), where as a Scala Array[T] is /* A Java Array<T> is erased to Array[Object] (T can only be a reference type), where as a Scala Array[T] is
* erased to Object. However, there is only symbol for the Array class. So to make the distinction between * erased to Object. However, there is only symbol for the Array class. So to make the distinction between
* a Java and a Scala array, we check if the owner of T comes from a Java class. * a Java and a Scala array, we check if the owner of T comes from a Java class.
Expand All @@ -36,7 +36,7 @@ trait Erasure {
* then Some((N, T)) where N is the number of Array constructors enclosing `T`, * then Some((N, T)) where N is the number of Array constructors enclosing `T`,
* otherwise None. Existentials on any level are ignored. * otherwise None. Existentials on any level are ignored.
*/ */
def unapply(tp: Type): Option[(Int, Type)] = tp.normalize match { def unapply(tp: Type): Option[(Int, Type)] = tp.dealiasWiden match {
case TypeRef(_, ArrayClass, List(arg)) => case TypeRef(_, ArrayClass, List(arg)) =>
genericCore(arg) match { genericCore(arg) match {
case NoType => case NoType =>
Expand Down Expand Up @@ -101,7 +101,7 @@ trait Erasure {
def valueClassIsParametric(clazz: Symbol): Boolean = { def valueClassIsParametric(clazz: Symbol): Boolean = {
assert(!phase.erasedTypes) assert(!phase.erasedTypes)
clazz.typeParams contains clazz.typeParams contains
clazz.derivedValueClassUnbox.tpe.resultType.normalize.typeSymbol clazz.derivedValueClassUnbox.tpe.resultType.typeSymbol
} }


abstract class ErasureMap extends TypeMap { abstract class ErasureMap extends TypeMap {
Expand Down
10 changes: 9 additions & 1 deletion src/reflect/scala/reflect/internal/transform/UnCurry.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ trait UnCurry {
import global._ import global._
import definitions._ import definitions._


/** Note: changing tp.normalize to tp.dealias in this method leads to a single
* test failure: run/t5688.scala, where instead of the expected output
* Vector(ta, tb, tab)
* we instead get
* Vector(tab, tb, tab)
* I think that difference is not the product of sentience but of randomness.
* Let us figure out why it is and then change this method.
*/
private def expandAlias(tp: Type): Type = if (!tp.isHigherKinded) tp.normalize else tp private def expandAlias(tp: Type): Type = if (!tp.isHigherKinded) tp.normalize else tp


val uncurry: TypeMap = new TypeMap { val uncurry: TypeMap = new TypeMap {
Expand Down Expand Up @@ -60,4 +68,4 @@ trait UnCurry {
*/ */
def transformInfo(sym: Symbol, tp: Type): Type = def transformInfo(sym: Symbol, tp: Type): Type =
if (sym.isType) uncurryType(tp) else uncurry(tp) if (sym.isType) uncurryType(tp) else uncurry(tp)
} }
Loading

0 comments on commit 039b1cb

Please sign in to comment.