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