Quuxplusone added inline comments.
================ Comment at: docs/LanguageExtensions.rst:1096 + equivalent to copying the underlying bytes and then dropping the source object + on the floor. * ``__is_destructible`` (MSVC 2013) ---------------- dblaikie wrote: > Quuxplusone wrote: > > rjmccall wrote: > > > Quuxplusone wrote: > > > > rjmccall wrote: > > > > > Quuxplusone wrote: > > > > > > rjmccall wrote: > > > > > > > Quuxplusone wrote: > > > > > > > > rjmccall wrote: > > > > > > > > > Quuxplusone wrote: > > > > > > > > > > @rjmccall wrote: > > > > > > > > > > > trivial_abi permits annotated types to be passed and > > > > > > > > > > > returned in registers, which is ABI-breaking. Skimming > > > > > > > > > > > the blog post, it looks like trivially_relocatable does > > > > > > > > > > > not permit this — it merely signifies that destruction is > > > > > > > > > > > a no-op after a move construction or assignment. > > > > > > > > > > > > > > > > > > > > Not necessarily a "no-op"; my canonical example is a > > > > > > > > > > CopyOnlyCXX03SharedPtr which increments a refcount on > > > > > > > > > > construction and decrements on destruction. But > > > > > > > > > > move-construction plus destruction should "balance out" and > > > > > > > > > > result in no observable side effects. > > > > > > > > > > > > > > > > > > > > > This is usefully different in the design space, since it > > > > > > > > > > > means you can safely add the attribute retroactively to > > > > > > > > > > > e.g. std::unique_ptr, and other templates can then detect > > > > > > > > > > > that std::unique_ptr is trivially-relocatable and > > > > > > > > > > > optimize themselves to use memcpy or realloc or whatever > > > > > > > > > > > it is that they want to do. So in that sense trivial_abi > > > > > > > > > > > is a *stronger* attribute, not a *weaker* one: the > > > > > > > > > > > property it determines ought to imply > > > > > > > > > > > trivially_relocatable. > > > > > > > > > > > > > > > > > > > > `trivial_abi` is an "orthogonal" attribute: you can have > > > > > > > > > > `trivial_abi` types with non-trivial constructors and > > > > > > > > > > destructors, which can have observable side effects. For > > > > > > > > > > example, > > > > > > > > > > ``` > > > > > > > > > > struct [[clang::trivial_abi]] DestructionAnnouncer { > > > > > > > > > > ~DestructionAnnouncer() { puts("hello!"); } > > > > > > > > > > }; > > > > > > > > > > ``` > > > > > > > > > > is `trivial_abi` (because of the annotation) yet not > > > > > > > > > > trivially relocatable, because its "move plus destroy" > > > > > > > > > > operation has observable side effects. > > > > > > > > > > > > > > > > > > > > > The only interesting question in the language design that > > > > > > > > > > > I know of is what happens if you put the attribute on a > > > > > > > > > > > template that's instantiated to contain a sub-object that > > > > > > > > > > > is definitely not trivially relocatable / trivial-ABI. > > > > > > > > > > > For trivial_abi, we decided that the attribute is simply > > > > > > > > > > > ignored — it implicitly only applies to specializations > > > > > > > > > > > where the attribute would be legal. I haven't dug into > > > > > > > > > > > the design enough to know what trivially_relocatable > > > > > > > > > > > decides in this situation, but the three basic options > > > > > > > > > > > are: > > > > > > > > > > > > > > > > > > > > > > - the attribute always has effect and allows trivial > > > > > > > > > > > relocation regardless of the subobject types; this is > > > > > > > > > > > obviously unsafe, so it limits the safe applicability of > > > > > > > > > > > the attribute to templates > > > > > > > > > > > - the attribute is ignored, like trivial_abi is > > > > > > > > > > > - the attribute is ill-formed, and you'll need to add a > > > > > > > > > > > [[trivially_relocatable(bool)]] version to support > > > > > > > > > > > templates > > > > > > > > > > > > > > > > > > > > What happens is basically the first thing you said, except > > > > > > > > > > that I disagree that it's "obviously unsafe." Right now, > > > > > > > > > > conditionally trivial relocation is possible via template > > > > > > > > > > metaprogramming; see the libcxx patch at e.g. > > > > > > > > > > https://github.com/Quuxplusone/libcxx/commit/6524822c009e#diff-38adc80cec663f2f29c22e9ffc0de912 > > > > > > > > > > Since the attribute is an opt-in mechanism, it makes > > > > > > > > > > perfect sense to me that if you put it on a class (or class > > > > > > > > > > template), then it applies to the class, without any > > > > > > > > > > further sanity-checking by the compiler. The compiler has > > > > > > > > > > no reason to second-guess the programmer here. > > > > > > > > > > > > > > > > > > > > However, there's one more interesting case. Suppose the > > > > > > > > > > programmer puts the attribute on a class that isn't > > > > > > > > > > relocatable at all! (For example, the union case > > > > > > > > > > @erichkeane mentioned, or a class type with a deleted > > > > > > > > > > destructor.) In that case, this patch *does* give an > > > > > > > > > > error... *unless* the class was produced by instantiating a > > > > > > > > > > template, in which case we *don't* give an error, because > > > > > > > > > > it's not the template-writer's fault. > > > > > > > > > > https://p1144.godbolt.org/z/wSZPba > > > > > > > > > > trivial_abi is an "orthogonal" attribute: you can have > > > > > > > > > > trivial_abi types with non-trivial constructors and > > > > > > > > > > destructors, which can have observable side effects. > > > > > > > > > > > > > > > > > > Let me cut this conversation short. `trivial_abi` is not > > > > > > > > > such an old and widely-established attribute that we are > > > > > > > > > unable to revise its definition. I am comfortable making the > > > > > > > > > same semantic guarantees for `trivial_abi` that you're making > > > > > > > > > for `trivially_relocatable`, because I think it is in the > > > > > > > > > language's interest for `trivial_abi` to be strictly stronger > > > > > > > > > than `trivially_relocatable`. > > > > > > > > > > > > > > > > > > > What happens is basically the first thing you said, except > > > > > > > > > > that I disagree that it's "obviously unsafe." > > > > > > > > > > > > > > > > > > Under your semantics, the attribute is an unchecked assertion > > > > > > > > > about all of a class's subobjects. A class template which > > > > > > > > > fails to correctly apply the template metaprogramming trick > > > > > > > > > to all of its dependently-typed subobjects — which can be > > > > > > > > > quite awkward because it creates an extra dimension of > > > > > > > > > partial specialization, and which breaks ABI by adding extra > > > > > > > > > template parameters — will be silently miscompiled to allow > > > > > > > > > objects to be memcpy'ed when they're potentially not legal to > > > > > > > > > memcpy. That is a footgun, and it is indeed "obviously > > > > > > > > > unsafe". > > > > > > > > > > > > > > > > > > Now, it's fair to say that it's unsafe in a useful way: > > > > > > > > > because the attribute isn't checked, you can wrap a type you > > > > > > > > > don't control in a `trivially_relocatable` struct and thereby > > > > > > > > > get the advantages of triviality on the wrapper. The model > > > > > > > > > used by `trivial_abi` doesn't allow that. But I feel pretty > > > > > > > > > strongly that that is not the right default behavior for the > > > > > > > > > language. > > > > > > > > > Under your semantics, the attribute is an unchecked assertion > > > > > > > > > about all of a class's subobjects. > > > > > > > > > > > > > > > > The attribute is an unchecked assertion about the class's > > > > > > > > //special member functions//. The attribute doesn't have > > > > > > > > anything to do with subobjects, period. > > > > > > > > Vice versa, the property currently expressed by > > > > > > > > "IsNaturallyTriviallyRelocatable" is deduced from all of the > > > > > > > > class's subobjects. The programmer can overrule the "natural" > > > > > > > > property in an "unnatural" way by annotating their class with > > > > > > > > the attribute. > > > > > > > > > > > > > > > > And we know this is true because it is possible to make a > > > > > > > > trivially-relocatable class type containing > > > > > > > > non-trivially-relocatable members (e.g. a class having a member > > > > > > > > of type boost::interprocess::offset_ptr), and vice versa it is > > > > > > > > possible to make a non-trivially-relocatable class containing > > > > > > > > trivially-relocatable members (e.g. > > > > > > > > boost::interprocess::offset_ptr itself, which has only one > > > > > > > > member, of integral type). > > > > > > > > > > > > > > > > > A class template which fails to correctly apply the template > > > > > > > > > metaprogramming trick to all of its dependently-typed > > > > > > > > > subobjects — which can be quite awkward because it creates an > > > > > > > > > extra dimension of partial specialization > > > > > > > > > > > > > > > > Agreed that it's awkward. The libc++ implementation was > > > > > > > > awkward, but definitely not challenging. The only thing that > > > > > > > > makes it at all tricky in the STL is that the STL allocator > > > > > > > > model permits fancy "pointer" types that can make e.g. > > > > > > > > std::vector non-trivially relocatable. If it weren't for fancy > > > > > > > > pointers, you wouldn't need the extra dimension. > > > > > > > > > > > > > > > > > and which breaks ABI by adding extra template parameters > > > > > > > > > > > > > > > > The libc++ implementation does not break ABI. The extra > > > > > > > > template parameter is concealed in a private base class. > > > > > > > > https://github.com/Quuxplusone/libcxx/commit/6524822c009e#diff-38adc80cec663f2f29c22e9ffc0de912 > > > > > > > > > > > > > > > > > I feel pretty strongly that that is not the right default > > > > > > > > > behavior for the language. > > > > > > > > > > > > > > > > Can you elaborate on that feeling (maybe in private email)? My > > > > > > > > intent with P1144 is that no industry programmer should ever > > > > > > > > see this attribute; the right default for industry programmers > > > > > > > > is to use the Rule of Zero. The reason we need the attribute is > > > > > > > > as an opt-in mechanism for the implementor of `unique_ptr`, > > > > > > > > `shared_ptr`, `vector`, and so on, //so that// the end-user can > > > > > > > > just use the Rule of Zero and everything will work fine. > > > > > > > > End-users shouldn't be messing with attributes. > > > > > > > > And we know this is true because it is possible to make a > > > > > > > > trivially-relocatable class type containing > > > > > > > > non-trivially-relocatable members (e.g. a class having a member > > > > > > > > of type boost::interprocess::offset_ptr), and vice versa it is > > > > > > > > possible to make a non-trivially-relocatable class containing > > > > > > > > trivially-relocatable members (e.g. > > > > > > > > boost::interprocess::offset_ptr itself, which has only one > > > > > > > > member, of integral type). > > > > > > > > > > > > > > Why would a class containing a member of type > > > > > > > `boost::interprocess::offset_ptr` be trivially-relocatable? If > > > > > > > you actually trivially relocate an object of the class, the > > > > > > > pointer will not be rebased and so will be invalidated. It would > > > > > > > have to be an `offset_ptr` where you happen to know that the > > > > > > > referent will always be copied simultaneously, e.g. because it's > > > > > > > a member of the object itself. Of course that's possible, but > > > > > > > it's also such a corner case that we shouldn't balk at saying > > > > > > > that the programmer ought to be more explicit about recognizing > > > > > > > it. > > > > > > > > > > > > > > > Agreed that it's awkward. The libc++ implementation was > > > > > > > > awkward, but definitely not challenging. The only thing that > > > > > > > > makes it at all tricky in the STL is that the STL allocator > > > > > > > > model permits fancy "pointer" types that can make e.g. > > > > > > > > std::vector non-trivially relocatable. If it weren't for fancy > > > > > > > > pointers, you wouldn't need the extra dimension. > > > > > > > > > > > > > > Sure. My point about the awkwardness is quite narrow: making the > > > > > > > attribute take a `bool` argument is just a superior way of > > > > > > > managing this over requiring a partial specialization. Several > > > > > > > other language attributes have been heading in this same > > > > > > > direction. > > > > > > > > > > > > > > > The libc++ implementation does not break ABI. The extra > > > > > > > > template parameter is concealed in a private base class. > > > > > > > > > > > > > > Ah, apologies. > > > > > > > > > > > > > > > My intent with P1144 is that no industry programmer should > > > > > > > > ever see this attribute; the right default for industry > > > > > > > > programmers is to use the Rule of Zero. ... End-users > > > > > > > > shouldn't be messing with attributes. > > > > > > > > > > > > > > Neither of these statements matches my experience. This is an > > > > > > > "expert" feature to be sure, but the C++ community is full of > > > > > > > experts who write their own rule-of-five types and who will > > > > > > > happily use whatever attributes are available to them to make > > > > > > > them faster. > > > > > > > > > > > > > > Also, I assume you are intending for this attribute to be > > > > > > > standardized eventually, which will greatly expand its reach. > > > > > > > Why would a class containing a member of type > > > > > > > `boost::interprocess::offset_ptr` be trivially-relocatable? If > > > > > > > you actually trivially relocate an object of the class, the > > > > > > > pointer will not be rebased and so will be invalidated. It would > > > > > > > have to be an offset_ptr where you happen to know that the > > > > > > > referent will always be copied simultaneously, e.g. because it's > > > > > > > a member of the object itself. > > > > > > > > > > > > Exactly! (And to preserve the class invariant, you'd have to add a > > > > > > copy-constructor.) > > > > > > > > > > > > > Of course that's possible, but it's also such a corner case that > > > > > > > we shouldn't balk at saying that the programmer ought to be more > > > > > > > explicit about recognizing it. > > > > > > > > > > > > Exactly — and the way for the programmer to explicitly recognize > > > > > > (or I say "warrant") that their class has the property is for them > > > > > > to annotate it with `[[trivially_relocatable]]`. So I guess maybe I > > > > > > don't understand what you mean by "more explicit"? > > > > > > > > > > > > > making the attribute take a `bool` argument is just a superior > > > > > > > way of managing this > > > > > > > > > > > > That's possible, but it's also possible that it would increase the > > > > > > complexity of parsing attributes for some implementations. I mean, > > > > > > we're talking about something like the following, right? (Using the > > > > > > libc++ patch as the example, but I've de-uglified some of the > > > > > > names.) So I think it's a tradeoff and I'm ambivalent about it, so > > > > > > far. (This is one of the [[ > > > > > > https://quuxplusone.github.io/blog/2018/11/11/trivially-relocatable-in-san-diego/#if-you-feel-comfortable-respondi > > > > > > | straw poll questions in P1144R0 ]].) > > > > > > ``` > > > > > > template <class T, class A = allocator<T>> > > > > > > class [[trivially_relocatable(__deque_base<T, > > > > > > A>::__allow_trivial_relocation::value)]] deque > > > > > > : private __deque_base<T, A> > > > > > > ``` > > > > > > > > > > > > > This is an "expert" feature to be sure, but the C++ community is > > > > > > > full of experts who write their own rule-of-five types and who > > > > > > > will happily use whatever attributes are available to them to > > > > > > > make them faster. > > > > > > > > > > > > Agreed. But the C++ community is //also// full of working > > > > > > programmers who just write simple code with strings and vectors. :) > > > > > > I want `[[trivially_relocatable]]` to be approximately as > > > > > > frequently seen in real codebases as `[[no_unique_address]]` — i.e. > > > > > > maybe a couple times in that smart-pointer library the contractor > > > > > > wrote, but nowhere near the user code. If it's seen frequently in > > > > > > user code, then we've failed those users. > > > > > > Exactly! (And to preserve the class invariant, you'd have to add a > > > > > > copy-constructor.) > > > > > > > > > > But then it still wouldn't be trivially relocatable, because there's > > > > > user-defined code that has to run to copy it correctly. The only way > > > > > such a type could ever be meaningfully trivially relocatable outside > > > > > of obviously unknowable external conditions is if it has fields that > > > > > it never uses after it's been relocated. > > > > > > > > > > > Exactly — and the way for the programmer to explicitly recognize > > > > > > (or I say "warrant") that their class has the property is for them > > > > > > to annotate it with [[trivially_relocatable]]. So I guess maybe I > > > > > > don't understand what you mean by "more explicit"? > > > > > > > > > > I think it is far more likely that some well-intentioned library > > > > > author will add `[[trivially_relocatable]]` incorrectly than that > > > > > they'll actually intend to override the trivial relocatability of > > > > > their subobjects. > > > > > > > > > > By "more explicit", I was suggesting that you add some kind of > > > > > "force" syntax to the attribute (straw-man suggestion: > > > > > `[[trivially_relocatable!]]`). Without the force, the attribute will > > > > > negate non-triviality from special members in the class but won't > > > > > override natural non-triviality from subobjects. > > > > > > > > > > > That's possible, but it's also possible that it would increase the > > > > > > complexity of parsing attributes for some implementations. > > > > > > > > > > All conforming implementations have to do the work to support things > > > > > like this already because of `alignas`, `noexcept`, etc. > > > > > > > > > > > Agreed. But the C++ community is also full of working programmers > > > > > > who just write simple code with strings and vectors. :) I want > > > > > > [[trivially_relocatable]] to be approximately as frequently seen in > > > > > > real codebases as [[no_unique_address]] — i.e. maybe a couple times > > > > > > in that smart-pointer library the contractor wrote, but nowhere > > > > > > near the user code. If it's seen frequently in user code, then > > > > > > we've failed those users. > > > > > > > > > > I think you are underestimating the sophistication of "working > > > > > programmers" and overestimating the sophistication of library > > > > > developers. A `[[trivially_relocatable]]` that doesn't override > > > > > subobject triviality is far easier for library authors to use > > > > > correctly and will avoid an endless cascade of oversights. > > > > > > > > > > Case in point, every single subtle thing that you had to anticipate > > > > > and call out in your patch to `std::deque` would just go away if the > > > > > language simply propagated non-triviality of subobjects. > > > > > I think it is far more likely that some well-intentioned library > > > > > author will add `[[trivially_relocatable]]` incorrectly than that > > > > > they'll actually intend to override the trivial relocatability of > > > > > their subobjects. > > > > > > > > But overriding "natural" non-trivial relocatability is precisely the > > > > reason for P1144 `[[trivially_relocatable]]`! If you just have a plain > > > > old Rule-of-Zero object with trivially relocatable subobjects, and you > > > > want your object to be trivially relocatable as a result, the core > > > > language takes care of that for you (just like with trivial > > > > {con,de}structibility and trivial-abi-ness: a Rule-of-Zero composite of > > > > trivial objects is itself trivial). The //only// use-case for the > > > > `[[trivially_relocatable]]` attribute is when you are trying to tell > > > > the compiler that you know exactly what you're doing. (Which is why > > > > normal working programmers won't generally use it.) > > > > > > > > > By "more explicit", I was suggesting that you add some kind of > > > > > "force" syntax to the attribute (straw-man suggestion: > > > > > `[[trivially_relocatable!]]`). Without the force, the attribute will > > > > > negate non-triviality from special members in the class but won't > > > > > override natural non-triviality from subobjects. > > > > > > > > Can you give an example of how it would work with `deque`, for example? > > > > What part of the `deque` implementation would become simpler, in > > > > exchange for this added complexity of specification? > > > > > > > > You say: > > > > > Case in point, every single subtle thing that you had to anticipate > > > > > and call out in your patch to `std::deque` would just go away if the > > > > > language simply propagated non-triviality of subobjects. > > > > > > > > But I don't understand what you mean by this. Are you saying that you > > > > want to be able to write `class [[trivially_relocatable]] deque { ... > > > > }` to mean that you want the trivially-relocatable-ness of `deque` to > > > > match the trivially-relocatable-ness of its least relocatable > > > > subobject? But then for example in the libc++ patch, I'd either have to > > > > go out of my way to make sure that `__map` and `__deque_base` were > > > > trivially relocatable (which would require metaprogramming similar to > > > > what's there now, except one turtle lower down in the stack — or were > > > > you thinking of adding `[[trivially_relocatable]]` to //all// the > > > > turtles in the stack?), or else I'd have to use `class > > > > [[trivially_relocatable!]] deque` to overrule the > > > > non-trivial-relocatability of `deque`'s `__map` and `__deque_base` > > > > subobjects, in which case I'd still need the four lines you were trying > > > > to eliminate. > > > > https://github.com/Quuxplusone/libcxx/commit/6524822c009e#diff-38adc80cec663f2f29c22e9ffc0de912R957 > > > > > > > > My kneejerk reaction is that it is a bad idea to have two > > > > similarly-named things, one of which has subtly correct semantics and > > > > the other of which has subtly incorrect semantics, especially when it's > > > > not obvious which one is correct in any specific situation. (OT: This > > > > is basically the reason behind my [[ > > > > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1155r0.html | > > > > P1155 ]].) But even beyond that //general// reaction, I > > > > //specifically// have not understood how `[[trivially_relocatable!]]` > > > > would help the programmer of `deque`. > > > > > > > > > All conforming implementations have to do the work to support things > > > > > like this already because of alignas, noexcept, etc. > > > > > > > > Yes, but those aren't attributes, grammatically... Well, I guess there > > > > is already a standard grammar for parsing unknown attributes in terms > > > > of `balanced-token-seq`, and I can't think of any boolean expression > > > > that is not a `balanced-token-seq`, so okay, I'll retract my FUD over > > > > the //technical// difficulties of `[[trivially_relocatable(bool)]]`. I > > > > am still ambivalent as to whether it'd be a good tradeoff. (Complexity > > > > of specification and arcane terseness of code, versus simplicity of > > > > specification and boilerplate verbosity of code.) > > > > But then for example in the libc++ patch, I'd either have to go out of > > > > my way to make sure that __map and __deque_base were trivially > > > > relocatable (which would require metaprogramming similar to what's > > > > there now, except one turtle lower down in the stack — or were you > > > > thinking of adding [[trivially_relocatable]] to all the turtles in the > > > > stack?), > > > > > > You would need the attribute only at the level(s) that actually defined > > > the special members; all the "rule of zero" levels would of course > > > propagate trivial relocatability. > > > > > > > I specifically have not understood how [[trivially_relocatable!]] would > > > > help the programmer of deque. > > > > > > It wouldn't. I don't think it's worth adding at all, actually. I'm just > > > saying it's possible to add it if you really think that > > > "trivially-relocatable type with a non-trivially-relocatable subobject" > > > is a relevant use case. > > > > > > > Yes, but those aren't attributes, grammatically... > > > > > > True, `alignas` is not spelled as an attribute (which I constantly forget > > > — it was a very odd decision). > > > > > > Recent drafts of the standard do include `expects` and `ensures`, which > > > take arbitrary expressions as operands. The spelling's a bit different > > > from the strawman I suggested, though: it's `[[expects: x > 0]]`. > > > > > > > I can't think of any boolean expression that is not a balanced-token-seq > > > > > > That's not a coincidence: all expressions are `balanced-token-seq`s, as > > > is every other major production in the C++ grammar. The grammar allows a > > > `balanced-token-seq` there precisely because the committee was > > > anticipating attributes that take arbitrarily complex expressions as > > > operands, which are quite common in all the vendor extensions they were > > > looking at. > > > > > > > I am still ambivalent as to whether it'd be a good tradeoff. > > > > (Complexity of specification and arcane terseness of code, versus > > > > simplicity of specification and boilerplate verbosity of code.) > > > > > > My two pieces of feedback are separable. Even with your preferred > > > semantics, your proposal would be much better if the attribute followed a > > > `noexcept`-like design where it can optionally take a boolean argument. > > > In fact, adding that is much more important with your semantics for the > > > attribute since so many use sites will be conditional. > > > > > > Also, I don't think your semantics actually give rise to a simpler > > > specification. The specification has to formalize "naturally trivially > > > relocatable" in either case because it's important for rule-of-zero types > > > to be trivially relocatable if all their subobjects are. My suggested > > > semantics are basically just that the attribute doesn't override the > > > natural relocatability of the type; it only prevents the presence of > > > non-trivial special members from changing it. That's a short paragraph > > > in the spec in exchange for an attribute that's much less prone to errors > > > in corner cases (e.g. ignoring the possibility of non-trivial pointer > > > types) and which rarely needs to be explicitly conditionalized. But it > > > does make the (unsafe) override case impossible, although, again, I think > > > the motivation for that is pretty weak. > > > I don't think your semantics actually give rise to a simpler > > > specification. The specification has to formalize "naturally trivially > > > relocatable" in either case > > > > I think the spec is already simple: [[ > > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1144r0.html#wording-inheritance > > | P1144R0 section 4.4 ]]. The paper spec doesn't need to formalize > > "naturally trivially relocatable"; that's an artifact of the Clang > > implementation. > > > > > My suggested semantics are basically just that the attribute doesn't > > > override the natural relocatability of the type; it only prevents the > > > presence of non-trivial special members from changing it. > > > > In the Clang patch, I'm //currently// using "naturally trivially > > relocatable" to mean "has defaulted special members //and// all subobjects > > are trivially relocatable." (So when I say "Xly Yly Zable," it implies "Yly > > Zable" as well as "Zable".) IIUC, you've been using it to mean "all > > subobjects are trivially relocatable but maybe there are user-provided > > special members"? I.e., if I had a class type with no data members, a > > user-defined destructor, and no attribute, you would have considered that > > class type to be "naturally trivially relocatable, but //not// trivially > > relocatable"? ("Xly Yly Zable" wouldn't imply "Yly Zable"?) > > > > > if you really think that "trivially-relocatable type with a > > > non-trivially-relocatable subobject" is a relevant use case > > > > Yes, that use-case is absolutely indispensable. For example, we must > > provide a way for the programmer to express that `struct Widget { > > boost::shared_ptr<Widget> sp; };` is trivially relocatable. (Without > > upgrading our Boost distribution. ;)) In P1144R0, we can do that by putting > > the attribute on `Widget`, or by putting the attribute on an "extremely > > loud and incredibly narrow" wrapper class: > > https://quuxplusone.github.io/blog/2018/10/04/trivially-relocatable-faq/#what-if-i-use-the-trivially_relo > "Yes, that use-case is absolutely indispensable. For example, we must provide > a way for the programmer to express that struct Widget { > boost::shared_ptr<Widget> sp; }; is trivially relocatable. (Without upgrading > our Boost distribution. ;)) " > > That's something I'd disagree with on first blush - why is this functionality > absolutely indispensable? > > I'd be pretty concerned about people effectively annotating types they don't > own with a guarantee they probably can't actually make - how's someone going > to make the determination that a third party type is safe to (indirectyl) add > this attribute to? & what if that type changes in the future (or has a debug > mode, or something else the user hasn't anticipated) - and it only solves the > cases where the third party type is embedded within a user type - which, for > something like shared_ptr misses lots of cases where the shared_ptr itself is > passed around. > > To me that doesn't seem like a "must have" feature - compared to the ability > to annotate a type where I've written some user-defined special members, but > I know/can guarantee (until I change the class in such a way that it doesn't > have that feature - at which point I can remove the attribute too, because I > control both implementation and attribution) that move+destroy is > semantically equivalent to memcpy. > > Yes, that use-case is absolutely indispensable. For example, we must > > provide a way for the programmer to express that `struct Widget { > > boost::shared_ptr<Widget> sp; };` is trivially relocatable. (Without > > upgrading our Boost distribution. ;)) > That's something I'd disagree with on first blush - why is this functionality > absolutely indispensable? Because it's close to functionality that people are trying to use today (e.g. Folly uses `FOLLY_ASSUME_RELOCATABLE` to apply trivial relocatability onto non-annotated types such as `boost::shared_ptr` or `std::string`). Admittedly, this is a source of bugs. But without it, I think people would just ask to have it — because it's the thing that gives them the codegen they want. Repository: rC Clang https://reviews.llvm.org/D50119 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits