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
13 changes: 10 additions & 3 deletions compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1286,6 +1286,9 @@ class CheckCaptures extends Recheck, SymTransformer:
else if runInConstructor then
pushConstructorEnv()

if sym.is(Synthetic) then
tree.tpt.putAttachment(SafeRefs.SkipAnnotsInType, ())

checkInferredResult(super.recheckValDef(tree, sym), tree)
finally
if !sym.is(Param) then
Expand Down Expand Up @@ -1348,12 +1351,16 @@ class CheckCaptures extends Recheck, SymTransformer:
SafeRefs.checkSafeAnnots(sym)
for params <- tree.paramss; param <- params do
SafeRefs.checkSafeAnnots(param.symbol)
param match
case param: ValDef => SafeRefs.checkSafeAnnotsInType(param.tpt)
case param: TypeDef => SafeRefs.checkSafeAnnotsInType(param.rhs)
if !param.symbol.is(Synthetic) then
param match
case param: ValDef => SafeRefs.checkSafeAnnotsInType(param.tpt)
case param: TypeDef => SafeRefs.checkSafeAnnotsInType(param.rhs)

checkNoUnboxedReaches(tree)

if sym.is(Synthetic) then
tree.tpt.putAttachment(SafeRefs.SkipAnnotsInType, ())

try checkInferredResult(super.recheckDefDef(tree, sym)(using bodyCtx), tree)
finally
if !sym.isAnonymousFunction then
Expand Down
8 changes: 5 additions & 3 deletions compiler/src/dotty/tools/dotc/cc/SafeRefs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import core.*
import Symbols.*
import Annotations.*
import util.Spans.NoSpan
import util.SrcPos
import util.{Property, SrcPos}
import Contexts.Context
import Constants.Constant
import Decorators.*
Expand All @@ -20,6 +20,8 @@ import typer.ProtoTypes.SelectionProto

/** Check whether references from safe mode should be allowed */
object SafeRefs {

val SkipAnnotsInType: Property.Key[Unit] = Property.Key()

val assumedSafePackages = List(
"scala", "scala.runtime", "scala.collection.immutable", "scala.compiletime.ops",
Expand Down Expand Up @@ -195,14 +197,14 @@ object SafeRefs {
checkNotRejected(ann.symbol, errpos)

def checkSafeAnnots(sym: Symbol)(using Context): Unit =
if Feature.safeEnabled then
if Feature.safeEnabled && !sym.is(Synthetic) then
for ann <- sym.annotations do
checkSafeAnnot(ann, sym.srcPos)

def checkSafeAnnotsInType(tree: Tree)(using Context): Unit =
def checkAnnotatedType(tp: Type) = tp match
case AnnotatedType(tp, ann) => checkSafeAnnot(ann, tree.srcPos)
case _ =>
if Feature.safeEnabled then
if Feature.safeEnabled && !tree.hasAttachment(SkipAnnotsInType) then
tree.tpe.foreachPart(checkAnnotatedType(_))
}
11 changes: 11 additions & 0 deletions tests/pos-custom-args/captures/safemode-synthetic/A_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import language.experimental.captureChecking
import caps.assumeSafe

@assumeSafe
object A:
// get @uncheckedVariance on the types
def f(
a: List[String] = List.empty,
b: Option[String] = None,
c: Long = 30000
) = ()
9 changes: 9 additions & 0 deletions tests/pos-custom-args/captures/safemode-synthetic/B_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import language.experimental.safe

def test(i: Int, j: (String, Int)) =
// desugared to:
// val a$1: List[String] = List.apply[String](["bar" : String]*)
// val b$1: Option[String] @uncheckedVariance = A.f$default$2
// A.f(a = a$1, b$1, c = 1000L)
// We need to skip annotation check for the synthetic b$1 in safe mode
A.f(a = List("bar"), c = 1000)
Loading