mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 10:52:44 +00:00 
			
		
		
		
	 604d5f5bca
			
		
	
	
		604d5f5bca
		
	
	
	
	
		
			
			For example, consider cases where we want to propagate errors only in
specific instances:
    auto result = read_data(); // something like ErrorOr<ByteBuffer>
    if (result.is_error() && result.error().code() != EINTR)
        continue;
    auto bytes = TRY(result);
The TRY invocation will currently copy the byte buffer when the
expression (in this case, just a local variable) is stored into
_temporary_result.
This patch binds the expression to a reference to prevent such copies.
In less trival invocations (such as TRY(some_function()), this will
incur only temporary lifetime extensions, i.e. no functional change.
		
	
			
		
			
				
	
	
		
			45 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			45 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <AK/Diagnostics.h>
 | |
| #include <AK/StdLibExtras.h>
 | |
| 
 | |
| // NOTE: This macro works with any result type that has the expected APIs.
 | |
| //       It's designed with AK::Result and AK::Error in mind.
 | |
| //
 | |
| //       It depends on a non-standard C++ extension, specifically
 | |
| //       on statement expressions [1]. This is known to be implemented
 | |
| //       by at least clang and gcc.
 | |
| //       [1] https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
 | |
| //
 | |
| //       If the static_assert below is triggered, it means you tried to return a reference
 | |
| //       from a fallible expression. This will not do what you want; the statement expression
 | |
| //       will create a copy regardless, so it is explicitly disallowed.
 | |
| 
 | |
| #define TRY(expression)                                                                              \
 | |
|     ({                                                                                               \
 | |
|         /* Ignore -Wshadow to allow nesting the macro. */                                            \
 | |
|         AK_IGNORE_DIAGNOSTIC("-Wshadow",                                                             \
 | |
|             auto&& _temporary_result = (expression));                                                \
 | |
|         static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_result.release_value())>, \
 | |
|             "Do not return a reference from a fallible expression");                                 \
 | |
|         if (_temporary_result.is_error()) [[unlikely]]                                               \
 | |
|             return _temporary_result.release_error();                                                \
 | |
|         _temporary_result.release_value();                                                           \
 | |
|     })
 | |
| 
 | |
| #define MUST(expression)                                                                             \
 | |
|     ({                                                                                               \
 | |
|         /* Ignore -Wshadow to allow nesting the macro. */                                            \
 | |
|         AK_IGNORE_DIAGNOSTIC("-Wshadow",                                                             \
 | |
|             auto&& _temporary_result = (expression));                                                \
 | |
|         static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_result.release_value())>, \
 | |
|             "Do not return a reference from a fallible expression");                                 \
 | |
|         VERIFY(!_temporary_result.is_error());                                                       \
 | |
|         _temporary_result.release_value();                                                           \
 | |
|     })
 |