Skip to content

Backport "Fix stale symbol crashes in some path depended types in macro contexts" to LTS #19051

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
Dec 8, 2023
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
19 changes: 12 additions & 7 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2677,7 +2677,10 @@ object Types {
else {
if (isType) {
val res =
if (currentSymbol.isAllOf(ClassTypeParam)) argForParam(prefix)
val sym =
if (currentSymbol.isValidInCurrentRun) currentSymbol
else computeSymbol
if (sym.isAllOf(ClassTypeParam)) argForParam(prefix)
else prefix.lookupRefined(name)
if (res.exists) return res
if (Config.splitProjections)
Expand Down Expand Up @@ -2751,14 +2754,16 @@ object Types {
/** A reference like this one, but with the given prefix. */
final def withPrefix(prefix: Type)(using Context): Type = {
def reload(): NamedType = {
val lastSym = lastSymbol.nn
val allowPrivate = !lastSym.exists || lastSym.is(Private)
val sym =
if lastSymbol.nn.isValidInCurrentRun then lastSymbol.nn
else computeSymbol
val allowPrivate = !sym.exists || sym.is(Private)
var d = memberDenot(prefix, name, allowPrivate)
if (d.isOverloaded && lastSym.exists)
if (d.isOverloaded && sym.exists)
d = disambiguate(d,
if (lastSym.signature == Signature.NotAMethod) Signature.NotAMethod
else lastSym.asSeenFrom(prefix).signature,
lastSym.targetName)
if (sym.signature == Signature.NotAMethod) Signature.NotAMethod
else sym.asSeenFrom(prefix).signature,
sym.targetName)
NamedType(prefix, name, d)
}
if (prefix eq this.prefix) this
Expand Down
82 changes: 82 additions & 0 deletions tests/neg-macros/i17152/DFBits.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// nopos-error
package crash

import scala.quoted.*

class IRDFType
class IRDFBoolOrBit extends IRDFType
class IRDFDecimal extends IRDFType
class IRDFBits extends IRDFType

final class DFType[+T <: IRDFType, +A]
type DFTypeAny = DFType[IRDFType, Any]

trait Baz

trait Width[T]:
type Out <: Int
object Width:
given fromDFBoolOrBit[T <: DFBoolOrBit]: Width[T] with
type Out = 1
transparent inline given [T]: Width[T] = ${ getWidthMacro[T] }
def getWidthMacro[T](using Quotes, Type[T]): Expr[Width[T]] =
'{
new Width[T]:
type Out = 1
}
end Width

extension [T](t: T)(using baz: Baz) def width: 1 = ???

trait Check[T1 <: Int, T2 <: Int]

type DFBits[W <: Int] = DFType[IRDFBits, Tuple1[W]]

private object CompanionsDFBits:
object Val:
trait Candidate[R]:
type OutW <: Int
def apply(value: R): DFValOf[DFBits[OutW]]
object Candidate:
given fromDFUInt[W <: Int, R <: DFValOf[DFDecimal]]: Candidate[R] with
type OutW = W
def apply(value: R): DFValOf[DFBits[W]] =
import DFVal.Ops.bits
value.bits
???
end Candidate

object TC:
import DFVal.TC
given DFBitsFromCandidate[
LW <: Int,
V
](using candidate: Candidate[V])(using
check: Check[LW, candidate.OutW]
): TC[DFBits[LW], V] with
def conv(dfType: DFBits[LW], value: V): DFValOf[DFBits[LW]] =
val dfVal = candidate(value)
???
end TC
end Val

end CompanionsDFBits

type DFBoolOrBit = DFType[IRDFBoolOrBit, Any]
type DFDecimal = DFType[IRDFDecimal, Any]
object DFDecimal:
def foo(arg1: Int, arg2: Int): Unit = ???

object Val:
object TC:
import DFVal.TC
given [R]: TC[DFDecimal, R] = ???
def apply(
dfType: DFDecimal,
dfVal: DFValOf[DFDecimal]
): DFValOf[DFDecimal] =
foo(dfType.width, dfVal.width)
dfVal
end TC
end Val
end DFDecimal
25 changes: 25 additions & 0 deletions tests/neg-macros/i17152/DFVal.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package crash

trait TCConv[T <: DFTypeAny, V, O]:
type Out <: O
def conv(dfType: T, value: V): Out

class DFVal[+T <: DFTypeAny]
type DFValAny = DFVal[DFTypeAny]
type DFValOf[+T <: DFTypeAny] = DFVal[T]

object DFVal:
trait TC[T <: DFTypeAny, R] extends TCConv[T, R, DFValAny]:
type Out = DFValOf[T]
final def apply(dfType: T, value: R): Out = ???

object TC:
export CompanionsDFBits.Val.TC.given
end TC

object Ops:
extension [T <: DFTypeAny, A, C, I](dfVal: DFVal[T])
def bits(using w: Width[T]): DFValOf[DFBits[w.Out]] = ???
end extension
end Ops
end DFVal
3 changes: 3 additions & 0 deletions tests/neg-macros/i17294/DFVal.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package crash

def bits[T](t: T)(using w: Width[T]): w.Out = ???
12 changes: 12 additions & 0 deletions tests/neg-macros/i17294/Width.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// nopos-error
package crash
import scala.quoted.*

trait Width[T]:
type Out
object Width:
transparent inline given [T]: Width[T] = ${ getWidthMacro[T] }
def getWidthMacro[T](using Quotes, Type[T]): Expr[Width[T]] = '{ new Width[T] {} }
end Width

val x = bits(1)
6 changes: 6 additions & 0 deletions tests/pos-macros/i17294/Bar.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import scala.quoted.*

class Bar[T]
object Bar:
transparent inline def bar[T](a: Foo, b: a.Out): Bar[T] = ${ getBarMacro[T] }
def getBarMacro[T](using Quotes, Type[T]): Expr[Bar[T]] = '{ new Bar[T] }
3 changes: 3 additions & 0 deletions tests/pos-macros/i17294/Foo.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Foo:
type Out = Int
val a = Bar.bar(new Foo(), 0)