Skip to content

Typer#escapingRefs: don't let the types of lower bounds escape #749

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 14, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -257,9 +257,14 @@ object Types {

/** The parts of this type which are type or term refs and which
* satisfy predicate `p`.
*
* @param p The predicate to satisfy
* @param excludeLowerBounds If set to true, the lower bounds of abstract
* types will be ignored.
*/
def namedPartsWith(p: NamedType => Boolean)(implicit ctx: Context): collection.Set[NamedType] =
new NamedPartsAccumulator(p).apply(mutable.LinkedHashSet(), this)
def namedPartsWith(p: NamedType => Boolean, excludeLowerBounds: Boolean = false)
(implicit ctx: Context): collection.Set[NamedType] =
new NamedPartsAccumulator(p, excludeLowerBounds).apply(mutable.LinkedHashSet(), this)

/** Map function `f` over elements of an AndType, rebuilding with function `g` */
def mapReduceAnd[T](f: Type => T)(g: (T, T) => T)(implicit ctx: Context): T = stripTypeVar match {
Expand Down Expand Up @@ -3331,7 +3336,8 @@ object Types {
def apply(x: Boolean, tp: Type) = x || tp.isUnsafeNonvariant || foldOver(x, tp)
}

class NamedPartsAccumulator(p: NamedType => Boolean)(implicit ctx: Context) extends TypeAccumulator[mutable.Set[NamedType]] {
class NamedPartsAccumulator(p: NamedType => Boolean, excludeLowerBounds: Boolean = false)
(implicit ctx: Context) extends TypeAccumulator[mutable.Set[NamedType]] {
override def stopAtStatic = false
def maybeAdd(x: mutable.Set[NamedType], tp: NamedType) = if (p(tp)) x += tp else x
val seen: mutable.Set[Type] = mutable.Set()
Expand All @@ -3344,7 +3350,8 @@ object Types {
apply(foldOver(maybeAdd(x, tp), tp), tp.underlying)
case tp: TypeRef =>
foldOver(maybeAdd(x, tp), tp)
case TypeBounds(_, hi) =>
case TypeBounds(lo, hi) =>
if (!excludeLowerBounds) apply(x, lo)
apply(x, hi)
case tp: ThisType =>
apply(x, tp.underlying)
Expand Down
4 changes: 3 additions & 1 deletion src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,9 @@ trait ImplicitRunInfo { self: RunInfo =>
}
tp.classSymbols(liftingCtx) foreach addClassScope
case _ =>
for (part <- tp.namedPartsWith(_.isType))
// We exclude lower bounds to conform to SLS 7.2:
// "The parts of a type T are: [...] if T is an abstract type, the parts of its upper bound"
for (part <- tp.namedPartsWith(_.isType, excludeLowerBounds = true))
comps ++= iscopeRefs(part)
}
comps
Expand Down
10 changes: 1 addition & 9 deletions src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -515,16 +515,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}

def escapingRefs(block: Tree, localSyms: => List[Symbol])(implicit ctx: Context): collection.Set[NamedType] = {
var hoisted: Set[Symbol] = Set()
lazy val locals = localSyms.toSet
def leakingTypes(tp: Type): collection.Set[NamedType] =
tp namedPartsWith (tp => locals.contains(tp.symbol))
def typeLeaks(tp: Type): Boolean = leakingTypes(tp).nonEmpty
def classLeaks(sym: ClassSymbol): Boolean =
(ctx.owner is Method) || // can't hoist classes out of method bodies
(sym.info.parents exists typeLeaks) ||
(sym.info.decls.toList exists (t => typeLeaks(t.info)))
leakingTypes(block.tpe)
block.tpe namedPartsWith (tp => locals.contains(tp.symbol))
}

/** Check that expression's type can be expressed without references to locally defined
Expand Down