Skip to content
Open
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
46 changes: 32 additions & 14 deletions compiler/src/dotty/tools/dotc/cc/SafeRefs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -120,28 +120,46 @@ object SafeRefs {
sym.hasAnnotation(defn.AssumeSafeAnnot)
|| isSafe(if sym.is(ModuleVal) then sym.moduleClass else sym.owner)

val (sym, checkLater) = tree match
case tree: New =>
(tree.tpt.symbol, false)
case tree: RefTree =>
val checkLater =
!tree.symbol.is(Method)
&& pt.match
case pt: PathSelectionProto => pt.selector.isStatic
case _: SelectionProto => true
case _ => false
(tree.symbol, checkLater)
val sym = tree match
case tree: New => tree.tpt.symbol
case tree: RefTree => tree.symbol

def checkLater =
sym.isTerm && !sym.is(Method) && pt.match
case pt: PathSelectionProto => pt.selector.isStatic
case _: SelectionProto => true
case _ => false

def isStatic = tree match
case tree: Ident =>
// Idents might refer to inherited symbols of static objects.
// in this case we need to check whether the prefix is static
// For Selects this is not an issue since we have already checked
// the qualifier for safety. safemode-pkg-inherit.scala is a test case.
tree.tpe match
case NamedType(prefix, _) =>
prefix.dealias match
case prefix: ThisType => prefix.cls.isStatic
case prefix: TermRef => prefix.symbol.isStatic
case _ => sym.isStatic
case _ => sym.isStatic
case _ => sym.isStatic

if Feature.safeEnabled
&& sym.exists
&& !sym.is(Package)
&& checkNotRejected(sym, tree.srcPos)
&& !checkLater
&& sym.isStatic // if it's not static it is local, a parameter, or comes from another symbol,
// which has been checked
&& !sym.is(Package)
&& isStatic // if it's not static it is local, a parameter, or comes from another symbol,
// which has been checked
&& !isSafe(sym)
then
fail(sym, "it is neither compiled in safe mode nor tagged with @assumedSafe", tree.srcPos)
else if false then
tree.tpe match
case TermRef(prefix: TermRef, _) =>
println(i"safe: $tree, ${tree.tpe}, ${prefix.symbol.isStaticOwner}")
case _ =>
}

private def checkSafeAnnot(ann: Annotation, pos: SrcPos)(using Context): Unit =
Expand Down
4 changes: 4 additions & 0 deletions tests/neg-custom-args/captures/safemode-pkg-inherit.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-- Error: tests/neg-custom-args/captures/safemode-pkg-inherit.scala:4:13 -----------------------------------------------
4 |val result = Seq("sh", "-c", "echo 'oh no'").!! // error
| ^
|Cannot refer to method stringSeqToProcess in trait ProcessImplicits from safe code since it is neither compiled in safe mode nor tagged with @assumedSafe
5 changes: 5 additions & 0 deletions tests/neg-custom-args/captures/safemode-pkg-inherit.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import scala.language.experimental.safe
import scala.sys.process.*

val result = Seq("sh", "-c", "echo 'oh no'").!! // error

Loading