Skip to content

refactor Type#normalize #200

@retronym

Description

@retronym

I think it would be easier to understand as follows:

  final def normalizeType(tp: Type): Type = {
    tp match {
      case tp: TypeRef =>
        def normalizeUncached = tp match {
          case tp: AliasTypeRef if tp.typeParamsMatchArgs => tp.betaReduce.normalize
          case tp: AliasTypeRef if !tp.isHigherKinded =>
            // if we are overriding a type alias in an erroneous way, don't just
            // return an ErrorType since that will result in useless error msg.
            // Instead let's try to recover from it and rely on refcheck reporting the correct error,
            // if that fails fallback to the old behaviour.
            val overriddenSym = tp.sym.nextOverriddenSymbol
            if (overriddenSym != NoSymbol) tp.pre.memberType(overriddenSym).normalize
            else ErrorType
          case _: RefinementTypeRef =>
            // I think this is okay, but see #1241 (r12414), #2208, and typedTypeConstructor in Typers
            // !!! JZ discards prefix
            tp.sym.info.normalize
          case _ if tp.isHigherKinded => tp.etaExpand
          case _ => tp
        }
        // arises when argument-dependent types are approximated (see def depoly in implicits)
        if (tp.pre eq WildcardType) WildcardType
        else if (phase.erasedTypes) normalizeUncached
        else {
          if (tp.normalized eq null)
            tp.normalized = normalizeUncached
          tp.normalized
        }

      case tp: RefinedType =>
        def normalizeUncached = {
          // TODO see comments around def intersectionType and def merge
          // SI-8575 The dealias is needed here to keep subtyping transitive, example in run/t8575b.scala
          def flatten(tps: List[Type]): List[Type] = {
            def dealiasRefinement(tp: Type) = if (tp.dealias.isInstanceOf[RefinedType]) tp.dealias else tp
            tps map dealiasRefinement flatMap {
              case RefinedType(parents, ds) if ds.isEmpty => flatten(parents)
              case tp => List(tp)
            }
          }
          val flattened = flatten(tp.parents).distinct
          if (tp.decls.isEmpty && hasLength(flattened, 1)) {
            flattened.head
          } else if (flattened != tp.parents) {
            refinedType(flattened, if (tp.typeSymbol eq NoSymbol) NoSymbol else tp.typeSymbol.owner, tp.decls, NoPosition)
          } else if (tp.isHigherKinded) {
            tp.etaExpand
          } else tp
        }

        if (phase.erasedTypes) normalizeUncached
        else {
          if (tp.normalized eq null) tp.normalized = normalizeUncached
          tp.normalized
        }
      case _ => tp
    }
  }

Deferring this task for now as it isn't critical for 2.12.0

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions