digitalmars.dip.development - First Draft: Implicit Type Template Instantiation via Constructors
- Meta (49/49) Mar 11 2025 This DIP is a partial resurrection of DIP 40
- jmh530 (3/9) Mar 11 2025 Glad to see someone working on this problem.
- Meta (29/39) Mar 11 2025 From my understanding, it should work the same way as IFTI, i.e.,
- 12345swordy (6/55) Mar 20 2025 You spell "Changes" wrong, you better fixed that.
- Meta (6/11) May 12 2025 I know, and I agree, but that can be added by a later DIP, and
- Sebastiaan Koppe (12/25) May 12 2025 Makes a lot of sense to me.
- Meta (3/32) May 13 2025 That is not actually a constructor - it is struct literal syntax.
- Sebastiaan Koppe (6/42) May 14 2025 Fair enough, but could the dip support it, or perhaps in the
- jmh530 (5/14) May 14 2025 Struct literal syntax only works if there are no constructors. So
- Meta (14/58) May 14 2025 I was going to say that this is not possible without at least 1
- Dennis (15/20) May 14 2025 It could be added, but there's something to watch out for: as the
- Quirin Schroll (45/66) Jul 16 2025 Simple things ought to work.
This DIP is a partial resurrection of DIP 40 (https://wiki.dlang.org/DIP40) by me and Dennis Korpel. Dennis is working on the implementation (https://github.com/dlang/dmd/pull/16910) while I am writing the DIP. The purpose of this DIP is to propose a new avenue for Implicit Template Instantiation (ITI) via constructors. Currently (that I'm aware of) D only does Implicit _Function_ Template Instantiation (IFTI); the proposal is to extend this implicit instantiation to types as well, via their constructors. Before this DIP: ```d struct Pair(T, U) { T t; U u; this(T t, U u) { this.t = t; this.u = u; } } void main() { auto p1 = Pair(1, "asdf"); // Error: struct `Pair` is not callable using argument types `!()(int, string)` // Candidate is: `Pair(T, U)` } ``` After this DIP: ``` struct Pair(T, U) { T t; U u; this(T t, U u) { this.t = t; this.u = u; } } void main() { auto p1 = Pair(1, "asdf"); // Okay, T is deduced as int and U as string } ``` The DIP: https://github.com/MetaLang/DIPs/blob/dip1050/DIPs/DIP1050.md
Mar 11 2025
On Wednesday, 12 March 2025 at 00:20:55 UTC, Meta wrote:This DIP is a partial resurrection of DIP 40 (https://wiki.dlang.org/DIP40) by me and Dennis Korpel. Dennis is working on the implementation (https://github.com/dlang/dmd/pull/16910) while I am writing the DIP. [...]Glad to see someone working on this problem. How would this apply to template aliases (e.g. DIP1023)?
Mar 11 2025
On Wednesday, 12 March 2025 at 02:37:06 UTC, jmh530 wrote:On Wednesday, 12 March 2025 at 00:20:55 UTC, Meta wrote:From my understanding, it should work the same way as IFTI, i.e., if eventually this code compiles: ```d struct TemplateType(T) { } alias TemplateAlias(T) = TemplateType!T; void templateFunction(T)(TemplateAlias!T arg) { } void main() { TemplateAlias!int ta; templateFunction(ta); } ``` Then this code should as well: ```d struct TemplateType(T) { } alias TemplateAlias(T) = TemplateType!T; struct AnotherTemplateType(T) { this(TemplateAlias!T arg) {} } void main() { TemplateAlias!int ta; auto att = AnotherTemplateType(ta); // Currently does not compile, even if you add AnotherTemplateType!(TemplateAlias!int)(ta) } ```This DIP is a partial resurrection of DIP 40 (https://wiki.dlang.org/DIP40) by me and Dennis Korpel. Dennis is working on the implementation (https://github.com/dlang/dmd/pull/16910) while I am writing the DIP. [...]Glad to see someone working on this problem. How would this apply to template aliases (e.g. DIP1023)?
Mar 11 2025
On Wednesday, 12 March 2025 at 00:20:55 UTC, Meta wrote:This DIP is a partial resurrection of DIP 40 (https://wiki.dlang.org/DIP40) by me and Dennis Korpel. Dennis is working on the implementation (https://github.com/dlang/dmd/pull/16910) while I am writing the DIP. The purpose of this DIP is to propose a new avenue for Implicit Template Instantiation (ITI) via constructors. Currently (that I'm aware of) D only does Implicit _Function_ Template Instantiation (IFTI); the proposal is to extend this implicit instantiation to types as well, via their constructors. Before this DIP: ```d struct Pair(T, U) { T t; U u; this(T t, U u) { this.t = t; this.u = u; } } void main() { auto p1 = Pair(1, "asdf"); // Error: struct `Pair` is not callable using argument types `!()(int, string)` // Candidate is: `Pair(T, U)` } ``` After this DIP: ``` struct Pair(T, U) { T t; U u; this(T t, U u) { this.t = t; this.u = u; } } void main() { auto p1 = Pair(1, "asdf"); // Okay, T is deduced as int and U as string } ``` The DIP: https://github.com/MetaLang/DIPs/blob/dip1050/DIPs/DIP1050.mdYou spell "Changes" wrong, you better fixed that. It is a straight up massive miss opportunity to not handle Partial template parameter deduction here. C++ doesn't even handle that edge case which due to that you had to resort to an all or nothing in C++, which can be very annoying at times.
Mar 20 2025
On Thursday, 20 March 2025 at 18:01:05 UTC, 12345swordy wrote:You spell "Changes" wrong, you better fixed that.Thank you, fixed.It is a straight up massive miss opportunity to not handle Partial template parameter deduction here. C++ doesn't even handle that edge case which due to that you had to resort to an all or nothing in C++, which can be very annoying at times.I know, and I agree, but that can be added by a later DIP, and W&A suggested that _this_ DIP be as simple as possible. We hope to expand on this feature further with subsequent proposals; this is just a first step.
May 12 2025
On Wednesday, 12 March 2025 at 00:20:55 UTC, Meta wrote:This DIP is a partial resurrection of DIP 40 (https://wiki.dlang.org/DIP40) by me and Dennis Korpel. Dennis is working on the implementation (https://github.com/dlang/dmd/pull/16910) while I am writing the DIP. The purpose of this DIP is to propose a new avenue for Implicit Template Instantiation (ITI) via constructors. Currently (that I'm aware of) D only does Implicit _Function_ Template Instantiation (IFTI); the proposal is to extend this implicit instantiation to types as well, via their constructors. [...] The DIP: https://github.com/MetaLang/DIPs/blob/dip1050/DIPs/DIP1050.mdMakes a lot of sense to me. What about implicit constructors though? ``` struct Pair(T,U) { T t; U u; } void main() { auto p = Pair(1,"string"); } ```
May 12 2025
On Tuesday, 13 May 2025 at 06:06:54 UTC, Sebastiaan Koppe wrote:On Wednesday, 12 March 2025 at 00:20:55 UTC, Meta wrote:That is not actually a constructor - it is struct literal syntax. I did not realize there was a difference either until recently.This DIP is a partial resurrection of DIP 40 (https://wiki.dlang.org/DIP40) by me and Dennis Korpel. Dennis is working on the implementation (https://github.com/dlang/dmd/pull/16910) while I am writing the DIP. The purpose of this DIP is to propose a new avenue for Implicit Template Instantiation (ITI) via constructors. Currently (that I'm aware of) D only does Implicit _Function_ Template Instantiation (IFTI); the proposal is to extend this implicit instantiation to types as well, via their constructors. [...] The DIP: https://github.com/MetaLang/DIPs/blob/dip1050/DIPs/DIP1050.mdMakes a lot of sense to me. What about implicit constructors though? ``` struct Pair(T,U) { T t; U u; } void main() { auto p = Pair(1,"string"); } ```
May 13 2025
On Wednesday, 14 May 2025 at 06:46:09 UTC, Meta wrote:On Tuesday, 13 May 2025 at 06:06:54 UTC, Sebastiaan Koppe wrote:Fair enough, but could the dip support it, or perhaps in the future? The fact that we both expected it was a constructor - and you could argue it actually is, on the grounds that it does in fact construct an object - suggests more users would expect it to work.On Wednesday, 12 March 2025 at 00:20:55 UTC, Meta wrote:That is not actually a constructor - it is struct literal syntax. I did not realize there was a difference either until recently.This DIP is a partial resurrection of DIP 40 (https://wiki.dlang.org/DIP40) by me and Dennis Korpel. Dennis is working on the implementation (https://github.com/dlang/dmd/pull/16910) while I am writing the DIP. The purpose of this DIP is to propose a new avenue for Implicit Template Instantiation (ITI) via constructors. Currently (that I'm aware of) D only does Implicit _Function_ Template Instantiation (IFTI); the proposal is to extend this implicit instantiation to types as well, via their constructors. [...] The DIP: https://github.com/MetaLang/DIPs/blob/dip1050/DIPs/DIP1050.mdMakes a lot of sense to me. What about implicit constructors though? ``` struct Pair(T,U) { T t; U u; } void main() { auto p = Pair(1,"string"); } ```
May 14 2025
On Wednesday, 14 May 2025 at 16:41:44 UTC, Sebastiaan Koppe wrote:[snip]Struct literal syntax only works if there are no constructors. So at (current) step 4, you would want to check if there are no constructors. But then it might be a little more complicated to actually handle that case.That is not actually a constructor - it is struct literal syntax. I did not realize there was a difference either until recently.Fair enough, but could the dip support it, or perhaps in the future? The fact that we both expected it was a constructor - and you could argue it actually is, on the grounds that it does in fact construct an object - suggests more users would expect it to work.
May 14 2025
On Wednesday, 14 May 2025 at 16:41:44 UTC, Sebastiaan Koppe wrote:On Wednesday, 14 May 2025 at 06:46:09 UTC, Meta wrote:I was going to say that this is not possible without at least 1 defined constructor due to how the implementation works. However, look at step 5 of the algorithm in the DIP: ``` 5. If a matching constructor is found (in this case, this(T t, U u), create a new constructor this(T, U)(T t, U u) and try IFTI with that. ``` If it's creating a new constructor anyway to be instantiated, it could probably do this for structs even when there are no explicit constructors defined... I'll see what Dennis thinks want this and whether it's worth doing, because it *should* be very simple to add.On Tuesday, 13 May 2025 at 06:06:54 UTC, Sebastiaan Koppe wrote:Fair enough, but could the dip support it, or perhaps in the future? The fact that we both expected it was a constructor - and you could argue it actually is, on the grounds that it does in fact construct an object - suggests more users would expect it to work.On Wednesday, 12 March 2025 at 00:20:55 UTC, Meta wrote:That is not actually a constructor - it is struct literal syntax. I did not realize there was a difference either until recently.This DIP is a partial resurrection of DIP 40 (https://wiki.dlang.org/DIP40) by me and Dennis Korpel. Dennis is working on the implementation (https://github.com/dlang/dmd/pull/16910) while I am writing the DIP. The purpose of this DIP is to propose a new avenue for Implicit Template Instantiation (ITI) via constructors. Currently (that I'm aware of) D only does Implicit _Function_ Template Instantiation (IFTI); the proposal is to extend this implicit instantiation to types as well, via their constructors. [...] The DIP: https://github.com/MetaLang/DIPs/blob/dip1050/DIPs/DIP1050.mdMakes a lot of sense to me. What about implicit constructors though? ``` struct Pair(T,U) { T t; U u; } void main() { auto p = Pair(1,"string"); } ```
May 14 2025
On Wednesday, 14 May 2025 at 16:41:44 UTC, Sebastiaan Koppe wrote:Fair enough, but could the dip support it, or perhaps in the future? The fact that we both expected it was a constructor - and you could argue it actually is, on the grounds that it does in fact construct an object - suggests more users would expect it to work.It could be added, but there's something to watch out for: as the DIP specifies, the search for constructors in a template is shallow, so just because the search didn't find one, doesn't mean there is none. I'm imagining a scenario where a constructor is hidden behind a mixin / static if or whatever, so Implicit Template Instantiation would assume a generated 'default constructor', but after the instantiation it ends up calling the written constructor instead but with template parameters resolved incorrectly. Granted, that might also happen when a 'hidden' constructor exists with a stronger match than the constructor found for IFTI, so I'm not sure. Perhaps an extra check can be added that the constructor used for deriving template parameters is the one that ends up actually being called, but it's getting rather complex.
May 14 2025
On Wednesday, 14 May 2025 at 22:30:27 UTC, Dennis wrote:On Wednesday, 14 May 2025 at 16:41:44 UTC, Sebastiaan Koppe wrote:Simple things ought to work. D’s templates, contrary to C++’s templates, are extremely flexible. Without actually instantiating them, you can’t really know what’s going to be in there. To assess if an instantiated template won’t have a constructor explicitly defined, the language rules must do a conservative guess. It’ll never good enough for some, but pretending this isn’t possible won’t make people happy either. A lexical analysis can look for a constructor. This is quick and cheap. Contrary to semantic analysis, lexical analysis can see through `static if`, `version`, and `debug`. It can also see if there’s any mixin template or a string mixin. If s string mixin is present, things get really difficult. ITTI cannot assume the template instance (the type) has an implicitly defined constructor. Since we’re inferring the arguments from a constructor call, we need to know which constructor it will be, and it won’t be the implicitly defined one if it won’t exist. The same kind of lexical analysis can examine mixin templates and show that it can’t possibly add constructors. Then, instantiating the the mixin template is fine, even if it’s instantiated using some of the struct template’s type parameters. Here, semantic is needed to examine it. One option is to synthesize a new template with only the string mixin present, instantiating all type parameters with the internal `__error__` type and try running the string mixin. If it succeeds without error and doesn’t add a constructor, it won’t do so in the original struct template. That might be too expensive to run, though. If I’m not mistaken, `version` and `debug` cannot depend on template arguments, so it can be decided which branch they take. If that excludes a the only constructors defined, the template instance definitely won’t have any even if they’re lexically present. A deeper analysis might be able to show that the `static if` condition or the mixin stuff doesn’t depend on the struct template’s arguments. That is only relevant if one branch defines a constructor or has a string mixin and the other does neither. In that case, we can employ an approach similar to the one for string mixins.Fair enough, but could the dip support it, or perhaps in the future? The fact that we both expected it was a constructor - and you could argue it actually is, on the grounds that it does in fact construct an object - suggests more users would expect it to work.It could be added, but there's something to watch out for: as the DIP specifies, the search for constructors in a template is shallow, so just because the search didn't find one, doesn't mean there is none. I'm imagining a scenario where a constructor is hidden behind a mixin / static if or whatever, so Implicit Template Instantiation would assume a generated 'default constructor', but after the instantiation it ends up calling the written constructor instead but with template parameters resolved incorrectly. Granted, that might also happen when a 'hidden' constructor exists with a stronger match than the constructor found for IFTI, so I'm not sure. Perhaps an extra check can be added that the constructor used for deriving template parameters is the one that ends up actually being called, but it's getting rather complex.
Jul 16 2025









Meta <jared771 gmail.com> 