First Draft: Implicit Type Template Instantiation via Constructors

Quirin Schroll qs.il.paperinik at gmail.com
Wed Jul 16 23:07:50 UTC 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:
>> 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.

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.

### What can be done

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.

### Mixin Templates

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.

### String Mixins

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.

### Version and Debug

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.

### Static If

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.


More information about the dip.development mailing list