Skip to content
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
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1996,6 +1996,8 @@ class Definitions {
asContextFunctionType(TypeComparer.bounds(tp1).hiBound)
case tp1 @ PolyFunctionOf(mt: MethodType) if mt.isContextualMethod =>
tp1
case tp1: FlexibleType =>
asContextFunctionType(tp1.underlying)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I'm missing something here so I do have a question: Why do we drop the information that this was a Flexible Type (FT) instead of wrapping it over FT?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the purpose here, we only want to extract the information of a context function, so it's ok to widen a flexible type. I would prefer to strip any OrNull/flexible type at the beginning of this function.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So do you mean changing

    tp.stripTypeVar.dealias match

to

    tp.stripTypeVar.dealias.stripNull match

at the beginning (instead of adding this case)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, maybe before stripTypeVar

case tp1 =>
if tp1.typeSymbol.name.isContextFunction && isFunctionNType(tp1) then tp1
else NoType
Expand Down
14 changes: 13 additions & 1 deletion tests/explicit-nulls/flexible-unpickle/Flexible_2.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import unsafeNulls.Foo.*
import unsafeNulls.Unsafe_1
import unsafeNulls.{A, B, C, F, G, H, I, J, L, M}
import unsafeNulls.{A, B, C, F, G, H, I, J, L, M, S, T, U, expects}
import scala.reflect.Selectable.reflectiveSelectable
import scala.quoted.*

class Inherit_1 extends Unsafe_1 {
override def foo(s: String): String = s
Expand Down Expand Up @@ -34,6 +35,8 @@ case class cc()
class K(val b: String) extends J(b) {
}

def typeNameMacro[A: Type](using Quotes) = Expr(Type.show[A])

@main
def Flexible_2() =
val s2: String | Null = "foo"
Expand Down Expand Up @@ -97,3 +100,12 @@ def Flexible_2() =

val m: String = M.test(null)

// i23845
transparent inline def typeName[A]: String = ${typeNameMacro[A]}

implicit val givenT: T = ???
def alphaTypeNameMacro[A: S](using T) = U(S.show[A])
def res[A] = {
implicit val givenS: S[A] = ???
expects(alphaTypeNameMacro[A])
}
6 changes: 6 additions & 0 deletions tests/explicit-nulls/flexible-unpickle/Unsafe_1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,9 @@ object M {
def test(input: => String): String = "foo " + input
}

class S[X]
object S { def show[X] = "dummyStr" }
class T
class U[Y](a: Y)
def expects(take: (T) ?=> U[String]) = ???

Loading