Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add & use is_none_or Option extension in the compiler #111873

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -617,8 +617,7 @@ impl<'a> AstValidator<'a> {
.session
.source_map()
.span_to_snippet(span)
.map(|snippet| snippet.starts_with("#["))
.unwrap_or(true);
.map_or(true, |snippet| snippet.starts_with("#["));
if !is_macro_callsite {
Comment on lines 617 to 621
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this condition is only used inverted, it might be easier to read to just use is_some_and with the inverted condition:

        if self
            .session
            .source_map()
            .span_to_snippet(span)
            .is_some_and(|snippet| !snippet.starts_with("#["))
        {

Then it clearly reads as "if the snippet is available and doesn't start with #[".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, thanks!

(as a side note span_to_snippet returns a result, so this would have to be a is_ok_and, but yeah)

self.lint_buffer.buffer_lint_with_diagnostic(
MISSING_ABI,
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use rustc_ast as ast;
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
use rustc_ast::{attr, AssocConstraint, AssocConstraintKind, NodeId};
use rustc_ast::{PatKind, RangeEnd};
use rustc_data_structures::OptionExt as _;
use rustc_errors::{Applicability, StashKey};
use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP};
use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
Expand Down Expand Up @@ -101,7 +102,7 @@ impl<'a> PostExpansionVisitor<'a> {
.emit();
}
Err(abi::AbiDisabled::Unrecognized) => {
if self.sess.opts.pretty.map_or(true, |ppm| ppm.needs_hir()) {
if self.sess.opts.pretty.is_none_or(|ppm| ppm.needs_hir()) {
self.sess.parse_sess.span_diagnostic.delay_span_bug(
span,
format!(
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_attr/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use rustc_ast::{self as ast, attr};
use rustc_ast::{Attribute, LitKind, MetaItem, MetaItemKind, MetaItemLit, NestedMetaItem, NodeId};
use rustc_ast_pretty::pprust;
use rustc_data_structures::OptionExt as _;
use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg};
use rustc_macros::HashStable_Generic;
use rustc_session::config::ExpectedValues;
Expand Down Expand Up @@ -1096,7 +1097,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
// the `check_mod_attrs` pass, but this pass doesn't always run
// (e.g. if we only pretty-print the source), so we have to gate
// the `delay_span_bug` call as follows:
if sess.opts.pretty.map_or(true, |pp| pp.needs_analysis()) {
if sess.opts.pretty.is_none_or(|pp| pp.needs_analysis()) {
diagnostic.delay_span_bug(item.span(), "unrecognized representation hint");
}
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::iter;
use either::Either;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::OptionExt as _;
use rustc_errors::{
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
};
Expand Down Expand Up @@ -1328,7 +1329,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
&& ex.span.contains(self.borrow_span)
// To support cases like `|| { v.call(|this| v.get()) }`
// FIXME: actually support such cases (need to figure out how to move from the capture place to original local)
&& self.res.as_ref().map_or(true, |(prev_res, _)| prev_res.span.contains(ex.span))
&& self.res.as_ref().is_none_or(|(prev_res, _)| prev_res.span.contains(ex.span))
{
self.res = Some((ex, closure));
}
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Print diagnostics to explain why values are borrowed.

use rustc_data_structures::OptionExt as _;
use rustc_errors::{Applicability, Diagnostic};
use rustc_hir as hir;
use rustc_hir::intravisit::Visitor;
Expand Down Expand Up @@ -106,8 +107,8 @@ impl<'tcx> BorrowExplanation<'tcx> {
LaterUseKind::Other => "used here",
};
// We can use `var_or_use_span` if either `path_span` is not present, or both spans are the same
if path_span.map(|path_span| path_span == var_or_use_span).unwrap_or(true) {
if borrow_span.map(|sp| !sp.overlaps(var_or_use_span)).unwrap_or(true) {
if path_span.is_none_or(|path_span| path_span == var_or_use_span) {
if borrow_span.is_none_or(|sp| !sp.overlaps(var_or_use_span)) {
err.span_label(
var_or_use_span,
format!("{borrow_desc}borrow later {message}"),
Expand Down Expand Up @@ -142,14 +143,14 @@ impl<'tcx> BorrowExplanation<'tcx> {
LaterUseKind::Other => "borrow used here, in later iteration of loop",
};
// We can use `var_or_use_span` if either `path_span` is not present, or both spans are the same
if path_span.map(|path_span| path_span == var_or_use_span).unwrap_or(true) {
if path_span.is_none_or(|path_span| path_span == var_or_use_span) {
err.span_label(var_or_use_span, format!("{borrow_desc}{message}"));
} else {
// path_span must be `Some` as otherwise the if condition is true
let path_span = path_span.unwrap();
// path_span is only present in the case of closure capture
assert!(matches!(later_use_kind, LaterUseKind::ClosureCapture));
if borrow_span.map(|sp| !sp.overlaps(var_or_use_span)).unwrap_or(true) {
if borrow_span.is_none_or(|sp| !sp.overlaps(var_or_use_span)) {
let path_label = "used here by closure";
let capture_kind_label = message;
err.span_label(
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use either::Either;
use hir::OpaqueTyOrigin;
use rustc_data_structures::frozen::Frozen;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::OptionExt as _;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
Expand Down Expand Up @@ -1812,7 +1813,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// than 1.
// If the length is larger than 1, the repeat expression will need to copy the
// element, so we require the `Copy` trait.
if len.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
if len.try_eval_target_usize(tcx, self.param_env).is_none_or(|len| len > 1) {
match operand {
Operand::Copy(..) | Operand::Constant(..) => {
// These are always okay: direct use of a const, or a value that can evidently be copied.
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_cranelift/src/num.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Various operations on integer and floating-point numbers

use crate::prelude::*;
use rustc_data_structures::OptionExt as _;

pub(crate) fn bin_op_to_intcc(bin_op: BinOp, signed: bool) -> Option<IntCC> {
use BinOp::*;
Expand Down Expand Up @@ -368,8 +369,7 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
.layout()
.ty
.builtin_deref(true)
.map(|TypeAndMut { ty, mutbl: _ }| !has_ptr_meta(fx.tcx, ty))
.unwrap_or(true);
.is_none_or(|TypeAndMut { ty, mutbl: _ }| !has_ptr_meta(fx.tcx, ty));

if is_thin_ptr {
match bin_op {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_const_eval/src/interpret/intern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

use super::validity::RefTracking;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::OptionExt as _;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_middle::mir::interpret::InterpResult;
Expand Down Expand Up @@ -114,7 +115,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval:
if let InternMode::Static(mutability) = mode {
// For this, we need to take into account `UnsafeCell`. When `ty` is `None`, we assume
// no interior mutability.
let frozen = ty.map_or(true, |ty| ty.is_freeze(*ecx.tcx, ecx.param_env));
let frozen = ty.is_none_or(|ty| ty.is_freeze(*ecx.tcx, ecx.param_env));
// For statics, allocation mutability is the combination of place mutability and
// type mutability.
// The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere.
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_const_eval/src/interpret/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use std::ptr;

use rustc_ast::Mutability;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::OptionExt as _;
use rustc_middle::mir::display_allocation;
use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
use rustc_target::abi::{Align, HasDataLayout, Size};
Expand Down Expand Up @@ -422,7 +423,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let (alloc_size, alloc_align, ret_val) = alloc_size(alloc_id, offset, prov)?;
// Test bounds. This also ensures non-null.
// It is sufficient to check this for the end pointer. Also check for overflow!
if offset.checked_add(size, &self.tcx).map_or(true, |end| end > alloc_size) {
if offset.checked_add(size, &self.tcx).is_none_or(|end| end > alloc_size) {
throw_ub!(PointerOutOfBounds {
alloc_id,
alloc_size,
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_const_eval/src/interpret/projection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

use either::{Left, Right};

use rustc_data_structures::OptionExt as _;
use rustc_middle::mir;
use rustc_middle::ty;
use rustc_middle::ty::layout::LayoutOf;
Expand Down Expand Up @@ -294,7 +295,7 @@ where
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
let len = base.len(self)?; // also asserts that we have a type where this makes sense
let actual_to = if from_end {
if from.checked_add(to).map_or(true, |to| to > len) {
if from.checked_add(to).is_none_or(|to| to > len) {
// This can only be reached in ConstProp and non-rustc-MIR.
throw_ub!(BoundsCheckFailed { len: len, index: from.saturating_add(to) });
}
Expand Down
59 changes: 31 additions & 28 deletions compiler/rustc_data_structures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,61 +46,64 @@ extern crate cfg_if;
#[macro_use]
extern crate rustc_macros;

pub use ena::snapshot_vec;
pub use ena::undo_log;
pub use ena::unify;
pub use rustc_index::static_assert_size;

#[inline(never)]
#[cold]
pub fn cold_path<F: FnOnce() -> R, R>(f: F) -> R {
f()
}

#[macro_use]
pub mod stable_hasher;
pub mod aligned;
pub mod base_n;
pub mod binary_search_util;
pub mod captures;
pub mod fingerprint;
pub mod flat_map_in_place;
pub mod flock;
pub mod frozen;
pub mod functor;
pub mod fx;
pub mod graph;
pub mod intern;
pub mod jobserver;
pub mod macros;
pub mod marker;
pub mod memmap;
pub mod obligation_forest;
pub mod owned_slice;
pub mod profiling;
pub mod sharded;
pub mod sip128;
pub mod small_c_str;
pub mod small_str;
pub mod snapshot_map;
pub mod svh;
pub use ena::snapshot_vec;
pub mod memmap;
pub mod sorted_map;
#[macro_use]
pub mod stable_hasher;
mod atomic_ref;
pub mod fingerprint;
pub mod marker;
pub mod profiling;
pub mod sharded;
pub mod sso;
pub mod stack;
pub mod steal;
pub mod svh;
pub mod sync;
pub mod tagged_ptr;
pub mod temp_dir;
pub mod tiny_list;
pub mod transitive_relation;
pub mod unhash;
pub mod unord;
pub mod vec_linked_list;
pub mod work_queue;
pub use atomic_ref::AtomicRef;
pub mod aligned;
pub mod frozen;

mod atomic_ref;
mod hashes;
pub mod owned_slice;
pub mod sso;
pub mod steal;
pub mod tagged_ptr;
pub mod temp_dir;
pub mod unhash;
pub mod unord;
mod option_ext;

pub use ena::undo_log;
pub use ena::unify;
pub use atomic_ref::AtomicRef;
pub use option_ext::OptionExt;

#[inline(never)]
#[cold]
pub fn cold_path<F: FnOnce() -> R, R>(f: F) -> R {
f()
}

pub struct OnDrop<F: Fn()>(pub F);

Expand Down
18 changes: 18 additions & 0 deletions compiler/rustc_data_structures/src/option_ext.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/// Extension for [`Option`] that adds handy methods missing from it.
pub trait OptionExt {
type T;

/// Returns `true` if `self` is `None` or the value inside the `Some` matches a predicate `f`.
fn is_none_or(self, f: impl FnOnce(Self::T) -> bool) -> bool;
}

impl<T> OptionExt for Option<T> {
type T = T;

fn is_none_or(self, f: impl FnOnce(T) -> bool) -> bool {
match self {
None => true,
Some(x) => f(x),
}
}
}
5 changes: 3 additions & 2 deletions compiler/rustc_expand/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use rustc_ast::{self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem
use rustc_attr as attr;
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::OptionExt as _;
use rustc_feature::{Feature, Features, State as FeatureState};
use rustc_feature::{
ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
Expand Down Expand Up @@ -427,15 +428,15 @@ impl<'a> StripUnconfigured<'a> {
return true;
}
};
parse_cfg(&meta_item, &self.sess).map_or(true, |meta_item| {
parse_cfg(&meta_item, &self.sess).is_none_or(|meta_item| {
attr::cfg_matches(&meta_item, &self.sess.parse_sess, self.lint_node_id, self.features)
})
}

/// If attributes are not allowed on expressions, emit an error for `attr`
#[instrument(level = "trace", skip(self))]
pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
if !self.features.map_or(true, |features| features.stmt_expr_attributes) {
if !self.features.is_none_or(|features| features.stmt_expr_attributes) {
let mut err = feature_err(
&self.sess.parse_sess,
sym::stmt_expr_attributes,
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_expand/src/mbe/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::mbe::{
use rustc_ast::token::{self, Token, TokenKind};
use rustc_ast::tokenstream::TokenStream;
use rustc_ast_pretty::pprust;
use rustc_data_structures::OptionExt as _;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage};
use rustc_parse::parser::{Parser, Recovery};
use rustc_span::source_map::SourceMap;
Expand Down Expand Up @@ -155,7 +156,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx,
if self
.best_failure
.as_ref()
.map_or(true, |failure| failure.is_better_position(*approx_position))
.is_none_or(|failure| failure.is_better_position(*approx_position))
{
self.best_failure = Some(BestFailure {
token: token.clone(),
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir/src/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use rustc_ast as ast;
use rustc_ast::NodeId;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::ToStableHashKey;
use rustc_data_structures::OptionExt as _;
use rustc_macros::HashStable_Generic;
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::hygiene::MacroKind;
Expand Down Expand Up @@ -731,7 +732,7 @@ impl<Id> Res<Id> {

/// Always returns `true` if `self` is `Res::Err`
pub fn matches_ns(&self, ns: Namespace) -> bool {
self.ns().map_or(true, |actual_ns| actual_ns == ns)
self.ns().is_none_or(|actual_ns| actual_ns == ns)
}

/// Returns whether such a resolved path can occur in a tuple struct/variant pattern
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,19 +140,19 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
impl1_def_id: DefId,
impl2_def_id: DefId,
) {
traits::overlapping_impls(
let maybe_overlap = traits::overlapping_impls(
self.tcx,
impl1_def_id,
impl2_def_id,
// We go ahead and just skip the leak check for
// inherent impls without warning.
SkipLeakCheck::Yes,
overlap_mode,
)
.map_or(true, |overlap| {
);

if let Some(overlap) = maybe_overlap {
self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap);
false
});
}
}

fn check_item(&mut self, id: hir::ItemId) {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::collect::ItemCtxt;
use crate::constrained_generic_params as cgp;
use hir::{HirId, Node};
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::OptionExt as _;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
Expand Down Expand Up @@ -803,7 +804,7 @@ impl<'tcx> ItemCtxt<'tcx> {
bound_ty,
predicate.bounds.iter().filter(|bound| {
assoc_name
.map_or(true, |assoc_name| self.bound_defines_assoc_item(bound, assoc_name))
.is_none_or(|assoc_name| self.bound_defines_assoc_item(bound, assoc_name))
}),
&mut bounds,
bound_vars,
Expand Down
Loading