diff --git a/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala b/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala index 24aa5b031f55..a516fb81cf5f 100644 --- a/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala +++ b/compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala @@ -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 @@ -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 diff --git a/compiler/src/dotty/tools/dotc/cc/SafeRefs.scala b/compiler/src/dotty/tools/dotc/cc/SafeRefs.scala index 1e167d2efd55..d31aa6dc72de 100644 --- a/compiler/src/dotty/tools/dotc/cc/SafeRefs.scala +++ b/compiler/src/dotty/tools/dotc/cc/SafeRefs.scala @@ -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.* @@ -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", @@ -195,7 +197,7 @@ 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) @@ -203,6 +205,6 @@ object SafeRefs { 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(_)) } diff --git a/tests/pos-custom-args/captures/safemode-synthetic/A_1.scala b/tests/pos-custom-args/captures/safemode-synthetic/A_1.scala new file mode 100644 index 000000000000..b28a1a4df0cb --- /dev/null +++ b/tests/pos-custom-args/captures/safemode-synthetic/A_1.scala @@ -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 + ) = () diff --git a/tests/pos-custom-args/captures/safemode-synthetic/B_2.scala b/tests/pos-custom-args/captures/safemode-synthetic/B_2.scala new file mode 100644 index 000000000000..a3626ccc0c76 --- /dev/null +++ b/tests/pos-custom-args/captures/safemode-synthetic/B_2.scala @@ -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)