Use more slice patterns inside the compiler

This commit is contained in:
León Orell Valerian Liehr 2024-08-07 12:41:49 +02:00
parent 60d146580c
commit c4c518d2d4
No known key found for this signature in database
GPG Key ID: D17A07215F68E713
40 changed files with 191 additions and 221 deletions

View File

@ -585,7 +585,9 @@ impl Pat {
} }
// A slice/array pattern `[P]` can be reparsed as `[T]`, an unsized array, // A slice/array pattern `[P]` can be reparsed as `[T]`, an unsized array,
// when `P` can be reparsed as a type `T`. // 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)` // A tuple pattern `(P0, .., Pn)` can be reparsed as `(T0, .., Tn)`
// assuming `T0` to `Tn` are all syntactically valid as types. // assuming `T0` to `Tn` are all syntactically valid as types.
PatKind::Tuple(pats) => { PatKind::Tuple(pats) => {
@ -1187,8 +1189,8 @@ impl Expr {
/// Does not ensure that the path resolves to a const param, the caller should check this. /// 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 { pub fn is_potential_trivial_const_arg(&self) -> bool {
let this = if let ExprKind::Block(block, None) = &self.kind let this = if let ExprKind::Block(block, None) = &self.kind
&& block.stmts.len() == 1 && let [stmt] = block.stmts.as_slice()
&& let StmtKind::Expr(expr) = &block.stmts[0].kind && let StmtKind::Expr(expr) = &stmt.kind
{ {
expr expr
} else { } else {
@ -1248,7 +1250,9 @@ impl Expr {
expr.to_ty().map(|ty| TyKind::Array(ty, expr_len.clone()))? 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) => { ExprKind::Tup(exprs) => {
let tys = exprs.iter().map(|expr| expr.to_ty()).collect::<Option<ThinVec<_>>>()?; let tys = exprs.iter().map(|expr| expr.to_ty()).collect::<Option<ThinVec<_>>>()?;

View File

@ -275,8 +275,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
// FIXME(fn_delegation): Alternatives for target expression lowering: // FIXME(fn_delegation): Alternatives for target expression lowering:
// https://github.com/rust-lang/rfcs/pull/3530#issuecomment-2197170600. // https://github.com/rust-lang/rfcs/pull/3530#issuecomment-2197170600.
fn lower_target_expr(&mut self, block: &Block) -> hir::Expr<'hir> { fn lower_target_expr(&mut self, block: &Block) -> hir::Expr<'hir> {
if block.stmts.len() == 1 if let [stmt] = block.stmts.as_slice()
&& let StmtKind::Expr(expr) = &block.stmts[0].kind && let StmtKind::Expr(expr) = &stmt.kind
{ {
return self.lower_expr_mut(expr); return self.lower_expr_mut(expr);
} }

View File

@ -502,8 +502,8 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
if !self.is_beginning_of_line() { if !self.is_beginning_of_line() {
self.word(" "); self.word(" ");
} }
if cmnt.lines.len() == 1 { if let [line] = cmnt.lines.as_slice() {
self.word(cmnt.lines[0].clone()); self.word(line.clone());
self.hardbreak() self.hardbreak()
} else { } else {
self.visual_align(); self.visual_align();

View File

@ -783,8 +783,8 @@ impl<'a> State<'a> {
} }
if items.is_empty() { if items.is_empty() {
self.word("{}"); self.word("{}");
} else if items.len() == 1 { } else if let [(item, _)] = items.as_slice() {
self.print_use_tree(&items[0].0); self.print_use_tree(item);
} else { } else {
self.cbox(INDENT_UNIT); self.cbox(INDENT_UNIT);
self.word("{"); self.word("{");

View File

@ -665,12 +665,12 @@ pub fn eval_condition(
res & eval_condition(mi.meta_item().unwrap(), sess, features, eval) res & eval_condition(mi.meta_item().unwrap(), sess, features, eval)
}), }),
sym::not => { sym::not => {
if mis.len() != 1 { let [mi] = mis.as_slice() else {
dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span }); dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span });
return false; return false;
} };
!eval_condition(mis[0].meta_item().unwrap(), sess, features, eval) !eval_condition(mi.meta_item().unwrap(), sess, features, eval)
} }
sym::target => { sym::target => {
if let Some(features) = features if let Some(features) = features
@ -1051,10 +1051,10 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
MetaItemKind::List(nested_items) => { MetaItemKind::List(nested_items) => {
if meta_item.has_name(sym::align) { if meta_item.has_name(sym::align) {
recognised = true; recognised = true;
if nested_items.len() == 1 { if let [nested_item] = nested_items.as_slice() {
sess.dcx().emit_err( sess.dcx().emit_err(
session_diagnostics::IncorrectReprFormatExpectInteger { session_diagnostics::IncorrectReprFormatExpectInteger {
span: nested_items[0].span(), span: nested_item.span(),
}, },
); );
} else { } else {
@ -1066,10 +1066,10 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
} }
} else if meta_item.has_name(sym::packed) { } else if meta_item.has_name(sym::packed) {
recognised = true; recognised = true;
if nested_items.len() == 1 { if let [nested_item] = nested_items.as_slice() {
sess.dcx().emit_err( sess.dcx().emit_err(
session_diagnostics::IncorrectReprFormatPackedExpectInteger { session_diagnostics::IncorrectReprFormatPackedExpectInteger {
span: nested_items[0].span(), span: nested_item.span(),
}, },
); );
} else { } else {

View File

@ -206,8 +206,8 @@ impl OutlivesSuggestionBuilder {
// If there is exactly one suggestable constraints, then just suggest it. Otherwise, emit a // If there is exactly one suggestable constraints, then just suggest it. Otherwise, emit a
// list of diagnostics. // list of diagnostics.
let mut diag = if suggested.len() == 1 { let mut diag = if let [constraint] = suggested.as_slice() {
mbcx.dcx().struct_help(match suggested.last().unwrap() { mbcx.dcx().struct_help(match constraint {
SuggestedConstraint::Outlives(a, bs) => { SuggestedConstraint::Outlives(a, bs) => {
let bs: SmallVec<[String; 2]> = bs.iter().map(|r| r.to_string()).collect(); let bs: SmallVec<[String; 2]> = bs.iter().map(|r| r.to_string()).collect();
format!("add bound `{a}: {}`", bs.join(" + ")) format!("add bound `{a}: {}`", bs.join(" + "))

View File

@ -745,10 +745,9 @@ fn expand_preparsed_asm(
unused_operands.push((args.operands[idx].1, msg)); unused_operands.push((args.operands[idx].1, msg));
} }
} }
match unused_operands.len() { match unused_operands[..] {
0 => {} [] => {}
1 => { [(sp, msg)] => {
let (sp, msg) = unused_operands.into_iter().next().unwrap();
ecx.dcx() ecx.dcx()
.struct_span_err(sp, msg) .struct_span_err(sp, msg)
.with_span_label(sp, msg) .with_span_label(sp, msg)

View File

@ -378,8 +378,8 @@ impl BlockOrExpr {
None => cx.expr_block(cx.block(span, ThinVec::new())), None => cx.expr_block(cx.block(span, ThinVec::new())),
Some(expr) => expr, Some(expr) => expr,
} }
} else if self.0.len() == 1 } else if let [stmt] = self.0.as_slice()
&& let ast::StmtKind::Expr(expr) = &self.0[0].kind && let ast::StmtKind::Expr(expr) = &stmt.kind
&& self.1.is_none() && self.1.is_none()
{ {
// There's only a single statement expression. Pull it out. // There's only a single statement expression. Pull it out.
@ -1273,7 +1273,7 @@ impl<'a> MethodDef<'a> {
} }
FieldlessVariantsStrategy::Default => (), 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 // If there is a single variant, we don't need an operation on
// the discriminant(s). Just use the most degenerate result. // the discriminant(s). Just use the most degenerate result.
return self.call_substructure_method( return self.call_substructure_method(
@ -1281,7 +1281,7 @@ impl<'a> MethodDef<'a> {
trait_, trait_,
type_ident, type_ident,
nonselflike_args, nonselflike_args,
&EnumMatching(0, &variants[0], Vec::new()), &EnumMatching(0, variant, Vec::new()),
); );
} }
} }

View File

@ -180,8 +180,8 @@ fn make_format_args(
Ok((mut err, suggested)) => { Ok((mut err, suggested)) => {
if !suggested { if !suggested {
if let ExprKind::Block(block, None) = &efmt.kind if let ExprKind::Block(block, None) = &efmt.kind
&& block.stmts.len() == 1 && let [stmt] = block.stmts.as_slice()
&& let StmtKind::Expr(expr) = &block.stmts[0].kind && let StmtKind::Expr(expr) = &stmt.kind
&& let ExprKind::Path(None, path) = &expr.kind && let ExprKind::Path(None, path) = &expr.kind
&& path.is_potential_trivial_const_arg() && path.is_potential_trivial_const_arg()
{ {
@ -196,8 +196,8 @@ fn make_format_args(
} else { } else {
let sugg_fmt = match args.explicit_args().len() { let sugg_fmt = match args.explicit_args().len() {
0 => "{}".to_string(), 0 => "{}".to_string(),
_ => { count => {
format!("{}{{}}", "{} ".repeat(args.explicit_args().len())) format!("{}{{}}", "{} ".repeat(count))
} }
}; };
err.span_suggestion( err.span_suggestion(

View File

@ -203,9 +203,9 @@ impl<T: Eq + Hash + Copy> TransitiveRelation<T> {
/// exists). See `postdom_upper_bound` for details. /// exists). See `postdom_upper_bound` for details.
pub fn mutual_immediate_postdominator(&self, mut mubs: Vec<T>) -> Option<T> { pub fn mutual_immediate_postdominator(&self, mut mubs: Vec<T>) -> Option<T> {
loop { loop {
match mubs.len() { match mubs[..] {
0 => return None, [] => return None,
1 => return Some(mubs[0]), [mub] => return Some(mub),
_ => { _ => {
let m = mubs.pop().unwrap(); let m = mubs.pop().unwrap();
let n = mubs.pop().unwrap(); let n = mubs.pop().unwrap();

View File

@ -335,12 +335,11 @@ fn run_compiler(
config.input = input; config.input = input;
true // has input: normal compilation true // has input: normal compilation
} }
Ok(None) => match matches.free.len() { Ok(None) => match matches.free.as_slice() {
0 => false, // no input: we will exit early [] => false, // no input: we will exit early
1 => panic!("make_input should have provided valid inputs"), [_] => panic!("make_input should have provided valid inputs"),
_ => default_early_dcx.early_fatal(format!( [fst, snd, ..] => default_early_dcx.early_fatal(format!(
"multiple input filenames provided (first two filenames are `{}` and `{}`)", "multiple input filenames provided (first two filenames are `{fst}` and `{snd}`)"
matches.free[0], matches.free[1],
)), )),
}, },
}; };
@ -488,15 +487,14 @@ fn make_input(
early_dcx: &EarlyDiagCtxt, early_dcx: &EarlyDiagCtxt,
free_matches: &[String], free_matches: &[String],
) -> Result<Option<Input>, ErrorGuaranteed> { ) -> Result<Option<Input>, ErrorGuaranteed> {
if free_matches.len() == 1 { let [ifile] = free_matches else { return Ok(None) };
let ifile = &free_matches[0];
if ifile == "-" { if ifile == "-" {
let mut src = String::new(); let mut src = String::new();
if io::stdin().read_to_string(&mut src).is_err() { if io::stdin().read_to_string(&mut src).is_err() {
// Immediately stop compilation if there was an issue reading // Immediately stop compilation if there was an issue reading
// the input (for example if the input stream is not UTF-8). // the input (for example if the input stream is not UTF-8).
let reported = early_dcx let reported =
.early_err("couldn't read from stdin, as it did not contain valid UTF-8"); early_dcx.early_err("couldn't read from stdin, as it did not contain valid UTF-8");
return Err(reported); return Err(reported);
} }
if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") { if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
@ -514,9 +512,6 @@ fn make_input(
} else { } else {
Ok(Some(Input::File(PathBuf::from(ifile)))) Ok(Some(Input::File(PathBuf::from(ifile))))
} }
} else {
Ok(None)
}
} }
/// Whether to stop or continue compilation. /// Whether to stop or continue compilation.

View File

@ -231,17 +231,17 @@ pub trait Emitter: Translate {
) { ) {
if let Some((sugg, rest)) = suggestions.split_first() { if let Some((sugg, rest)) = suggestions.split_first() {
let msg = self.translate_message(&sugg.msg, fluent_args).map_err(Report::new).unwrap(); 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 // ^ if there is only one suggestion
// don't display multi-suggestions as labels // don't display multi-suggestions as labels
sugg.substitutions.len() == 1 && && let [substitution] = sugg.substitutions.as_slice()
// don't display multipart suggestions as labels // 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 // don't display long messages as labels
msg.split_whitespace().count() < 10 && && msg.split_whitespace().count() < 10
// don't display multiline suggestions as labels // 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 // when this style is set we want the suggestion to be a message, not inline
SuggestionStyle::HideCodeAlways, SuggestionStyle::HideCodeAlways,
// trivial suggestion for tooling's sake, never shown // trivial suggestion for tooling's sake, never shown
@ -250,8 +250,8 @@ pub trait Emitter: Translate {
SuggestionStyle::ShowAlways, SuggestionStyle::ShowAlways,
].contains(&sugg.style) ].contains(&sugg.style)
{ {
let substitution = &sugg.substitutions[0].parts[0].snippet.trim(); let snippet = part.snippet.trim();
let msg = if substitution.is_empty() || sugg.style.hide_inline() { let msg = if snippet.is_empty() || sugg.style.hide_inline() {
// This substitution is only removal OR we explicitly don't want to show the // 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. // code inline (`hide_inline`). Therefore, we don't show the substitution.
format!("help: {msg}") format!("help: {msg}")
@ -260,19 +260,18 @@ pub trait Emitter: Translate {
format!( format!(
"help: {}{}: `{}`", "help: {}{}: `{}`",
msg, msg,
if self.source_map().is_some_and(|sm| is_case_difference( if self
sm, .source_map()
substitution, .is_some_and(|sm| is_case_difference(sm, snippet, part.span,))
sugg.substitutions[0].parts[0].span, {
)) {
" (notice the capitalization)" " (notice the capitalization)"
} else { } 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 // We return only the modified primary_span
suggestions.clear(); suggestions.clear();

View File

@ -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" /// 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 { pub fn display_list_with_comma_and<T: std::fmt::Display>(v: &[T]) -> String {
match v.len() { match v {
0 => "".to_string(), [] => "".to_string(),
1 => v[0].to_string(), [a] => a.to_string(),
2 => format!("{} and {}", v[0], v[1]), [a, b] => format!("{a} and {b}"),
_ => format!("{}, {}", v[0], display_list_with_comma_and(&v[1..])), [a, v @ ..] => format!("{a}, {}", display_list_with_comma_and(v)),
} }
} }

View File

@ -1306,12 +1306,12 @@ pub fn parse_macro_name_and_helper_attrs(
// that it's of the form `#[proc_macro_derive(Foo)]` or // that it's of the form `#[proc_macro_derive(Foo)]` or
// `#[proc_macro_derive(Foo, attributes(A, ..))]` // `#[proc_macro_derive(Foo, attributes(A, ..))]`
let list = attr.meta_item_list()?; 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 }); dcx.emit_err(errors::AttrNoArguments { span: attr.span });
return None; return None;
} };
let Some(trait_attr) = list[0].meta_item() else { let Some(trait_attr) = trait_attr.meta_item() else {
dcx.emit_err(errors::NotAMetaItem { span: list[0].span() }); dcx.emit_err(errors::NotAMetaItem { span: trait_attr.span() });
return None; return None;
}; };
let trait_ident = match trait_attr.ident() { let trait_ident = match trait_attr.ident() {

View File

@ -2734,15 +2734,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else if let ty::RawPtr(ptr_ty, _) = expr_t.kind() } else if let ty::RawPtr(ptr_ty, _) = expr_t.kind()
&& let ty::Adt(adt_def, _) = ptr_ty.kind() && let ty::Adt(adt_def, _) = ptr_ty.kind()
&& let ExprKind::Field(base_expr, _) = expr.kind && let ExprKind::Field(base_expr, _) = expr.kind
&& adt_def.variants().len() == 1 && let [variant] = &adt_def.variants().raw
&& adt_def && variant.fields.iter().any(|f| f.ident(self.tcx) == field)
.variants()
.iter()
.next()
.unwrap()
.fields
.iter()
.any(|f| f.ident(self.tcx) == field)
{ {
err.multipart_suggestion( err.multipart_suggestion(
"to access the field, dereference first", "to access the field, dereference first",

View File

@ -654,17 +654,17 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
traits::upcast_choices(self.tcx, source_trait_ref, target_trait_def_id); traits::upcast_choices(self.tcx, source_trait_ref, target_trait_def_id);
// must be exactly one trait ref or we'd get an ambig error etc // must be exactly one trait ref or we'd get an ambig error etc
if upcast_trait_refs.len() != 1 { let [upcast_trait_ref] = upcast_trait_refs.as_slice() else {
span_bug!( span_bug!(
self.span, self.span,
"cannot uniquely upcast `{:?}` to `{:?}`: `{:?}`", "cannot uniquely upcast `{:?}` to `{:?}`: `{:?}`",
source_trait_ref, source_trait_ref,
target_trait_def_id, target_trait_def_id,
upcast_trait_refs upcast_trait_refs
); )
} };
upcast_trait_refs.into_iter().next().unwrap() *upcast_trait_ref
} }
fn instantiate_binder_with_fresh_vars<T>(&self, value: ty::Binder<'tcx, T>) -> T fn instantiate_binder_with_fresh_vars<T>(&self, value: ty::Binder<'tcx, T>) -> T

View File

@ -321,19 +321,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
); );
}; };
let suggest_for_privacy = let suggest_for_privacy =
|err: &mut Diag<'_>, mut msg: String, sugg: Vec<String>| { |err: &mut Diag<'_>, mut msg: String, suggs: Vec<String>| {
if sugg.len() == 1 { if let [sugg] = suggs.as_slice() {
let msg = format!("\ err.help(format!("\
trait `{}` provides `{item_name}` is implemented but not reachable", trait `{}` provides `{item_name}` is implemented but not reachable",
sugg[0].trim() sugg.trim(),
); ));
err.help(msg);
} else { } else {
msg += &format!(" but {} not reachable", pluralize!("is", sugg.len())); msg += &format!(" but {} not reachable", pluralize!("is", suggs.len()));
err.span_suggestions( err.span_suggestions(
span, span,
msg, msg,
sugg, suggs,
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
} }
@ -2988,11 +2987,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
} }
if local_spans.primary_span().is_some() { if local_spans.primary_span().is_some() {
let msg = if local_preds.len() == 1 { let msg = if let [local_pred] = local_preds.as_slice() {
format!( format!(
"an implementation of `{}` might be missing for `{}`", "an implementation of `{}` might be missing for `{}`",
local_preds[0].trait_ref.print_trait_sugared(), local_pred.trait_ref.print_trait_sugared(),
local_preds[0].self_ty() local_pred.self_ty()
) )
} else { } else {
format!( format!(
@ -3034,11 +3033,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
} }
if foreign_spans.primary_span().is_some() { if foreign_spans.primary_span().is_some() {
let msg = if foreign_preds.len() == 1 { let msg = if let [foreign_pred] = foreign_preds.as_slice() {
format!( format!(
"the foreign item type `{}` doesn't implement `{}`", "the foreign item type `{}` doesn't implement `{}`",
foreign_preds[0].self_ty(), foreign_pred.self_ty(),
foreign_preds[0].trait_ref.print_trait_sugared() foreign_pred.trait_ref.print_trait_sugared()
) )
} else { } else {
format!( format!(
@ -3388,26 +3387,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
); );
self.suggest_use_candidates(candidates, |accessible_sugg, inaccessible_sugg, span| { self.suggest_use_candidates(candidates, |accessible_sugg, inaccessible_sugg, span| {
let suggest_for_access = |err: &mut Diag<'_>, mut msg: String, sugg: Vec<_>| { let suggest_for_access = |err: &mut Diag<'_>, mut msg: String, suggs: Vec<_>| {
msg += &format!( msg += &format!(
"; perhaps you want to import {one_of}", "; perhaps you want to import {one_of}",
one_of = if sugg.len() == 1 { "it" } else { "one of them" }, one_of = if suggs.len() == 1 { "it" } else { "one of them" },
); );
err.span_suggestions(span, msg, sugg, Applicability::MaybeIncorrect); err.span_suggestions(span, msg, suggs, Applicability::MaybeIncorrect);
}; };
let suggest_for_privacy = |err: &mut Diag<'_>, sugg: Vec<String>| { let suggest_for_privacy = |err: &mut Diag<'_>, suggs: Vec<String>| {
let msg = format!( let msg = format!(
"{this_trait_is} implemented but not reachable", "{this_trait_is} implemented but not reachable",
this_trait_is = if sugg.len() == 1 { this_trait_is = if let [sugg] = suggs.as_slice() {
format!("trait `{}` which provides `{item_name}` is", sugg[0].trim()) format!("trait `{}` which provides `{item_name}` is", sugg.trim())
} else { } else {
format!("the following traits which provide `{item_name}` are") format!("the following traits which provide `{item_name}` are")
} }
); );
if sugg.len() == 1 { if suggs.len() == 1 {
err.help(msg); err.help(msg);
} else { } else {
err.span_suggestions(span, msg, sugg, Applicability::MaybeIncorrect); err.span_suggestions(span, msg, suggs, Applicability::MaybeIncorrect);
} }
}; };
if accessible_sugg.is_empty() { if accessible_sugg.is_empty() {

View File

@ -527,11 +527,11 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
// Lint for constants that look like binding identifiers (#7526) // Lint for constants that look like binding identifiers (#7526)
if let PatKind::Path(hir::QPath::Resolved(None, path)) = p.kind { if let PatKind::Path(hir::QPath::Resolved(None, path)) = p.kind {
if let Res::Def(DefKind::Const, _) = path.res { if let Res::Def(DefKind::Const, _) = path.res {
if path.segments.len() == 1 { if let [segment] = path.segments {
NonUpperCaseGlobals::check_upper_case( NonUpperCaseGlobals::check_upper_case(
cx, cx,
"constant in pattern", "constant in pattern",
&path.segments[0].ident, &segment.ident,
); );
} }
} }

View File

@ -211,15 +211,12 @@ fn lint_overflowing_range_endpoint<'tcx>(
if !is_range_literal(struct_expr) { if !is_range_literal(struct_expr) {
return false; return false;
}; };
let ExprKind::Struct(_, eps, _) = &struct_expr.kind else { return false }; let ExprKind::Struct(_, [start, end], _) = &struct_expr.kind else { return false };
if eps.len() != 2 {
return false;
}
// We can suggest using an inclusive range // We can suggest using an inclusive range
// (`..=`) instead only if it is the `end` that is // (`..=`) instead only if it is the `end` that is
// overflowing and only by 1. // overflowing and only by 1.
if !(eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max) { if !(end.expr.hir_id == expr.hir_id && lit_val - 1 == max) {
return false; return false;
}; };
@ -232,7 +229,7 @@ fn lint_overflowing_range_endpoint<'tcx>(
}; };
let sub_sugg = if expr.span.lo() == lit_span.lo() { let sub_sugg = if expr.span.lo() == lit_span.lo() {
let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) else { return false }; let Ok(start) = cx.sess().source_map().span_to_snippet(start.span) else { return false };
UseInclusiveRange::WithoutParen { UseInclusiveRange::WithoutParen {
sugg: struct_expr.span.shrink_to_lo().to(lit_span.shrink_to_hi()), sugg: struct_expr.span.shrink_to_lo().to(lit_span.shrink_to_hi()),
start, start,

View File

@ -801,7 +801,7 @@ trait UnusedDelimLint {
return; return;
} }
let spans = match value.kind { let spans = match value.kind {
ast::ExprKind::Block(ref block, None) if block.stmts.len() == 1 => block.stmts[0] ast::ExprKind::Block(ref block, None) if let [stmt] = block.stmts.as_slice() => stmt
.span .span
.find_ancestor_inside(value.span) .find_ancestor_inside(value.span)
.map(|span| (value.span.with_hi(span.lo()), value.span.with_lo(span.hi()))), .map(|span| (value.span.with_hi(span.lo()), value.span.with_lo(span.hi()))),
@ -1537,14 +1537,12 @@ impl UnusedImportBraces {
} }
// Trigger the lint only if there is one nested item // Trigger the lint only if there is one nested item
if items.len() != 1 { let [(tree, _)] = items.as_slice() else { return };
return;
}
// Trigger the lint if the nested item is a non-self single item // Trigger the lint if the nested item is a non-self single item
let node_name = match items[0].0.kind { let node_name = match tree.kind {
ast::UseTreeKind::Simple(rename) => { ast::UseTreeKind::Simple(rename) => {
let orig_ident = items[0].0.prefix.segments.last().unwrap().ident; let orig_ident = tree.prefix.segments.last().unwrap().ident;
if orig_ident.name == kw::SelfLower { if orig_ident.name == kw::SelfLower {
return; return;
} }

View File

@ -483,9 +483,11 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
// Check if the match is exhaustive. // Check if the match is exhaustive.
let witnesses = report.non_exhaustiveness_witnesses; let witnesses = report.non_exhaustiveness_witnesses;
if !witnesses.is_empty() { if !witnesses.is_empty() {
if source == hir::MatchSource::ForLoopDesugar && arms.len() == 2 { if source == hir::MatchSource::ForLoopDesugar
&& let [_, snd_arm] = *arms
{
// the for loop pattern is not irrefutable // the for loop pattern is not irrefutable
let pat = &self.thir[arms[1]].pattern; let pat = &self.thir[snd_arm].pattern;
// `pat` should be `Some(<pat_field>)` from a desugared for loop. // `pat` should be `Some(<pat_field>)` from a desugared for loop.
debug_assert_eq!(pat.span.desugaring_kind(), Some(DesugaringKind::ForLoop)); debug_assert_eq!(pat.span.desugaring_kind(), Some(DesugaringKind::ForLoop));
let PatKind::Variant { ref subpatterns, .. } = pat.kind else { bug!() }; let PatKind::Variant { ref subpatterns, .. } = pat.kind else { bug!() };

View File

@ -350,8 +350,8 @@ fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> Covera
// An inline asm terminator can normally be chained, except when it diverges or uses asm // An inline asm terminator can normally be chained, except when it diverges or uses asm
// goto. // goto.
InlineAsm { ref targets, .. } => { InlineAsm { ref targets, .. } => {
if targets.len() == 1 { if let [target] = targets[..] {
CoverageSuccessors::Chainable(targets[0]) CoverageSuccessors::Chainable(target)
} else { } else {
CoverageSuccessors::NotChainable(targets) CoverageSuccessors::NotChainable(targets)
} }

View File

@ -309,11 +309,11 @@ fn verify_candidate_branch<'tcx>(
) -> bool { ) -> bool {
// In order for the optimization to be correct, the branch must... // In order for the optimization to be correct, the branch must...
// ...have exactly one statement // ...have exactly one statement
if branch.statements.len() != 1 { let [statement] = branch.statements.as_slice() else {
return false; return false;
} };
// ...assign the discriminant of `place` in that statement // ...assign the discriminant of `place` in that statement
let StatementKind::Assign(boxed) = &branch.statements[0].kind else { return false }; let StatementKind::Assign(boxed) = &statement.kind else { return false };
let (discr_place, Rvalue::Discriminant(from_place)) = &**boxed else { return false }; let (discr_place, Rvalue::Discriminant(from_place)) = &**boxed else { return false };
if *from_place != place { if *from_place != place {
return false; return false;

View File

@ -264,9 +264,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
}; };
// It's definitely not a clone if there are multiple arguments // It's definitely not a clone if there are multiple arguments
if args.len() != 1 { let [arg] = &args[..] else { return };
return;
}
let Some(destination_block) = *target else { return }; let Some(destination_block) = *target else { return };
@ -280,7 +278,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
// These types are easily available from locals, so check that before // These types are easily available from locals, so check that before
// doing DefId lookups to figure out what we're actually calling. // doing DefId lookups to figure out what we're actually calling.
let arg_ty = args[0].node.ty(self.local_decls, self.tcx); let arg_ty = arg.node.ty(self.local_decls, self.tcx);
let ty::Ref(_region, inner_ty, Mutability::Not) = *arg_ty.kind() else { return }; let ty::Ref(_region, inner_ty, Mutability::Not) = *arg_ty.kind() else { return };

View File

@ -898,8 +898,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
self.param_env, self.param_env,
adt_def.non_enum_variant().fields[field].ty(self.tcx, args), adt_def.non_enum_variant().fields[field].ty(self.tcx, args),
); );
if fields.len() == 1 { if let [field] = fields.raw.as_slice() {
let src_ty = fields.raw[0].ty(self.body, self.tcx); let src_ty = field.ty(self.body, self.tcx);
if !self.mir_assign_valid_types(src_ty, dest_ty) { if !self.mir_assign_valid_types(src_ty, dest_ty) {
self.fail(location, "union field has the wrong type"); self.fail(location, "union field has the wrong type");
} }
@ -967,11 +967,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
self.fail(location, "RawPtr should be in runtime MIR only"); self.fail(location, "RawPtr should be in runtime MIR only");
} }
if fields.len() != 2 { if let [data_ptr, metadata] = fields.raw.as_slice() {
self.fail(location, "raw pointer aggregate must have 2 fields"); let data_ptr_ty = data_ptr.ty(self.body, self.tcx);
} else { let metadata_ty = metadata.ty(self.body, self.tcx);
let data_ptr_ty = fields.raw[0].ty(self.body, self.tcx);
let metadata_ty = fields.raw[1].ty(self.body, self.tcx);
if let ty::RawPtr(in_pointee, in_mut) = data_ptr_ty.kind() { if let ty::RawPtr(in_pointee, in_mut) = data_ptr_ty.kind() {
if *in_mut != mutability { if *in_mut != mutability {
self.fail(location, "input and output mutability must match"); self.fail(location, "input and output mutability must match");
@ -998,6 +996,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
self.fail(location, "metadata for pointer-to-thin must be unit"); self.fail(location, "metadata for pointer-to-thin must be unit");
} }
} }
} else {
self.fail(location, "raw pointer aggregate must have 2 fields");
} }
} }
}, },

View File

@ -694,12 +694,12 @@ impl<'a> Parser<'a> {
// `foo: ` // `foo: `
ExprKind::Path(None, ast::Path { segments, .. }), ExprKind::Path(None, ast::Path { segments, .. }),
token::Ident(kw::For | kw::Loop | kw::While, IdentIsRaw::No), token::Ident(kw::For | kw::Loop | kw::While, IdentIsRaw::No),
) if segments.len() == 1 => { ) if let [segment] = segments.as_slice() => {
let snapshot = self.create_snapshot_for_diagnostic(); let snapshot = self.create_snapshot_for_diagnostic();
let label = Label { let label = Label {
ident: Ident::from_str_and_span( ident: Ident::from_str_and_span(
&format!("'{}", segments[0].ident), &format!("'{}", segment.ident),
segments[0].ident.span, segment.ident.span,
), ),
}; };
match self.parse_expr_labeled(label, false) { match self.parse_expr_labeled(label, false) {

View File

@ -471,9 +471,8 @@ impl<'a> Parser<'a> {
Err(mut err) => { Err(mut err) => {
// Maybe the user misspelled `macro_rules` (issue #91227) // Maybe the user misspelled `macro_rules` (issue #91227)
if self.token.is_ident() if self.token.is_ident()
&& path.segments.len() == 1 && let [segment] = path.segments.as_slice()
&& edit_distance("macro_rules", &path.segments[0].ident.to_string(), 2) && edit_distance("macro_rules", &segment.ident.to_string(), 2).is_some()
.is_some()
{ {
err.span_suggestion( err.span_suggestion(
path.span, path.span,

View File

@ -826,7 +826,8 @@ impl<'a> Parser<'a> {
// We can only resolve single-segment paths at the moment, because multi-segment paths // We can only resolve single-segment paths at the moment, because multi-segment paths
// require type-checking: see `visit_generic_arg` in `src/librustc_resolve/late.rs`. // require type-checking: see `visit_generic_arg` in `src/librustc_resolve/late.rs`.
ast::ExprKind::Path(None, path) ast::ExprKind::Path(None, path)
if path.segments.len() == 1 && path.segments[0].args.is_none() => if let [segment] = path.segments.as_slice()
&& segment.args.is_none() =>
{ {
true true
} }

View File

@ -672,7 +672,7 @@ impl<'a> Parser<'a> {
match &expr.kind { match &expr.kind {
ExprKind::Path(None, ast::Path { segments, .. }) ExprKind::Path(None, ast::Path { segments, .. })
if segments.len() == 1 => if let [segment] = segments.as_slice() =>
{ {
if self.token == token::Colon if self.token == token::Colon
&& self.look_ahead(1, |token| { && self.look_ahead(1, |token| {
@ -689,8 +689,8 @@ impl<'a> Parser<'a> {
let snapshot = self.create_snapshot_for_diagnostic(); let snapshot = self.create_snapshot_for_diagnostic();
let label = Label { let label = Label {
ident: Ident::from_str_and_span( ident: Ident::from_str_and_span(
&format!("'{}", segments[0].ident), &format!("'{}", segment.ident),
segments[0].ident.span, segment.ident.span,
), ),
}; };
match self.parse_expr_labeled(label, false) { match self.parse_expr_labeled(label, false) {

View File

@ -2207,8 +2207,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
attr.name_or_empty(), attr.name_or_empty(),
sym::allow | sym::warn | sym::deny | sym::forbid | sym::expect sym::allow | sym::warn | sym::deny | sym::forbid | sym::expect
) && let Some(meta) = attr.meta_item_list() ) && let Some(meta) = attr.meta_item_list()
&& meta.len() == 1 && let [meta] = meta.as_slice()
&& let Some(item) = meta[0].meta_item() && let Some(item) = meta.meta_item()
&& let MetaItemKind::NameValue(_) = &item.kind && let MetaItemKind::NameValue(_) = &item.kind
&& item.path == sym::reason && item.path == sym::reason
{ {

View File

@ -19,9 +19,7 @@ impl DebuggerVisualizerCollector<'_> {
return; return;
}; };
let hint = if hints.len() == 1 { let [hint] = hints.as_slice() else {
&hints[0]
} else {
self.sess.dcx().emit_err(DebugVisualizerInvalid { span: attr.span }); self.sess.dcx().emit_err(DebugVisualizerInvalid { span: attr.span });
return; return;
}; };

View File

@ -46,15 +46,14 @@ pub struct EdgeFilter {
impl EdgeFilter { impl EdgeFilter {
pub fn new(test: &str) -> Result<EdgeFilter, Box<dyn Error>> { pub fn new(test: &str) -> Result<EdgeFilter, Box<dyn Error>> {
let parts: Vec<_> = test.split("->").collect(); if let [source, target] = *test.split("->").collect::<Vec<_>>() {
if parts.len() != 2 {
Err(format!("expected a filter like `a&b -> c&d`, not `{test}`").into())
} else {
Ok(EdgeFilter { Ok(EdgeFilter {
source: DepNodeFilter::new(parts[0]), source: DepNodeFilter::new(source),
target: DepNodeFilter::new(parts[1]), target: DepNodeFilter::new(target),
index_to_node: Lock::new(FxHashMap::default()), index_to_node: Lock::new(FxHashMap::default()),
}) })
} else {
Err(format!("expected a filter like `a&b -> c&d`, not `{test}`").into())
} }
} }

View File

@ -445,8 +445,8 @@ impl<'a> PathSource<'a> {
Some(ExprKind::Call(call_expr, _)) => match &call_expr.kind { Some(ExprKind::Call(call_expr, _)) => match &call_expr.kind {
// the case of `::some_crate()` // the case of `::some_crate()`
ExprKind::Path(_, path) ExprKind::Path(_, path)
if path.segments.len() == 2 if let [segment, _] = path.segments.as_slice()
&& path.segments[0].ident.name == kw::PathRoot => && segment.ident.name == kw::PathRoot =>
{ {
"external crate" "external crate"
} }
@ -2395,15 +2395,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
} }
fn future_proof_import(&mut self, use_tree: &UseTree) { fn future_proof_import(&mut self, use_tree: &UseTree) {
let segments = &use_tree.prefix.segments; if let [segment, rest @ ..] = use_tree.prefix.segments.as_slice() {
if !segments.is_empty() { let ident = segment.ident;
let ident = segments[0].ident;
if ident.is_path_segment_keyword() || ident.span.is_rust_2015() { if ident.is_path_segment_keyword() || ident.span.is_rust_2015() {
return; return;
} }
let nss = match use_tree.kind { let nss = match use_tree.kind {
UseTreeKind::Simple(..) if segments.len() == 1 => &[TypeNS, ValueNS][..], UseTreeKind::Simple(..) if rest.is_empty() => &[TypeNS, ValueNS][..],
_ => &[TypeNS], _ => &[TypeNS],
}; };
let report_error = |this: &Self, ns| { let report_error = |this: &Self, ns| {
@ -3999,16 +3998,15 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
if this.should_report_errs() { if this.should_report_errs() {
if candidates.is_empty() { if candidates.is_empty() {
if path.len() == 2 && prefix_path.len() == 1 { if path.len() == 2
&& let [segment] = prefix_path
{
// Delay to check whether methond name is an associated function or not // Delay to check whether methond name is an associated function or not
// ``` // ```
// let foo = Foo {}; // let foo = Foo {};
// foo::bar(); // possibly suggest to foo.bar(); // foo::bar(); // possibly suggest to foo.bar();
//``` //```
err.stash( err.stash(segment.ident.span, rustc_errors::StashKey::CallAssocMethod);
prefix_path[0].ident.span,
rustc_errors::StashKey::CallAssocMethod,
);
} else { } else {
// When there is no suggested imports, we can just emit the error // When there is no suggested imports, we can just emit the error
// and suggestions immediately. Note that we bypass the usually error // and suggestions immediately. Note that we bypass the usually error

View File

@ -650,14 +650,14 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
let typo_sugg = self let typo_sugg = self
.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected) .lookup_typo_candidate(path, following_seg, source.namespace(), is_expected)
.to_opt_suggestion(); .to_opt_suggestion();
if path.len() == 1 if let [segment] = path
&& !matches!(source, PathSource::Delegation) && !matches!(source, PathSource::Delegation)
&& self.self_type_is_available() && self.self_type_is_available()
{ {
if let Some(candidate) = if let Some(candidate) =
self.lookup_assoc_candidate(ident, ns, is_expected, source.is_call()) self.lookup_assoc_candidate(ident, ns, is_expected, source.is_call())
{ {
let self_is_available = self.self_value_is_available(path[0].ident.span); let self_is_available = self.self_value_is_available(segment.ident.span);
// Account for `Foo { field }` when suggesting `self.field` so we result on // Account for `Foo { field }` when suggesting `self.field` so we result on
// `Foo { field: self.field }`. // `Foo { field: self.field }`.
let pre = match source { let pre = match source {
@ -665,7 +665,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
if expr if expr
.fields .fields
.iter() .iter()
.any(|f| f.ident == path[0].ident && f.is_shorthand) => .any(|f| f.ident == segment.ident && f.is_shorthand) =>
{ {
format!("{path_str}: ") format!("{path_str}: ")
} }
@ -1258,8 +1258,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
) )
}) })
.collect(); .collect();
if targets.len() == 1 { if let [target] = targets.as_slice() {
let target = targets[0];
return Some(TypoSuggestion::single_item_from_ident(target.0.ident, target.1)); return Some(TypoSuggestion::single_item_from_ident(target.0.ident, target.1));
} }
} }
@ -2104,8 +2103,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
filter_fn: &impl Fn(Res) -> bool, filter_fn: &impl Fn(Res) -> bool,
) -> TypoCandidate { ) -> TypoCandidate {
let mut names = Vec::new(); let mut names = Vec::new();
if path.len() == 1 { if let [segment] = path {
let mut ctxt = path.last().unwrap().ident.span.ctxt(); let mut ctxt = segment.ident.span.ctxt();
// Search in lexical scope. // Search in lexical scope.
// Walk backwards up the ribs in scope and collect candidates. // Walk backwards up the ribs in scope and collect candidates.

View File

@ -108,8 +108,8 @@ pub(crate) fn sub_namespace_match(
// `format!("{}", path)`, because that tries to insert // `format!("{}", path)`, because that tries to insert
// line-breaks and is slow. // line-breaks and is slow.
fn fast_print_path(path: &ast::Path) -> Symbol { fn fast_print_path(path: &ast::Path) -> Symbol {
if path.segments.len() == 1 { if let [segment] = path.segments.as_slice() {
path.segments[0].ident.name segment.ident.name
} else { } else {
let mut path_str = String::with_capacity(64); let mut path_str = String::with_capacity(64);
for (i, segment) in path.segments.iter().enumerate() { for (i, segment) in path.segments.iter().enumerate() {
@ -724,10 +724,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// Possibly apply the macro helper hack // Possibly apply the macro helper hack
if deleg_impl.is_none() if deleg_impl.is_none()
&& kind == Some(MacroKind::Bang) && kind == Some(MacroKind::Bang)
&& path.len() == 1 && let [segment] = path.as_slice()
&& path[0].ident.span.ctxt().outer_expn_data().local_inner_macros && segment.ident.span.ctxt().outer_expn_data().local_inner_macros
{ {
let root = Ident::new(kw::DollarCrate, path[0].ident.span); let root = Ident::new(kw::DollarCrate, segment.ident.span);
path.insert(0, Segment::from_ident(root)); path.insert(0, Segment::from_ident(root));
} }

View File

@ -912,16 +912,9 @@ mod parse {
match v { match v {
None => false, None => false,
Some(s) => { Some(s) => {
let parts = s.split('=').collect::<Vec<_>>(); let [crate_name, fuel] = *s.split('=').collect::<Vec<_>>() else { return false };
if parts.len() != 2 { let Ok(fuel) = fuel.parse::<u64>() else { return false };
return false; *slot = Some((crate_name.to_string(), fuel));
}
let crate_name = parts[0].to_string();
let fuel = parts[1].parse::<u64>();
if fuel.is_err() {
return false;
}
*slot = Some((crate_name, fuel.unwrap()));
true true
} }
} }

View File

@ -3149,11 +3149,10 @@ impl Target {
if let Some(a) = o.as_array() { if let Some(a) = o.as_array() {
for o in a { for o in a {
if let Some(s) = o.as_str() { if let Some(s) = o.as_str() {
let p = s.split('=').collect::<Vec<_>>(); if let [k, v] = *s.split('=').collect::<Vec<_>>() {
if p.len() == 2 { base.$key_name
let k = p[0].to_string(); .to_mut()
let v = p[1].to_string(); .push((k.to_string().into(), v.to_string().into()))
base.$key_name.to_mut().push((k.into(), v.into()));
} }
} }
} }

View File

@ -943,8 +943,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// The current method call returns `Result<_, ()>` // The current method call returns `Result<_, ()>`
&& self.can_eq(obligation.param_env, ty, found_ty) && self.can_eq(obligation.param_env, ty, found_ty)
// There's a single argument in the method call and it is a closure // There's a single argument in the method call and it is a closure
&& args.len() == 1 && let [arg] = args
&& let Some(arg) = args.get(0)
&& let hir::ExprKind::Closure(closure) = arg.kind && let hir::ExprKind::Closure(closure) = arg.kind
// The closure has a block for its body with no tail expression // The closure has a block for its body with no tail expression
&& let body = self.tcx.hir().body(closure.body) && let body = self.tcx.hir().body(closure.body)

View File

@ -73,10 +73,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
} }
}); });
let impl_def_id_and_args = if self_match_impls.len() == 1 { let impl_def_id_and_args = if let [impl_] = self_match_impls[..] {
self_match_impls[0] impl_
} else if fuzzy_match_impls.len() == 1 { } else if let [impl_] = fuzzy_match_impls[..] {
fuzzy_match_impls[0] impl_
} else { } else {
return None; return None;
}; };

View File

@ -5300,7 +5300,8 @@ impl<'v> Visitor<'v> for FindTypeParam {
match ty.kind { match ty.kind {
hir::TyKind::Ptr(_) | hir::TyKind::Ref(..) | hir::TyKind::TraitObject(..) => {} hir::TyKind::Ptr(_) | hir::TyKind::Ref(..) | hir::TyKind::TraitObject(..) => {}
hir::TyKind::Path(hir::QPath::Resolved(None, path)) hir::TyKind::Path(hir::QPath::Resolved(None, path))
if path.segments.len() == 1 && path.segments[0].ident.name == self.param => if let [segment] = path.segments
&& segment.ident.name == self.param =>
{ {
if !self.nested { if !self.nested {
debug!(?ty, "FindTypeParam::visit_ty"); debug!(?ty, "FindTypeParam::visit_ty");