2.8. Unsafe

The unsafe keyword denotes unsafe contents, which is required for operations, but could potentially crash the application:

unsafe
    let px = addr(x)

Expressions (and subexpressions) can also be unsafe:

let px = unsafe(addr(x))

Unsafe is followed by a block which can include those operations. Nested unsafe sections are allowed. Unsafe is not inherited in lambda, generator, or local functions; it is, however, inherited in local blocks.

Individual expressions can cause a CompilationError::unsafe error, unless they are part of the unsafe section. Additionally, macros can explicitly set the ExprGenFlags::alwaysSafe flag.

The address of expression is unsafe:

unsafe
    let a : int
    let pa = addr(a)
    return pa                               // accessing *pa can potentially corrupt stack

Lambdas or generators require unsafe sections for the implicit capture by move or by reference:

var a : array<int>
unsafe
    var counter <- @ <| (extra:int) : int
        return a[0] + extra                 // a is implicitly moved

Deleting any pointer requires an unsafe section:

var p = new Foo()
var q = p
unsafe
    delete p                                // accessing q can potentially corrupt memory

Upcast and reinterpret cast require an unsafe section:

unsafe
    return reinterpret<void?> 13            // reinterpret can create unsafe pointers

Indexing into a pointer is unsafe:

unsafe
    var p = new Foo()
    return p[13]                            // accessing out of bounds pointer can potentially corrupt memory

A safe index is unsafe when not followed by the null coalescing operator:

var a = {{ 13 => 12 }}
unsafe
    var t = a?[13] ?? 1234                  // safe
    return a?[13]                           // unsafe; safe index is a form of 'addr' operation
                                            // it can create pointers to temporary objects

Variant ?as on local variables is unsafe when not followed by the null coalescing operator:

unsafe
    return a ?as Bar                        // safe as is a form of 'addr' operation

Variant .?field is unsafe when not followed by the null coalescing operator:

unsafe
    return a?.Bar                           // safe navigation of a variant is a form of 'addr' operation

Variant .field is unsafe:

unsafe
    return a.Bar                            // this is potentially a reinterpret cast

Certain functions and operators are inherently unsafe or marked unsafe via the [unsafe_operation] annotation:

unsafe
    var a : int?
    a += 13                                 // pointer arithmetic can create invalid pointers
    var boo : int[13]
    var it = each(boo)                      // each() of array is unsafe, for it does not capture

Moving from a smart pointer value requires unsafe, unless that value is the ‘new’ operator:

unsafe
    var a <- new TestObjectSmart()          // safe, its explicitly new
    var b <- someSmartFunction()            // unsafe since lifetime is not obvious
    b <- a                                  // safe, values are not lost

Moving or copying classes is unsafe:

def foo ( var b : TestClass )
    unsafe
        var a : TestClass
        a <- b                              // potentially moving from derived class

Local class variables are unsafe:

unsafe
    var g = Goo()                           // potential lifetime issues

2.9. implicit

implicit keyword is used to specify that type can be either temporary or regular type, and will be treated as defined. For example:

def foo ( a : Foo implicit )    // a will be treated as Foo, but will also accept Foo# as argument
def foo ( a : Foo# implicit )   // a will be treated as Foo#, but will also accept Foo as argument

Unfortunately implicit conversions like this are unsafe, so implicit is unsafe by definition.