DIP22.1

From D Wiki
Jump to: navigation, search
Title: Internal linkage attribute
DIP: 22.1
Version: 2
Status: Draft
Created: 2013-01-28
Last Modified: 2013-02-04
Author: Михаил Страшун (m.strashun gmail.com) (Dicebot)
Links: Access specifiers and visibility : data gathered before creating proposal

Changelog

Version 2

  • Separated internal linkage proposal from combined DIP22 as it was much more controversal
  • Other issues raised remain unchanged because best solution for them has not not yet been decided

Abstract

Currently there is no way to force internal linkage for a symbol, similar to C static and C++ unnamed namespaces. New definition of static storage class for module-scope symbol is proposed.

Rationale

If private is a source code level encapsulation tool then static is object file / binary level encapsulation tool. It allows even more struct separation of implementation-specific code and cleans up object files from unneeded symbols, providing more freedom for compiler optimizations.

Description

Currently static storage class is no-op for global symbols. It is a big luck as we can use it in the way similar to plain C:

  • All global static symbols are implicitly private
  • It is forbidden to leak static symbols outside of the module, i.e.
static struct Internal { }
void func1(Internal) { } // compile error
private void func2(Internal) { } // compile error, private still leaks its symbols to object file
void func3() { Internal t; } // fine, does not leak to func3 signature
alias Internal External; // compile error
static alias Internal InternalPrim; // fine
  • As can have just been seen, nested symbols can also be marked as static in case there were already static entities: enums, structs, classes, aliases. Variables and functions already have static defined for other usaged
  • No static symbols can be found in resulting object file. They are not shown in traits like __traits(allMembers). From the point of view of other modules they simply do not exist and may be all inlined or optimized away or whatever.
  • Only module-level symbols can be marked with global static, for example, nested struct types can't. It is minor limitation that greatly simplifies interaction with other language features like alias this.

Possible code breakage and solutions

  • global static had no meaning before and should not have been used like that. It may happen that is used by accident or in generic code gen. To be absolutely sure this brings no surprises I suggest to create a dmd option that will find and print all usages of static in global context. It should appear in a release _before_ this DIP release and kept for one release after, then removed.
  • Counter-example of valid generic code from Timon Gehr:
mixin template X(){
    static int x = 2;
}

class C{
    mixin X; // x is a public TLS variable
}

mixin X; // x is a public TLS variable.

Copyright

This document has been placed in the Public Domain.