Skip to content

Commit

Permalink
Simplify and fix avoid logic
Browse files Browse the repository at this point in the history
The previous formulation broke for named parameters.
Test case in flowops1.scala.
  • Loading branch information
odersky committed Mar 19, 2016
1 parent 3f231ab commit acd07c1
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 27 deletions.
8 changes: 0 additions & 8 deletions src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -841,14 +841,6 @@ object Types {
case _ => this
}

/** If this is a refinement type, the unrefined parent,
* else the type itself.
*/
final def unrefine(implicit ctx: Context): Type = stripTypeVar match {
case tp @ RefinedType(tycon, _) => tycon.unrefine
case _ => this
}

/** If this is a (possibly aliased, annotated, and/or parameterized) reference to
* a class, the class type ref, otherwise NoType.
* @param refinementOK If `true` we also skip non-parameter refinements.
Expand Down
29 changes: 10 additions & 19 deletions src/dotty/tools/dotc/typer/TypeAssigner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import core._
import ast._
import Scopes._, Contexts._, Constants._, Types._, Symbols._, Names._, Flags._, Decorators._
import ErrorReporting._, Annotations._, Denotations._, SymDenotations._, StdNames._, TypeErasure._
import TypeApplications.AppliedType
import util.Positions._
import config.Printers._
import ast.Trees._
Expand Down Expand Up @@ -93,27 +94,17 @@ trait TypeAssigner {
case _ =>
mapOver(tp)
}
case tp @ AppliedType(tycon, args) if toAvoid(tycon) =>
val base = apply(tycon)
apply(base.appliedTo(tp.baseArgInfos(base.typeSymbol)))
case tp @ RefinedType(parent, name) if variance > 0 =>
// The naive approach here would be to first approximate the parent,
// but if the base type of the approximated parent is different from
// the current base type, then the current refinement won't be valid
// if it's a type parameter refinement.
// Therefore we first approximate the base type, then use `baseArgInfos`
// to get correct refinements for the approximated base type, then
// recursively approximate the resulting type.
val base = tp.unrefine
if (toAvoid(base)) {
val base1 = apply(base)
apply(base1.appliedTo(tp.baseArgInfos(base1.typeSymbol)))
val parent1 = apply(tp.parent)
val refinedInfo1 = apply(tp.refinedInfo)
if (toAvoid(refinedInfo1)) {
typr.println(s"dropping refinement from $tp")
parent1
} else {
val parent1 = apply(tp.parent)
val refinedInfo1 = apply(tp.refinedInfo)
if (toAvoid(refinedInfo1)) {
typr.println(s"dropping refinement from $tp")
parent1
} else {
tp.derivedRefinedType(parent1, name, refinedInfo1)
}
tp.derivedRefinedType(parent1, name, refinedInfo1)
}
case tp: TypeVar if ctx.typerState.constraint.contains(tp) =>
val lo = ctx.typerState.constraint.fullLowerBound(tp.origin)
Expand Down
33 changes: 33 additions & 0 deletions tests/pos/flowops1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
object Test {
class NotUsed

trait FO[type +Out, type +Mat] { self =>
type Repr <: FO[Mat = self.Mat] {
type Repr = self.Repr
}
def map[T](f: Out => T): Repr[Out = T] = ???
}

class Source[type +Out, type +Mat] extends FO[Out, Mat] {
type Repr <: Source[Out, Mat]
}

class Flow[type -In, type +Out, type +Mat] extends FO[Out, Mat] {
type Repr <: Flow[In, Out, Mat]
}

implicit class x[O, M, F <: FO](val f: F[Out = O, Mat = M]) extends AnyVal {
def xx(i: Int): f.Repr[Out = O] = f.map(identity)
}

val s1 = new Source[Int, NotUsed].xx(12)
val s2: Source[Int, NotUsed] = s1
val f1 = x[Int, NotUsed, Flow[In = Int]](new Flow[Int, Int, NotUsed]).xx(12)
val f2: Flow[Int, Int, NotUsed] = f1


val f3 = x(new Flow[Int, Int, NotUsed]).xx(12)
val f4: Flow[Int, Int, NotUsed] = f3
val f5 = new Flow[Int, Int, NotUsed].xx(12)
val f6: Flow[Int, Int, NotUsed] = f5
}

0 comments on commit acd07c1

Please sign in to comment.