Skip to content

Commit

Permalink
Use more slice patterns inside the compiler
Browse files Browse the repository at this point in the history
  • Loading branch information
fmease committed Aug 7, 2024
1 parent 60d1465 commit a3e3eca
Show file tree
Hide file tree
Showing 41 changed files with 195 additions and 225 deletions.
12 changes: 8 additions & 4 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,9 @@ impl Pat {
}
// A slice/array pattern `[P]` can be reparsed as `[T]`, an unsized array,
// when `P` can be reparsed as a type `T`.
PatKind::Slice(pats) if pats.len() == 1 => pats[0].to_ty().map(TyKind::Slice)?,
PatKind::Slice(pats) if let [pat] = pats.as_slice() => {
pat.to_ty().map(TyKind::Slice)?
}
// A tuple pattern `(P0, .., Pn)` can be reparsed as `(T0, .., Tn)`
// assuming `T0` to `Tn` are all syntactically valid as types.
PatKind::Tuple(pats) => {
Expand Down Expand Up @@ -1187,8 +1189,8 @@ impl Expr {
/// Does not ensure that the path resolves to a const param, the caller should check this.
pub fn is_potential_trivial_const_arg(&self) -> bool {
let this = if let ExprKind::Block(block, None) = &self.kind
&& block.stmts.len() == 1
&& let StmtKind::Expr(expr) = &block.stmts[0].kind
&& let [stmt] = block.stmts.as_slice()
&& let StmtKind::Expr(expr) = &stmt.kind
{
expr
} else {
Expand Down Expand Up @@ -1248,7 +1250,9 @@ impl Expr {
expr.to_ty().map(|ty| TyKind::Array(ty, expr_len.clone()))?
}

ExprKind::Array(exprs) if exprs.len() == 1 => exprs[0].to_ty().map(TyKind::Slice)?,
ExprKind::Array(exprs) if let [expr] = exprs.as_slice() => {
expr.to_ty().map(TyKind::Slice)?
}

ExprKind::Tup(exprs) => {
let tys = exprs.iter().map(|expr| expr.to_ty()).collect::<Option<ThinVec<_>>>()?;
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_ast_lowering/src/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
// FIXME(fn_delegation): Alternatives for target expression lowering:
// https://github.com/rust-lang/rfcs/pull/3530#issuecomment-2197170600.
fn lower_target_expr(&mut self, block: &Block) -> hir::Expr<'hir> {
if block.stmts.len() == 1
&& let StmtKind::Expr(expr) = &block.stmts[0].kind
if let [stmt] = block.stmts.as_slice()
&& let StmtKind::Expr(expr) = &stmt.kind
{
return self.lower_expr_mut(expr);
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,8 +502,8 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
if !self.is_beginning_of_line() {
self.word(" ");
}
if cmnt.lines.len() == 1 {
self.word(cmnt.lines[0].clone());
if let [line] = cmnt.lines.as_slice() {
self.word(line.clone());
self.hardbreak()
} else {
self.visual_align();
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_ast_pretty/src/pprust/state/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -783,8 +783,8 @@ impl<'a> State<'a> {
}
if items.is_empty() {
self.word("{}");
} else if items.len() == 1 {
self.print_use_tree(&items[0].0);
} else if let [(item, _)] = items.as_slice() {
self.print_use_tree(item);
} else {
self.cbox(INDENT_UNIT);
self.word("{");
Expand Down
14 changes: 7 additions & 7 deletions compiler/rustc_attr/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -665,12 +665,12 @@ pub fn eval_condition(
res & eval_condition(mi.meta_item().unwrap(), sess, features, eval)
}),
sym::not => {
if mis.len() != 1 {
let [mi] = mis.as_slice() else {
dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span });
return false;
}
};

!eval_condition(mis[0].meta_item().unwrap(), sess, features, eval)
!eval_condition(mi.meta_item().unwrap(), sess, features, eval)
}
sym::target => {
if let Some(features) = features
Expand Down Expand Up @@ -1051,10 +1051,10 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
MetaItemKind::List(nested_items) => {
if meta_item.has_name(sym::align) {
recognised = true;
if nested_items.len() == 1 {
if let [nested_item] = nested_items.as_slice() {
sess.dcx().emit_err(
session_diagnostics::IncorrectReprFormatExpectInteger {
span: nested_items[0].span(),
span: nested_item.span(),
},
);
} else {
Expand All @@ -1066,10 +1066,10 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
}
} else if meta_item.has_name(sym::packed) {
recognised = true;
if nested_items.len() == 1 {
if let [nested_item] = nested_items.as_slice() {
sess.dcx().emit_err(
session_diagnostics::IncorrectReprFormatPackedExpectInteger {
span: nested_items[0].span(),
span: nested_item.span(),
},
);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,8 @@ impl OutlivesSuggestionBuilder {

// If there is exactly one suggestable constraints, then just suggest it. Otherwise, emit a
// list of diagnostics.
let mut diag = if suggested.len() == 1 {
mbcx.dcx().struct_help(match suggested.last().unwrap() {
let mut diag = if let [constraint] = suggested.as_slice() {
mbcx.dcx().struct_help(match constraint {
SuggestedConstraint::Outlives(a, bs) => {
let bs: SmallVec<[String; 2]> = bs.iter().map(|r| r.to_string()).collect();
format!("add bound `{a}: {}`", bs.join(" + "))
Expand Down
7 changes: 3 additions & 4 deletions compiler/rustc_builtin_macros/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -745,10 +745,9 @@ fn expand_preparsed_asm(
unused_operands.push((args.operands[idx].1, msg));
}
}
match unused_operands.len() {
0 => {}
1 => {
let (sp, msg) = unused_operands.into_iter().next().unwrap();
match unused_operands[..] {
[] => {}
[(sp, msg)] => {
ecx.dcx()
.struct_span_err(sp, msg)
.with_span_label(sp, msg)
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_builtin_macros/src/deriving/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,20 +181,20 @@ fn validate_default_attribute(
attr::filter_by_name(&default_variant.attrs, kw::Default).collect();

let attr = match attrs.as_slice() {
[attr] => attr,
[] => cx.dcx().bug(
"this method must only be called with a variant that has a `#[default]` attribute",
),
[first, rest @ ..] => {
[attr] => attr,
[first, second, rest @ ..] => {
let sugg = errors::MultipleDefaultAttrsSugg {
spans: rest.iter().map(|attr| attr.span).collect(),
};
let guar = cx.dcx().emit_err(errors::MultipleDefaultAttrs {
span: default_variant.ident.span,
first: first.span,
first_rest: rest[0].span,
first_rest: second.span,
rest: rest.iter().map(|attr| attr.span).collect::<Vec<_>>().into(),
only_one: rest.len() == 1,
only_one: rest.is_empty(),
sugg,
});

Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,8 +378,8 @@ impl BlockOrExpr {
None => cx.expr_block(cx.block(span, ThinVec::new())),
Some(expr) => expr,
}
} else if self.0.len() == 1
&& let ast::StmtKind::Expr(expr) = &self.0[0].kind
} else if let [stmt] = self.0.as_slice()
&& let ast::StmtKind::Expr(expr) = &stmt.kind
&& self.1.is_none()
{
// There's only a single statement expression. Pull it out.
Expand Down Expand Up @@ -1273,15 +1273,15 @@ impl<'a> MethodDef<'a> {
}
FieldlessVariantsStrategy::Default => (),
}
} else if variants.len() == 1 {
} else if let [variant] = variants.as_slice() {
// If there is a single variant, we don't need an operation on
// the discriminant(s). Just use the most degenerate result.
return self.call_substructure_method(
cx,
trait_,
type_ident,
nonselflike_args,
&EnumMatching(0, &variants[0], Vec::new()),
&EnumMatching(0, variant, Vec::new()),
);
}
}
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_builtin_macros/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,8 @@ fn make_format_args(
Ok((mut err, suggested)) => {
if !suggested {
if let ExprKind::Block(block, None) = &efmt.kind
&& block.stmts.len() == 1
&& let StmtKind::Expr(expr) = &block.stmts[0].kind
&& let [stmt] = block.stmts.as_slice()
&& let StmtKind::Expr(expr) = &stmt.kind
&& let ExprKind::Path(None, path) = &expr.kind
&& path.is_potential_trivial_const_arg()
{
Expand All @@ -196,8 +196,8 @@ fn make_format_args(
} else {
let sugg_fmt = match args.explicit_args().len() {
0 => "{}".to_string(),
_ => {
format!("{}{{}}", "{} ".repeat(args.explicit_args().len()))
count => {
format!("{}{{}}", "{} ".repeat(count))
}
};
err.span_suggestion(
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_data_structures/src/transitive_relation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,9 @@ impl<T: Eq + Hash + Copy> TransitiveRelation<T> {
/// exists). See `postdom_upper_bound` for details.
pub fn mutual_immediate_postdominator(&self, mut mubs: Vec<T>) -> Option<T> {
loop {
match mubs.len() {
0 => return None,
1 => return Some(mubs[0]),
match mubs[..] {
[] => return None,
[mub] => return Some(mub),
_ => {
let m = mubs.pop().unwrap();
let n = mubs.pop().unwrap();
Expand Down
55 changes: 25 additions & 30 deletions compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,12 +335,11 @@ fn run_compiler(
config.input = input;
true // has input: normal compilation
}
Ok(None) => match matches.free.len() {
0 => false, // no input: we will exit early
1 => panic!("make_input should have provided valid inputs"),
_ => default_early_dcx.early_fatal(format!(
"multiple input filenames provided (first two filenames are `{}` and `{}`)",
matches.free[0], matches.free[1],
Ok(None) => match matches.free.as_slice() {
[] => false, // no input: we will exit early
[_] => panic!("make_input should have provided valid inputs"),
[fst, snd, ..] => default_early_dcx.early_fatal(format!(
"multiple input filenames provided (first two filenames are `{fst}` and `{snd}`)"
)),
},
};
Expand Down Expand Up @@ -488,34 +487,30 @@ fn make_input(
early_dcx: &EarlyDiagCtxt,
free_matches: &[String],
) -> Result<Option<Input>, ErrorGuaranteed> {
if free_matches.len() == 1 {
let ifile = &free_matches[0];
if ifile == "-" {
let mut src = String::new();
if io::stdin().read_to_string(&mut src).is_err() {
// Immediately stop compilation if there was an issue reading
// the input (for example if the input stream is not UTF-8).
let reported = early_dcx
.early_err("couldn't read from stdin, as it did not contain valid UTF-8");
return Err(reported);
}
if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect(
"when UNSTABLE_RUSTDOC_TEST_PATH is set \
let [ifile] = free_matches else { return Ok(None) };
if ifile == "-" {
let mut src = String::new();
if io::stdin().read_to_string(&mut src).is_err() {
// Immediately stop compilation if there was an issue reading
// the input (for example if the input stream is not UTF-8).
let reported =
early_dcx.early_err("couldn't read from stdin, as it did not contain valid UTF-8");
return Err(reported);
}
if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect(
"when UNSTABLE_RUSTDOC_TEST_PATH is set \
UNSTABLE_RUSTDOC_TEST_LINE also needs to be set",
);
let line = isize::from_str_radix(&line, 10)
.expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be an number");
let file_name = FileName::doc_test_source_code(PathBuf::from(path), line);
Ok(Some(Input::Str { name: file_name, input: src }))
} else {
Ok(Some(Input::Str { name: FileName::anon_source_code(&src), input: src }))
}
);
let line = isize::from_str_radix(&line, 10)
.expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be an number");
let file_name = FileName::doc_test_source_code(PathBuf::from(path), line);
Ok(Some(Input::Str { name: file_name, input: src }))
} else {
Ok(Some(Input::File(PathBuf::from(ifile))))
Ok(Some(Input::Str { name: FileName::anon_source_code(&src), input: src }))
}
} else {
Ok(None)
Ok(Some(Input::File(PathBuf::from(ifile))))
}
}

Expand Down
29 changes: 14 additions & 15 deletions compiler/rustc_errors/src/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,17 +231,17 @@ pub trait Emitter: Translate {
) {
if let Some((sugg, rest)) = suggestions.split_first() {
let msg = self.translate_message(&sugg.msg, fluent_args).map_err(Report::new).unwrap();
if rest.is_empty() &&
if rest.is_empty()
// ^ if there is only one suggestion
// don't display multi-suggestions as labels
sugg.substitutions.len() == 1 &&
&& let [substitution] = sugg.substitutions.as_slice()
// don't display multipart suggestions as labels
sugg.substitutions[0].parts.len() == 1 &&
&& let [part] = substitution.parts.as_slice()
// don't display long messages as labels
msg.split_whitespace().count() < 10 &&
&& msg.split_whitespace().count() < 10
// don't display multiline suggestions as labels
!sugg.substitutions[0].parts[0].snippet.contains('\n') &&
![
&& !part.snippet.contains('\n')
&& ![
// when this style is set we want the suggestion to be a message, not inline
SuggestionStyle::HideCodeAlways,
// trivial suggestion for tooling's sake, never shown
Expand All @@ -250,8 +250,8 @@ pub trait Emitter: Translate {
SuggestionStyle::ShowAlways,
].contains(&sugg.style)
{
let substitution = &sugg.substitutions[0].parts[0].snippet.trim();
let msg = if substitution.is_empty() || sugg.style.hide_inline() {
let snippet = part.snippet.trim();
let msg = if snippet.is_empty() || sugg.style.hide_inline() {
// This substitution is only removal OR we explicitly don't want to show the
// code inline (`hide_inline`). Therefore, we don't show the substitution.
format!("help: {msg}")
Expand All @@ -260,19 +260,18 @@ pub trait Emitter: Translate {
format!(
"help: {}{}: `{}`",
msg,
if self.source_map().is_some_and(|sm| is_case_difference(
sm,
substitution,
sugg.substitutions[0].parts[0].span,
)) {
if self
.source_map()
.is_some_and(|sm| is_case_difference(sm, snippet, part.span,))
{
" (notice the capitalization)"
} else {
""
},
substitution,
snippet,
)
};
primary_span.push_span_label(sugg.substitutions[0].parts[0].span, msg);
primary_span.push_span_label(part.span, msg);

// We return only the modified primary_span
suggestions.clear();
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2024,11 +2024,11 @@ pub fn a_or_an(s: &str) -> &'static str {
///
/// Take a list ["a", "b", "c"] and output a display friendly version "a, b and c"
pub fn display_list_with_comma_and<T: std::fmt::Display>(v: &[T]) -> String {
match v.len() {
0 => "".to_string(),
1 => v[0].to_string(),
2 => format!("{} and {}", v[0], v[1]),
_ => format!("{}, {}", v[0], display_list_with_comma_and(&v[1..])),
match v {
[] => "".to_string(),
[a] => a.to_string(),
[a, b] => format!("{a} and {b}"),
[a, v @ ..] => format!("{a}, {}", display_list_with_comma_and(v)),
}
}

Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1306,12 +1306,12 @@ pub fn parse_macro_name_and_helper_attrs(
// that it's of the form `#[proc_macro_derive(Foo)]` or
// `#[proc_macro_derive(Foo, attributes(A, ..))]`
let list = attr.meta_item_list()?;
if list.len() != 1 && list.len() != 2 {
let ([trait_attr] | [trait_attr, _]) = list.as_slice() else {
dcx.emit_err(errors::AttrNoArguments { span: attr.span });
return None;
}
let Some(trait_attr) = list[0].meta_item() else {
dcx.emit_err(errors::NotAMetaItem { span: list[0].span() });
};
let Some(trait_attr) = trait_attr.meta_item() else {
dcx.emit_err(errors::NotAMetaItem { span: trait_attr.span() });
return None;
};
let trait_ident = match trait_attr.ident() {
Expand Down
Loading

0 comments on commit a3e3eca

Please sign in to comment.