Skip to content

Commit afa4a09

Browse files
committed
add SAM support
1 parent 040360b commit afa4a09

File tree

3 files changed

+30
-40
lines changed

3 files changed

+30
-40
lines changed

compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import core._
55
import Contexts._, Symbols._, Types._, Flags._, Decorators._, StdNames._, Constants._
66
import MegaPhase._
77
import SymUtils._
8+
import NullOpsDecorator._
89
import ast.Trees._
910
import reporting._
1011
import dotty.tools.dotc.util.Spans.Span
@@ -45,7 +46,8 @@ class ExpandSAMs extends MiniPhase {
4546
checkRefinements(tpe, fn)
4647
tree
4748
case tpe =>
48-
val tpe1 = checkRefinements(tpe, fn)
49+
val tpe0 = if ctx.explicitNulls then tpe.stripNull else tpe
50+
val tpe1 = checkRefinements(tpe0, fn)
4951
val Seq(samDenot) = tpe1.possibleSamMethods
5052
cpy.Block(tree)(stats,
5153
AnonClass(tpe1 :: Nil, fn.symbol.asTerm :: Nil, samDenot.symbol.asTerm.name :: Nil))

compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -367,14 +367,11 @@ object ProtoTypes {
367367
def typedArg(arg: untpd.Tree, formal: Type)(using Context): Tree = {
368368
val wideFormal = formal.widenExpr
369369
val argCtx =
370-
if wideFormal eq formal then ctx
371-
else ctx.withNotNullInfos(ctx.notNullInfos.retractMutables)
370+
(if wideFormal eq formal then ctx
371+
else ctx.withNotNullInfos(ctx.notNullInfos.retractMutables))
372+
.retractMode(Mode.UnsafeNullConversion)
372373
val locked = ctx.typerState.ownedVars
373-
val targ = if ctx.mode.is(Mode.UnsafeNullConversion) then
374-
typer.typedUnadaptedWithBlock(arg, wideFormal, locked)
375-
(using argCtx.retractMode(Mode.UnsafeNullConversion))
376-
else
377-
cacheTypedArg(arg,
374+
val targ = cacheTypedArg(arg,
378375
typer.typedUnadapted(_, wideFormal, locked)(using argCtx),
379376
force = true)
380377
typer.adapt(targ, wideFormal, locked)

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -912,24 +912,6 @@ class Typer extends Namer
912912
pt, localSyms(stats1))
913913
}
914914

915-
def typedUnadaptedWithBlock(tree: untpd.Tree, pt: Type, locked: TypeVars)(using Context): Tree = {
916-
tree match {
917-
case block: untpd.Block =>
918-
val (stats1, exprCtx) = withoutMode(Mode.Pattern) {
919-
typedBlockStats(block.stats)(using ctx.fresh.setNewScope)
920-
}
921-
val expr1 = typedUnadaptedWithBlock(block.expr, pt.dropIfProto, locked)(using exprCtx)
922-
val expr1Tpe = expr1.tpe
923-
ensureNoLocalRefs(
924-
cpy.Block(block)(stats1, expr1)
925-
.withType(expr1Tpe)
926-
.withNotNullInfo(stats1.foldRight(expr1.notNullInfo)(_.notNullInfo.seq(_))),
927-
expr1Tpe, localSyms(stats1))
928-
case _ =>
929-
typedUnadapted(tree, pt, locked)
930-
}
931-
}
932-
933915
def escapingRefs(block: Tree, localSyms: => List[Symbol])(using Context): List[NamedType] = {
934916
lazy val locals = localSyms.toSet
935917
block.tpe.namedPartsWith(tp => locals.contains(tp.symbol) && !tp.isErroneous)
@@ -3452,13 +3434,23 @@ class Typer extends Namer
34523434
return tpd.Block(tree1 :: Nil, Literal(Constant(())))
34533435
}
34543436

3437+
val adaptWithUnsafeNullConver =
3438+
ctx.explicitNulls && (
3439+
config.Feature.enabled(nme.unsafeNulls) ||
3440+
ctx.mode.is(Mode.UnsafeNullConversion))
3441+
34553442
// convert function literal to SAM closure
34563443
tree match {
34573444
case closure(Nil, id @ Ident(nme.ANON_FUN), _)
34583445
if defn.isFunctionType(wtp) && !defn.isFunctionType(pt) =>
3459-
pt match {
3446+
val pt1 =
3447+
if adaptWithUnsafeNullConver then
3448+
pt.stripNull
3449+
else pt
3450+
pt1 match {
34603451
case SAMType(sam)
3461-
if wtp <:< sam.toFunctionType() =>
3452+
if wtp <:< sam.toFunctionType() ||
3453+
(adaptWithUnsafeNullConver && wtp.isUnsafeConvertable(sam.toFunctionType())) =>
34623454
// was ... && isFullyDefined(pt, ForceDegree.flipBottom)
34633455
// but this prevents case blocks from implementing polymorphic partial functions,
34643456
// since we do not know the result parameter a priori. Have to wait until the
@@ -3544,7 +3536,17 @@ class Typer extends Namer
35443536
tree
35453537
else recover(failure.reason)
35463538

3547-
def process(using Context): Tree = {
3539+
val javaCompatibleCall = ctx.explicitNullsJavaCompatible && (tree match {
3540+
case Apply(_, _) => tree.symbol.is(JavaDefined)
3541+
case _ => false
3542+
})
3543+
3544+
val searchCtx =
3545+
if ctx.explicitNulls && (javaCompatibleCall || config.Feature.enabled(nme.unsafeNulls)) then
3546+
ctx.addMode(Mode.UnsafeNullConversion)
3547+
else ctx
3548+
3549+
inContext(searchCtx) {
35483550
if ctx.mode.is(Mode.ImplicitsEnabled) && tree.typeOpt.isValueType then
35493551
if pt.isRef(defn.AnyValClass) || pt.isRef(defn.ObjectClass) then
35503552
report.error(em"the result of an implicit conversion must be more specific than $pt", tree.srcPos)
@@ -3558,17 +3560,6 @@ class Typer extends Namer
35583560
}
35593561
else tryUnsafeNullConver(recover(NoMatchingImplicits))
35603562
}
3561-
3562-
val javaCompatibleCall = ctx.explicitNullsJavaCompatible && (tree match {
3563-
case Apply(_, _) => tree.symbol.is(JavaDefined)
3564-
case _ => false
3565-
})
3566-
val searchCtx =
3567-
if ctx.explicitNulls && (javaCompatibleCall || config.Feature.enabled(nme.unsafeNulls)) then
3568-
ctx.addMode(Mode.UnsafeNullConversion)
3569-
else ctx
3570-
3571-
process(using searchCtx)
35723563
}
35733564

35743565
def adaptType(tp: Type): Tree = {

0 commit comments

Comments
 (0)