Introduce FindIfOrNull() FindIfOrNone() and Contains() (#5322)

`FindIfOrNull` returns a pointer to the element in the range if it's
found, and nullptr otherwise. `FindIfOrNone` returns a copy of the
element in the range if it's found, and `T::None` (for a range of
elements of type `T`) otherwise. `Contains` returns a bool indicating
whether the element in the range is found.

These functions replace `llvm::find()` and `llvm::find_if()` when you
want a single answer back instead of an iterator. This avoids the need
to check against `end()`, allowing the return condition to be tested as
a standard bool.

We replace uses of `find()` and `find_if()` that did not require an
iterator with these new helpers.

Note that the return type of `FindIfOrNull` is a pointer since we can
not write `optional<T&>`, which must be tested for null. If the null
check is omitted, UB occurs and the resulting code may end up with an
incorrect pointer (https://crbug.com/40153300) into the range (or
elsewhere), rather than a null dereference. And this would be very
confusing to debug. Hopefully debug builds and sanitizers keep this from
being an issue we sink a bunch of time into debugging.
This commit is contained in:
Dana Jansens
2025-04-18 14:17:48 +00:00
committed by GitHub
parent 55705aaef8
commit 9a6c74f0cd
11 changed files with 207 additions and 17 deletions
+4 -9
View File
@@ -5,6 +5,7 @@
#include <optional>
#include <utility>
#include "common/find.h"
#include "toolchain/base/kind_switch.h"
#include "toolchain/check/context.h"
#include "toolchain/check/control_flow.h"
@@ -90,15 +91,9 @@ static auto FindSelfPattern(Context& context,
-> SemIR::InstId {
auto implicit_param_patterns =
context.inst_blocks().GetOrEmpty(implicit_param_patterns_id);
if (const auto* i = llvm::find_if(implicit_param_patterns,
[&](auto implicit_param_id) {
return SemIR::IsSelfPattern(
context.sem_ir(), implicit_param_id);
});
i != implicit_param_patterns.end()) {
return *i;
}
return SemIR::InstId::None;
return FindIfOrNone(implicit_param_patterns, [&](auto implicit_param_id) {
return SemIR::IsSelfPattern(context.sem_ir(), implicit_param_id);
});
}
// Diagnoses issues with the modifiers, removing modifiers that shouldn't be