Counter-Proposal: restrict & tagged functions

Dmitry Olshansky dmitry.olsh at gmail.com
Sat Sep 1 09:20:12 PDT 2012


On 01-Sep-12 17:01, Adam D. Ruppe wrote:
> On Saturday, 1 September 2012 at 12:39:41 UTC, Dmitry Olshansky wrote:
>> I'd say
>> @nogc:
>> at the top and deal is sealed.
>
> BTW don't forget a @yesgc would be good to counter it. We need
> a way to turn off each attribute to use this pattern best.

What I see with this @nogc proposal is that that problem it tries to 
solve (and tool used to do so) is far more interesting and general.

Namely the problem is to specify that some functions can call only 
specific subset of functions and able to use only specific subset of 
language features. It's more far reaching then just gc, one may want to 
get @noblocking  or @async attribute to statically check e.g. that GUI 
thread can't ever block.
(it would however require to identify API calls that don't block, not 
possible on every OS, might entail some wrappers etc. but is very desirable)

To peek at what's more there that you can get this way see C++ AMP on 
why restricting a block of code or function is useful
e.g. here by Herb Sutter (including nice demo!):
http://www.youtube.com/watch?v=HK9rJFpX32Y

BTW @safe is in the same bucket, it does allow only to call @safe & 
@trusted (read as "subset of ") functions and use a subset of language 
features.

Actually exactly the same goes for pure (noglobal whatever) you just 
state this piece of code can't use this language feature (global 
variables, static variables, you name it), same for nothrow.

And not long ago David Nadlinger showed that function level trusted 
doesn't help much with templates that are @trusted for their own code, 
but need normal safety guarantee from foreign code brought by 
parameters. Thus restriction has to be able to work on a block scope too.

So what I want with this? I want to bring together C++ AMP restrict and 
@safe/@trusted/@system/pure/nothrow machinery in one clean and 
user-extensible future-proof feature.

The idea in a nutshell:

- specify a way attach tags to function declarations (to "paint" functions)

- allow specifying is-a relation between tags (supertags and subtags).

- add restrict specification that allows user to enforce on a block of 
code the following:
	a) disallow use of certain language features
	b) allow(or disallow) calling function with specific tags

- fit with existing world and provide clean migration path, specify defaults

I claim that it's enough to implement pure/safe/trusted/nothrow/nogc and 
proposed nogc.


The following is the draft of proposal.

1. Introduce a restrict keyword. Restrict applies to a block of code or 
a function:

auto foo(...) restrict(<restriction spec>)
{
	
}

auto bar(...)
{
	restrict(<restriction spec>){
	}
}

And the usual

restrict(<restrict spec>):

to affect all subsequent declarations in the module.

Multiple restrict blocks on the same declaration are treated as single 
restrict with restrict specifications concatenated.

The effect of such a clause is that declarations and statements inside 
of a block have to pass restriction check in order to compile.
The kind of check is described in restrict specification.

2. Functions declared with restrict(<restrict spec>) can only be bound 
by function pointer of more permissive type w.r.t. spec:

(assume A,B,C,D,E are elements of spec)
void funcABCD() restrict(A,B,C,D);
void funcACD() restrict(A,C,D);


function void() restrict(A,B,D) fp;
fp = &funcABCD; ///okay, fp is more permissive
fp = &funcACD; //fail, B is allowed inside of funcACD but not by fp

3. Function tags. Tag is a special literal associated with function 
declaration and type of function pointer. Any FP or function 
declarations can have an arbitrary amount of tags attached:

@tag(mytag, safe, nothrow)
void foobar();

function void () @tag(default, nothrow)
Every function without tags has one implicit 'default' tag (name clashes 
with 'default' keyword may require another name). To only add tags 
include 'default' among others and to override it just don't list default.

User defined tags are specified as follows:

@tag tag_name; //new tag called tag_name

@tag tag_name : supertag; //tag_name is a subtag of super tag

The following tags are declared in object.d:

//pure is subtag of default, address of pure function can be assigned to 
default FP
@tag pure : default;
@tag system : default; //and system is subtag of default
@tag nothrow: default;
@tag trusted: system;
@tag safe: trusted;

Any assignments of FP allows only compatible pointer types.
Namely for the left hand side of assignment exp (LHS) and the right hand 
side (RHS):
all of RHS tags must have super tag or direct match in LHS's set of tags.

4. Restrict specifications

Introduce a list of language features that can be enabled/disabled with 
descriptive names, the list may be extended in the future.
Common suspects are:
	- heap stack frames and implicit GC actions
	- ability to declare/access kinds of variables (immutable, shared, 
static ...)
	- pointers to functions
	- pointers to ...
	- virtual functions
	- labels & goto
	- RTTI
	- inline assembler
	- pointer arithmetic
	- unions & reinterpret casts
	- C and D style varargs
	- other casts (integer/float coercing, const, dynamic)
	- exceptions
	...

each of those should have an IDs akin to __traits like 'virtual_calls', 
'gc' etc. Also all of the built-in names are reserved in a tags namespace.

Restrict specification is a comma separated list of:
1) tag - allow to call only functions that have tag 'tag' or have 
supertag of 'tag'

2) language_feature_id - disable feature with name language_feature_id

5. Backward compatibility.
@safe, @trusted, @system, nothrow and pure work as aliases respectively:
@safe - @tag(safe) restrict(safe)
@trusted - @tag(trusted) restrict(trusted)
@system - @tag(system) restrict(system)
pure - @tag(pure) restrict(globals, static, pure)
nothrow - @tag(nothrow) restrict(nothrow)

Sometime later these could be deprecated or left as simple shortcuts.

6. Probably we need a way to alias a list of restictions to ease the use 
of frequent combinations. (No idea, but any sane syntax around alias 
will do)

-- 
Olshansky Dmitry


More information about the Digitalmars-d mailing list