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