Skip to content

Commit e7dc46f

Browse files
committed
Typer#escapingRefs: don't let the types of lower bounds escape
In 0efa171 I changed the definition of NamedPartsAccumulator to exclude lower bounds as this is required for the implicit search, but NamedPartsAccumulator is also used by Typer#escapingRefs so in the following code: class Foo[T] val z = { class C ??? : Foo[_ >: C] } the type of z was inferred to be Foo[_ >: C] instead of Foo. To avoid this, NamedPartsAccumulator will only exclude lower bounds if the parameter excludeLowerBounds is explicitely set to true. No test because there is no way to detect that a type has escaped, this might be something that could be added to TreeChecker.
1 parent 1b29119 commit e7dc46f

File tree

2 files changed

+14
-5
lines changed

2 files changed

+14
-5
lines changed

src/dotty/tools/dotc/core/Types.scala

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -257,9 +257,14 @@ object Types {
257257

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

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

3334-
class NamedPartsAccumulator(p: NamedType => Boolean)(implicit ctx: Context) extends TypeAccumulator[mutable.Set[NamedType]] {
3339+
class NamedPartsAccumulator(p: NamedType => Boolean, excludeLowerBounds: Boolean = false)
3340+
(implicit ctx: Context) extends TypeAccumulator[mutable.Set[NamedType]] {
33353341
override def stopAtStatic = false
33363342
def maybeAdd(x: mutable.Set[NamedType], tp: NamedType) = if (p(tp)) x += tp else x
33373343
val seen: mutable.Set[Type] = mutable.Set()
@@ -3344,7 +3350,8 @@ object Types {
33443350
apply(foldOver(maybeAdd(x, tp), tp), tp.underlying)
33453351
case tp: TypeRef =>
33463352
foldOver(maybeAdd(x, tp), tp)
3347-
case TypeBounds(_, hi) =>
3353+
case TypeBounds(lo, hi) =>
3354+
if (!excludeLowerBounds) apply(x, lo)
33483355
apply(x, hi)
33493356
case tp: ThisType =>
33503357
apply(x, tp.underlying)

src/dotty/tools/dotc/typer/Implicits.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,9 @@ trait ImplicitRunInfo { self: RunInfo =>
329329
}
330330
tp.classSymbols(liftingCtx) foreach addClassScope
331331
case _ =>
332-
for (part <- tp.namedPartsWith(_.isType))
332+
// We exclude lower bounds to conform to SLS 7.2:
333+
// "The parts of a type T are: [...] if T is an abstract type, the parts of its upper bound"
334+
for (part <- tp.namedPartsWith(_.isType, excludeLowerBounds = true))
333335
comps ++= iscopeRefs(part)
334336
}
335337
comps

0 commit comments

Comments
 (0)