xref: /aosp_15_r20/external/cronet/base/functional/bind_nocompile.nc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker// Copyright 2011 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker// Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker// found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker// This is a "No Compile Test" suite.
6*6777b538SAndroid Build Coastguard Worker// http://dev.chromium.org/developers/testing/no-compile-tests
7*6777b538SAndroid Build Coastguard Worker
8*6777b538SAndroid Build Coastguard Worker#define FORCE_UNRETAINED_COMPLETENESS_CHECKS_FOR_TESTS 1
9*6777b538SAndroid Build Coastguard Worker
10*6777b538SAndroid Build Coastguard Worker#include <stdint.h>
11*6777b538SAndroid Build Coastguard Worker
12*6777b538SAndroid Build Coastguard Worker#include <utility>
13*6777b538SAndroid Build Coastguard Worker
14*6777b538SAndroid Build Coastguard Worker#include "base/functional/bind.h"
15*6777b538SAndroid Build Coastguard Worker#include "base/functional/callback.h"
16*6777b538SAndroid Build Coastguard Worker#include "base/functional/disallow_unretained.h"
17*6777b538SAndroid Build Coastguard Worker#include "base/memory/raw_ptr.h"
18*6777b538SAndroid Build Coastguard Worker#include "base/memory/raw_ref.h"
19*6777b538SAndroid Build Coastguard Worker#include "base/memory/ref_counted.h"
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Workernamespace base {
22*6777b538SAndroid Build Coastguard Worker
23*6777b538SAndroid Build Coastguard Workervoid NonConstFunctionWithConstObject() {
24*6777b538SAndroid Build Coastguard Worker  struct S : RefCounted<S> {
25*6777b538SAndroid Build Coastguard Worker    void Method() {}
26*6777b538SAndroid Build Coastguard Worker  } s;
27*6777b538SAndroid Build Coastguard Worker  const S* const const_s_ptr = &s;
28*6777b538SAndroid Build Coastguard Worker  // Non-`const` methods may not be bound with a `const` receiver.
29*6777b538SAndroid Build Coastguard Worker  BindRepeating(&S::Method, const_s_ptr);  // expected-error@*:* {{Type mismatch between bound argument and bound functor's parameter.}}
30*6777b538SAndroid Build Coastguard Worker  // `const` pointer cannot be bound to non-`const` parameter.
31*6777b538SAndroid Build Coastguard Worker  BindRepeating([] (S*) {}, const_s_ptr);  // expected-error@*:* {{Type mismatch between bound argument and bound functor's parameter.}}
32*6777b538SAndroid Build Coastguard Worker}
33*6777b538SAndroid Build Coastguard Worker
34*6777b538SAndroid Build Coastguard Workervoid WrongReceiverTypeForNonRefcounted() {
35*6777b538SAndroid Build Coastguard Worker  // 1. Non-refcounted objects must use `Unretained()` for the `this` argument.
36*6777b538SAndroid Build Coastguard Worker  // 2. Reference-like objects may not be used as the receiver.
37*6777b538SAndroid Build Coastguard Worker  struct A {
38*6777b538SAndroid Build Coastguard Worker    void Method() {}
39*6777b538SAndroid Build Coastguard Worker    void ConstMethod() const {}
40*6777b538SAndroid Build Coastguard Worker  } a;
41*6777b538SAndroid Build Coastguard Worker  // Using distinct types causes distinct template instantiations, so we get
42*6777b538SAndroid Build Coastguard Worker  // assertion failures below where we expect. These types facilitate that.
43*6777b538SAndroid Build Coastguard Worker  struct B : A {} b;
44*6777b538SAndroid Build Coastguard Worker  struct C : A {} c;
45*6777b538SAndroid Build Coastguard Worker  struct D : A {} d;
46*6777b538SAndroid Build Coastguard Worker  struct E : A {};
47*6777b538SAndroid Build Coastguard Worker  A* ptr_a = &a;
48*6777b538SAndroid Build Coastguard Worker  A& ref_a = a;
49*6777b538SAndroid Build Coastguard Worker  raw_ptr<A> rawptr_a(&a);
50*6777b538SAndroid Build Coastguard Worker  raw_ref<A> rawref_a(a);
51*6777b538SAndroid Build Coastguard Worker  const B const_b;
52*6777b538SAndroid Build Coastguard Worker  B* ptr_b = &b;
53*6777b538SAndroid Build Coastguard Worker  const B* const_ptr_b = &const_b;
54*6777b538SAndroid Build Coastguard Worker  B& ref_b = b;
55*6777b538SAndroid Build Coastguard Worker  const B& const_ref_b = const_b;
56*6777b538SAndroid Build Coastguard Worker  raw_ptr<B> rawptr_b(&b);
57*6777b538SAndroid Build Coastguard Worker  raw_ptr<const B> const_rawptr_b(&const_b);
58*6777b538SAndroid Build Coastguard Worker  raw_ref<B> rawref_b(b);
59*6777b538SAndroid Build Coastguard Worker  raw_ref<const B> const_rawref_b(const_b);
60*6777b538SAndroid Build Coastguard Worker  C& ref_c = c;
61*6777b538SAndroid Build Coastguard Worker  D& ref_d = d;
62*6777b538SAndroid Build Coastguard Worker  const E const_e;
63*6777b538SAndroid Build Coastguard Worker  const E& const_ref_e = const_e;
64*6777b538SAndroid Build Coastguard Worker  BindRepeating(&A::Method, &a);                   // expected-error@*:* {{Receivers may not be raw pointers.}}
65*6777b538SAndroid Build Coastguard Worker  BindRepeating(&A::Method, ptr_a);                // expected-error@*:* {{Receivers may not be raw pointers.}}
66*6777b538SAndroid Build Coastguard Worker  BindRepeating(&A::Method, a);                    // expected-error@*:* {{Cannot convert `this` argument to address.}}
67*6777b538SAndroid Build Coastguard Worker  BindRepeating(&C::Method, ref_c);                // expected-error@*:* {{Cannot convert `this` argument to address.}}
68*6777b538SAndroid Build Coastguard Worker  BindRepeating(&A::Method, std::ref(a));          // expected-error@*:* {{Cannot convert `this` argument to address.}}
69*6777b538SAndroid Build Coastguard Worker  BindRepeating(&A::Method, std::cref(a));         // expected-error@*:* {{Cannot convert `this` argument to address.}}
70*6777b538SAndroid Build Coastguard Worker  BindRepeating(&A::Method, rawptr_a);             // expected-error@*:* {{Receivers may not be raw pointers.}}
71*6777b538SAndroid Build Coastguard Worker  BindRepeating(&A::Method, rawref_a);             // expected-error@*:* {{Receivers may not be raw_ref<T>.}}
72*6777b538SAndroid Build Coastguard Worker  BindRepeating(&B::ConstMethod, &b);              // expected-error@*:* {{Receivers may not be raw pointers.}}
73*6777b538SAndroid Build Coastguard Worker  BindRepeating(&B::ConstMethod, &const_b);        // expected-error@*:* {{Receivers may not be raw pointers.}}
74*6777b538SAndroid Build Coastguard Worker  BindRepeating(&B::ConstMethod, ptr_b);           // expected-error@*:* {{Receivers may not be raw pointers.}}
75*6777b538SAndroid Build Coastguard Worker  BindRepeating(&B::ConstMethod, const_ptr_b);     // expected-error@*:* {{Receivers may not be raw pointers.}}
76*6777b538SAndroid Build Coastguard Worker  BindRepeating(&B::ConstMethod, b);               // expected-error@*:* {{Cannot convert `this` argument to address.}}
77*6777b538SAndroid Build Coastguard Worker  BindRepeating(&D::ConstMethod, ref_d);           // expected-error@*:* {{Cannot convert `this` argument to address.}}
78*6777b538SAndroid Build Coastguard Worker  BindRepeating(&E::ConstMethod, const_ref_e);     // expected-error@*:* {{Cannot convert `this` argument to address.}}
79*6777b538SAndroid Build Coastguard Worker  BindRepeating(&B::ConstMethod, std::ref(b));     // expected-error@*:* {{Cannot convert `this` argument to address.}}
80*6777b538SAndroid Build Coastguard Worker  BindRepeating(&B::ConstMethod, std::cref(b));    // expected-error@*:* {{Cannot convert `this` argument to address.}}
81*6777b538SAndroid Build Coastguard Worker  BindRepeating(&B::ConstMethod, rawptr_b);        // expected-error@*:* {{Receivers may not be raw pointers.}}
82*6777b538SAndroid Build Coastguard Worker  BindRepeating(&B::ConstMethod, const_rawptr_b);  // expected-error@*:* {{Receivers may not be raw pointers.}}
83*6777b538SAndroid Build Coastguard Worker  BindRepeating(&B::ConstMethod, rawref_b);        // expected-error@*:* {{Receivers may not be raw_ref<T>.}}
84*6777b538SAndroid Build Coastguard Worker  BindRepeating(&B::ConstMethod, const_rawref_b);  // expected-error@*:* {{Receivers may not be raw_ref<T>.}}
85*6777b538SAndroid Build Coastguard Worker}
86*6777b538SAndroid Build Coastguard Worker
87*6777b538SAndroid Build Coastguard Workervoid WrongReceiverTypeForRefcounted() {
88*6777b538SAndroid Build Coastguard Worker  // Refcounted objects must pass a pointer-like `this` argument.
89*6777b538SAndroid Build Coastguard Worker  struct A : RefCounted<A> {
90*6777b538SAndroid Build Coastguard Worker    void Method() const {}
91*6777b538SAndroid Build Coastguard Worker  } a;
92*6777b538SAndroid Build Coastguard Worker  // Using distinct types causes distinct template instantiations, so we get
93*6777b538SAndroid Build Coastguard Worker  // assertion failures below where we expect. These types facilitate that.
94*6777b538SAndroid Build Coastguard Worker  struct B : A {} b;
95*6777b538SAndroid Build Coastguard Worker  struct C : A {};
96*6777b538SAndroid Build Coastguard Worker  const A const_a;
97*6777b538SAndroid Build Coastguard Worker  B& ref_b = b;
98*6777b538SAndroid Build Coastguard Worker  const C const_c;
99*6777b538SAndroid Build Coastguard Worker  const C& const_ref_c = const_c;
100*6777b538SAndroid Build Coastguard Worker  raw_ref<A> rawref_a(a);
101*6777b538SAndroid Build Coastguard Worker  raw_ref<const A> const_rawref_a(const_a);
102*6777b538SAndroid Build Coastguard Worker  BindRepeating(&A::Method, a);               // expected-error@*:* {{Cannot convert `this` argument to address.}}
103*6777b538SAndroid Build Coastguard Worker  BindRepeating(&B::Method, ref_b);           // expected-error@*:* {{Cannot convert `this` argument to address.}}
104*6777b538SAndroid Build Coastguard Worker  BindRepeating(&C::Method, const_ref_c);     // expected-error@*:* {{Cannot convert `this` argument to address.}}
105*6777b538SAndroid Build Coastguard Worker  BindRepeating(&A::Method, std::ref(a));     // expected-error@*:* {{Cannot convert `this` argument to address.}}
106*6777b538SAndroid Build Coastguard Worker  BindRepeating(&A::Method, std::cref(a));    // expected-error@*:* {{Cannot convert `this` argument to address.}}
107*6777b538SAndroid Build Coastguard Worker  BindRepeating(&A::Method, rawref_a);        // expected-error@*:* {{Receivers may not be raw_ref<T>.}}
108*6777b538SAndroid Build Coastguard Worker  BindRepeating(&A::Method, const_rawref_a);  // expected-error@*:* {{Receivers may not be raw_ref<T>.}}
109*6777b538SAndroid Build Coastguard Worker}
110*6777b538SAndroid Build Coastguard Worker
111*6777b538SAndroid Build Coastguard Workervoid RemovesConst() {
112*6777b538SAndroid Build Coastguard Worker  // Callbacks that expect non-const refs/ptrs should not be callable with const
113*6777b538SAndroid Build Coastguard Worker  // ones.
114*6777b538SAndroid Build Coastguard Worker  const int i = 0;
115*6777b538SAndroid Build Coastguard Worker  const int* p = &i;
116*6777b538SAndroid Build Coastguard Worker  BindRepeating([] (int&) {}).Run(i);  // expected-error {{no matching member function for call to 'Run'}}
117*6777b538SAndroid Build Coastguard Worker  BindRepeating([] (int*) {}, p);      // expected-error@*:* {{Type mismatch between bound argument and bound functor's parameter.}}
118*6777b538SAndroid Build Coastguard Worker  BindRepeating([] (int*) {}).Run(p);  // expected-error {{no matching member function for call to 'Run'}}
119*6777b538SAndroid Build Coastguard Worker}
120*6777b538SAndroid Build Coastguard Worker
121*6777b538SAndroid Build Coastguard Workervoid PassingIncorrectRef() {
122*6777b538SAndroid Build Coastguard Worker  // Functions that take non-const reference arguments require the parameters to
123*6777b538SAndroid Build Coastguard Worker  // be bound as matching `std::ref()`s or `OwnedRef()`s.
124*6777b538SAndroid Build Coastguard Worker  int i = 1;
125*6777b538SAndroid Build Coastguard Worker  float f = 1.0f;
126*6777b538SAndroid Build Coastguard Worker  // No wrapper.
127*6777b538SAndroid Build Coastguard Worker  BindOnce([] (int&) {}, i);       // expected-error@*:* {{Bound argument for non-const reference parameter must be wrapped in std::ref() or base::OwnedRef().}}
128*6777b538SAndroid Build Coastguard Worker  BindRepeating([] (int&) {}, i);  // expected-error@*:* {{Bound argument for non-const reference parameter must be wrapped in std::ref() or base::OwnedRef().}}
129*6777b538SAndroid Build Coastguard Worker  // Wrapper, but with mismatched type.
130*6777b538SAndroid Build Coastguard Worker  BindOnce([] (int&) {}, f);            // expected-error@*:* {{Type mismatch between bound argument and bound functor's parameter.}}
131*6777b538SAndroid Build Coastguard Worker  BindOnce([] (int&) {}, std::ref(f));  // expected-error@*:* {{Type mismatch between bound argument and bound functor's parameter.}}
132*6777b538SAndroid Build Coastguard Worker  BindOnce([] (int&) {}, OwnedRef(f));  // expected-error@*:* {{Type mismatch between bound argument and bound functor's parameter.}}
133*6777b538SAndroid Build Coastguard Worker}
134*6777b538SAndroid Build Coastguard Worker
135*6777b538SAndroid Build Coastguard Workervoid ArrayAsReceiver() {
136*6777b538SAndroid Build Coastguard Worker  // A method should not be bindable with an array of objects. Users could
137*6777b538SAndroid Build Coastguard Worker  // unintentionally attempt to do this via array->pointer decay.
138*6777b538SAndroid Build Coastguard Worker  struct S : RefCounted<S> {
139*6777b538SAndroid Build Coastguard Worker    void Method() const {}
140*6777b538SAndroid Build Coastguard Worker  };
141*6777b538SAndroid Build Coastguard Worker  S s[2];
142*6777b538SAndroid Build Coastguard Worker  BindRepeating(&S::Method, s);  // expected-error@*:* {{First bound argument to a method cannot be an array.}}
143*6777b538SAndroid Build Coastguard Worker}
144*6777b538SAndroid Build Coastguard Worker
145*6777b538SAndroid Build Coastguard Workervoid RefCountedArgs() {
146*6777b538SAndroid Build Coastguard Worker  // Refcounted types should not be bound as a raw pointers.
147*6777b538SAndroid Build Coastguard Worker  struct S : RefCounted<S> {};
148*6777b538SAndroid Build Coastguard Worker  S s;
149*6777b538SAndroid Build Coastguard Worker  const S const_s;
150*6777b538SAndroid Build Coastguard Worker  S* ptr_s = &s;
151*6777b538SAndroid Build Coastguard Worker  const S* const_ptr_s = &const_s;
152*6777b538SAndroid Build Coastguard Worker  raw_ptr<S> rawptr(&s);
153*6777b538SAndroid Build Coastguard Worker  raw_ptr<const S> const_rawptr(&const_s);
154*6777b538SAndroid Build Coastguard Worker  raw_ref<S> rawref(s);
155*6777b538SAndroid Build Coastguard Worker  raw_ref<const S> const_rawref(const_s);
156*6777b538SAndroid Build Coastguard Worker  BindRepeating([] (S*) {}, &s);                          // expected-error@*:* {{A parameter is a refcounted type and needs scoped_refptr.}}
157*6777b538SAndroid Build Coastguard Worker  BindRepeating([] (const S*) {}, &const_s);              // expected-error@*:* {{A parameter is a refcounted type and needs scoped_refptr.}}
158*6777b538SAndroid Build Coastguard Worker  BindRepeating([] (S*) {}, ptr_s);                       // expected-error@*:* {{A parameter is a refcounted type and needs scoped_refptr.}}
159*6777b538SAndroid Build Coastguard Worker  BindRepeating([] (const S*) {}, const_ptr_s);           // expected-error@*:* {{A parameter is a refcounted type and needs scoped_refptr.}}
160*6777b538SAndroid Build Coastguard Worker  BindRepeating([] (S*) {}, rawptr);                      // expected-error@*:* {{A parameter is a refcounted type and needs scoped_refptr.}}
161*6777b538SAndroid Build Coastguard Worker  BindRepeating([] (const S*) {}, const_rawptr);          // expected-error@*:* {{A parameter is a refcounted type and needs scoped_refptr.}}
162*6777b538SAndroid Build Coastguard Worker  BindRepeating([] (raw_ref<S>) {}, rawref);              // expected-error@*:* {{A parameter is a refcounted type and needs scoped_refptr.}}
163*6777b538SAndroid Build Coastguard Worker  BindRepeating([] (raw_ref<const S>) {}, const_rawref);  // expected-error@*:* {{A parameter is a refcounted type and needs scoped_refptr.}}
164*6777b538SAndroid Build Coastguard Worker}
165*6777b538SAndroid Build Coastguard Worker
166*6777b538SAndroid Build Coastguard Workervoid WeakPtrWithReturnType() {
167*6777b538SAndroid Build Coastguard Worker  // WeakPtrs cannot be bound to methods with return types, since if the WeakPtr
168*6777b538SAndroid Build Coastguard Worker  // is null when the callback runs, it's not clear what the framework should
169*6777b538SAndroid Build Coastguard Worker  // return.
170*6777b538SAndroid Build Coastguard Worker  struct S {
171*6777b538SAndroid Build Coastguard Worker    int ReturnsInt() const { return 1; }
172*6777b538SAndroid Build Coastguard Worker  } s;
173*6777b538SAndroid Build Coastguard Worker  WeakPtrFactory<S> weak_factory(&s);
174*6777b538SAndroid Build Coastguard Worker  BindRepeating(&S::ReturnsInt, weak_factory.GetWeakPtr());  // expected-error@*:* {{WeakPtrs can only bind to methods without return values.}}
175*6777b538SAndroid Build Coastguard Worker}
176*6777b538SAndroid Build Coastguard Worker
177*6777b538SAndroid Build Coastguard Workervoid CallbackConversion() {
178*6777b538SAndroid Build Coastguard Worker  // Callbacks should not be constructible from other callbacks in ways that
179*6777b538SAndroid Build Coastguard Worker  // would drop ref or pointer constness or change arity.
180*6777b538SAndroid Build Coastguard Worker  RepeatingCallback<int(int&)> wrong_ref_constness = BindRepeating([] (const int&) {});  // expected-error {{no viable conversion from 'RepeatingCallback<UnboundRunType>' to 'RepeatingCallback<int (int &)>'}}
181*6777b538SAndroid Build Coastguard Worker  RepeatingCallback<int(int*)> wrong_ptr_constness = BindRepeating([] (const int*) {});  // expected-error {{no viable conversion from 'RepeatingCallback<UnboundRunType>' to 'RepeatingCallback<int (int *)>'}}
182*6777b538SAndroid Build Coastguard Worker  RepeatingClosure arg_count_too_low = BindRepeating([] (int) {});                       // expected-error {{no viable conversion from 'RepeatingCallback<UnboundRunType>' to 'RepeatingCallback<void ()>'}}
183*6777b538SAndroid Build Coastguard Worker  RepeatingCallback<int(int)> arg_count_too_high = BindRepeating([] { return 0; });      // expected-error {{no viable conversion from 'RepeatingCallback<UnboundRunType>' to 'RepeatingCallback<int (int)>'}}
184*6777b538SAndroid Build Coastguard Worker  RepeatingClosure discarding_return = BindRepeating([] { return 0; });                  // expected-error {{no viable conversion from 'RepeatingCallback<UnboundRunType>' to 'RepeatingCallback<void ()>'}}
185*6777b538SAndroid Build Coastguard Worker}
186*6777b538SAndroid Build Coastguard Worker
187*6777b538SAndroid Build Coastguard Workervoid CapturingLambdaOrFunctor() {
188*6777b538SAndroid Build Coastguard Worker  // Bind disallows capturing lambdas and stateful functors.
189*6777b538SAndroid Build Coastguard Worker  int i = 0, j = 0;
190*6777b538SAndroid Build Coastguard Worker  struct S {
191*6777b538SAndroid Build Coastguard Worker    void operator()() const {}
192*6777b538SAndroid Build Coastguard Worker    int x;
193*6777b538SAndroid Build Coastguard Worker  };
194*6777b538SAndroid Build Coastguard Worker  BindOnce([&]() { j = i; });        // expected-error@*:* {{Capturing lambdas and stateful functors are intentionally not supported.}}
195*6777b538SAndroid Build Coastguard Worker  BindRepeating([&]() { j = i; });   // expected-error@*:* {{Capturing lambdas and stateful functors are intentionally not supported.}}
196*6777b538SAndroid Build Coastguard Worker  BindRepeating(S());                // expected-error@*:* {{Capturing lambdas and stateful functors are intentionally not supported.}}
197*6777b538SAndroid Build Coastguard Worker}
198*6777b538SAndroid Build Coastguard Worker
199*6777b538SAndroid Build Coastguard Workervoid OnceCallbackRequiresNonConstRvalue() {
200*6777b538SAndroid Build Coastguard Worker  // `OnceCallback::Run()` can only be invoked on a non-const rvalue.
201*6777b538SAndroid Build Coastguard Worker  // Using distinct types causes distinct template instantiations, so we get
202*6777b538SAndroid Build Coastguard Worker  // assertion failures below where we expect. These types facilitate that.
203*6777b538SAndroid Build Coastguard Worker  enum class A {};
204*6777b538SAndroid Build Coastguard Worker  enum class B {};
205*6777b538SAndroid Build Coastguard Worker  enum class C {};
206*6777b538SAndroid Build Coastguard Worker  OnceCallback<void(A)> cb_a = BindOnce([] (A) {});
207*6777b538SAndroid Build Coastguard Worker  const OnceCallback<void(B)> const_cb_b = BindOnce([] (B) {});
208*6777b538SAndroid Build Coastguard Worker  const OnceCallback<void(C)> const_cb_c = BindOnce([] (C) {});
209*6777b538SAndroid Build Coastguard Worker  cb_a.Run(A{});                   // expected-error@*:* {{OnceCallback::Run() may only be invoked on a non-const rvalue, i.e. std::move(callback).Run().}}
210*6777b538SAndroid Build Coastguard Worker  const_cb_b.Run(B{});             // expected-error@*:* {{OnceCallback::Run() may only be invoked on a non-const rvalue, i.e. std::move(callback).Run().}}
211*6777b538SAndroid Build Coastguard Worker  std::move(const_cb_c).Run(C{});  // expected-error@*:* {{OnceCallback::Run() may only be invoked on a non-const rvalue, i.e. std::move(callback).Run().}}
212*6777b538SAndroid Build Coastguard Worker}
213*6777b538SAndroid Build Coastguard Worker
214*6777b538SAndroid Build Coastguard Workervoid OnceCallbackAsArgMustBeNonConstRvalue() {
215*6777b538SAndroid Build Coastguard Worker  // A `OnceCallback` passed to another callback must be a non-const rvalue.
216*6777b538SAndroid Build Coastguard Worker  auto cb = BindOnce([] (int) {});
217*6777b538SAndroid Build Coastguard Worker  const auto const_cb = BindOnce([] (int) {});
218*6777b538SAndroid Build Coastguard Worker  BindOnce(cb, 0);                   // expected-error@*:* {{BindOnce() requires non-const rvalue for OnceCallback binding, i.e. base::BindOnce(std::move(callback)).}}
219*6777b538SAndroid Build Coastguard Worker  BindOnce(std::move(const_cb), 0);  // expected-error@*:* {{BindOnce() requires non-const rvalue for OnceCallback binding, i.e. base::BindOnce(std::move(callback)).}}
220*6777b538SAndroid Build Coastguard Worker}
221*6777b538SAndroid Build Coastguard Worker
222*6777b538SAndroid Build Coastguard Workervoid OnceCallbackBoundByRepeatingCallback() {
223*6777b538SAndroid Build Coastguard Worker  // `BindRepeating()` does not accept `OnceCallback`s.
224*6777b538SAndroid Build Coastguard Worker  BindRepeating(BindOnce([] (int) {}), 0);  // expected-error@*:* {{BindRepeating() cannot bind OnceCallback. Use BindOnce() with std::move().}}
225*6777b538SAndroid Build Coastguard Worker}
226*6777b538SAndroid Build Coastguard Worker
227*6777b538SAndroid Build Coastguard Workervoid MoveOnlyArg() {
228*6777b538SAndroid Build Coastguard Worker  // Move-only types require `std::move()` for `BindOnce()` and `base::Passed()` for `BindRepeating()`.
229*6777b538SAndroid Build Coastguard Worker  struct S {
230*6777b538SAndroid Build Coastguard Worker    S() = default;
231*6777b538SAndroid Build Coastguard Worker    S(S&&) = default;
232*6777b538SAndroid Build Coastguard Worker    S& operator=(S&&) = default;
233*6777b538SAndroid Build Coastguard Worker  } s1, s2;
234*6777b538SAndroid Build Coastguard Worker  BindOnce([] (S) {}, s1);                  // expected-error@*:* {{Attempting to bind a move-only type. Use std::move() to transfer ownership to the created callback.}}
235*6777b538SAndroid Build Coastguard Worker  BindOnce([] (S) {}, Passed(&s1));         // expected-error@*:* {{Use std::move() instead of base::Passed() with base::BindOnce().}}
236*6777b538SAndroid Build Coastguard Worker  BindRepeating([] (S) {}, s2);             // expected-error@*:* {{base::BindRepeating() argument is a move-only type. Use base::Passed() instead of std::move() to transfer ownership from the callback to the bound functor.}}
237*6777b538SAndroid Build Coastguard Worker  BindRepeating([] (S) {}, std::move(s2));  // expected-error@*:* {{base::BindRepeating() argument is a move-only type. Use base::Passed() instead of std::move() to transfer ownership from the callback to the bound functor.}}
238*6777b538SAndroid Build Coastguard Worker}
239*6777b538SAndroid Build Coastguard Worker
240*6777b538SAndroid Build Coastguard Workervoid NonCopyableNonMovable() {
241*6777b538SAndroid Build Coastguard Worker  // Arguments must be either copyable or movable to be captured.
242*6777b538SAndroid Build Coastguard Worker  struct S {
243*6777b538SAndroid Build Coastguard Worker    S() = default;
244*6777b538SAndroid Build Coastguard Worker    S(const S&) = delete;
245*6777b538SAndroid Build Coastguard Worker    S& operator=(const S&) = delete;
246*6777b538SAndroid Build Coastguard Worker  } s;
247*6777b538SAndroid Build Coastguard Worker  BindOnce([](const S&) {}, s);  // expected-error@*:* {{Cannot capture argument: is the argument copyable or movable?}}
248*6777b538SAndroid Build Coastguard Worker}
249*6777b538SAndroid Build Coastguard Worker
250*6777b538SAndroid Build Coastguard Workervoid OverloadedFunction() {
251*6777b538SAndroid Build Coastguard Worker  // Overloaded function types cannot be disambiguated. (It might be nice to fix
252*6777b538SAndroid Build Coastguard Worker  // this.)
253*6777b538SAndroid Build Coastguard Worker  void F(int);
254*6777b538SAndroid Build Coastguard Worker  void F(float);
255*6777b538SAndroid Build Coastguard Worker  BindOnce(&F, 1);          // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}}
256*6777b538SAndroid Build Coastguard Worker  BindRepeating(&F, 1.0f);  // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}}
257*6777b538SAndroid Build Coastguard Worker}
258*6777b538SAndroid Build Coastguard Worker
259*6777b538SAndroid Build Coastguard Workervoid OverloadedOperator() {
260*6777b538SAndroid Build Coastguard Worker  // It's not possible to bind to a functor with an overloaded `operator()()`
261*6777b538SAndroid Build Coastguard Worker  // unless the caller supplies arguments that can invoke a unique overload.
262*6777b538SAndroid Build Coastguard Worker  struct A {
263*6777b538SAndroid Build Coastguard Worker    int64_t operator()(int, int64_t x) { return x; }
264*6777b538SAndroid Build Coastguard Worker    uint64_t operator()(int, uint64_t x) { return x; }
265*6777b538SAndroid Build Coastguard Worker    A operator()(double, A a) { return a; }
266*6777b538SAndroid Build Coastguard Worker  } a;
267*6777b538SAndroid Build Coastguard Worker  // Using distinct types causes distinct template instantiations, so we get
268*6777b538SAndroid Build Coastguard Worker  // assertion failures below where we expect. These types facilitate that.
269*6777b538SAndroid Build Coastguard Worker  struct B : A {} b;
270*6777b538SAndroid Build Coastguard Worker  struct C : A {} c;
271*6777b538SAndroid Build Coastguard Worker  struct D : A {} d;
272*6777b538SAndroid Build Coastguard Worker
273*6777b538SAndroid Build Coastguard Worker  // Partial function application isn't supported, even if it's sufficient to
274*6777b538SAndroid Build Coastguard Worker  // "narrow the field" to a single candidate that _could_ eventually match.
275*6777b538SAndroid Build Coastguard Worker  BindOnce(a);              // expected-error@*:* {{Could not determine how to invoke functor.}}
276*6777b538SAndroid Build Coastguard Worker  BindOnce(b, 1.0);         // expected-error@*:* {{Could not determine how to invoke functor.}}
277*6777b538SAndroid Build Coastguard Worker
278*6777b538SAndroid Build Coastguard Worker  // The supplied args don't match any candidates.
279*6777b538SAndroid Build Coastguard Worker  BindOnce(c, 1, nullptr);  // expected-error@*:* {{Could not determine how to invoke functor.}}
280*6777b538SAndroid Build Coastguard Worker
281*6777b538SAndroid Build Coastguard Worker  // The supplied args inexactly match multiple candidates.
282*6777b538SAndroid Build Coastguard Worker  BindOnce(d, 1, 1);        // expected-error@*:* {{Could not determine how to invoke functor.}}
283*6777b538SAndroid Build Coastguard Worker}
284*6777b538SAndroid Build Coastguard Worker
285*6777b538SAndroid Build Coastguard Workervoid RefQualifiedOverloadedOperator() {
286*6777b538SAndroid Build Coastguard Worker  // Invocations with lvalues should attempt to use lvalue-ref-qualified
287*6777b538SAndroid Build Coastguard Worker  // methods.
288*6777b538SAndroid Build Coastguard Worker  struct A {
289*6777b538SAndroid Build Coastguard Worker    void operator()() const& = delete;
290*6777b538SAndroid Build Coastguard Worker    void operator()() && {}
291*6777b538SAndroid Build Coastguard Worker  } a;
292*6777b538SAndroid Build Coastguard Worker  // Using distinct types causes distinct template instantiations, so we get
293*6777b538SAndroid Build Coastguard Worker  // assertion failures below where we expect. This type facilitates that.
294*6777b538SAndroid Build Coastguard Worker  struct B : A {};
295*6777b538SAndroid Build Coastguard Worker  BindRepeating(a);    // expected-error@*:* {{Could not determine how to invoke functor.}}
296*6777b538SAndroid Build Coastguard Worker  BindRepeating(B());  // expected-error@*:* {{Could not determine how to invoke functor.}}
297*6777b538SAndroid Build Coastguard Worker
298*6777b538SAndroid Build Coastguard Worker  // Invocations with rvalues should attempt to use rvalue-ref-qualified
299*6777b538SAndroid Build Coastguard Worker  // methods.
300*6777b538SAndroid Build Coastguard Worker  struct C {
301*6777b538SAndroid Build Coastguard Worker    void operator()() const& {}
302*6777b538SAndroid Build Coastguard Worker    void operator()() && = delete;
303*6777b538SAndroid Build Coastguard Worker  };
304*6777b538SAndroid Build Coastguard Worker  BindRepeating(Passed(C()));  // expected-error@*:* {{Could not determine how to invoke functor.}}
305*6777b538SAndroid Build Coastguard Worker  BindOnce(C());               // expected-error@*:* {{Could not determine how to invoke functor.}}
306*6777b538SAndroid Build Coastguard Worker}
307*6777b538SAndroid Build Coastguard Worker
308*6777b538SAndroid Build Coastguard Worker// Define a type that disallows `Unretained()` via the internal customization
309*6777b538SAndroid Build Coastguard Worker// point, so the next test can use it.
310*6777b538SAndroid Build Coastguard Workerstruct BlockViaCustomizationPoint {};
311*6777b538SAndroid Build Coastguard Workernamespace internal {
312*6777b538SAndroid Build Coastguard Workertemplate <>
313*6777b538SAndroid Build Coastguard Workerconstexpr bool kCustomizeSupportsUnretained<BlockViaCustomizationPoint> = false;
314*6777b538SAndroid Build Coastguard Worker}  // namespace internal
315*6777b538SAndroid Build Coastguard Worker
316*6777b538SAndroid Build Coastguard Workervoid CanDetectTypesThatDisallowUnretained() {
317*6777b538SAndroid Build Coastguard Worker  // It shouldn't be possible to directly bind any type that doesn't support
318*6777b538SAndroid Build Coastguard Worker  // `Unretained()`, whether because it's incomplete, or is marked with
319*6777b538SAndroid Build Coastguard Worker  // `DISALLOW_RETAINED()`, or has `kCustomizeSupportsUnretained` specialized to
320*6777b538SAndroid Build Coastguard Worker  // be `false`.
321*6777b538SAndroid Build Coastguard Worker  struct BlockPublicly {
322*6777b538SAndroid Build Coastguard Worker    DISALLOW_UNRETAINED();
323*6777b538SAndroid Build Coastguard Worker  } publicly;
324*6777b538SAndroid Build Coastguard Worker  class BlockPrivately {
325*6777b538SAndroid Build Coastguard Worker    DISALLOW_UNRETAINED();
326*6777b538SAndroid Build Coastguard Worker  } privately;
327*6777b538SAndroid Build Coastguard Worker  struct BlockViaInheritance : BlockPublicly {} inheritance;
328*6777b538SAndroid Build Coastguard Worker  BlockViaCustomizationPoint customization;
329*6777b538SAndroid Build Coastguard Worker  struct BlockDueToBeingIncomplete;
330*6777b538SAndroid Build Coastguard Worker  BlockDueToBeingIncomplete* ptr_incomplete;
331*6777b538SAndroid Build Coastguard Worker  BindOnce([](BlockPublicly*) {}, &publicly);                    // expected-error@*:* {{Argument requires unretained storage, but type does not support `Unretained()`.}}
332*6777b538SAndroid Build Coastguard Worker  BindOnce([](BlockPrivately*) {}, &privately);                  // expected-error@*:* {{Argument requires unretained storage, but type does not support `Unretained()`.}}
333*6777b538SAndroid Build Coastguard Worker  BindOnce([](BlockViaInheritance*) {}, &inheritance);           // expected-error@*:* {{Argument requires unretained storage, but type does not support `Unretained()`.}}
334*6777b538SAndroid Build Coastguard Worker  BindOnce([](BlockViaCustomizationPoint*) {}, &customization);  // expected-error@*:* {{Argument requires unretained storage, but type does not support `Unretained()`.}}
335*6777b538SAndroid Build Coastguard Worker  BindOnce([](BlockDueToBeingIncomplete*) {}, ptr_incomplete);   // expected-error@*:* {{Argument requires unretained storage, but type is not fully defined.}}
336*6777b538SAndroid Build Coastguard Worker}
337*6777b538SAndroid Build Coastguard Worker
338*6777b538SAndroid Build Coastguard Workervoid OtherWaysOfPassingDisallowedTypes() {
339*6777b538SAndroid Build Coastguard Worker  // In addition to the direct passing tested above, arguments passed as
340*6777b538SAndroid Build Coastguard Worker  // `Unretained()` pointers or as refs must support `Unretained()`.
341*6777b538SAndroid Build Coastguard Worker  struct A {
342*6777b538SAndroid Build Coastguard Worker    void Method() {}
343*6777b538SAndroid Build Coastguard Worker    DISALLOW_UNRETAINED();
344*6777b538SAndroid Build Coastguard Worker  } a;
345*6777b538SAndroid Build Coastguard Worker  // Using distinct types causes distinct template instantiations, so we get
346*6777b538SAndroid Build Coastguard Worker  // assertion failures below where we expect. This type facilitates that.
347*6777b538SAndroid Build Coastguard Worker  struct B : A {} b;
348*6777b538SAndroid Build Coastguard Worker  BindOnce(&A::Method, Unretained(&a));      // expected-error@*:* {{Argument requires unretained storage, but type does not support `Unretained()`.}}
349*6777b538SAndroid Build Coastguard Worker  BindOnce([] (const A&) {}, std::cref(a));  // expected-error@*:* {{Argument requires unretained storage, but type does not support `Unretained()`.}}
350*6777b538SAndroid Build Coastguard Worker  BindOnce([] (B&) {}, std::ref(b));         // expected-error@*:* {{Argument requires unretained storage, but type does not support `Unretained()`.}}
351*6777b538SAndroid Build Coastguard Worker}
352*6777b538SAndroid Build Coastguard Worker
353*6777b538SAndroid Build Coastguard Workervoid UnsafeDangling() {
354*6777b538SAndroid Build Coastguard Worker  // Pointers marked as `UnsafeDangling` may only be be received by
355*6777b538SAndroid Build Coastguard Worker  // `MayBeDangling` args with matching traits.
356*6777b538SAndroid Build Coastguard Worker  int i;
357*6777b538SAndroid Build Coastguard Worker  BindOnce([] (int*) {}, UnsafeDangling(&i));                      // expected-error@*:* {{base::UnsafeDangling() pointers should only be passed to parameters marked MayBeDangling<T>.}}
358*6777b538SAndroid Build Coastguard Worker  BindOnce([] (MayBeDangling<int>) {},
359*6777b538SAndroid Build Coastguard Worker           UnsafeDangling<int, RawPtrTraits::kDummyForTest>(&i));  // expected-error@*:* {{Pointers passed to MayBeDangling<T> parameters must be created by base::UnsafeDangling() with the same RawPtrTraits.}}
360*6777b538SAndroid Build Coastguard Worker  BindOnce([] (raw_ptr<int>) {}, UnsafeDanglingUntriaged(&i));     // expected-error@*:* {{Use T* or T& instead of raw_ptr<T> for function parameters, unless you must mark the parameter as MayBeDangling<T>.}}
361*6777b538SAndroid Build Coastguard Worker}
362*6777b538SAndroid Build Coastguard Worker
363*6777b538SAndroid Build Coastguard Worker}  // namespace base
364