-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix #11464: avoid expanding local paramRef in HKTypeLambda #11465
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
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -401,6 +401,7 @@ object TypeOps: | |
def avoid(tp: Type, symsToAvoid: => List[Symbol])(using Context): Type = { | ||
val widenMap = new ApproximatingTypeMap { | ||
@threadUnsafe lazy val forbidden = symsToAvoid.toSet | ||
val locals = util.HashSet[Type]() | ||
def toAvoid(sym: Symbol) = !sym.isStatic && forbidden.contains(sym) | ||
def partsToAvoid = new NamedPartsAccumulator(tp => toAvoid(tp.symbol)) | ||
|
||
|
@@ -429,17 +430,22 @@ object TypeOps: | |
case _ => | ||
emptyRange // should happen only in error cases | ||
} | ||
case tp: ThisType if toAvoid(tp.cls) => | ||
range(defn.NothingType, apply(classBound(tp.cls.classInfo))) | ||
case tp: ThisType => | ||
tp | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you explain why this change is needed and why it's safe to not do avoidance here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't need this, this is an optimization -- the rationale is that ThisType doesn't exist outside of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, I think this makes sense but it'd be good to check with an assert that this never happens in our tests (once the tests pass we can disable the assert for performance), and to add a comment explaining that this is safe. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @smarter The CI confirmed the assertion. See https://github.com/lampepfl/dotty/actions/runs/614834038 |
||
case tp: SkolemType if partsToAvoid(Nil, tp.info).nonEmpty => | ||
range(defn.NothingType, apply(tp.info)) | ||
case tp: TypeVar if mapCtx.typerState.constraint.contains(tp) => | ||
val lo = TypeComparer.instanceType( | ||
tp.origin, fromBelow = variance > 0 || variance == 0 && tp.hasLowerBound)(using mapCtx) | ||
val lo1 = apply(lo) | ||
if (lo1 ne lo) lo1 else tp | ||
case tp: LazyRef if isExpandingBounds => | ||
emptyRange | ||
case tp: LazyRef => | ||
if locals.contains(tp.ref) then tp | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is it safe to return tp here, doesn't it need to be avoided if it contains a local symbol? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh I see, would be good to give it another name to avoid confusing it with |
||
else if isExpandingBounds then emptyRange | ||
else mapOver(tp) | ||
case tl: HKTypeLambda => | ||
locals ++= tl.paramRefs | ||
mapOver(tl) | ||
case _ => | ||
mapOver(tp) | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -60,4 +60,3 @@ i9793.scala | |
|
||
# lazy_implicit symbol has different position after pickling | ||
i8182.scala | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
trait Txn[T <: Txn[T]] | ||
|
||
trait Adjunct | ||
|
||
trait Type0 | ||
trait Type[A1, Repr[~ <: Txn[~]] <: Expr[~, A1]] extends Type0 | ||
|
||
object Expr { | ||
def test(peer: Type0): Adjunct = { | ||
new AdjunctImpl(peer.asInstanceOf[Type[Any, ({ type R[~ <: Txn[~]] <: Expr[~, Any] }) # R]]) | ||
} | ||
} | ||
|
||
trait Expr[T <: Txn[T], +A] | ||
|
||
class AdjunctImpl[A, E[~ <: Txn[~]] <: Expr[~, A]](tpe: Type[A, E]) extends Adjunct |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As an optimization, this could be an uninitialized var which is only initialized the first time we encounter an HKTypeLambda.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(or just make it a lazy val).