During the Clang WG meeting yesterday an idea was surfaced to have a dedicated regular meeting to discuss C++26 reflection in Clang. This would be a perfect place to discuss ongoing upstreaming efforts, news coming from WG21, and future directions of reflection implementation in Clang.
I invite interested parties to fill their availability here: C++ Reflection in Clang - Crab Fit. I estimate this to be an open one hour meeting every two weeks, but details are subject to change based on feedback in this thread.
Thank you for getting the ball rolling on this! I think this is such a large feature with so many questions, it makes a lot of sense to have a meeting at least every two weeks to help ensure that reviewers and patch authors are on the same page, make progress more quickly on points than we can do in a PR, etc.
Thank you for starting the conversation. I think it is unavoidable that we will need a dedicated meeting for this, considering how much time it takes up in existing meetings, it could easily dominate a prevent us from getting to other stuff. The first PR is still ongoing it would likely benefit from having a forum to discuss upstreaming issues.
I think since we are already filing new core issues, it would be in our interest to get on the same page wrt those new issues and hopefully come to core with a well thought out position on how to resolve them
As discussed on Dec 5th, weâre going to have a recurring meeting every 2 weeks starting Jan 9th, at the same time slot of 17:00 UTC (9 AM PST, 12 PM EST) for one hour.
When: December 5th, 17:00 UTC (9 AM PST, 12 PM EST)
Initial introductions as needed
Aaron Ballman
Clang maintainer from Intel
Interested from design perspective
Planning to help with code reviews, but not direct implementation efforts
Nhat Ngyuen
From Bloomberg
Working on upstream implementation
Ambrose
Mostly frontend stuff, more review than implementation
but working on expansion statements too
Shafik Yagmour
A Clang frontend maintainer from Intel
Member of CWG
Active on reviews
Corentin Jabot
From Bloomberg
Donât plan to work much on reflection
Will try to work on exposing Sema to constant evaluation
Is going to have opinions
Michael Levine
From compiler group in Bloomberg
Project manager
Engage in more projects and help people
Valentyn Yukhumenko
From bloomberg
Contributor to open source projects
Beginner-level contributor to LLVM and GCC
Vlad Serebrennikov
Maintainer in Clang, used to contract for Bloomberg, have been interested in Reflection for a long while
Helping coordinate between Reflection authors and other clang maintainers
Plan to do code reviews, mainly on the test side
Corentin is picking up my PR on exposing Sema to constant evaluation
Vassil Vassilev
Princeton University, researcher
Built clang-based tools around reflection
Alicja Texler
From Bloomberg compilers working group
Still learning, hoping to get involved with implementation work
Hubert Tong
From IBM compiler group
In C++ standards committee for a decade
Hoping to do code review
Needs buy-in from management to have time
Interested in alignment between implementations and the wording
Aurelien Cassagnes
Bloomberg engineer
Interested in annotations
Japanese timezone
Meeting cadence for the next year
Aaron: holiday season, not a good idea to meet in december once again
Aaron: is every two weeks works?
Aaron: Jan 9th next meeting?
Hubert: Iâm available. Today we have CWG, 9th would be the same situation
Shafik: this might be a feature. Can discuss Core issues right before CWG telecons
Aaron: Iâm typically good at ending meetings on time
Hubert: Iâm fine to have it before Core
Aaron: next meeting Jan 9th, same time, every two weeks
Start discussing the high-level plan for how to surface reflection
to Clang users
to downstream consumers of clang as a library
Aaron: feature is expansive, need to plan ahead even though prototype implementation is available. Experimental feature, donât want to surface as a feature in older language modes or C until more deployment experience. Do we want to put it under a flag? Flag to control FTM? Cc1 flag?
Corentin: I like the idea of only cc1 flag, because it will take a while to make reflection useful and usable. Cc1 should be fairly limited in what it hides. Opposed to setting FTM before the feature is ready. Should not expose in older language modes for now.
Aaron: reflection is different for older language modes, because they have different language rules (asking questions about implementation details).
Corentin: weâre in agreement. We should not backport features that are not ready
Aaron: need distinction between reflection and metaprogramming. Reflection is well-known, but metaprogramming is terrifying. WG21 might not understand the ramifications themselves
Vassil: generally itâs a good idea to split the const part for tools, the const parts are thread safe in ways that the generative parts are not
Vlad: there are so many things that change during the translation; parameters can change names, get default arguments, namespaces can be reopened, etc. We also have substitute() which makes us instantiate templates during constant evaluation. So it might be more challenging to find the subset of reflection that is clear. Core is making more expressions value-dependent than before, so even basic stuff is changing.
Corentin: 1) itâs going to take us a long time to implementa reflection (>6 months). We should postpone define_aggregate. From the user perspective, if they need to pass a flag to get define_aggregate, this is user-hostile, because itâs a core feature. When we get to it, we should accept that define_aggregate is there to stay.
Aaron: I agree on delaying generative bits. I think the biggest use case is enum_to_string and type traits. Generative bits are a different kind of feature which needs a flag. Invalidates assumptions of library authors, because users can change stuff. Not sure what the way is, but the use of generative bits should break the build.
Vassil: I think that makes sense. Vlad mentioned that things change during translation, but I meant something different. Iâm concerned with changes to AST.
Aaron: interesting thing to think about is that we currently rely on some things running in debugger. I donât want expression evaluator to change AST.
Corentin: it wonât work and canât work.
Aaron: if you evaluate rvalue it gives you a value you can expect.
Corentin:
Vassil: what Aaron means is that you can run expression in debugger, and debugger parses them. Modules are reflections for us. We should be cognizant of this perspective
Corentin: AST is finished, you canât change it
Vlad: lldb generates an AST and runs it
Vassil: the metaquestion is that clang is different from gcc, because there is an ecosystem of tools around clang, and weâre discussing how to make reflection work for them. Tools will have access to Sema, and will be changing their ASTs. if you debug clang within lldb, and you dump, then there are a bunch of effects happening on the state of clang. We need âno module loadâ modes to prevent that
Ambrose: I see Sema usage in lldb
Aaron: Vassil and I are on the same page, but different from Corentin. When Iâm debugging clang, I donât want dump to change anything.
Corentin: why would that happen?
Aaron: because we already do this with modules
Corenin: they are happening at different times.
Shafik: you can debug while youâre compiling
Aaron: run expression evaluator before TU is complete
Corentin: there are specific points where define_aggregate is called
Aaron: we donât want clang-tidy to redo effects of consteval blocks.
Corentin: I think weâre in agreement. AST you have in the tool is not changing
Vassil: this might be true from language perspective, but not from implementation perspective
Corentin: I think we donât agree on how clang works or should work
Aaron: any of our internal APIs can be called by any tool at any point in time, and in the past weâve made assumptions that did not alway hold
Hubert: Iâm in agreement with you about internal APIs. scenario: someone is using internal API to evaluate a constant expression in a consteval block. Not sure if we can protect ourselves from this evaluation.
Aaron: this is what Iâm worried about. What if they create an AST node and evaluate it
Vassil: Iâve seen this problem in libraries. They do hooks into clang to assert if declarations happen in wrong contexts. Weâd need to significantly change AST to detect if someone is changing it from outside. It will help modules, too.
Aaron: Corentin mentioned that our tools donât have access to Sema, but we need to think about downstream tools as well
Corentin: reflection canât do arbitrary mutation at arbitrary points, we might be able to protect just those points
Vlad: indirect changes to AST: inject a default argument, and let the program to observe it later
Vassil: one of the reasons tools want to use clang is to instantiate templates. Not wise to think that tools are not using Sema.
Corentin: if we assume that, then itâs the same if you call instantiate()
Aaron: we wanted to turn off generative bits.
Corentin: it can do very specific things
Aaron: can it declare arbitrary functions?
Corentin: no
Hubert: currently evaluation request from a tool is harmless, but with generative bits it may be not.
Aaron: good way to put it
Vassil: code will behave differently depending on what tools does
Hubert: we need to find subset of things that are not going to have effect on subsequent translation
Vlad: even harmless queries like names of function parameters can impact the values the metafunctions produce
Hubert: declarations hidden from reflection
Start discussing the high-level plan for how to upstream existing reflection fork into Clang
Timelines of when people are available, including reviewers
Corentin: I plan to work over the holidays. For Clang 22, I think we want everything hidden behind a cc1 flag, and do generative bits later. Are we agreed?
The room loves the idea
Corentin: we can start landing PRs in the next few weeks?
Aaron: sure, subject to usual review rules
Request from Nick: post the meeting minutes as something other than a google doc
Background: some of the generative parts of reflection, as well as things like substitute(), etc require the ability to invoke Sema during constant evaluation
Vlad started a PR with a few approaches to try to see how it works. Corentin needs the functionality for something.
Corentin: two different concerns. We have needs to access Sema during constant expression evaluation, even outside of reflection. We have some issues already filed on this. But then we need the same functionality for expansion statements as well as reflection.
Not trying to answer the question for reflection with this PR.
We need a way to tell when constant evaluation can or cannot modify the AST, thatâs currently handled by consteval blocks.
In some cases, we evaluate a constexpr function before itâs defined and at that point we need to define it.
Hubert: that was discussed on the CWG reflectors in Dec. We want to extend the evaluation points for reflection & access context to constant evaluation in general. A lot of it comes down to âusable in constant expressionsâ. For the variable side, thatâs the concept in the wording. Thatâs depending on the point of the start of the evaluation. But we use the term various times in the standard without specifying the context. The wording is completely wrong because the context is required. Dan and Hubert have been trying to fix that wording on the reflector.
Corentin: Iâm trying to match GCC rather than the wording in the standard. libstdc++ doesnât work unless we fix some of these bugs.
Hubert: could try to take a look at the wording for mismatches so we can work with the committee to repair it. The committee might still say ânoâ because the wording is moving towards a principled design.
Corentin: we want to instantiate a function in a consteval context unless it is not a trial evaluation. You donât want side effects just because youâre trying something. Thatâs why Iâm following GCCâs behavior, the standard doesnât seem to say anything about this.
Vlad: there might be a similar case when we handle most vexing parse where we try to parse initializers and instantiate stuff there and back off when we find that doesnât work. Iâll dig up an example.
Corentin: when doing constant evaluation, if you call a function thatâs not been instantiated, you do not want to instantiate it at that point if itâs a trial evaluation.
Hubert: the wording says you do not do it in the constant evaluator at all. Itâs not a property of the evaluation. Itâs a property of whether itâs manifestly constant evaluated. At which point that may cause an instantiation. You can do the instantiation ahead of time and not avoid the instantiation.
Corentin: the issue we ran into is that itâs very hard to do ahead of time.
Hubert: but weâre parsing? After you parse, you know what context youâre in, so now you know that all the names within the expression that you have to care about
Corentin: trying to avoid walking multiple times
Hubert: but thatâs basically what the standard requires
Corentin: this is a long-standing issue with uninstantiated functions
Hubert: because we have issues with instantiations as well as lookup context for names, so Iâm concerned about trying to do this in the constant evaluator. That moves us away from the model in the standard. Iâm fairly certain the committee is not going to be able to review any wording tying instantiation behavior based on the evaluation.
Corentin: the standard already says âwhen neededâ
Hubert: yes, but âwhen neededâ is based on context. If you have a false path during constant evaluation, itâs not supposed to make a different.
Corentin: I donât think thatâs what implementations are doing in practice. Any time you have a constexpr function calling another, you need the instantiation.
Hubert: okay, thatâs not a constant evaluated context.
Corentin: so the standard saying âwhen neededâ is not sufficiently clear.
Hubert: the standard has two ways of causing the instantiation. ODR-use and needed for constant evaluation. In the case of the function body, thatâs an ODR use. So I guess itâs a question of the order of instantiation that youâre trying to do. Are you trying to say thereâs a circular dependency if you try to instantiate before?
Hubert: thatâs an ODR use in the definition, but you cannot do the instantiation at that point.
Corentin: Clang is going to try to instantiate that function at the end of the TU unless we do something. But then we use it before the end of the TU.
Hubert: and it is defined at the point where you do the constant evaluation. I think if you didnât defer instantiation until codegen, and instead tracked that you need the instantiation when you see it. That might be a road of madness leading to circular dependency where thereâs no good order.
Corentin: yes
Hubert: the standard wording may not be great; it doesnât talk about timing of instantiations. The direction weâre trying to move to, at the point you do the call to f() is the point where we care if g() is instantiated or not. g() is needed for constant evaluation and it will be instantiated, but the standard never says when. So the case where you need to instantiate is the case the standard doesnât say much about.
Vlad: the idea to instantiate at the end of template definition is what Richard suggested and Corentin implemented (in the comments on the issue). It had to be reverted. The next example in the thread shows the kind of code that doesnât work, such as things like specializations.
Hubert: at some point you have to say thatâs not going to work.
Corentin: but code relies on this (existing GCC behavior); I donât want to break Qt
Hubert: needs to be discussed in the committee for sure. Itâs not like this is the first time where patches had to be made to other projects.
Vlad: I think Richard is convinced that code should work (comment), but that ship might have sailed. So far Clang seems to be the only implementation upholding the model Hubert described.
Hubert: not surprising, a lot of this constexpr wording was driven by Richard (and Jens).
Corentin: if we did not have reflection, it might be worth it to not mix constant evaluation and sema. But with reflection, we have to do that anyway.
Hubert: Iâve already pointed out to the committee these issues around reflection and point of instantiation. If you start going down the reflection path, then when you do the instantiation, youâre going to drag a point of instantiation with you. In the reflection world, thatâs what happens. If you move in the direction youâre suggesting, youâre going to have issues figuring out what your point of instantiation is for name lookup, ADL, etc. The additional aspect that is very surprising is that we end up seeing block scope declarations in the point of instantiation now, that never happened before.
Vlad: is unique_ptr in scope for your PR?
Corentin: no, going to come after. Clang has issues when trying to instantiate a constexpr function too late and too early.
Shafik: it sounds like what weâre saying is that Clang is strictly following the wording but recent changes in the standard are pulling us in a different direction. Is that right?
Hubert: Clang currently does something close to the wording, but wonât cover the first case in Corentinâs issue. What the standard says about that case is not very clear but it leans towards saying it should work. So the attempt at making it work in a manner consistent with what the standard might do exposed the further issue with ordering.
Corentin: yes, and I suspect there are many variations of ordering issues.
Shafik: so we have too much real world code doing it this way but it will significantly break our users.
Corentin: like scenarios where unique_ptr doesnât work for people.
Vlad: worth mentioning itâs not going to break people; unique_ptr issue is only for C++23 because thatâs when unique_ptr started having a constexpr destructor. We have the data that not many of our users are on C++23 or newer.
Corentin: unfortunately, thereâs a difference between what Standard says and was users do
Hubert & Aaron: doing it during evaluation is weird code
Aaron: comma operator convinces me that this is weird code (joke)
Corentin: are we going to be the only implementation which doesnât instantiate during constant evaluation?
Aaron: the only implementation that follows the standard? That happened before
Corentin: Iâm not sure whether I should be talking to other implementations or with the committee
Hubert: CWG is coming up, we can talk there
Aaron: we should talk more to the committee
Corentin: agreed
Aaron: reflection is experimental all over the place and should not influence our decision here
Hubert: even queries require implicit instantiations
Aaron: I see this being generative in the same way as define_aggregate
Corentin: then the entirety of the reflection is generative
Aaron: why canât we instantiate upon parsing?
Corentin: if you do a query that requires class completion, it requires definitions
Hubert: even substitute doesnât cause instantiation
Vlad: what meta::info points to?
Hubert: instantiation of declaration, not definition. But (I guess there may be cases where) declaration can require other instantiations
Vlad: itâs not news that we need to instantiate stuff other than via define_aggregate. members_of requires instantiation. No reflection queries are immune to this
Corentin: there is a case of expansion statements, which also need instantiations
Ambrose: I donât remember that we need to instantiate during constant evaluation
Ambrose: do you mean creating a lambda out of this air? That happens in Sema
Corentin: oh, did I invent something?
Ambrose: I canât think of anything
Corentin: Maybe I misunderstood something
Ambrose: maybe I didnât do a good job explaining. We need to evaluate the loop to get a number out of it.
Hubert: Aaron, can you give me link to the minutes. We need to discuss whether Google Meet is the best place to have this meeting
Aaron: Nick asked to post minutes elsewhere, we didnât do that
Action item for Vlad to post minutes to Discourse
Hubert: Google Meet works the worst for me. Can we use anything else?
Aaron: happy to use anything else
Vlad: Discord doesnât work for you
Aaron: Iâll make it work
Alicja: Google Meet works so much better than Zoom for me
Ambrose: I prefer google meet
Shafik: âŚ
Aaron: sounds like folks prefer meet. Hubert, if meet is untenable, let us know
Aaron: I like you all too much to suggest Teams
Hubert: Iâm glad to hear that
Aaron: next meeting will be held in Google Meet on 23rd
Hubert: Jens did not point be to this core issue (2794). Telecons donât have enough quorum to discuss this, so waiting for in-person meeting. A paper might be needed
Shafik: agreed, this will need a significant effort to get right
Dan: Daveed mentioned that they instantiate during evaluation, and that MSVC does something similar
Hubert will email Jens to ask him to discuss 2497 CCing Corentin
Hubert: (speaking about 2497) there is a fine line understanding that g is used in a manifestly-constant evaluation, so that thereâs a dependency on the definition of f()
Dan: we need to do dynamic path instantiation for reflection
Hubert: we need an example, and see what other implementations do
Dan: the problem is that it can be arbitrarily nested in function calls
Hubert: there has to be a structure that describe the dependencies
Hubert: then weâd need to know whether side effects of define aggregate was observed
Dan: define_aggregate canât define arbitrary structs. You have the same issue with friend injection
Hubert: I have an idea what two models look like, but I have hard time coming up with examples to show what differences are
Dan: define_aggregate makes it observable whether you instantiated something
Dan: if weâre going after instantiation during evaluation model, at least we can try to specify precisely when instantiations are produced. This is made harder by immediately-escalated expressions. Tentative evaluations make it harder, too. Instantiations would persists even after failed trial evaluations
Hubert: if weâre going to codify all the stuff out of constant-evaluation, we could also codify odr-uses
Hubert: there are two cases for instantiation to happen: when you referenced it: you need to for constant evaluation, and needed for codegen. We can codify the latter, too
Hubert: g() is code-gened, it references f, so it has to be instantiated
Dan: f already has a point of instantiation at the end of the TU. We can try to say that if the primary template is not reachable from namespace
Hubert: you might not be able to parse if the end of the TU is the only point of instantiation
Dan: itâs possible to contrive a program that is IFNDR but itâs not possible to translate the program the bad way
Hubert: this is why I said there are two cases for odr-use
Hubert: IFNDR supports AST-based implementations
Dan: sure thereâs a well-formed program that contains a template. At least one.
Dan: so it was a bridge too far to discard points of instantiation at the end of the TU. we need to see what other implementations are doing
Hubert: that is our homework. Then weâll have enough material to come to Jens and describe what the options are
Which synthesized points are included in the evaluation context?
Dan: program points historically describes state of the compiler, despite being a spatial property. Define_aggregate breaks that, because state of the compiler changes during evaluation. So we introduced evaluation context which includes program points and synthesized points which describes what is observable for translation: both lexical and injected declarations. It works like this: synthesized point is included in the evaluation context, and that point brings corresponding injected declaration into consideration.
Shafik: how does this affect instantiation?
Dan: evaluation and instantiation interleaved in two ways: evaluation can cause instantiation, and template specialization can have manifestly-constant evaluated expressions.
Dan: members_of can cause implicit instantiations.
Dan: yes, I want to specify that instantiation context is immutable
Dan: the issues here is that line 5 has an initializer
Dan: is_complete_type has been phrased in terms of evaluation context of the expression under evaluation
Dan: but thereâs no distinction between runtime and compile-time evaluation in the abstract machine. Thereâs only one evaluation
Dan: the wording asks b on line 5 to be different depending on whether line 11 has executed.
Shafik: we need examples that show how the code executes
Dan: the question is whether initializer on line 5 has to be cached
Dan: in standardese cached is whether initializer is evaluated with the same evaluation context
Dan: Iâm arguing that caching is what we want. Compilers are already has to verify whether an initializer is constant, and we donât want them to throw out the result
Dan: to fix this I want to tweak the definition of evaluation context
Vlad: you can take 20 words and make sentences out of them
Dan: they will be completed in the course of execution consteval block
Dan: we have function f, which has variable b with automatic storage duration. It observes completeness of S. the observation influences the width of a bitfield in T
Dan: in the course of doing P2996 there was an unjustified assumptions that constant evaluations are self-contained
Dan: evaluation context is codifying translation state that will be observed by metafunctions
Dan: initializer of b is manifestly constant-evaluated
Dan: when we were considering expressions under evaluation in consteval block, weâre passing through initialization of b, which is now supposed to observe the side-effects of line 11.
Dan: there is divergence between Clang and GCC, but only for automatic storage duration
Dan: b is a new variable every time f is evaluated
Dan: formally b is initialized every time f is called
Dan: but initializer of b is evaluated for validation purposes, and then we throw away the result
Dan: the idea is to specify caching in the wording
Hubert: weâll take it as a core issue
Hubert: the expression under evaluation is the smallest one is the model we have
Dan: I want implementation feedback on how possible it is to mandate caching
Hubert: with respect to the state of constant evaluator, can we create a separate context?
Dan: re-entracy is handled quite good. Everything is kept in EvalInfo
Hubert: it needs something like this anyway
Hubert: the problem you talk about might exist in the rules about starting the lifetime
Hubert: itâs a question whether something is core constant expression. You anchor it to the smallest one.
Dan: I want to say that initializer context of initializer of b is evaluated in the same context irrespective of how it was reached
Hubert: makes sense
Hubert: caching is not the question. The question is whether you can create new evaluation context
Dan: in clang you wouldnât re-enter the evaluation context, you return cached APValue
Hubert: âŚ
Hubert: in terms of how to approach this in the committee, for the sake of transparency, this might be considered an oversight. Example might complicate things. We might process this without looking at code
Shafik: context is always important, so we should be explicit more often
Hubert: the issue with making every constexpr static is that you have the pure value problem again. We need objects
Dan: evaluation of a metafunction is a function of expression itself and of the evaluation context. For other things itâs just the expression itself. If we say that for manifestly contant-evaluations evaluation context is fixed, then it removes the parametrization for them.
Dan: Consteval-only types are compounded from meta::info
Dan: References and pointers can also be consteval-only
Dan: You can have a pointer to incomplete type that becomes consteval-only later:
Dan: idea is to make this property dependent on a program point
Vlad: like completeness of a type
Dan: the initial idea was to prevent meta::info from being emitted
Dan: do we really need to disallow emitting meta::info?
Hubert: we need to understand the mechanics. Maybe we can check consteval-onlyness on the usage
Dan: you can ODR-use B
Hubert: but meta::info is something you canât talk about still
Hubert: the really interesting thing is entanglement between consteval-only and immediate escalation and all that
Dan: why so?
Hubert: you could have a different interpretation whether something is immediate-escalating, depending on where you are evaluating your expression
Dan: it would. You have to evaluate immediate invocation after parsing to see whether itâs constant
Hubert: but can you have a case when you donât know if it was an immediate expression
Dan: definition of immediate expression will have to be rewritten
Hubert: the model will need to change on how we identify the boundaries of constant evaluation
Hubert: I donât know how we deal with something at parse time is immediate or not
Dan: I think itâs a matter of type of an expression after you parse it
Dan: if you know that something is consteval-only, itâs not changing
Dan: weâd run into trouble specifying the second half of [baisc.types.general]/12. It doesnât make sense to talk about object w.r.t. a point. Weâd need to better account for temporaries
Going to focus on remaining items for reflect-expression next
Hubert: my concern is that weâre doing parsing, and then Iâm not sure what weâre generating out of it. We need meta::info, even as an opaque type, to do meaningful testing.
Nhat: agree. Implementing meta::info might be the next step
Dan: thereâre developments on consteval-only types that might influence this
Hubert: now compiler doesnât enforce some restrictions around consteval-only types
Dan: you mean trunk?
Hubert: yes
Hubert: it would alleviate my concerns if we run tests through the other compiler (Danât fork)
Shafik: Hubert, do you have a suggestion or this is a general concern?
Hubert: I think we want to have an informal policy that tests should be tested against Danâs fork
Vlad: makes sense to me. How is it going to work? Locally? Godbolt?
Hubert: godbolt links in the review, I guess
Shafik: makes sense to me
Dan: happy to review any tests
Vlad: Dan, is your fork separate from Bloombergâs?
Dan: Bloombergâs fork is dated, but the best we have
Hubert: Dan, do you have an opinion on whether we should ignore EDG? Itâs not up-to-date
Dan: I agree that we should ignore it
Hubert: going back to parsing. Not having meta::info made tests less useful, with weird limitations. Thereâs still a scoping issue. Going breadth-first leaves us with a lot of danger in the future. Can we go depth-first?
Hubert: limit parsing, but take it forward, create meta::info, maybe even down to splices.
Dan: Iâve always thought of splicing, expressions, and metafunctions as separate branches of P2996. Thereâs a separate question of how weâre going to implement it upstream. Tablegen? You might be right that meta::info is the right approach. Maybe omitting consteval-only semantics, since itâs still in flux. What do you think, Hubert?
Hubert: makes sense
Dan: or implement the tracking of consteval-only, but not the semantic restrictions
Hubert: maybe we want to avoid the consteval-only question for now
Hubert: if we have meta::info, we can have metafunctions. Letâs try to get one query in
Vlad: what about instantiation problem that we want to discuss in Core?
Dan: we can implement scaffolding, then implement metafunctions that do not implicitly instantiate
Hubert: the ship has sailed on whether you need to instantiate during constant evaluation
Dan: agreed
Hubert: in which instances do synthesized point appear, going back to the issue of point of instantiation
Dan: we could have a call to members_of, which needs an implicit instantiation. The question is that compilers like yours what to constant-fold everything. We want to specify that point of instantiation is right after the expression. But then we have tentative evaluations
Hubert: the are treated as manifestly constant-evaluated
Dan: but we canât treat them this way
Hubert: I donât agree
Dan: if we were to pursue this, which I think we should, while you determining
Hubert: itâs time travel, but not time travel
Dan: itâs about evaluations you hit before you give up
Hubert: yes, but I was trying to explain what it was not
Hubert: compile is a process during which we have evaluations, but the standard doesnât describe it this way: it will state facts, like whether something is a core constant expression. Itâs something that compiler determines after following a process. If side effects happened, this is bad. WEâre trying to say that thereâs a portion of evaluation that is going to happen anyway. The other prong of the discussion is where the point of instantiation is. Weâre trying to tie to where the evaluation emanates.
Shafik: it almost feels like we need a design paper
Dan: probably
Shafil: every time we discuss this, I feel like Iâm diving into a cold water. This needs to be laid down on a paper.
Hubert: sometimes weâre writing papers to resolve core issue, not always going through evolution
Shafik: sure
Hubert: I thought you want a trade-off review
Shafik: no, trade-off within core
Dan: Iâd already written it if I had time
Shafik: Hubert, are we going to discuss this in core?
Hubert: it is one of those places where you need a paper before discussion in core can happen
Dan: I wonât have time to put a paper before Croydon. I have ideas which someone else can put into a paper. This is one of the places where we can strengthen the specification
Shafik: what is it blocking? Or we can go forward assuming itâs going to be resolved in a particular way
Hubert: itâs safe to assume that our ideas to resolve this will be accepted, because it feels natural to me. Dan, when one of the metafunctions get to a point where it needs instantiation, we stop?
Dan: yes, we do it in many places
Hubert: compilers arelady separately establish the idea where the point of instantiation comes from. Dan, you have a wording, but we donât have a Core issue that Jens can open
Hubert: in the end, I think this issue is to reflect in the wording what the implementation reality is. Fixing the wording gives us a better idea how things work, but it doesnât block us
Dan: status quo is not worse than the rest of the template wording
Shafik: sure, makes sense
Hubert: I think we havenât confirmed how weâre going to proceed. We discussed a lot of things, now need to decide. Does Nhat understand how to do meta::info.
Nhat: weâre doing meta::Info, but without consteval-only
Hubert: we donât need to do anything on codegen for meta::info
Nhat: works for me, Iâll follow-up when I start working
Dan: I was reading about contracts and ran into this. Constification says that if you name outside variables, they are const. Reflection and contracts went in parallel through the committee. If you designate a variable through a splice, constification doesnât happen. Compilers should be able to diagnose the example. We need to integrate splicing into constificatin wording
Vlad: not a fan of constification, so this might be a feature, but still worth bringing up for consistency.
Dan: me neither
Hubert: makes sense to me
Aaron: is this applicable when the variable is not named directly?
Dan: yes
Vlad: constification would apply to the result of splice-expreesion, irrespecituve of whatâs within
Aaron: makes sense, thank you
Dan: pointers to consteval-only types
Dan: letâs open CWG3150
Dan: I hate this issues
Dan: we look at consteval-only as being a global property of a type, but from a given point you donât know whether a type is consteval. Especially fun if you go cross-TU. My current thinking is that GCC does a good thing. They donât care and donât emit anything that is consteavl-only. You get a linker error.
Hubert:
Dan: my goal is to never force an implementation to emit meta::info. Maybe itâs fine to emit composite types with it, as long as you donât need to emit info itself. Something like function with info* parameter.
Hubert: so this is why youâre saying IFNDR
Hubert: this direction leads to question of what is the value of having consteval-only types in the specification.
Corentin: if nothing in your type is odr-used, it wonât be emitted anyway
Hubert: one of the more recent core issues opened was that there is a way to make compiler emit it, which caused Clang ICE
Dan: I think that crux motivation to have consteval-only types was that by prevening emitting info you âre more strict on zero-cost nature of reflection.
Hubert: this pointer concern doensât hold. You have a ponter to meta::Info. If itâs null, youâre good.
Dan: if pointer type is not consteval-only, why canât you use it
Hubert: hmm, you might be right
Corentin: weâre forcing frontend to do a lot of work to prevent emitting an integer that is meaningless. I donât think we need to do anything
Dan: if you can have infos at runtime, people would try to have hashsets of them at runtime
Dan: I wouldnât underestimate reflection being zero-cost
Hubert: we made this mistake with inline variables
Hubert: but with info itâs IFNDR, so youâre just allowing it to be zero-cost