--Daniel
You received this message because you are subscribed to the Google Groups "cxx" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cxx+uns...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CAF3XrKqUZORDJ2yQsZNc%3DYJnFOkfiy9eHSEaVsM8Mtw%3DR9tk%2Bg%40mail.gmail.com.
----Daniel
You received this message because you are subscribed to the Google Groups "cxx" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cxx+uns...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CAF3XrKqUZORDJ2yQsZNc%3DYJnFOkfiy9eHSEaVsM8Mtw%3DR9tk%2Bg%40mail.gmail.com.
You received this message because you are subscribed to the Google Groups "cxx" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cxx+uns...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CAHtyhaSBOksE6Zt7o8J8kc8UCE%2BduYVMyMGMMnon8oKK5Yk5eQ%40mail.gmail.com.
Would the extra work of writing a base wrapper around
absl::FunctionRef be helpful here? Both for developer education, and
maybe to fit in raw_ptr use.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CAHtyhaQ5aV6JgUp%2BrSo71rWzciKg9vCM878TpT_ip-1VMJEn4g%40mail.gmail.com.
You received this message because you are subscribed to the Google Groups "memory-safety-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to memory-safety-...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/memory-safety-dev/CAA_NCUEEJrPLB%3DThLNg9H1RKUYwaSXDDZHSWQV3vj0wYqAVWRg%40mail.gmail.com.
For more options, visit https://groups.google.com/a/chromium.org/d/optout.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CABg10jyy0wU0wsq-abhEW86Tf5Z0JuA17P2L_GEoECkmx5xENQ%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CAJTZ7LLx%2BkL5-pJhcP7h4ZxSnKo%3Dw-UoFiT00oEnjmWbWNFyKw%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CACuR13dqS-Bk_kHvzQCGcB0Ufp-HMak-fZmULKFyAoMi1hQFKQ%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CADsXd2OmzbOWUacX1HzrdhamtzgEru%3DBm6320a9xt84wOjen8Q%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CAKqK8MkQUw6xg%2BV%2BCVCYa5NcMezoFoAuN_sRZOz5crf_vQY9dw%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/memory-safety-dev/CAHtyhaTeq0KyChSVoS8MSQA%3DRzmJHzPnZZTbax6xNJOYVsYizw%40mail.gmail.com.
I'm working on writing this up, but I'm not entirely sure how to resolve the OnceCallback / RepeatingCallback -> FunctionRef implicit conversion.FunctionRef doesn't have any notion of how many times it can run; does that mean we should only allow an implicit conversion from RepeatingCallback?
If we don't do this, should we add something like RepeatingCallbackRef/OnceCallbackRef?
If we had operator() rather than Run it would just work for RepeatingCallback. Otherwise, it's of course possible to adapt, like:[&callback](auto&& args...) { std::move(callback).Run(std::forward<decltype(args)>(args)...); }and the same without std::move for RepeatingCallback. (Or a version without template voodoo if you know the concrete types involved. We could provide a helper function or conversion operator if we wished. In any case I don't think this confines callers from using callbacks.On Thu, Jun 16, 2022 at 5:25 PM K. Moon <km...@chromium.org> wrote:If we don't do this, should we add something like RepeatingCallbackRef/OnceCallbackRef?How would this be different from a normal reference to RepeatingCallback/OnceCallback?
On Fri, Jun 17, 2022 at 10:48 AM Jeremy Roman <jbr...@chromium.org> wrote:If we had operator() rather than Run it would just work for RepeatingCallback. Otherwise, it's of course possible to adapt, like:[&callback](auto&& args...) { std::move(callback).Run(std::forward<decltype(args)>(args)...); }and the same without std::move for RepeatingCallback. (Or a version without template voodoo if you know the concrete types involved. We could provide a helper function or conversion operator if we wished. In any case I don't think this confines callers from using callbacks.On Thu, Jun 16, 2022 at 5:25 PM K. Moon <km...@chromium.org> wrote:If we don't do this, should we add something like RepeatingCallbackRef/OnceCallbackRef?How would this be different from a normal reference to RepeatingCallback/OnceCallback?It should be different in the same way FunctionRef is different or it's not adding anything.
This class is suitable for use wherever a "const std::function<>&"
would be used without making a copy. ForEach functions and other versions of
the visitor pattern are a good example of when this class should be used.
FWIW, the absl::FunctionRef documentation has this to say:This class is suitable for use wherever a "const std::function<>&"
would be used without making a copy. ForEach functions and other versions of
the visitor pattern are a good example of when this class should be used.So only supporting RepeatingCallback might not be that bad an outcome. I'm sure there are cases where a OnceCallback would be useful (boilerplate wrapper, I guess), but probably much rarer.On Fri, Jun 17, 2022 at 8:56 AM K. Moon <km...@chromium.org> wrote:I think base::*Callback& would require a heap allocation, while base::*CallbackRef wouldn't? I thought this was the key motivation behind supporting something like this in the first place.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CACwGi-58fS1kPv3SdXnjuCO9aSLOyZqEzrHQjU%2B6%3DS25K%2BNZwQ%40mail.gmail.com.
I agree, but I think danakj@'s arguments are that:1. It shouldn't be hard to adapt an existing OnceCallback/RepeatingCallback to a signature that only takes a FunctionRef.2. It's useful to capture the once vs. repeating distinction in the type system, just as we do with *Callback.std::function and absl::FunctionRef are unconcerned with (2), so if that's important, I don't think absl::FunctionRef satisfies our requirements. In which case, the question is whether that requirement is useful for the situations that absl::FunctionRef is appropriate. (As a thought experiment, I do wonder now if some sort of Once<std::function<foo()>> or std::function<Once<foo()>> wrapper would be able to express the same requirements.)(1) possibly is not that valuable, since the whole point of an API taking a FunctionRef is to avoid the overhead of *Callback. It should be easy to adapt this case, but also inconvenient enough to perhaps encourage a better design, so I don't think this is as critical as (2).
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/memory-safety-dev/CACwGi-5xk_yb9YzDHXAX7mivmPJ7T1YF0tkkE9AE8f2445Smmg%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/memory-safety-dev/CACuR13cWfsxBOmRVaiOBVyMCApOdZz%2ByFJB8_z2QugTdujiv4w%40mail.gmail.com.
I think we should distinguish between:- allowing the conversion when making the actual call- converting between function pointer typesI see absl::FunctionRef's implicit conversions as far more in the spirit of the latter than the former. For example, it's not legal to pass a void (*)(Base*) to a void (*)(Derived*), even though it's possible to invoke a void (*)(Base*) by passing it a Derived*. There are times when it's convenient of course—but that seems to be relatively rare at the moment, based on my initial conversion attempts. It's always possible to consider ways to relax the conversions in the future (e.g. allow Derived -> Base conversions but not non-void -> void).
On Mon, Jul 18, 2022 at 12:17 PM Daniel Cheng <dch...@chromium.org> wrote:I think we should distinguish between:- allowing the conversion when making the actual call- converting between function pointer typesI see absl::FunctionRef's implicit conversions as far more in the spirit of the latter than the former. For example, it's not legal to pass a void (*)(Base*) to a void (*)(Derived*), even though it's possible to invoke a void (*)(Base*) by passing it a Derived*. There are times when it's convenient of course—but that seems to be relatively rare at the moment, based on my initial conversion attempts. It's always possible to consider ways to relax the conversions in the future (e.g. allow Derived -> Base conversions but not non-void -> void).The reason this isn't possible with function pointers seems to me to have more to do with ABI level considerations than API level considerations.The other approach would be to identify cases we think are more likely to be problematic and introduce (bypassable?) warnings for those exact cases, rather than changing the semantics of existing behavior.
I'd also register my generic resistance to swimming upstream against both the C++ standard library and Abseil (and by extension, Google internal C++) without any Chromium-specific reason.
On Mon, 18 Jul 2022 at 10:47, Jeremy Roman <jbr...@chromium.org> wrote:On Mon, Jul 18, 2022 at 12:17 PM Daniel Cheng <dch...@chromium.org> wrote:I think we should distinguish between:- allowing the conversion when making the actual call- converting between function pointer typesI see absl::FunctionRef's implicit conversions as far more in the spirit of the latter than the former. For example, it's not legal to pass a void (*)(Base*) to a void (*)(Derived*), even though it's possible to invoke a void (*)(Base*) by passing it a Derived*. There are times when it's convenient of course—but that seems to be relatively rare at the moment, based on my initial conversion attempts. It's always possible to consider ways to relax the conversions in the future (e.g. allow Derived -> Base conversions but not non-void -> void).The reason this isn't possible with function pointers seems to me to have more to do with ABI level considerations than API level considerations.The other approach would be to identify cases we think are more likely to be problematic and introduce (bypassable?) warnings for those exact cases, rather than changing the semantics of existing behavior.I guess that would require clang plugin modifications, which I can't say I'm enthusiastic about.I'd also register my generic resistance to swimming upstream against both the C++ standard library and Abseil (and by extension, Google internal C++) without any Chromium-specific reason.Well, there are reasons though :)1. absl::FunctionRef's adaptability is a mismatch from base::{Once,Repeating}Callback [1]. What should be a straightforward migration becomes much trickier when our core constructs have pitfalls like this. It *can* be worked around, but this brings me to #2.2. In general, Chrome has been trending towards encouraging constructs that are resistant to misuse, *even if* that means some divergence from the C++ standard library. Some differences are less obvious (e.g. explicitly crashing when trying to deref a null optional rather than treating it as UB), but some are more obvious (e.g. base::expected does not have operator*).
3. It's always much easier to relax restrictions rather than try to add them later. Why not start out with the use cases we know we need, and work on allowing more in the future?
On Mon, Jul 18, 2022 at 2:39 PM Daniel Cheng <dch...@chromium.org> wrote:On Mon, 18 Jul 2022 at 10:47, Jeremy Roman <jbr...@chromium.org> wrote:On Mon, Jul 18, 2022 at 12:17 PM Daniel Cheng <dch...@chromium.org> wrote:I think we should distinguish between:- allowing the conversion when making the actual call- converting between function pointer typesI see absl::FunctionRef's implicit conversions as far more in the spirit of the latter than the former. For example, it's not legal to pass a void (*)(Base*) to a void (*)(Derived*), even though it's possible to invoke a void (*)(Base*) by passing it a Derived*. There are times when it's convenient of course—but that seems to be relatively rare at the moment, based on my initial conversion attempts. It's always possible to consider ways to relax the conversions in the future (e.g. allow Derived -> Base conversions but not non-void -> void).The reason this isn't possible with function pointers seems to me to have more to do with ABI level considerations than API level considerations.The other approach would be to identify cases we think are more likely to be problematic and introduce (bypassable?) warnings for those exact cases, rather than changing the semantics of existing behavior.I guess that would require clang plugin modifications, which I can't say I'm enthusiastic about.I'd also register my generic resistance to swimming upstream against both the C++ standard library and Abseil (and by extension, Google internal C++) without any Chromium-specific reason.Well, there are reasons though :)1. absl::FunctionRef's adaptability is a mismatch from base::{Once,Repeating}Callback [1]. What should be a straightforward migration becomes much trickier when our core constructs have pitfalls like this. It *can* be worked around, but this brings me to #2.2. In general, Chrome has been trending towards encouraging constructs that are resistant to misuse, *even if* that means some divergence from the C++ standard library. Some differences are less obvious (e.g. explicitly crashing when trying to deref a null optional rather than treating it as UB), but some are more obvious (e.g. base::expected does not have operator*).I do admit to wondering why some of these are so bad for Chromium but perfectly fine in Google servers. I suspect this boils down to the individual opinions of the people making the decisions.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/cxx/CACuR13f%3DcCH-vqFeB6z-Mp%3DK5gEzUYVpd73a49gBj04WnuGNsQ%40mail.gmail.com.
On Mon, Jul 18, 2022 at 2:39 PM Daniel Cheng <dch...@chromium.org> wrote:On Mon, 18 Jul 2022 at 10:47, Jeremy Roman <jbr...@chromium.org> wrote:On Mon, Jul 18, 2022 at 12:17 PM Daniel Cheng <dch...@chromium.org> wrote:I think we should distinguish between:- allowing the conversion when making the actual call- converting between function pointer typesI see absl::FunctionRef's implicit conversions as far more in the spirit of the latter than the former. For example, it's not legal to pass a void (*)(Base*) to a void (*)(Derived*), even though it's possible to invoke a void (*)(Base*) by passing it a Derived*. There are times when it's convenient of course—but that seems to be relatively rare at the moment, based on my initial conversion attempts. It's always possible to consider ways to relax the conversions in the future (e.g. allow Derived -> Base conversions but not non-void -> void).The reason this isn't possible with function pointers seems to me to have more to do with ABI level considerations than API level considerations.The other approach would be to identify cases we think are more likely to be problematic and introduce (bypassable?) warnings for those exact cases, rather than changing the semantics of existing behavior.I guess that would require clang plugin modifications, which I can't say I'm enthusiastic about.I'd also register my generic resistance to swimming upstream against both the C++ standard library and Abseil (and by extension, Google internal C++) without any Chromium-specific reason.Well, there are reasons though :)1. absl::FunctionRef's adaptability is a mismatch from base::{Once,Repeating}Callback [1]. What should be a straightforward migration becomes much trickier when our core constructs have pitfalls like this. It *can* be worked around, but this brings me to #2.2. In general, Chrome has been trending towards encouraging constructs that are resistant to misuse, *even if* that means some divergence from the C++ standard library. Some differences are less obvious (e.g. explicitly crashing when trying to deref a null optional rather than treating it as UB), but some are more obvious (e.g. base::expected does not have operator*).I do admit to wondering why some of these are so bad for Chromium but perfectly fine in Google servers. I suspect this boils down to the individual opinions of the people making the decisions.
On Mon, Jul 18, 2022 at 6:55 PM Daniel Cheng <dch...@chromium.org> wrote:On Mon, Jul 18, 2022 at 2:39 PM Daniel Cheng <dch...@chromium.org> wrote:On Mon, 18 Jul 2022 at 10:47, Jeremy Roman <jbr...@chromium.org> wrote:On Mon, Jul 18, 2022 at 12:17 PM Daniel Cheng <dch...@chromium.org> wrote:I think we should distinguish between:- allowing the conversion when making the actual call- converting between function pointer typesI see absl::FunctionRef's implicit conversions as far more in the spirit of the latter than the former. For example, it's not legal to pass a void (*)(Base*) to a void (*)(Derived*), even though it's possible to invoke a void (*)(Base*) by passing it a Derived*. There are times when it's convenient of course—but that seems to be relatively rare at the moment, based on my initial conversion attempts. It's always possible to consider ways to relax the conversions in the future (e.g. allow Derived -> Base conversions but not non-void -> void).The reason this isn't possible with function pointers seems to me to have more to do with ABI level considerations than API level considerations.The other approach would be to identify cases we think are more likely to be problematic and introduce (bypassable?) warnings for those exact cases, rather than changing the semantics of existing behavior.I guess that would require clang plugin modifications, which I can't say I'm enthusiastic about.I'd also register my generic resistance to swimming upstream against both the C++ standard library and Abseil (and by extension, Google internal C++) without any Chromium-specific reason.Well, there are reasons though :)1. absl::FunctionRef's adaptability is a mismatch from base::{Once,Repeating}Callback [1]. What should be a straightforward migration becomes much trickier when our core constructs have pitfalls like this. It *can* be worked around, but this brings me to #2.2. In general, Chrome has been trending towards encouraging constructs that are resistant to misuse, *even if* that means some divergence from the C++ standard library. Some differences are less obvious (e.g. explicitly crashing when trying to deref a null optional rather than treating it as UB), but some are more obvious (e.g. base::expected does not have operator*).I do admit to wondering why some of these are so bad for Chromium but perfectly fine in Google servers. I suspect this boils down to the individual opinions of the people making the decisions.I think it is for similar reasons why we need to use raw_ptr<T> instead of T*. Chrome is required to handle an enormous amount of arbitrary (and malicious) inputs, and has full access to users' machines. The threat model differs, which has produced different requirements, and as we continue to invest in hardening and improving the Chrome codebase, they continue to diverge along similar axes. go/google3-builds-for-chrome-binaries
I don't have an opinion on FunctionRef, but FWIW, I've always found ForEachRenderFrameHost()'s overloaded behavior based on the callback's return type to be clever, but confusing. I find myself always checking the ForEachRenderFrameHost() to see what's allowed, as well as the call site to see which version is being invoked. I think not using overloading would be an improvement in this case.
This behavior seems to trace back to the C++ standard's definition of invocability (such as https://en.cppreference.com/w/cpp/types/is_invocable), which explicitly allows the conversion of any return type to void. I can see this being useful in some cases, but in any case, I think it might be unfair to single out FunctionRef for this concern, as it seems like the same problem can exist when using any API that relies on this definition of invocability. If it's something we want to prevent, a compiler plugin does sound like a better approach to me.