May 19, 2022

On Thursday, 19 May 2022 at 07:13:05 UTC, Dukc wrote:

>

There are times when you want to treat data in a scoped struct as non-scoped.

I suggest using a helper function to cast away scope:

auto ref assumeNonScope(T)(auto ref scope T arg)
{
    return *(cast(T*) cast(size_t) &arg);
}

struct MyType
{
    // (...)
    @trusted auto content() scope {return assumeNonScope(_content);}
}
May 19, 2022

On Thursday, 19 May 2022 at 09:29:50 UTC, Dennis wrote:

>

I also don't agree with the "principle of least astonishment" violation. Consider this slice example:

struct Slice(T)
{
    size_t length;
    private @system T* _ptr;

    // `@safe` read-only access to _ptr
    T* ptr() @trusted { return length == 0 ? null : _ptr; }
}

I expect the compiler to infer return scope for ptr() here.

Sorry, I don't think that can be helped. The compiler can infer simple cases like this, but then it has to draw a line in water where it stops the inference as the function body gets more complex. You're going to be surprised anyway at some point if you expect inference from a @trusted function.

It would probably be reasonable to have the compiler error in cases like this. But if the function compiles, there should be nothing implementation dependent about scope, return scope or lack thereof.

May 19, 2022

On Thursday, 19 May 2022 at 09:37:32 UTC, Dennis wrote:

>

I suggest using a helper function to cast away scope:

auto ref assumeNonScope(T)(auto ref scope T arg)
{
    return *(cast(T*) cast(size_t) &arg);
}

struct MyType
{
    // (...)
    @trusted auto content() scope {return assumeNonScope(_content);}
}

Not bad. Worth considering.

May 19, 2022

On Thursday, 19 May 2022 at 09:44:29 UTC, Dukc wrote:

>

but then it has to draw a line in water
where it stops the inference as the function body gets more complex. You're going to be surprised anyway at some point if you expect inference from a @trusted function.

You get the same inference as a non-@trusted function, it stops at the exact same point (i.e. as soon as aliases are created).

May 19, 2022

On Thursday, 19 May 2022 at 09:57:47 UTC, Dennis wrote:

>

You get the same inference as a non-@trusted function, it stops at the exact same point (i.e. as soon as aliases are created).

Yes. But the point is, AFAIK it is implementation-defined how far a compiler will take checks like this. For example, this code:

@system int* wrong()
{ int local;
  return &local;
}

...fails with DMD. But this is an implementation-defined error. Nothing in the spec says a compiler must check for this, and nothing in the spec says that the checks cannot be taken further than what DMD currently does.

A little unportable, but reasonable. You can have helper functions like the one you just posted for cases like this, that are easy to port from one compiler to another in centralised fashion.

But if such implementation-dependent checks cause the same function to compile with different semantics, then it's a problem. A @trusted function might infer return scope of a parameter on one compiler and work well, but suddenly stop doing so for another. Then you have cryptic errors in another part of the application. Or even worse, you might escape pointers in the future due to the checks working differently than when you last tested them.

May 19, 2022

On Thursday, 19 May 2022 at 10:21:00 UTC, Dukc wrote:

>

On Thursday, 19 May 2022 at 09:57:47 UTC, Dennis wrote:

>

You get the same inference as a non-@trusted function, it stops at the exact same point (i.e. as soon as aliases are created).

Yes. But the point is, AFAIK it is implementation-defined how far a compiler will take checks like this.

Plus, that aliasing rule isn't exactly common documented knowledge. If the language behaviour depends on that, it's a recipe for confusion.

May 19, 2022

On Thursday, 19 May 2022 at 10:21:00 UTC, Dukc wrote:

>

But if such implementation-dependent checks cause the same function to compile with different semantics, then it's a problem.

You're raising a valid concern, but this is a problem whether scope inference is enabled in @trusted code or not. One implementation could infer an unannotated function @system because it thinks scope pointers might escape, and a smarter implementation could find it's actually @safe, resulting in different mangling, different is(F == G), different __traits(compiles) etc.

May 19, 2022

On Thursday, 19 May 2022 at 10:48:13 UTC, Dennis wrote:

>

You're raising a valid concern, but this is a problem whether scope inference is enabled in @trusted code or not. One implementation could infer an unannotated function @system because it thinks scope pointers might escape, and a smarter implementation could find it's actually @safe

As I understand it, an unannotated function, when inference is on, is checked just like it had @safe except that it's made @system instead of compilation failure if the check fails. You're probably right that the DIP1000 checking rules aren't well defined in the spec. But DIP1000 had a draft of those rules, meaning that they are at least intended to be specified - in principle they are not implementation-defined.

Does the same apply to the more minimal escape checks in @trusted/@system? I have always understood that they are intentionally implementation-defined checks. I think they must either be specified, or the langauge semantics must stop relying on them. I'd prefer the latter, as it does not feel as special cased.

May 19, 2022

On Thursday, 19 May 2022 at 11:29:17 UTC, Dukc wrote:

>

As I understand it, an unannotated function, when inference is on, is checked just like it had @safe except that it's made @system instead of compilation failure if the check fails. (...) the more minimal escape checks in @trusted/@system

The escape checks are not more minimal in @trusted/@system, the only difference the attributes make is the behavior once it spots an error:

  • when the function is being inferred, it's set to @system
  • when the function is @trusted, @system, or @system by default, it ignores the error
  • when the function is @safe, it prints the error
May 23, 2022

On Thursday, 19 May 2022 at 12:26:38 UTC, Dennis wrote:

>

On Thursday, 19 May 2022 at 11:29:17 UTC, Dukc wrote:

>

the more minimal escape checks in @trusted/@system

The escape checks are not more minimal in @trusted/@system, the only difference the attributes make is the behavior once it spots an error:

  • when the function is @trusted, @system, or @system by default, it ignores the error

If there is a check that does nothing on failure, there is no check from user perspective.

With the more minimal checks, I meant the ones that can still silently add return to @trusted functions parameter.

1 2
Next ›   Last »