June 18, 2021

Are asserts enough to make method @trusted or is something like throw exception or return error code necessary? How it work in phobos?

Example:

struct Slice(T){
	private T[] data;

	this(T[] data){
    	this.data = data;
    }
    inout(T)[] opSlice()inout scope return pure nothrow @safe @nogc{
    	return data;
    }
    inout(T)[] opSlice(size_t b, size_t e)inout scope return pure nothrow @safe @nogc{
    	return data[b .. e];
    }

    /*
        Remove subset `slice` from `this.data`
    	`slice` is subset of `this.data`.
    */
    void erase1(scope const(T)[] slice)scope pure nothrow @trusted @nogc{
        assert(data.ptr <= slice.ptr);
        assert((slice.ptr + slice.length) <= (data.ptr + data.length));

        //...
    }

    // ditto
    bool erase2(scope const(T)[] slice)scope pure nothrow @trusted @nogc{
        if(data.ptr > slice.ptr)
        	return false;

        if((slice.ptr + slice.length) > (data.ptr + data.length))
            return false;

        //...
        assert(0, "TODO impl");
    }

}


void main()@safe{
    scope slice = Slice!int([1, 2, 3, 4]);
    scope slice2 = Slice!int([1, 2, 3, 4]);


    slice.erase2(slice2[1 .. 2]);	//return false
    slice.erase1(slice2[1 .. 2]);	//assert error in debug

}

June 18, 2021
On 18.06.21 14:40, vit wrote:
> Are asserts enough to make method @trusted or is something like throw exception or return error code necessary?
Asserts are a debugging feature. They're not suitable to ensure safety, because they're simply skipped in release mode.

`assert(false);` is the exception. It aborts the program even in release mode. So you can use it to bail out when your expectations fail.

So:

assert(expected); /* Don't do this. */

import std.exception: enforce;
enforce(expected); /* Instead, do this */
if (!expected) throw new Exception("..."); /* or this */
if (!expected) assert(false); /* or this. */