Repository navigation
Take no .init of the inspected type in traits - #77
Open
ehudt-weka wants to merge 2 commits into
Open
ehudt-weka wants to merge 2 commits into
ehudt-weka wants to merge 2 commits into
Conversation
With LDC's `.init` size check (weka/ldc), Phobos templates failed on types whose `.init` literal is huge: the range traits (`isInputRange`, `isForwardRange`, `isBidirectionalRange`, `hasSlicing`, `ElementType`), `CommonType`, `isIterable`, `ForeachType`, `fullyQualifiedName`, `hasNested`, `hasElaborateAssign`, the alias-this `*TypeOf` traits, `ifTestable`, `isTuple`, `Rebindable`, `apply`, `map`, `each`, `substitute`, `min`/`max` (`extremum`) and `Appender.put`. Each built `T.init` only to name a type or call a member. They now use `lvalueOf`/`rvalueOf`, a null dereference, or a type-only form, so no literal is built. `CommonType` and `ifTestable` keep `.init` for operands that are not structs or unions: null and array literals merge differently in `?:`, and a scalar or null literal converts where a function result does not. The range traits add `is(typeof(R.sizeof))`, which lays out a struct before its member functions' attributes are inferred, as `R.init` did. Answers that change: `ifTestable` with a `const` or `immutable` parameter is false for a struct or union with indirections; `ElementType` of an enum based on an array is `void` (it was `inout(int)` for `int[]`, and `isInputRange` is false for such enums); `each` with a `ref` parameter compiles on a range whose `front` is a field.
ehudt-weka
force-pushed
the
init-literal-size-check
branch
from
October 15, 2026 14:57
b2acfe9 to
8764193
Compare
|
Thanks! please also submit this upstream to |
ehudt-weka
marked this pull request as ready for review
October 18, 2026 11:14
Author
|
@JohanEngelen this targets your |
…683364 Brings in the review fixes of dlang#11119 and dlang#11143. `ifTestable` on a struct or union: when `pred` does not take a `T`, try an rvalue of each other qualifier of `T`, since the unique literal `T.init` converted to all of them. A struct with indirections and a `const` or `immutable` predicate parameter is testable again, as before this change. Tests for `isIterable`/`ForeachType` (`ref @safe` opApply, non-copyable range), the range traits without `@property`, a member named `init`, an enum based on an array, `each` with a `ref` parameter on a field `front`, `Chunks` over an infinite range in `@safe pure` code, and qualified `isTuple`. Comments reworded.
ehudt-weka
added a commit
to weka/ldc
that referenced
this pull request
Oct 21, 2026
Member
|
@ehudt-weka Most of the changes look benign and useful, but the more complex ones need careful review which is very difficult now because it is unclear if the AI added random changes/unittests or whether they are needed and catch actual bugs. The PR description is also tediously long, indicating the same: split this PR into several. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Companion to weka/ldc#18, which makes a
.initan error when its literal costs more than--ctfe-max-alloc..initof a static array or struct builds a literal with one slot per element and per field even when only its type is used, as intypeof(T.init.field), so a large type can cost gigabytes of compiler memory.Phobos's traits and common algorithms built
T.initof the type they inspect only to name a type or call a member, so under the check they failed on such types. This replaces those uses withlvalueOf/rvalueOf, a null dereference, or a type-only form:std.range.primitives:isInputRange,isForwardRange,isBidirectionalRange,hasSlicing,ElementType.std.traits:CommonType,isIterable,ForeachType,fullyQualifiedName,hasNested,hasElaborateAssign, the alias-this*TypeOftraits,ifTestable.std.typecons:isTuple, the tuple compatibility check,Rebindable,apply.std.algorithm:map,each,substitute,min/max(extremum);std.array:Appender.put.Three places are not a plain substitution:
is(typeof(R.sizeof)).R.initused to lay a struct out before the traits' lambdas inferred its members' attributes. Without it, a trait evaluated inside the struct's own declaration infers them impure and@system. An example isChunks.opSlice, whose return type istypeof(takeExactly(this, 0)).CommonTypekeeps.initfor operands that are not structs or unions, because null and array literals merge differently in?:.ifTestablekeeps.initfor the same operands, because a scalar's.initconverts by value range (ifTestable!(int, (ubyte a) => a)is true) and a null literal converts to any qualifier. For a struct or union whosepreddoes not take aT, it tries an rvalue of each qualifier ofTinstead: the literalT.initis unique, so it converted to all of them, andifTestable!(S, (immutable S s) => s)stays true for a struct with a pointer field.So
min/max,eitherand the one-predicateendsWith/findSkip/skipOveron a static-array type whose literal is over the limit still report it.Answers that change. A differential check, written for the upstream review, asks every changed trait and the algorithms built on them about a zoo of types in 5 qualifiers: 64,860 answers, compiled with LDC 1.38 and stock druntime. 770 differ from the stock Phobos.
712 are on the zoo's 6 types with a member named
init(a member function, directly or from a mixin template, a field, or a static factory). Such a member hides the built-in property, soT.initnamed the member:CommonType!InitFieldwasintforstruct InitField { int x; int init; }, and for a structSwith a member functionvoid init(...),ElementType!(S[])was that function's type andisRandomAccessRange!(S[])was false. The answers are now about the type itself (InitField,S, true). Compiling our code base (~3,100 files) with each changed site also computing its old answer finds one such answer and no other change.The other 58, in three groups (counts include the zoo's
eachcall whose parameter is typedElementType!T, which followsElementType):ElementTypeandElementEncodingTypeof an enum based on an array (int[],const(int)[],int[3]) are nowvoid; they wereinout(int).frontaccepts such an enum only as its constant-folded literal, andisInputRangeis false for it before and after. (45)eachwith arefparameter now compiles on a range whosefront(orback) is a field. (3)sharedstruct withalias thisto a static array:ElementType,ElementEncodingType,isIterableandForeachTypedepended on what had been asked about the same type before; they now always give the answer it gets when asked first. (10)Compile cost. Even without the check, these traits no longer build the literals. On 8 of our heaviest modules (same source, stock vs patched druntime and Phobos, macOS, one file per compile): CPU −14% and peak RSS −39% without
-unittest(one module went from 23.7 to 4.8 GB); unchanged with-unittest.Tests (LDC's CMake test targets, macOS arm64)
.initliterals costing more than --ctfe-max-alloc WEKAPP-683364 weka/ldc#18's four.initlit tests pass. The differential check above; against 8764193, 64 answers differ, allifTestablewith aconstorimmutableparameter on a struct with indirections, which now match stock.-unittestand LDC's runtime test flags with the same result as without this change (no errors), so the static asserts in their unittests hold. 283 old-form/new-form pairs of the changed expressions, compiled with the stock compiler over nested structs with context pointers, qualified types,@disable this(),@disable this(this), classes, alias this,opApplywith aref @safedelegate and non-copyable elements, give the same answers..initliterals costing more than --ctfe-max-alloc WEKAPP-683364 weka/ldc#18 addstests/compilable/ctfe_max_alloc_init_phobos.d, which runs these templates on types whose literal is over the limit. Its cases fail with the previous Phobos, except oneChunkscase, which fails if the range traits dropR.sizeof.weka/ldc#18 pins this PR's head as
runtime/phobos, so this PR merges first; if the merge rewrites the commits, #18 re-pins. The same change is going upstream as dlang#11119 (traits) and dlang#11143 (ElementTypeandeach); this PR has their review fixes as of 2026-10-21.LLM/AI disclosure. This PR was written entirely by an LLM/AI. An AI coding agent (Claude, by Anthropic) wrote the code, the tests and this description, ran the checks and measurements in it, and opened this PR at @ehudt-weka's request, from that account. Its only review so far is the agent's own, not a human code review.