diff options
author | odersky <odersky@gmail.com> | 2016-10-14 10:53:01 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-10-14 10:53:01 +0200 |
commit | 148551ae5598542c023514b104160a528767e290 (patch) | |
tree | 171b7224dce194c33a6fe1daf2ada1df4be46f90 | |
parent | 8bfaadaae141e83db7f515b042fcee26ed0e54fd (diff) | |
parent | f13fe7147ddf8d527df855b1dfa0db4ae22107bb (diff) | |
download | dotty-148551ae5598542c023514b104160a528767e290.tar.gz dotty-148551ae5598542c023514b104160a528767e290.tar.bz2 dotty-148551ae5598542c023514b104160a528767e290.zip |
Merge pull request #749 from smarter/fix/escaping-refs-2
Typer#escapingRefs: don't let the types of lower bounds escape
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 15 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Implicits.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 10 |
3 files changed, 15 insertions, 14 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index d242843e5..1212cdd81 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -239,9 +239,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 { @@ -3710,7 +3715,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() @@ -3723,7 +3729,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.tref) diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala index d6cf7fb2b..f3dceea71 100644 --- a/src/dotty/tools/dotc/typer/Implicits.scala +++ b/src/dotty/tools/dotc/typer/Implicits.scala @@ -343,7 +343,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 diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 6be119319..6fb0dd7c7 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -577,16 +577,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 |