Again, the C++ standard does not say that moving from an object leaves the object in an undefined state.
The C++ standard does say: > Objects of types defined in the C++ standard library may be moved from > (12.8). Move operations may be explicitly specified or implicitly generated. > Unless otherwise specified, such moved-from objects shall be placed in a > valid but unspecified state. A few ways this differs from the claim that moving from an object leaves the object in an undefined state: (1) The standard makes no mention of objects in general, only of objects in the C++ standard library; (2) Even for objects in the C++ standard library, the standard makes no mention of objects in general, only of objects that are not “otherwise specified”; (3) The standard avoids undefined-ness entirely and instead specifies a valid but unspecified state. I think it is accurate to say that the C++ standard specifies that some objects in the standard library have valid but unspecified state when moved from. I think it’s also accurate to say that a function that accepts an rvalue reference as an argument does not promise to move from that rvalue reference. I think both of these statements are compatible with specifying what happens in WebKit libraries when we do move from an object. Geoff > On Dec 17, 2018, at 5:04 PM, Alex Christensen <achristen...@apple.com> wrote: > > We can definitely make our own WTF::Optional instead of using std::optional > and change its move constructor/operator= and I personally think that would > not be worth it but if I’m in the minority I’ll deal with it. We cannot > diverge from the C++ standards that say that moving from an object leaves the > object in an undefined state, and right now in WebKit we are relying quite a > lot on that undefined state. I think that is the bigger problem that Chris > was trying to solve. > >> On Dec 17, 2018, at 4:32 PM, Ryosuke Niwa <rn...@webkit.org >> <mailto:rn...@webkit.org>> wrote: >> >> Let me add this. >> >> The situation we have here is analogous to having a member function "move()" >> which leave std::optional in undefined state as in: >> >> std::optional<int> a; >> std::optional<int> b = a.move(); >> >> would leave a in some undefined state. I don't care what C++ standards say >> or what STL does. That's insane. >> Every object should remain in a well defined state after performing an >> operation. >> >> - R. Niwa >> >> >> On Mon, Dec 17, 2018 at 4:22 PM Ryosuke Niwa <rn...@webkit.org >> <mailto:rn...@webkit.org>> wrote: >> It's true that WTFMove or std::move doesn't do anything if the moved >> variable is not used because WTFMove / std::move is just a type cast. >> >> However, that behavior is orthogonal from the issue that calling WTFMove / >> std::move on std::optional, and the returned value is assigned to another >> std::optional, the original std::optional will be left a bad state. >> >> I completely disagree with your assessment that this calls for the use of >> std::exchange. >> >> >> On Mon, Dec 17, 2018 at 3:55 PM Alex Christensen <achristen...@apple.com >> <mailto:achristen...@apple.com>> wrote: >> Let me give a concrete example on why, even with our nice-to-use WTF types, >> the state of a C++ object is undefined after being moved from: >> >> #include <wtf/RefCounted.h> >> #include <wtf/RefPtr.h> >> #include <iostream> >> >> class Test : public RefCounted<Test> { }; >> >> void useParameter(RefPtr<Test>&& param) >> { >> RefPtr<Test> usedParam = WTFMove(param); >> } >> >> void dontUseParameter(RefPtr<Test>&&) { } >> >> int main() { >> RefPtr<Test> a = adoptRef(new Test); >> RefPtr<Test> b = adoptRef(new Test); >> std::cout << "a null? " << !a << std::endl; >> std::cout << "b null? " << !b << std::endl; >> useParameter(WTFMove(a)); >> dontUseParameter(WTFMove(b)); >> std::cout << "a null? " << !a << std::endl; >> std::cout << "b null? " << !b << std::endl; >> return 0; >> } >> >> // clang++ test.cpp -I Source/WTF -L WebKitBuild/Debug -l WTF -framework >> Foundation -L /usr/lib -l icucore --std=c++17 && ./a.out >> >> // a null? 0 >> >> >> // b null? 0 >> >> >> // a null? 1 >> >> >> // b null? 0 >> >> >> >> >> As you can see, the internals of callee dontUseParameter (which could be in >> a different translation unit) affects the state of the local variable b in >> this function. This is one of the reasons why the state of a moved-from >> variable is intentionally undefined, and we can’t fix that by using our own >> std::optional replacement. If we care about the state of a moved-from >> object, that is what std::exchange is for. I think we should do something >> to track and prevent the use of moved-from values instead of introducing our >> own std::optional replacement. >> >>> On Dec 17, 2018, at 2:47 PM, Ryosuke Niwa <rn...@webkit.org >>> <mailto:rn...@webkit.org>> wrote: >>> >>> Yeah, it seems like making std::optional more in line with our own >>> convention provides more merits than downsides here. People are using >>> WTFMove as if it's some sort of a swap operation in our codebase, and as >>> Maciej pointed out, having rules where people have to think carefully as to >>> when & when not to use WTFMove seems more troublesome than the proposed >>> fix, which would mean this work for optional. >>> >>> - R. Niwa >>> >>> On Mon, Dec 17, 2018 at 2:24 PM Geoffrey Garen <gga...@apple.com >>> <mailto:gga...@apple.com>> wrote: >>> I don’t understand the claim about “undefined behavior” here. As Maciej >>> pointed out, these are our libraries. We are free to define their behaviors. >>> >>> In general, “undefined behavior” is an unwanted feature of programming >>> languages and libraries, which we accept begrudgingly simply because there >>> are practical limits to what we can define. This acceptance is not a >>> mandate to carry forward undefined-ness as a badge of honor. In any case >>> where it would be practical to define a behavior, that defined behavior >>> would be preferable to undefined behavior. >>> >>> I agree that the behavior of move constructors in the standard library is >>> undefined. The proposal here, as I understand it, is to (a) define the >>> behaviors move constructors in WebKit and (b) avoid std::optional and use >>> an optional class with well-defined behavior instead. >>> >>> Because I do not ❤️ security updates, I do ❤️ defined behavior, and so I ❤️ >>> this proposal. >>> >>> Geoff >>> >>>> On Dec 17, 2018, at 12:50 PM, Alex Christensen <achristen...@apple.com >>>> <mailto:achristen...@apple.com>> wrote: >>>> >>>> This one and the many others like it are fragile, relying on undefined >>>> behavior, and should be replaced by std::exchange. Such a change was made >>>> in https://trac.webkit.org/changeset/198755/webkit >>>> <https://trac.webkit.org/changeset/198755/webkit> and we probably need >>>> many more like that, but we are getting away with relying on undefined >>>> behavior which works for us in most places. >>>> >>>>> On Dec 17, 2018, at 11:24 AM, Chris Dumez <cdu...@apple.com >>>>> <mailto:cdu...@apple.com>> wrote: >>>>> >>>>> >>>>> >>>>>> On Dec 17, 2018, at 11:10 AM, Chris Dumez <cdu...@apple.com >>>>>> <mailto:cdu...@apple.com>> wrote: >>>>>> >>>>>> >>>>>> >>>>>>> On Dec 17, 2018, at 10:27 AM, Alex Christensen <achristen...@apple.com >>>>>>> <mailto:achristen...@apple.com>> wrote: >>>>>>> >>>>>>>>>>> On Dec 14, 2018, at 1:37 PM, Chris Dumez <cdu...@apple.com >>>>>>>>>>> <mailto:cdu...@apple.com>> wrote: >>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> As far as I know, our convention in WebKit so far for our types has >>>>>>>>>>> been that types getting moved-out are left in a valid “empty” state. >>>>>>> This is not necessarily true. When we move out of an object to pass >>>>>>> into a function parameter, for example, the state of the moved-from >>>>>>> object depends on the behavior of the callee. If the callee function >>>>>>> uses the object, we often have behavior that leaves the object in an >>>>>>> “empty” state of some kind, but we are definitely relying on fragile >>>>>>> undefined behavior when we do so because changing the callee to not use >>>>>>> the parameter changes the state of the caller. We should never assume >>>>>>> that WTFMove or std::move leaves the object in an empty state. That is >>>>>>> always a bug that needs to be replaced by std::exchange. >>>>>> >>>>>> Feel like we’re taking about different things. I am talking about move >>>>>> constructors (and assignment operators), which have a well defined >>>>>> behavior in WebKit. And it seems you are talking about WTFMove(), which >>>>>> despite the name does not “move” anything, it is merely a cast. >>>>>> In the case you’re talking about the caller does NOT call the move >>>>>> constructor, it merely does a cast so I do not think your comment >>>>>> invalidates my statement. Note that in my patch, I was nearly >>>>>> WTFMove()ing the data member and assigning it to a local variable right >>>>>> away, calling the move constructor. >>>>> >>>>> Also note that may of us already rely on our move constructors’ behavior, >>>>> just search for WTFMove(m_responseCompletionHandler) in: >>>>> https://trac.webkit.org/changeset/236463/webkit >>>>> <https://trac.webkit.org/changeset/236463/webkit> >>>> _______________________________________________ >>>> webkit-dev mailing list >>>> webkit-dev@lists.webkit.org <mailto:webkit-dev@lists.webkit.org> >>>> https://lists.webkit.org/mailman/listinfo/webkit-dev >>>> <https://lists.webkit.org/mailman/listinfo/webkit-dev> >>> >>> _______________________________________________ >>> webkit-dev mailing list >>> webkit-dev@lists.webkit.org <mailto:webkit-dev@lists.webkit.org> >>> https://lists.webkit.org/mailman/listinfo/webkit-dev >>> <https://lists.webkit.org/mailman/listinfo/webkit-dev> >> > > _______________________________________________ > webkit-dev mailing list > webkit-dev@lists.webkit.org > https://lists.webkit.org/mailman/listinfo/webkit-dev
_______________________________________________ webkit-dev mailing list webkit-dev@lists.webkit.org https://lists.webkit.org/mailman/listinfo/webkit-dev