diff --git a/changelog/2.075.0_pre.dd b/changelog/2.075.0_pre.dd new file mode 100644 index 0000000000..5620f41848 --- /dev/null +++ b/changelog/2.075.0_pre.dd @@ -0,0 +1,548 @@ +Ddoc + +$(CHANGELOG_NAV_LAST 2.074.1) + +$(VERSION Jul 9, 2017, =================================================, + +$(BUGSTITLE Compiler changes, + +$(LI $(RELATIVE_LINK2 changelog17425,add __traits(getParameterStorageClasses, f, i))) +$(LI $(RELATIVE_LINK2 b6227,Comparison of values belonging to different enums is deprecated.)) +$(LI $(RELATIVE_LINK2 removeArrayProps,The deprecated built-in array properties `.sort` and `.reverse` were removed.)) +$(LI $(RELATIVE_LINK2 disallowSemiEmpty,Deprecate empty statements made by semicolon)) +$(LI $(RELATIVE_LINK2 changelog17421,add __traits(getFunctionVariadicStyle, f))) + +) + +$(BUGSTITLE Runtime changes, + +$(LI $(RELATIVE_LINK2 scandataseg-precise,Windows: the DATA and TLS segment can now be configured to be scanned precisely.)) +$(LI $(RELATIVE_LINK2 fiber-configure,Make fiber stack protection-page size configurable)) +$(LI $(RELATIVE_LINK2 fiber,Add Fiber's stack-protection page for Posix.)) +$(LI $(RELATIVE_LINK2 remove-TypeInfo.init,`TypeInfo.init` now refers to type property.)) + +) + +$(BUGSTITLE Library changes, + +$(LI $(RELATIVE_LINK2 std-range-has-length,`hasLength` now enforces that `length` has type `size_t`)) +$(LI $(RELATIVE_LINK2 split-std-datetime,std.datetime has been split into a package.)) +$(LI $(RELATIVE_LINK2 std-range-slides,`std.range.slide` (a fixed-size sliding window range) was added)) +$(LI $(RELATIVE_LINK2 pattern-deprecate,Several functions in `std.string` have been deprecated)) +$(LI $(RELATIVE_LINK2 std-digest-digest-secureCompare,Added a constant time comparison function for cryptographic hashes)) +$(LI $(RELATIVE_LINK2 std-digest-crc64,Added support for 64 bit CRC)) + +) + +$(BR)$(BIG $(RELATIVE_LINK2 bugfix-list, List of all bug fixes and enhancements in D $(VER).)) + +$(HR) + +$(BUGSTITLE Compiler changes, + +$(LI $(LNAME2 changelog17425,add __traits(getParameterStorageClasses, f, i)) +$(P +$(LINK2 https://issues.dlang.org/show_bug.cgi?id=17425, Bugzilla 17425) +) + +--- +ref int foo(return ref const int* p, scope int* a, out int b, lazy int c); + +pragma(msg, __traits(getParameterStorageClasses, foo, 0)); + +static assert(__traits(getParameterStorageClasses, foo, 0)[0] == "return"); +static assert(__traits(getParameterStorageClasses, foo, 0)[1] == "ref"); + +pragma(msg, __traits(getParameterStorageClasses, foo, 1)); +static assert(__traits(getParameterStorageClasses, foo, 1)[0] == "scope"); +static assert(__traits(getParameterStorageClasses, foo, 2)[0] == "out"); +static assert(__traits(getParameterStorageClasses, typeof(&foo), 3)[0] == "lazy"); +--- +) + +$(LI $(LNAME2 b6227,Comparison of values belonging to different enums is deprecated.) +$(P +This change does not affect anonymous enumerations. +) + +--- +enum Status +{ + good, + bad +} +enum OtherStatus +{ + ok + no, +} + +// Deprecated - Even though both good and ok evaluate to 0 they belong to +// different enumeration types +static assert(Status.good == OtherStatus.ok); +--- +) + +$(LI $(LNAME2 removeArrayProps,The deprecated built-in array properties `.sort` and `.reverse` were removed.) +$(P +Usage of those built-in array properties was deprecated since 2.072.0 and they have now been removed. +Use $(REF sort, std, algorithm, sorting) and $(REF reverse, std, algorithm, mutation) instead. +) +) + +$(LI $(LNAME2 disallowSemiEmpty,Deprecate empty statements made by semicolon) +$(P +Creating empty statements using semicolons, for which +was previously issued a warning is now causing a deprecation +hint. +) +) + +$(LI $(LNAME2 changelog17421,add __traits(getFunctionVariadicStyle, f)) +$(P +$(LINK2 https://issues.dlang.org/show_bug.cgi?id=17421, Bugzilla 17421) +) + +--- +import core.stdc.stdarg; + +void novar() {} +extern(C) void cstyle(int, ...) {} +extern(C++) void cppstyle(int, ...) {} +void dstyle(...) {} +void typesafe(int[]...) {} + +static assert(__traits(getFunctionVariadicStyle, novar) == "none"); +static assert(__traits(getFunctionVariadicStyle, cstyle) == "stdarg"); +static assert(__traits(getFunctionVariadicStyle, cppstyle) == "stdarg"); +static assert(__traits(getFunctionVariadicStyle, dstyle) == "argptr"); +static assert(__traits(getFunctionVariadicStyle, typesafe) == "typesafe"); + +static assert(__traits(getFunctionVariadicStyle, (int[] a...) {}) == "typesafe"); +static assert(__traits(getFunctionVariadicStyle, typeof(cstyle)) == "stdarg"); +--- +) + + +) + +$(BUGSTITLE Runtime changes, + +$(LI $(LNAME2 scandataseg-precise,Windows: the DATA and TLS segment can now be configured to be scanned precisely.) +$(P +A new runtime option "scanDataSeg" has been added to enable precise scanning of the +DATA and the TLS segments. This uses information generated by the compiler to +identify possible pointers inside these segments. Possible option values are +"conservative" (default) and "precise". +) + +$(P +As usual, this option can be set by the environment, the command line or by +embedding the option into the executable similar to the +$(LINK2 $(ROOT_DIR)spec/garbage.html#gc_config, GC options). +) + +$(P +For example add this code to your main module to enable precise scanning: +) +--------- +extern(C) __gshared string[] rt_options = [ "scanDataSeg=precise" ]; +--------- +) + +$(LI $(LNAME2 fiber-configure,Make fiber stack protection-page size configurable) +$(P +It is now possible to change the guard page size by using +the new Fiber's constructor argument - guard_page_size. It defaults to +`PAGE_SIZE` (the same it used to be on Windows), and specifying 0 will +turn this feature off. +) +) + +$(LI $(LNAME2 fiber,Add Fiber's stack-protection page for Posix.) +$(P +The feature already existing for Windows' fiber implementation is now added to +the systems using mmap to allocate fibers' stacks: After (or before) the last +page used for the Fiber's stack, the page is allocate which is protected for +any kind of access. This will cause system to trap immediately on the fiber's +stack overflow. If in debugger session, one can inspect contents of the memory +before or after stack pointer and it can be seen if it contains END OF FIBER +string pattern. +) +) + +$(LI $(LNAME2 remove-TypeInfo.init,`TypeInfo.init` now refers to type property.) +$(P +`TypeInfo.init` used to refer to the method that is now called +$(REF_OBJECT_SHORT TypeInfo.initializer). The name change was necessary because +the name "init" would clash with the type property of the same name +($(GLINK2 property, init)). `TypeInfo.init` now refers to the type property. +) +) + + +) + +$(BUGSTITLE Library changes, + +$(LI $(LNAME2 std-range-has-length,`hasLength` now enforces that `length` has type `size_t`) +$(P +Historically `hasLength!R` yielded `true` for types whereby +`R.length` returns other types convertible to `ulong`, such as `int`, `ushort`, +`const(size_t)`, user-defined types using `alias this`, or notably `ulong` on +32-bit systems. This behavior has been deprecated. After December 2017, +$(REF hasLength, std, range, primitives) will yield `true` only if `R.length` +yields the exact type `size_t`. +) +) + +$(LI $(LNAME2 split-std-datetime,std.datetime has been split into a package.) +$(P +std.datetime is now a package containing the following modules: +) + +$(P +$(UL + $(LI $(MREF std,datetime,date)) + $(LI $(MREF std,datetime,interval)) + $(LI $(MREF std,datetime,stopwatch)) + $(LI $(MREF std,datetime,systime)) + $(LI $(MREF std,datetime,timezone)) +) +) + +$(P +$(MREF std,datetime,package) publicly imports all of those modules. So, it +should be the case that no existing code will break, as everything in +std.datetime will still be imported by importing std.datetime. New code can +choose to import the modules individually or to import the entire package. +) + +$(P +$(MREF std,datetime,date) contains Date, TimeOfDay, DateTime, and the related +free functions. It also contains DateTimeException. +) + +$(P +$(MREF std,datetime,interval) contains the *Interval and *IntervalRange types +as well as the related free functions. +) + +$(P +$(MREF std,datetime,systime) contains SysTime and the related free functions. +) + +$(P +$(MREF std,datetime,timezone) contains the time zone types. +) + +$(P +$(MREF std,datetime,package) contains StopWatch and the benchmarking functions +(so, they can only be imported via std.datetime and not via a submodule). As +those functions use $(REF TickDuration,core,time) (which is being replaced by +$(REF MonoTime,core,time), they are slated for deprecation). +) + +$(P +$(MREF std,datetime,stopwatch) has been added. It contains versions of +StopWatch and benchmark which have almost the same API as the existing symbols, +but they use $(REF MonoTime,core,time) and $(REF Duration,core,time) instead of +$(REF TickDuration,core,time). In the next major release, the old functions in +std.datetime.package will be deprecated, so code which uses the old +benchmarking functions should be updated to use std.datetime.stopwatch. +) + +$(P +However, note that in order to avoid irreconcilable symbol conflicts between +the new and old versions, std.datetime.stopwatch will not be publicly imported +by std.datetime.package until the old symbols have been removed. So, for the +time being, code using $(REF StopWatch,std,datetime,stopwatch) or +$(REF StopWatch,std,datetime,benchmark) will need to import +std.datetime.stopwatch directly. Code which imports both std.datetime and +std.datetime.stopwatch will need to either use selective imports or fully +qualified symbols to reconcile the symbol conflicts, but no code will be +affected by the changes until it's updated to import std.datetime.stopwatch, +and when the old symbols are finally removed, the selective imports and fully +qualified paths to the new symbols will continue to work and won't break +(though at that point, simply importing std.datetime will work, since +std.datetime.package will have been updated to publicly import +std.datetime.stopwatch). Code that simply imporst std.datetime.stopwatch without +importing std.datetime will not have to worry about symbol conflicts. +) +) + +$(LI $(LNAME2 std-range-slides,`std.range.slide` (a fixed-size sliding window range) was added) +$(P +$(REF slide, std, range) allows to iterate a range in sliding windows: +) + +--- +import std.array : array; +import std.algorithm.comparison : equal; + +assert([0, 1, 2, 3].slide(2).equal!equal( + [[0, 1], [1, 2], [2, 3]] +)); +assert(5.iota.slide(3).equal!equal( + [[0, 1, 2], [1, 2, 3], [2, 3, 4]] +)); + +assert(iota(7).slide(2, 2).equal!equal([[0, 1], [2, 3], [4, 5]])); +assert(iota(12).slide(2, 4).equal!equal([[0, 1], [4, 5], [8, 9]])); + +// set a custom stepsize (default 1) +assert(6.iota.slide(1, 2).equal!equal( + [[0], [2], [4]] +)); + +assert(6.iota.slide(2, 4).equal!equal( + [[0, 1], [4, 5]] +)); + +// allow slide with less elements than the window size +assert(3.iota.slide!(No.withFewerElements)(4).empty); +assert(3.iota.slide!(Yes.withFewerElements)(4).equal!equal( + [[0, 1, 2]] +)); +--- +) + +$(LI $(LNAME2 pattern-deprecate,Several functions in `std.string` have been deprecated) +$(P +The functions $(REF inPattern, std, string), $(REF countchars, std, string), +$(REF removechars, std, string), $(REF squeeze, std, string), and +$(REF munch, std, string), have all been deprecated. These functions are +obsolete, as their functionality is better covered by the functions in +$(MREF std, regex) and $(MREF std, algorithm). They will be removed from +$(MREF std, string) on May 2018. +) + +$(P +If you still need to use these, please see $(LINK2 https://github.com/dlang/undeaD, undeaD). +) + +$(P +The following are examples of the deprecated functions, and their modern replacements. +) + +$(P +Use $(REF find, std, algorithm, searching) to replace $(REF munch, std, string): +) +------- +import std.algorithm; +import std.ascii; +import std.string; +import std.utf; + +string s = "\tabc"; + +// old +s.munch(whitespace); + +// new +s = s.find!(a => !isWhite(a)); +------- + +$(P +Use $(REF matchFirst, std, regex) to replace $(REF inPattern, std, string): +) +------- +import std.string; +import std.regex; + +// old +if (inPattern('x', "a-z")) { ... } + +// new +if ("x".matchFirst(regex("[a-z]"))) { ... } +------- + +$(P +Use $(REF replaceAll, std, regex) to replace $(REF removechars, std, string): +) +------- +import std.string; +import std.regex; + +// old +"abc".removechars("a-z"); + +// new +"abc".replaceAll(regex("[a-z]"), ""); +------- + +$(P +Use $(REF uniq, std, algorithm, iteration) to replace $(REF squeeze, std, string): +) +------- +import std.algorithm; +import std.string; + +// old +"hello".squeeze; + +// new +"hello".uniq; +------- +) + +$(LI $(LNAME2 std-digest-digest-secureCompare,Added a constant time comparison function for cryptographic hashes) +$(P +Added a new function to $(REF secureEqual, std, digest, digest) that compares +two ranges that represent hashes in a secure manner. The comparison is done in +constant time regardless of the equality of the two ranges in order to protect +against timing attacks. For more information on the attack, please refer to +the docs on $(REF secureEqual, std, digest, digest). +) + +----- +import std.digest.digest : secureEqual, toHexString; +import std.digest.hmac : hmac; +import std.digest.sha : SHA1; +import std.string : representation; + +void main() +{ + // a typical HMAC data integrity verification + auto secret = "A7GZIP6TAQA6OHM7KZ42KB9303CEY0MOV5DD6NTV".representation; + auto data = "data".representation; + + string hex1 = data.hmac!SHA1(secret).toHexString; + string hex2 = data.hmac!SHA1(secret).toHexString; + + string hex3 = "data1".representation.hmac!SHA1(secret).toHexString; + + assert( secureEqual(hex1, hex2)); + assert(!secureEqual(hex1, hex3)); +} +----- +) + +$(LI $(LNAME2 std-digest-crc64,Added support for 64 bit CRC) +$(P +Support for both ISO and ECMA 64 bit CRC was added to $(MREF std, digest, crc). +) + +------- +import std.digest.crc; + +void main() +{ + ubyte[8] hash64ecma = crc64ECMAOf("abc"); + assert(crcHexString(hash64ecma) == "2CD8094A1A277627"); + + ubyte[8] hash64iso = crc64ISOOf("abc"); + assert(crcHexString(hash64iso) == "3776C42000000000"); +} +------- +) + + +) + +$(BR)$(BIG $(LNAME2 bugfix-list, List of all bug fixes and enhancements in D $(VER):)) + +$(BUGSTITLE DMD Compiler regressions, + +$(LI $(BUGZILLA 16408): [REG2.065] left-to-right order of evaluation of function arguments not consistently followed) +$(LI $(BUGZILLA 17275): [REG 2.072.0] AssertError@declaration.d$(LPAREN)2121$(RPAREN): Assertion failure) +$(LI $(BUGZILLA 17293): "Using C++ Classes From D" example no longer works) +$(LI $(BUGZILLA 17338): [Reg 2.075] link failure unsupported symbol section 0xff01) +$(LI $(BUGZILLA 17356): [Reg 2.075] __simd_sto no longer executed) +$(LI $(BUGZILLA 17399): [REG2.071] core.checkedint.addu cannot inline function) +$(LI $(BUGZILLA 17451): ICE in ddmd/declaration.d$(LPAREN)2179$(RPAREN)) +$(LI $(BUGZILLA 17502): [REG2.064] Out contract in class method causes dmd segfault.) +$(LI $(BUGZILLA 17505): [REG2.075] @safe constructor requires the deconstructor to be safe as well) +$(LI $(BUGZILLA 17506): [REG2.075] @disable constructor requires members to be initialized) +) +$(BUGSTITLE DMD Compiler bugs, + +$(LI $(BUGZILLA 7016): local import does not create -deps dependency) +$(LI $(BUGZILLA 13331): naked asm functions are broken when compiling with -profile) +$(LI $(BUGZILLA 14246): RAII - proper destruction of partially constructed objects/structs) +$(LI $(BUGZILLA 15896): private ignored when import bindings are used) +$(LI $(BUGZILLA 15945): sizeof on an invalid type seems to compile.) +$(LI $(BUGZILLA 16244): compiler ICE on complex `typeof$(LPAREN)$(RPAREN)` for method arg type) +$(LI $(BUGZILLA 16566): hasLength should enforce that length has type size_t) +$(LI $(BUGZILLA 17289): With Xcode 8.3 linker, warnings of "pointer not aligned") +$(LI $(BUGZILLA 17317): 2.074.0 release candidate does not have updated backend license) +$(LI $(BUGZILLA 17335): Function calls in conjunctions do not short circuit when evaluated during compilation) +$(LI $(BUGZILLA 17337): SIGILL for AVX vector initialization) +$(LI $(BUGZILLA 17339): ambiguous mangling with const alias argument) +$(LI $(BUGZILLA 17344): ICE with assignment of post inc-/decremented integral vector) +$(LI $(BUGZILLA 17349): Covariant overrides should be allowed) +$(LI $(BUGZILLA 17367): CodeView/MSCOFF: bad debug information for enumerators) +$(LI $(BUGZILLA 17391): SECURITY: XSS through DDOC comments) +$(LI $(BUGZILLA 17422): [scope] class reference not initialized as scope variable) +$(LI $(BUGZILLA 17432): [DIP1000] scope delegates change type, but not mangling) +$(LI $(BUGZILLA 17450): escaping delegate context pointer not detected for member functions) +$(LI $(BUGZILLA 17468): Internal assertion fails during CTFE) +$(LI $(BUGZILLA 17491): Compiles on invalid: *&s.init.var is not an lvalue) +$(LI $(BUGZILLA 17495): __traits$(LPAREN)getParameterStorageClasses$(RPAREN) doesn't work with tuples as parameters) +) +$(BUGSTITLE DMD Compiler enhancements, + +$(LI $(BUGZILLA 6227): Comparison of different enums) +$(LI $(BUGZILLA 16197): Constructors/postblits and destructors don't match up for array initialisation) +$(LI $(BUGZILLA 16540): Attributes do not propagate correctly in lazy params) +$(LI $(BUGZILLA 16600): Wrong error message for ambiguous mutable/immutable constructor) +$(LI $(BUGZILLA 17396): Add colorized syntax highlighting to error messages emitted by dmd) +$(LI $(BUGZILLA 17419): add __traits$(LPAREN)getLinkage, s$(RPAREN) to the the linkage of symbol s) +$(LI $(BUGZILLA 17425): add __traits$(LPAREN)getParameterStorageClasses, f, i$(RPAREN)) +$(LI $(BUGZILLA 17429): [scope] each scope class references adds another delete call) +$(LI $(BUGZILLA 17457): Named Return Value Optimization $(LPAREN)NRVO$(RPAREN) not done with return of constructor call) +$(LI $(BUGZILLA 17494): Do not execute scope$(LPAREN)...$(RPAREN) if an Error exception has been thrown) +) +$(BUGSTITLE Phobos regressions, + +$(LI $(BUGZILLA 17452): Undefined references in std.container.array) +$(LI $(BUGZILLA 17472): [Reg 2.075] typeof$(LPAREN)stdin$(RPAREN) is no longer a File) +$(LI $(BUGZILLA 17511): [REG 2.075a] std.xml puts grand-children into items) +) +$(BUGSTITLE Phobos bugs, + +$(LI $(BUGZILLA 15517): std.experimental.logger: using 'sharedLog' to change to file logging for default logger does not work) +$(LI $(BUGZILLA 15534): [std.experimental.logger.core] Documentation mismatch) +$(LI $(BUGZILLA 15720): iota$(LPAREN)long.max, long.min, step$(RPAREN) does not work properly) +$(LI $(BUGZILLA 15763): std.math.approxEqual is not symmetric) +$(LI $(BUGZILLA 16232): std.experimental.logger.core.sharedLog isn't thread-safe) +$(LI $(BUGZILLA 16246): cannot call iota with 3 [u]bytes or 3 [u]shorts) +$(LI $(BUGZILLA 16256): std.experimental.logger cant log a dstring properly) +$(LI $(BUGZILLA 16326): filter is not lazy enough & has weird save behavior) +$(LI $(BUGZILLA 17251): Appender.put errors out with const input range elements) +$(LI $(BUGZILLA 17270): std.experimental.Final fails on pointers) +$(LI $(BUGZILLA 17283): std.experimental.typecons uses private module members) +$(LI $(BUGZILLA 17288): formattedWrite error when width/precision provided and no value to format) +$(LI $(BUGZILLA 17314): BinaryHeap crashes upon insertion if heapified with an array of length 1) +$(LI $(BUGZILLA 17328): std.experimental.logger: wrong hex formatting for zeros) +$(LI $(BUGZILLA 17519): RedBlackTree doesn't like const/immutable elements) +) +$(BUGSTITLE Phobos enhancements, + +$(LI $(BUGZILLA 6621): Superimposition amount for std.range.chunks) +$(LI $(BUGZILLA 7102): std.numeric.gcd with BigInts too) +$(LI $(BUGZILLA 10001): string formatting with underscores) +$(LI $(BUGZILLA 16108): `to!string` fails on struct with disabled postblit) +$(LI $(BUGZILLA 16615): std.process is missing functionality for child processes) +$(LI $(BUGZILLA 17286): A function for comparing two digests securely) +$(LI $(BUGZILLA 17327): std.getopt: repeated options unrecognised) +$(LI $(BUGZILLA 17394): std.file.mkdirRecurse isn't @safe) +) +$(BUGSTITLE Druntime bugs, + +$(LI $(BUGZILLA 9275): [GC] removeRoot hits assert$(LPAREN)0$(RPAREN) instead of being a no-op $(LPAREN)as documented$(RPAREN)) +$(LI $(BUGZILLA 12233): Attempting to use TypeInfo.init results in a compiler error due to lack of 'this'.) +$(LI $(BUGZILLA 13186): core/sys/posix/sys/uio.d is not linked into the standard lib) +) +$(BUGSTITLE dlang.org bugs, + +$(LI $(BUGZILLA 8107): Float literals are not specified as they are implemented) +$(LI $(BUGZILLA 17303): type error in the href url under the link Systems Programming) +$(LI $(BUGZILLA 17469): View source code) +$(LI $(BUGZILLA 17501): Runnable unittest problem with AST rewrite) +) +) +$(CHANGELOG_NAV_LAST 2.074.1) +Macros: + VER=2.075.0 + TITLE=Change Log: $(VER) diff --git a/download.dd b/download.dd index 9a79a77ee1..1da51a39a3 100644 --- a/download.dd +++ b/download.dd @@ -167,9 +167,9 @@ Macros: DMDV2=$(LATEST) - BETA=$(COMMENT $0) - _=BETA=$0 - B_DMDV2=2.074.1 + _=BETA=$(COMMENT $0) + BETA=$0 + B_DMDV2=2.075.0 B_SUFFIX=b1 DEB32=$(DLSITE dmd_$(DMDV2)-0_i386.deb) diff --git a/spec/garbage.dd b/spec/garbage.dd index 01cb57d73e..dc3421f815 100644 --- a/spec/garbage.dd +++ b/spec/garbage.dd @@ -434,6 +434,49 @@ $(H2 $(LNAME2 gc_config, Configuring the Garbage Collector)) options specified through the environment or embedded in the executable. ) +$(H2 $(LNAME2 precise_dataseg, Precise Scanning of the DATA and TLS segment)) + + $(P $(B Windows only:) As of version 2.075, the DATA (global shared data) + and TLS segment (thread local data) of an executable + or DLL can be configured to be scanned precisely by the garbage collector + instead of conservatively. This takes + advantage of information emitted by the compiler to + identify possible mutable pointers inside these segments. Immutable pointers + $(DDSUBLINK spec/const3, immutable_storage_class, with initializers) + are excluded from scanning, too, as they can only point to preallocated memory. + ) + + $(P Precise scanning can be enabled with the D runtime option "scanDataSeg". Possible option + values are "conservative" (default) and "precise". As with the GC options, it can be + specified on the command line, in the environment or embedded into the executable, e.g. + --------- + extern(C) __gshared string[] rt_options = [ "scanDataSeg=precise" ]; + --------- + ) + + $(P $(RED Attention:) Enabling precise scanning needs slightly more caution typing + global memory. For example, if you pre-allocate memory in the DATA/TLS segment and later + emplace an object instance with references to other allocations into this memory, + you must not use basic integer types to reserve the space. Doing so will cause the + garbage collector not to detect the references. Instead, use an array type that + will scan this area conservatively. Using `void*` is usually the best option as it also + ensures proper alignment for pointers being scanned by the GC. + --------- + class Singleton { void[] mem; } + void*[(__traits(classInstanceSize, Singleton) - 1) / (void*).sizeof + 1] singleton_store; + static this() { emplace!Singleton(singleton_store).mem = allocateMem(); } + Singleton singleton() { return cast(Singleton)singleton_store.ptr; } + --------- + For precise typing of that area, you can also let the compiler generate the class + instance into the DATA segment for you: + --------- + class Singleton { void[] mem; } + shared(Singleton) singleton = new Singleton; + shared static this() { singleton.mem = allocateSharedMem(); } + --------- + This doesn't work for TLS memory, though. + ) + $(H2 $(LNAME2 references, References)) $(UL