diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index df2f4b8871249..a43e5e4bc3d1c 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -534,13 +534,14 @@ impl MetaItemInner { pub fn singleton_lit_list(&self) -> Option<(Symbol, &MetaItemLit)> { self.meta_item().and_then(|meta_item| { meta_item.meta_item_list().and_then(|meta_item_list| { - if meta_item_list.len() == 1 - && let Some(ident) = meta_item.ident() - && let Some(lit) = meta_item_list[0].lit() + if let Some(ident) = meta_item.ident() + && let [item] = meta_item_list + && let Some(lit) = item.lit() { - return Some((ident.name, lit)); + Some((ident.name, lit)) + } else { + None } - None }) }) } diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 2f1f1269ece57..f29123dbe74a5 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -269,20 +269,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let valid_modifiers = class.valid_modifiers(asm_arch.unwrap()); if !valid_modifiers.contains(&modifier) { - let sub = if !valid_modifiers.is_empty() { - let mut mods = format!("`{}`", valid_modifiers[0]); - for m in &valid_modifiers[1..] { - let _ = write!(mods, ", `{m}`"); - } - InvalidAsmTemplateModifierRegClassSub::SupportModifier { - class_name: class.name(), - modifiers: mods, - } - } else { - InvalidAsmTemplateModifierRegClassSub::DoesNotSupportModifier { - class_name: class.name(), - } - }; + let sub = + if let [first_modifier, valid_modifiers @ ..] = valid_modifiers { + let mut mods = format!("`{first_modifier}`"); + for m in valid_modifiers { + let _ = write!(mods, ", `{m}`"); + } + InvalidAsmTemplateModifierRegClassSub::SupportModifier { + class_name: class.name(), + modifiers: mods, + } + } else { + InvalidAsmTemplateModifierRegClassSub::DoesNotSupportModifier { + class_name: class.name(), + } + }; self.dcx().emit_err(InvalidAsmTemplateModifierRegClass { placeholder_span, op_span: op_sp, diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 74870d741504c..78c626a98dffe 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -562,11 +562,13 @@ impl<'hir> LoweringContext<'_, 'hir> { } // Condition should match `build_reduced_graph_for_use_tree`. - let path = if trees.is_empty() - && !(prefix.segments.is_empty() - || prefix.segments.len() == 1 - && prefix.segments[0].ident.name == kw::PathRoot) - { + let empty_for_self = |prefix: &[PathSegment]| { + matches!( + prefix, + [] | [PathSegment { ident: Ident { name: kw::PathRoot, .. }, .. }] + ) + }; + let path = if trees.is_empty() && !empty_for_self(&prefix.segments) { // For empty lists we need to lower the prefix so it is checked for things // like stability later. let res = self.lower_import_res(id, span); diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 30e94b0bec708..b8acc95c8afdc 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -1,6 +1,8 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] +use std::fmt; + use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, DiagCtxtHandle, struct_span_code_err}; use rustc_hir as hir; @@ -48,6 +50,10 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, 'infcx, 'tcx> { .with_span_label(span, format!("use of borrowed {borrow_desc}")) } + fn print_via(msg: &str) -> impl fmt::Display + '_ { + fmt::from_fn(move |f| if msg.is_empty() { Ok(()) } else { write!(f, " (via {msg})") }) + } + pub(crate) fn cannot_mutably_borrow_multiply( &self, new_loan_span: Span, @@ -57,14 +63,13 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, 'infcx, 'tcx> { old_opt_via: &str, old_load_end_span: Option, ) -> Diag<'infcx> { - let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") }; let mut err = struct_span_code_err!( self.dcx(), new_loan_span, E0499, "cannot borrow {}{} as mutable more than once at a time", desc, - via(opt_via), + Self::print_via(opt_via), ); if old_loan_span == new_loan_span { // Both borrows are happening in the same place @@ -74,7 +79,7 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, 'infcx, 'tcx> { format!( "{}{} was mutably borrowed here in the previous iteration of the loop{}", desc, - via(opt_via), + Self::print_via(opt_via), opt_via, ), ); @@ -84,11 +89,11 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, 'infcx, 'tcx> { } else { err.span_label( old_loan_span, - format!("first mutable borrow occurs here{}", via(old_opt_via)), + format!("first mutable borrow occurs here{}", Self::print_via(old_opt_via)), ); err.span_label( new_loan_span, - format!("second mutable borrow occurs here{}", via(opt_via)), + format!("second mutable borrow occurs here{}", Self::print_via(opt_via)), ); if let Some(old_load_end_span) = old_load_end_span { err.span_label(old_load_end_span, "first borrow ends here"); @@ -201,18 +206,17 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, 'infcx, 'tcx> { msg_old: &str, old_load_end_span: Option, ) -> Diag<'infcx> { - let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") }; let mut err = struct_span_code_err!( self.dcx(), span, E0502, "cannot borrow {}{} as {} because {} is also borrowed as {}{}", desc_new, - via(msg_new), + Self::print_via(msg_new), kind_new, noun_old, kind_old, - via(msg_old), + Self::print_via(msg_old), ); if msg_new.is_empty() { @@ -227,7 +231,10 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, 'infcx, 'tcx> { "{kind_new} borrow of {msg_new} -- which overlaps with {msg_old} -- occurs here", ), ); - err.span_label(old_span, format!("{} borrow occurs here{}", kind_old, via(msg_old))); + err.span_label( + old_span, + format!("{} borrow occurs here{}", kind_old, Self::print_via(msg_old)), + ); } if let Some(old_load_end_span) = old_load_end_span { diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index f200f77203c9b..b618ccadd113d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2656,13 +2656,14 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { && let Res::Local(hir_id) = seg.res && Some(hir_id) == self.closure_local_id { - let (span, arg_str) = if args.len() > 0 { - (args[0].span.shrink_to_lo(), "self, ".to_string()) - } else { - let span = e.span.trim_start(seg.ident.span).unwrap_or(e.span); - (span, "(self)".to_string()) - }; - self.closure_call_changes.push((span, arg_str)); + let change = args + .get(0) + .map(|arg| (arg.span.shrink_to_lo(), "self, ".to_string())) + .unwrap_or_else(|| { + let span = e.span.trim_start(seg.ident.span).unwrap_or(e.span); + (span, "(self)".to_string()) + }); + self.closure_call_changes.push(change); } hir::intravisit::walk_stmt(self, s); } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 077d8f49df88c..3981a7c881cbd 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -5,6 +5,7 @@ #![doc(rust_logo)] #![feature(assert_matches)] #![feature(box_patterns)] +#![feature(debug_closure_helpers)] #![feature(file_buffered)] #![feature(if_let_guard)] #![feature(let_chains)] diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 5440d451ec8d6..c0df82a5dd19a 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -356,20 +356,22 @@ fn check_opaque_type_parameter_valid<'tcx>( } for (_, indices) in seen_params { - if indices.len() > 1 { - let descr = opaque_generics.param_at(indices[0], tcx).kind.descr(); - let spans: Vec<_> = indices - .into_iter() - .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id)) - .collect(); - #[allow(rustc::diagnostic_outside_of_impl)] - #[allow(rustc::untranslatable_diagnostic)] - return Err(infcx - .dcx() - .struct_span_err(span, "non-defining opaque type use in defining scope") - .with_span_note(spans, format!("{descr} used multiple times")) - .emit()); - } + let [first_index, _, ..] = indices[..] else { + continue; + }; + + let descr = opaque_generics.param_at(first_index, tcx).kind.descr(); + let spans: Vec<_> = indices + .into_iter() + .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id)) + .collect(); + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] + return Err(infcx + .dcx() + .struct_span_err(span, "non-defining opaque type use in defining scope") + .with_span_note(spans, format!("{descr} used multiple times")) + .emit()); } Ok(()) diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index 82417a86dd9ee..5da1de25ab196 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -78,27 +78,31 @@ pub(crate) fn expand_deriving_coerce_pointee( }) .collect(); - let pointee_param_idx = if type_params.is_empty() { - // `#[derive(CoercePointee)]` requires at least one generic type on the target `struct` - cx.dcx().emit_err(RequireOneGeneric { span }); - return; - } else if type_params.len() == 1 { - // Regardless of the only type param being designed as `#[pointee]` or not, we can just use it as such - type_params[0].0 - } else { - let mut pointees = type_params - .iter() - .filter_map(|&(idx, span, is_pointee)| is_pointee.then_some((idx, span))) - .fuse(); - match (pointees.next(), pointees.next()) { - (Some((idx, _span)), None) => idx, - (None, _) => { - cx.dcx().emit_err(RequireOnePointee { span }); - return; - } - (Some((_, one)), Some((_, another))) => { - cx.dcx().emit_err(TooManyPointees { one, another }); - return; + let pointee_param_idx = match type_params[..] { + [] => { + // `#[derive(CoercePointee)]` requires at least one generic type on the target `struct` + cx.dcx().emit_err(RequireOneGeneric { span }); + return; + } + [(idx, ..)] => { + // Regardless of the only type param being designed as `#[pointee]` or not, we can just use it as such + idx + } + _ => { + let mut pointees = type_params + .iter() + .filter_map(|&(idx, span, is_pointee)| is_pointee.then_some((idx, span))) + .fuse(); + match (pointees.next(), pointees.next()) { + (Some((idx, _span)), None) => idx, + (None, _) => { + cx.dcx().emit_err(RequireOnePointee { span }); + return; + } + (Some((_, one)), Some((_, another))) => { + cx.dcx().emit_err(TooManyPointees { one, another }); + return; + } } } }; diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 105a4cb81f0d1..80959326836c9 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -238,11 +238,7 @@ pub fn each_linked_rlib( f: &mut dyn FnMut(CrateNum, &Path), ) -> Result<(), errors::LinkRlibError> { let fmts = if let Some(crate_type) = crate_type { - let Some(fmts) = info.dependency_formats.get(&crate_type) else { - return Err(errors::LinkRlibError::MissingFormat); - }; - - fmts + info.dependency_formats.get(&crate_type).ok_or(errors::LinkRlibError::MissingFormat)? } else { for combination in info.dependency_formats.iter().combinations(2) { let (ty1, list1) = &combination[0]; @@ -256,28 +252,25 @@ pub fn each_linked_rlib( }); } } - if info.dependency_formats.is_empty() { - return Err(errors::LinkRlibError::MissingFormat); - } - info.dependency_formats.first().unwrap().1 + info.dependency_formats.first().ok_or(errors::LinkRlibError::MissingFormat)?.1 }; let used_dep_crates = info.used_crates.iter(); for &cnum in used_dep_crates { - match fmts.get(cnum) { - Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue, - Some(_) => {} - None => return Err(errors::LinkRlibError::MissingFormat), + let fmt = fmts.get(cnum).ok_or(errors::LinkRlibError::MissingFormat)?; + if matches!(fmt, Linkage::NotLinked | Linkage::Dynamic | Linkage::IncludedFromDylib) { + continue; } let crate_name = info.crate_name[&cnum]; let used_crate_source = &info.used_crate_source[&cnum]; - if let Some((path, _)) = &used_crate_source.rlib { - f(cnum, path); - } else if used_crate_source.rmeta.is_some() { - return Err(errors::LinkRlibError::OnlyRmetaFound { crate_name }); - } else { - return Err(errors::LinkRlibError::NotFound { crate_name }); - } + let Some((path, _)) = &used_crate_source.rlib else { + return Err(if used_crate_source.rmeta.is_some() { + errors::LinkRlibError::OnlyRmetaFound { crate_name } + } else { + errors::LinkRlibError::NotFound { crate_name } + }); + }; + f(cnum, path); } Ok(()) } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 914f2c21fa78c..98197cbc2c877 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -572,10 +572,10 @@ fn produce_final_output_artifacts( }; let copy_if_one_unit = |output_type: OutputType, keep_numbered: bool| { - if compiled_modules.modules.len() == 1 { + if let [module] = &compiled_modules.modules[..] { // 1) Only one codegen unit. In this case it's no difficulty // to copy `foo.0.x` to `foo.x`. - let module_name = Some(&compiled_modules.modules[0].name[..]); + let module_name = Some(&module.name[..]); let path = crate_output.temp_path(output_type, module_name); let output = crate_output.path(output_type); if !output_type.is_text_output() && output.is_tty() { @@ -707,8 +707,8 @@ fn produce_final_output_artifacts( } if sess.opts.json_artifact_notifications { - if compiled_modules.modules.len() == 1 { - compiled_modules.modules[0].for_each_output(|_path, ty| { + if let [module] = &compiled_modules.modules[..] { + module.for_each_output(|_path, ty| { if sess.opts.output_types.contains_key(&ty) { let descr = ty.shorthand(); // for single cgu file is renamed to drop cgu specific suffix @@ -864,7 +864,7 @@ pub(crate) fn compute_per_cgu_lto_type( // require LTO so the request for LTO is always unconditionally // passed down to the backend, but we don't actually want to do // anything about it yet until we've got a final product. - let is_rlib = sess_crate_types.len() == 1 && sess_crate_types[0] == CrateType::Rlib; + let is_rlib = matches!(sess_crate_types, [CrateType::Rlib]); match sess_lto { Lto::ThinLocal if !linker_does_lto && !is_allocator => ComputedLtoType::Thin, diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 549729548f537..eeb0e050cca3e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -14,7 +14,9 @@ #![feature(associated_type_defaults)] #![feature(box_into_inner)] #![feature(box_patterns)] +#![feature(debug_closure_helpers)] #![feature(error_reporter)] +#![feature(exact_size_is_empty)] #![feature(extract_if)] #![feature(if_let_guard)] #![feature(let_chains)] @@ -36,6 +38,7 @@ use std::borrow::Cow; use std::cell::Cell; use std::error::Report; use std::ffi::OsStr; +use std::fmt::Write as _; use std::hash::Hash; use std::io::Write; use std::num::NonZero; @@ -995,9 +998,9 @@ impl<'a> DiagCtxtHandle<'a> { count => Cow::from(format!("aborting due to {count} previous errors")), }; - match (errors.len(), warnings.len()) { - (0, 0) => return, - (0, _) => { + match (errors.is_empty(), warnings.is_empty()) { + (true, true) => return, + (true, _) => { // Use `ForceWarning` rather than `Warning` to guarantee emission, e.g. with a // configuration like `--cap-lints allow --force-warn bare_trait_objects`. inner.emit_diagnostic( @@ -1005,7 +1008,7 @@ impl<'a> DiagCtxtHandle<'a> { None, ); } - (_, 0) => { + (_, true) => { inner.emit_diagnostic(DiagInner::new(Error, errors), self.tainted_with_errors); } (_, _) => { @@ -1030,28 +1033,32 @@ impl<'a> DiagCtxtHandle<'a> { } }) .collect::>(); - if !error_codes.is_empty() { - error_codes.sort(); - if error_codes.len() > 1 { - let limit = if error_codes.len() > 9 { 9 } else { error_codes.len() }; - let msg1 = format!( - "Some errors have detailed explanations: {}{}", - error_codes[..limit].join(", "), - if error_codes.len() > 9 { "..." } else { "." } + error_codes.sort(); + match &error_codes[..] { + [code] => { + let msg = format!( + "For more information about this error, try `rustc --explain {code}`.", ); + inner.emit_diagnostic(DiagInner::new(FailureNote, msg), None); + } + [first_code, error_codes @ ..] => { + let error_codes = fmt::from_fn(|f| { + f.write_str(first_code)?; + let mut error_codes = error_codes.iter(); + for code in error_codes.by_ref().take(8) { + write!(f, ", {code}")?; + } + if error_codes.is_empty() { f.write_char('.') } else { f.write_str("...") } + }); + // let limit = error_codes.len().max(9); + let msg1 = format!("Some errors have detailed explanations: {error_codes}"); let msg2 = format!( - "For more information about an error, try `rustc --explain {}`.", - &error_codes[0] + "For more information about an error, try `rustc --explain {first_code}`.", ); inner.emit_diagnostic(DiagInner::new(FailureNote, msg1), None); inner.emit_diagnostic(DiagInner::new(FailureNote, msg2), None); - } else { - let msg = format!( - "For more information about this error, try `rustc --explain {}`.", - &error_codes[0] - ); - inner.emit_diagnostic(DiagInner::new(FailureNote, msg), None); } + _ => {} } } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index af2f86b67e007..837fb24f03b29 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -206,7 +206,7 @@ pub type UsePath<'hir> = Path<'hir, SmallVec<[Res; 3]>>; impl Path<'_> { pub fn is_global(&self) -> bool { - !self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot + self.segments.first().is_some_and(|segment| segment.ident.name == kw::PathRoot) } } @@ -245,12 +245,10 @@ impl<'hir> PathSegment<'hir> { } pub fn args(&self) -> &GenericArgs<'hir> { - if let Some(ref args) = self.args { - args - } else { + self.args.unwrap_or({ const DUMMY: &GenericArgs<'_> = &GenericArgs::none(); DUMMY - } + }) } } @@ -1061,10 +1059,7 @@ impl Attribute { pub fn value_lit(&self) -> Option<&MetaItemLit> { match &self.kind { - AttrKind::Normal(n) => match n.as_ref() { - AttrItem { args: AttrArgs::Eq { expr, .. }, .. } => Some(expr), - _ => None, - }, + AttrKind::Normal(box AttrItem { args: AttrArgs::Eq { expr, .. }, .. }) => Some(expr), _ => None, } } @@ -1077,12 +1072,9 @@ impl AttributeExt for Attribute { fn meta_item_list(&self) -> Option> { match &self.kind { - AttrKind::Normal(n) => match n.as_ref() { - AttrItem { args: AttrArgs::Delimited(d), .. } => { - ast::MetaItemKind::list_from_tokens(d.tokens.clone()) - } - _ => None, - }, + AttrKind::Normal(box AttrItem { args: AttrArgs::Delimited(d), .. }) => { + ast::MetaItemKind::list_from_tokens(d.tokens.clone()) + } _ => None, } } @@ -1098,25 +1090,19 @@ impl AttributeExt for Attribute { /// For a single-segment attribute, returns its name; otherwise, returns `None`. fn ident(&self) -> Option { match &self.kind { - AttrKind::Normal(n) => { - if let [ident] = n.path.segments.as_ref() { - Some(*ident) - } else { - None - } - } - AttrKind::DocComment(..) => None, + AttrKind::Normal(box AttrItem { + path: AttrPath { segments: box [ident], .. }, .. + }) => Some(*ident), + _ => None, } } fn path_matches(&self, name: &[Symbol]) -> bool { - match &self.kind { - AttrKind::Normal(n) => { - n.path.segments.len() == name.len() - && n.path.segments.iter().zip(name).all(|(s, n)| s.name == *n) - } - AttrKind::DocComment(..) => false, - } + matches!( + &self.kind, + AttrKind::Normal(box AttrItem { path: AttrPath { segments, .. }, .. }) + if segments.iter().map(|s| &s.name).eq(name) + ) } fn is_doc_comment(&self) -> bool { @@ -1128,12 +1114,7 @@ impl AttributeExt for Attribute { } fn is_word(&self) -> bool { - match &self.kind { - AttrKind::Normal(n) => { - matches!(n.args, AttrArgs::Empty) - } - AttrKind::DocComment(..) => false, - } + matches!(self.kind, AttrKind::Normal(box AttrItem { args: AttrArgs::Empty, .. })) } fn ident_path(&self) -> Option> { @@ -1287,9 +1268,11 @@ impl fmt::Debug for OwnerNodes<'_> { "parents", &fmt::from_fn(|f| { f.debug_list() - .entries(self.nodes.iter_enumerated().map(|(id, parented_node)| { - fmt::from_fn(move |f| write!(f, "({id:?}, {:?})", parented_node.parent)) - })) + .entries(self.nodes.iter_enumerated().map( + |(id, ParentedNode { parent, .. })| { + fmt::from_fn(move |f| write!(f, "({id:?}, {parent:?})")) + }, + )) .finish() }), ) @@ -1550,13 +1533,13 @@ pub struct DotDotPos(u32); impl DotDotPos { /// Panics if n >= u32::MAX. pub fn new(n: Option) -> Self { - match n { - Some(n) => { + Self( + n.map(|n| { assert!(n < u32::MAX as usize); - Self(n as u32) - } - None => Self(u32::MAX), - } + n as u32 + }) + .unwrap_or(u32::MAX), + ) } pub fn as_opt_usize(&self) -> Option { @@ -1973,7 +1956,7 @@ impl fmt::Display for ConstContext { } // NOTE: `IntoDiagArg` impl for `ConstContext` lives in `rustc_errors` -// due to a cyclical dependency between hir that crate. +// due to a cyclical dependency between hir and that crate. /// A literal. pub type Lit = Spanned; @@ -2345,10 +2328,10 @@ impl Expr<'_> { /// Checks if the specified expression is a built-in range literal. /// (See: `LoweringContext::lower_expr()`). pub fn is_range_literal(expr: &Expr<'_>) -> bool { - match expr.kind { + matches!( + expr.kind, // All built-in range literals but `..=` and `..` desugar to `Struct`s. - ExprKind::Struct(ref qpath, _, _) => matches!( - **qpath, + ExprKind::Struct( QPath::LangItem( LangItem::Range | LangItem::RangeTo @@ -2356,16 +2339,15 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool { | LangItem::RangeFull | LangItem::RangeToInclusive, .. - ) - ), - + ), + .. + ) | // `..=` desugars into `::std::ops::RangeInclusive::new(...)`. - ExprKind::Call(ref func, _) => { - matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..))) - } - - _ => false, - } + ExprKind::Call( + Expr { kind: ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)), .. }, + .. + ) + ) } /// Checks if the specified expression needs parentheses for prefix @@ -3546,10 +3528,10 @@ impl<'hir> FnRetTy<'hir> { } pub fn is_suggestable_infer_ty(&self) -> Option<&'hir Ty<'hir>> { - if let Self::Return(ty) = self { - if ty.is_suggestable_infer_ty() { - return Some(*ty); - } + if let Self::Return(ty) = self + && ty.is_suggestable_infer_ty() + { + return Some(*ty); } None } @@ -3918,11 +3900,11 @@ pub struct FnHeader { impl FnHeader { pub fn is_async(&self) -> bool { - matches!(&self.asyncness, IsAsync::Async(_)) + matches!(self.asyncness, IsAsync::Async(_)) } pub fn is_const(&self) -> bool { - matches!(&self.constness, Constness::Const) + matches!(self.constness, Constness::Const) } pub fn is_unsafe(&self) -> bool { @@ -4018,16 +4000,16 @@ pub struct Impl<'hir> { impl ItemKind<'_> { pub fn generics(&self) -> Option<&Generics<'_>> { - Some(match *self { - ItemKind::Fn { ref generics, .. } - | ItemKind::TyAlias(_, ref generics) - | ItemKind::Const(_, ref generics, _) - | ItemKind::Enum(_, ref generics) - | ItemKind::Struct(_, ref generics) - | ItemKind::Union(_, ref generics) - | ItemKind::Trait(_, _, ref generics, _, _) - | ItemKind::TraitAlias(ref generics, _) - | ItemKind::Impl(Impl { ref generics, .. }) => generics, + Some(match self { + ItemKind::Fn { generics, .. } + | ItemKind::TyAlias(_, generics) + | ItemKind::Const(_, generics, _) + | ItemKind::Enum(_, generics) + | ItemKind::Struct(_, generics) + | ItemKind::Union(_, generics) + | ItemKind::Trait(_, _, generics, _, _) + | ItemKind::TraitAlias(generics, _) + | ItemKind::Impl(Impl { generics, .. }) => generics, _ => return None, }) } @@ -4424,16 +4406,14 @@ impl<'hir> Node<'hir> { /// Get a `hir::Impl` if the node is an impl block for the given `trait_def_id`. pub fn impl_block_of_trait(self, trait_def_id: DefId) -> Option<&'hir Impl<'hir>> { - match self { - Node::Item(Item { kind: ItemKind::Impl(impl_block), .. }) - if impl_block - .of_trait - .and_then(|trait_ref| trait_ref.trait_def_id()) - .is_some_and(|trait_id| trait_id == trait_def_id) => - { - Some(impl_block) - } - _ => None, + if let Node::Item(Item { kind: ItemKind::Impl(impl_block), .. }) = self + && let Some(trait_ref) = impl_block.of_trait + && let Some(trait_id) = trait_ref.trait_def_id() + && trait_id == trait_def_id + { + Some(impl_block) + } else { + None } } @@ -4452,23 +4432,22 @@ impl<'hir> Node<'hir> { /// Get the type for constants, assoc types, type aliases and statics. pub fn ty(self) -> Option<&'hir Ty<'hir>> { match self { - Node::Item(it) => match it.kind { - ItemKind::TyAlias(ty, _) - | ItemKind::Static(ty, _, _) - | ItemKind::Const(ty, _, _) => Some(ty), - ItemKind::Impl(impl_item) => Some(&impl_item.self_ty), - _ => None, - }, - Node::TraitItem(it) => match it.kind { - TraitItemKind::Const(ty, _) => Some(ty), - TraitItemKind::Type(_, ty) => ty, - _ => None, - }, - Node::ImplItem(it) => match it.kind { - ImplItemKind::Const(ty, _) => Some(ty), - ImplItemKind::Type(ty) => Some(ty), - _ => None, - }, + Node::Item(Item { + kind: + ItemKind::TyAlias(ty, _) + | ItemKind::Static(ty, _, _) + | ItemKind::Const(ty, _, _) + | ItemKind::Impl(Impl { self_ty: ty, .. }), + .. + }) + | Node::TraitItem(TraitItem { + kind: TraitItemKind::Const(ty, _) | TraitItemKind::Type(_, Some(ty)), + .. + }) + | Node::ImplItem(ImplItem { + kind: ImplItemKind::Const(ty, _) | ImplItemKind::Type(ty), + .. + }) => Some(ty), _ => None, } } @@ -4484,29 +4463,25 @@ impl<'hir> Node<'hir> { pub fn associated_body(&self) -> Option<(LocalDefId, BodyId)> { match self { Node::Item(Item { - owner_id, + owner_id: OwnerId { def_id }, kind: ItemKind::Const(_, _, body) | ItemKind::Static(.., body) | ItemKind::Fn { body, .. }, .. }) | Node::TraitItem(TraitItem { - owner_id, + owner_id: OwnerId { def_id }, kind: TraitItemKind::Const(_, Some(body)) | TraitItemKind::Fn(_, TraitFn::Provided(body)), .. }) | Node::ImplItem(ImplItem { - owner_id, + owner_id: OwnerId { def_id }, kind: ImplItemKind::Const(_, body) | ImplItemKind::Fn(_, body), .. - }) => Some((owner_id.def_id, *body)), - - Node::Expr(Expr { kind: ExprKind::Closure(Closure { def_id, body, .. }), .. }) => { - Some((*def_id, *body)) - } - - Node::AnonConst(constant) => Some((constant.def_id, constant.body)), - Node::ConstBlock(constant) => Some((constant.def_id, constant.body)), + }) + | Node::Expr(Expr { kind: ExprKind::Closure(Closure { def_id, body, .. }), .. }) + | Node::AnonConst(AnonConst { def_id, body, .. }) + | Node::ConstBlock(ConstBlock { def_id, body, .. }) => Some((*def_id, *body)), _ => None, } @@ -4529,39 +4504,29 @@ impl<'hir> Node<'hir> { } pub fn as_owner(self) -> Option> { - match self { - Node::Item(i) => Some(OwnerNode::Item(i)), - Node::ForeignItem(i) => Some(OwnerNode::ForeignItem(i)), - Node::TraitItem(i) => Some(OwnerNode::TraitItem(i)), - Node::ImplItem(i) => Some(OwnerNode::ImplItem(i)), - Node::Crate(i) => Some(OwnerNode::Crate(i)), - Node::Synthetic => Some(OwnerNode::Synthetic), - _ => None, - } + Some(match self { + Node::Item(i) => OwnerNode::Item(i), + Node::ForeignItem(i) => OwnerNode::ForeignItem(i), + Node::TraitItem(i) => OwnerNode::TraitItem(i), + Node::ImplItem(i) => OwnerNode::ImplItem(i), + Node::Crate(i) => OwnerNode::Crate(i), + Node::Synthetic => OwnerNode::Synthetic, + _ => return None, + }) } pub fn fn_kind(self) -> Option> { - match self { - Node::Item(i) => match i.kind { - ItemKind::Fn { sig, generics, .. } => { - Some(FnKind::ItemFn(i.ident, generics, sig.header)) - } - _ => None, - }, - Node::TraitItem(ti) => match ti.kind { - TraitItemKind::Fn(ref sig, _) => Some(FnKind::Method(ti.ident, sig)), - _ => None, - }, - Node::ImplItem(ii) => match ii.kind { - ImplItemKind::Fn(ref sig, _) => Some(FnKind::Method(ii.ident, sig)), - _ => None, - }, - Node::Expr(e) => match e.kind { - ExprKind::Closure { .. } => Some(FnKind::Closure), - _ => None, - }, - _ => None, - } + Some(match self { + Node::Item(i @ Item { kind: ItemKind::Fn { sig, generics, .. }, .. }) => { + FnKind::ItemFn(i.ident, generics, sig.header) + } + Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(sig, _), ident, .. }) + | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(sig, _), ident, .. }) => { + FnKind::Method(*ident, sig) + } + Node::Expr(Expr { kind: ExprKind::Closure { .. }, .. }) => FnKind::Closure, + _ => return None, + }) } expect_methods_self! { diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 705c167e258c3..270d4fbec30f8 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -5,6 +5,7 @@ // tidy-alphabetical-start #![allow(internal_features)] #![feature(associated_type_defaults)] +#![feature(box_patterns)] #![feature(closure_track_caller)] #![feature(debug_closure_helpers)] #![feature(exhaustive_patterns)] diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 40049f96de4a1..d6681771a9f5b 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1421,37 +1421,38 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) return; } let mut prev_non_exhaustive_1zst = false; - for (span, _trivial, non_exhaustive_1zst) in field_infos { - if let Some((descr, def_id, args, non_exhaustive)) = non_exhaustive_1zst { - // If there are any non-trivial fields, then there can be no non-exhaustive 1-zsts. - // Otherwise, it's only an issue if there's >1 non-exhaustive 1-zst. - if non_trivial_count > 0 || prev_non_exhaustive_1zst { - tcx.node_span_lint( - REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, - tcx.local_def_id_to_hir_id(adt.did().expect_local()), - span, - |lint| { - lint.primary_message( - "zero-sized fields in `repr(transparent)` cannot \ + for (span, (descr, def_id, args, non_exhaustive)) in field_infos + .filter_map(|(span, _, non_exhaustive_1zst)| non_exhaustive_1zst.map(|zst| (span, zst))) + { + // If there are any non-trivial fields, then there can be no non-exhaustive 1-zsts. + // Otherwise, it's only an issue if there's >1 non-exhaustive 1-zst. + if non_trivial_count == 0 && !prev_non_exhaustive_1zst { + prev_non_exhaustive_1zst = true; + continue; + } + + tcx.node_span_lint( + REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, + tcx.local_def_id_to_hir_id(adt.did().expect_local()), + span, + |lint| { + lint.primary_message( + "zero-sized fields in `repr(transparent)` cannot \ contain external non-exhaustive types", - ); - let note = if non_exhaustive { - "is marked with `#[non_exhaustive]`" - } else { - "contains private fields" - }; - let field_ty = tcx.def_path_str_with_args(def_id, args); - lint.note(format!( - "this {descr} contains `{field_ty}`, which {note}, \ + ); + let note = if non_exhaustive { + "is marked with `#[non_exhaustive]`" + } else { + "contains private fields" + }; + let field_ty = tcx.def_path_str_with_args(def_id, args); + lint.note(format!( + "this {descr} contains `{field_ty}`, which {note}, \ and makes it not a breaking change to become \ non-zero-sized in the future." - )); - }, - ) - } else { - prev_non_exhaustive_1zst = true; - } - } + )); + }, + ) } } @@ -1663,14 +1664,18 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD }); let mut params_used = DenseBitSet::new_empty(generics.own_params.len()); - for leaf in ty.walk() { - if let GenericArgKind::Type(leaf_ty) = leaf.unpack() - && let ty::Param(param) = leaf_ty.kind() - { - debug!("found use of ty param {:?}", param); - params_used.insert(param.index); - } - } + ty.walk() + .filter_map(|leaf| { + if let GenericArgKind::Type(leaf_ty) = leaf.unpack() + && let ty::Param(param) = leaf_ty.kind() + { + debug!("found use of ty param {:?}", param); + Some(param.index) + } else { + None + } + }) + .collect_into(&mut params_used); for param in &generics.own_params { if !params_used.contains(param.index) diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index ae054a9eaeb7a..080466a9adc1b 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -65,6 +65,7 @@ This API is completely unstable and subject to change. #![feature(coroutines)] #![feature(debug_closure_helpers)] #![feature(if_let_guard)] +#![feature(iter_collect_into)] #![feature(iter_from_coroutine)] #![feature(iter_intersperse)] #![feature(let_chains)] diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index f12df831cb503..6b11ddc2119a6 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -346,6 +346,14 @@ impl fmt::Debug for DenseBitSet { } } +impl Extend for DenseBitSet { + fn extend>(&mut self, iter: I) { + for item in iter { + self.insert(item); + } + } +} + impl ToString for DenseBitSet { fn to_string(&self) -> String { let mut result = String::new(); diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index fd84d75b53f3d..05654e2b88a97 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -581,21 +581,21 @@ impl<'tcx> TypeFoldable> for GenericArgsRef<'tcx> { // typically hit in 90--99.99% of cases. When folding doesn't change // the args, it's faster to reuse the existing args rather than // calling `mk_args`. - match self.len() { - 1 => { - let param0 = self[0].try_fold_with(folder)?; - if param0 == self[0] { Ok(self) } else { Ok(folder.cx().mk_args(&[param0])) } + match self[..] { + [param0] => { + let folded0 = param0.try_fold_with(folder)?; + if folded0 == param0 { Ok(self) } else { Ok(folder.cx().mk_args(&[folded0])) } } - 2 => { - let param0 = self[0].try_fold_with(folder)?; - let param1 = self[1].try_fold_with(folder)?; - if param0 == self[0] && param1 == self[1] { + [param0, param1] => { + let folded0 = param0.try_fold_with(folder)?; + let folded1 = param1.try_fold_with(folder)?; + if folded0 == param0 && folded1 == param1 { Ok(self) } else { - Ok(folder.cx().mk_args(&[param0, param1])) + Ok(folder.cx().mk_args(&[folded0, folded1])) } } - 0 => Ok(self), + [] => Ok(self), _ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_args(v)), } } @@ -621,14 +621,14 @@ impl<'tcx> TypeFoldable> for &'tcx ty::List> { // I've tried it with some private repositories and got // close to the same result, with 4 and 0 swapping places // sometimes. - match self.len() { - 2 => { - let param0 = self[0].try_fold_with(folder)?; - let param1 = self[1].try_fold_with(folder)?; - if param0 == self[0] && param1 == self[1] { + match self[..] { + [param0, param1] => { + let folded0 = param0.try_fold_with(folder)?; + let folded1 = param1.try_fold_with(folder)?; + if folded0 == param0 && folded1 == param1 { Ok(self) } else { - Ok(folder.cx().mk_type_list(&[param0, param1])) + Ok(folder.cx().mk_type_list(&[folded0, folded1])) } } _ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_type_list(v)), diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 7eeed721d5a0f..4e72cf48cf9e7 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -289,10 +289,8 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { for var in var_infos.iter_mut() { // We simply put all regions from the input into the highest // compressed universe, so we only deal with them at the end. - if !var.is_region() { - if is_existential == var.is_existential() { - update_uv(var, orig_uv, is_existential) - } + if !var.is_region() && is_existential == var.is_existential() { + update_uv(var, orig_uv, is_existential) } } } @@ -317,40 +315,39 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { fn cached_fold_ty(&mut self, t: I::Ty) -> I::Ty { let kind = match t.kind() { - ty::Infer(i) => match i { - ty::TyVar(vid) => { - assert_eq!( - self.delegate.opportunistic_resolve_ty_var(vid), - t, - "ty vid should have been resolved fully before canonicalization" - ); + ty::Infer(ty::TyVar(vid)) => { + assert_eq!( + self.delegate.opportunistic_resolve_ty_var(vid), + t, + "ty vid should have been resolved fully before canonicalization" + ); + + CanonicalVarKind::Ty(CanonicalTyVarKind::General( + self.delegate + .universe_of_ty(vid) + .unwrap_or_else(|| panic!("ty var should have been resolved: {t:?}")), + )) + } + ty::Infer(ty::IntVar(vid)) => { + assert_eq!( + self.delegate.opportunistic_resolve_int_var(vid), + t, + "ty vid should have been resolved fully before canonicalization" + ); + CanonicalVarKind::Ty(CanonicalTyVarKind::Int) + } + ty::Infer(ty::FloatVar(vid)) => { + assert_eq!( + self.delegate.opportunistic_resolve_float_var(vid), + t, + "ty vid should have been resolved fully before canonicalization" + ); + CanonicalVarKind::Ty(CanonicalTyVarKind::Float) + } + ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { + panic!("fresh vars not expected in canonicalization") + } - CanonicalVarKind::Ty(CanonicalTyVarKind::General( - self.delegate - .universe_of_ty(vid) - .unwrap_or_else(|| panic!("ty var should have been resolved: {t:?}")), - )) - } - ty::IntVar(vid) => { - assert_eq!( - self.delegate.opportunistic_resolve_int_var(vid), - t, - "ty vid should have been resolved fully before canonicalization" - ); - CanonicalVarKind::Ty(CanonicalTyVarKind::Int) - } - ty::FloatVar(vid) => { - assert_eq!( - self.delegate.opportunistic_resolve_float_var(vid), - t, - "ty vid should have been resolved fully before canonicalization" - ); - CanonicalVarKind::Ty(CanonicalTyVarKind::Float) - } - ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => { - panic!("fresh vars not expected in canonicalization") - } - }, ty::Placeholder(placeholder) => match self.canonicalize_mode { CanonicalizeMode::Input { .. } => CanonicalVarKind::PlaceholderTy( PlaceholderLike::new(placeholder.universe(), self.variables.len().into()), diff --git a/compiler/rustc_next_trait_solver/src/resolve.rs b/compiler/rustc_next_trait_solver/src/resolve.rs index 71c87714745ee..04cc37e7aec90 100644 --- a/compiler/rustc_next_trait_solver/src/resolve.rs +++ b/compiler/rustc_next_trait_solver/src/resolve.rs @@ -44,18 +44,15 @@ impl, I: Interner> TypeFolder for EagerResolv } ty::Infer(ty::IntVar(vid)) => self.delegate.opportunistic_resolve_int_var(vid), ty::Infer(ty::FloatVar(vid)) => self.delegate.opportunistic_resolve_float_var(vid), - _ => { - if t.has_infer() { - if let Some(&ty) = self.cache.get(&t) { - return ty; - } - let res = t.super_fold_with(self); - assert!(self.cache.insert(t, res)); - res - } else { - t + _ if t.has_infer() => { + if let Some(&ty) = self.cache.get(&t) { + return ty; } + let res = t.super_fold_with(self); + assert!(self.cache.insert(t, res)); + res } + _ => t, } } @@ -76,13 +73,8 @@ impl, I: Interner> TypeFolder for EagerResolv resolved } } - _ => { - if c.has_infer() { - c.super_fold_with(self) - } else { - c - } - } + _ if c.has_infer() => c.super_fold_with(self), + _ => c, } } } diff --git a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs index d8c1dc8b4e9f3..bb38756165d77 100644 --- a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs +++ b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs @@ -36,23 +36,21 @@ where let Goal { param_env, predicate: (lhs, rhs, direction) } = goal; debug_assert!(lhs.to_alias_term().is_some() || rhs.to_alias_term().is_some()); - // Structurally normalize the lhs. - let lhs = if let Some(alias) = lhs.to_alias_term() { - let term = self.next_term_infer_of_kind(lhs); - self.add_normalizes_to_goal(goal.with(cx, ty::NormalizesTo { alias, term })); - term - } else { - lhs + let mut normalize = |term: I::Term| { + if let Some(alias) = term.to_alias_term() { + let term = self.next_term_infer_of_kind(term); + self.add_normalizes_to_goal(goal.with(cx, ty::NormalizesTo { alias, term })); + term + } else { + term + } }; + // Structurally normalize the lhs. + let lhs = normalize(lhs); + // Structurally normalize the rhs. - let rhs = if let Some(alias) = rhs.to_alias_term() { - let term = self.next_term_infer_of_kind(rhs); - self.add_normalizes_to_goal(goal.with(cx, ty::NormalizesTo { alias, term })); - term - } else { - rhs - }; + let rhs = normalize(rhs); // Add a `make_canonical_response` probe step so that we treat this as // a candidate, even if `try_evaluate_added_goals` bails due to an error. @@ -73,12 +71,10 @@ where match (lhs.to_alias_term(), rhs.to_alias_term()) { (None, None) => { self.relate(param_env, lhs, variance, rhs)?; - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } (Some(alias), None) => { self.relate_rigid_alias_non_alias(param_env, alias, variance, rhs)?; - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } (None, Some(alias)) => { self.relate_rigid_alias_non_alias( @@ -87,13 +83,12 @@ where variance.xform(ty::Contravariant), lhs, )?; - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } (Some(alias_lhs), Some(alias_rhs)) => { self.relate(param_env, alias_lhs, variance, alias_rhs)?; - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index d0b01b14d6358..5341229d93ecf 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -8,7 +8,9 @@ use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::solve::inspect; use rustc_type_ir::visit::TypeVisitableExt as _; -use rustc_type_ir::{self as ty, Interner, TypingMode, Upcast as _, elaborate}; +use rustc_type_ir::{ + self as ty, AliasTy, EarlyBinder, Interner, TypingMode, Upcast as _, elaborate, +}; use tracing::{debug, instrument}; use super::trait_goals::TraitGoalProvenVia; @@ -497,15 +499,18 @@ where goal: Goal, candidates: &mut Vec>, ) { - for (i, assumption) in goal.param_env.caller_bounds().iter().enumerate() { - candidates.extend(G::probe_and_consider_implied_clause( - self, - CandidateSource::ParamEnv(i), - goal, - assumption, - [], - )); - } + candidates.extend(goal.param_env.caller_bounds().iter().enumerate().filter_map( + |(i, assumption)| { + G::probe_and_consider_implied_clause( + self, + CandidateSource::ParamEnv(i), + goal, + assumption, + [], + ) + .ok() + }, + )); } #[instrument(level = "trace", skip_all)] @@ -514,7 +519,7 @@ where goal: Goal, candidates: &mut Vec>, ) { - let () = self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| { + self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| { ecx.assemble_alias_bound_candidates_recur( goal.predicate.self_ty(), goal, @@ -591,36 +596,49 @@ where } }; - match consider_self_bounds { - AliasBoundKind::SelfBounds => { - for assumption in self - .cx() - .item_self_bounds(alias_ty.def_id) - .iter_instantiated(self.cx(), alias_ty.args) - { - candidates.extend(G::probe_and_consider_implied_clause( - self, + fn probe_and_consider_implied_clause<'e, 'd, D, I, G, C, B>( + ecx: &'e mut EvalCtxt<'d, D, I>, + alias_ty: AliasTy, + bounds: B, + goal: Goal, + ) -> impl Iterator> + use<'e, 'd, D, I, G, C, B> + where + D: SolverDelegate, + I: Interner, + G: GoalKind, + C: IntoIterator, + B: Fn(I, I::DefId) -> EarlyBinder, + { + bounds(ecx.cx(), alias_ty.def_id).iter_instantiated(ecx.cx(), alias_ty.args).filter_map( + move |assumption| { + G::probe_and_consider_implied_clause( + ecx, CandidateSource::AliasBound, goal, assumption, [], - )); - } + ) + .ok() + }, + ) + } + + match consider_self_bounds { + AliasBoundKind::SelfBounds => { + candidates.extend(probe_and_consider_implied_clause( + self, + alias_ty, + Interner::item_self_bounds, + goal, + )); } AliasBoundKind::NonSelfBounds => { - for assumption in self - .cx() - .item_non_self_bounds(alias_ty.def_id) - .iter_instantiated(self.cx(), alias_ty.args) - { - candidates.extend(G::probe_and_consider_implied_clause( - self, - CandidateSource::AliasBound, - goal, - assumption, - [], - )); - } + candidates.extend(probe_and_consider_implied_clause( + self, + alias_ty, + Interner::item_non_self_bounds, + goal, + )); } } @@ -631,14 +649,14 @@ where } // Recurse on the self type of the projection. - match self.structurally_normalize_ty(goal.param_env, alias_ty.self_ty()) { - Ok(next_self_ty) => self.assemble_alias_bound_candidates_recur( + if let Ok(next_self_ty) = self.structurally_normalize_ty(goal.param_env, alias_ty.self_ty()) + { + self.assemble_alias_bound_candidates_recur( next_self_ty, goal, candidates, AliasBoundKind::NonSelfBounds, - ), - Err(NoSolution) => {} + ); } } @@ -695,36 +713,43 @@ where // Consider all of the auto-trait and projection bounds, which don't // need to be recorded as a `BuiltinImplSource::Object` since they don't // really have a vtable base... - for bound in bounds.iter() { + candidates.extend(bounds.iter().filter_map(|bound| { match bound.skip_binder() { ty::ExistentialPredicate::Trait(_) => { // Skip principal + None } ty::ExistentialPredicate::Projection(_) | ty::ExistentialPredicate::AutoTrait(_) => { - candidates.extend(G::probe_and_consider_object_bound_candidate( + G::probe_and_consider_object_bound_candidate( self, CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, bound.with_self_ty(cx, self_ty), - )); + ) + .ok() } } - } + })); // FIXME: We only need to do *any* of this if we're considering a trait goal, // since we don't need to look at any supertrait or anything if we are doing // a projection goal. if let Some(principal) = bounds.principal() { let principal_trait_ref = principal.with_self_ty(cx, self_ty); - for (idx, assumption) in elaborate::supertraits(cx, principal_trait_ref).enumerate() { - candidates.extend(G::probe_and_consider_object_bound_candidate( - self, - CandidateSource::BuiltinImpl(BuiltinImplSource::Object(idx)), - goal, - assumption.upcast(cx), - )); - } + candidates.extend( + elaborate::supertraits(cx, principal_trait_ref).enumerate().filter_map( + |(idx, assumption)| { + G::probe_and_consider_object_bound_candidate( + self, + CandidateSource::BuiltinImpl(BuiltinImplSource::Object(idx)), + goal, + assumption.upcast(cx), + ) + .ok() + }, + ), + ); } } diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 3c5d9b95e772d..43a8490b3ff74 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -342,13 +342,11 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable::Clause, then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult, ) -> Result, NoSolution> { - if let Some(host_clause) = assumption.as_host_effect_clause() { - if host_clause.def_id() == goal.predicate.def_id() - && host_clause.constness().satisfies(goal.predicate.constness) - { - if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( - goal.predicate.trait_ref.args, - host_clause.skip_binder().trait_ref.args, - ) { - return Err(NoSolution); - } - - ecx.probe_trait_candidate(source).enter(|ecx| { - let assumption_trait_pred = ecx.instantiate_binder_with_infer(host_clause); - ecx.eq( - goal.param_env, - goal.predicate.trait_ref, - assumption_trait_pred.trait_ref, - )?; - then(ecx) - }) - } else { - Err(NoSolution) - } - } else { - Err(NoSolution) + let Some(host_clause) = assumption.as_host_effect_clause() else { + return Err(NoSolution); + }; + + if host_clause.def_id() != goal.predicate.def_id() + || !host_clause.constness().satisfies(goal.predicate.constness) + || !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( + goal.predicate.trait_ref.args, + host_clause.skip_binder().trait_ref.args, + ) + { + return Err(NoSolution); } + + ecx.probe_trait_candidate(source).enter(|ecx| { + let assumption_trait_pred = ecx.instantiate_binder_with_infer(host_clause); + ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?; + then(ecx) + }) } /// Register additional assumptions for aliases corresponding to `~const` item bounds. @@ -82,20 +75,19 @@ where goal: Goal, alias_ty: ty::AliasTy, ) -> Vec> { - let cx = ecx.cx(); - let mut candidates = vec![]; - if !ecx.cx().alias_has_const_conditions(alias_ty.def_id) { return vec![]; } - for clause in elaborate::elaborate( + let cx = ecx.cx(); + elaborate::elaborate( cx, cx.explicit_implied_const_bounds(alias_ty.def_id) .iter_instantiated(cx, alias_ty.args) .map(|trait_ref| trait_ref.to_host_effect_clause(cx, goal.predicate.constness)), - ) { - candidates.extend(Self::probe_and_match_goal_against_assumption( + ) + .flat_map(|clause| { + Self::probe_and_match_goal_against_assumption( ecx, CandidateSource::AliasBound, goal, @@ -115,10 +107,9 @@ where ); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }, - )); - } - - candidates + ) + }) + .collect() } fn consider_impl_candidate( diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index e99cd3d272700..a56ffbc850027 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -442,13 +442,11 @@ where { // In case any fresh inference variables have been created between `state` // and the previous instantiation, extend `orig_values` for it. - assert!(orig_values.len() <= state.value.var_values.len()); - for &arg in &state.value.var_values.var_values.as_slice() - [orig_values.len()..state.value.var_values.len()] - { - let unconstrained = delegate.fresh_var_for_kind_with_span(arg, span); - orig_values.push(unconstrained); - } + orig_values.extend( + state.value.var_values.var_values.as_slice()[orig_values.len()..] + .iter() + .map(|&arg| delegate.fresh_var_for_kind_with_span(arg, span)), + ); let instantiation = EvalCtxt::compute_query_response_instantiation_values(delegate, orig_values, &state); diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 91ad24bff6743..8d96898593eb6 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -110,7 +110,7 @@ struct NestedGoals { impl NestedGoals { fn new() -> Self { - Self { normalizes_to_goals: Vec::new(), goals: Vec::new() } + Self::default() } fn is_empty(&self) -> bool { diff --git a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs index 1607fbb1b6a7b..24c29cc8443e8 100644 --- a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs +++ b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs @@ -286,40 +286,40 @@ impl, I: Interner> ProofTreeBuilder { &mut self, canonical_goal_evaluation: ProofTreeBuilder, ) { - if let Some(this) = self.as_mut() { - match (this, *canonical_goal_evaluation.state.unwrap()) { - ( - DebugSolver::GoalEvaluation(goal_evaluation), - DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation), - ) => { - let prev = goal_evaluation.evaluation.replace(canonical_goal_evaluation); - assert_eq!(prev, None); - } - _ => unreachable!(), + let Some(this) = self.as_mut() else { return }; + + match (this, *canonical_goal_evaluation.state.unwrap()) { + ( + DebugSolver::GoalEvaluation(goal_evaluation), + DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation), + ) => { + let prev = goal_evaluation.evaluation.replace(canonical_goal_evaluation); + assert_eq!(prev, None); } + _ => unreachable!(), } } pub(crate) fn canonical_goal_evaluation_overflow(&mut self) { - if let Some(this) = self.as_mut() { - match this { - DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => { - canonical_goal_evaluation.encountered_overflow = true; - } - _ => unreachable!(), - }; - } + let Some(this) = self.as_mut() else { return }; + + match this { + DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => { + canonical_goal_evaluation.encountered_overflow = true; + } + _ => unreachable!(), + }; } pub(crate) fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder) { - if let Some(this) = self.as_mut() { - match this { - DebugSolver::Root => *this = *goal_evaluation.state.unwrap(), - DebugSolver::CanonicalGoalEvaluationStep(_) => { - assert!(goal_evaluation.state.is_none()) - } - _ => unreachable!(), + let Some(this) = self.as_mut() else { return }; + + match this { + DebugSolver::Root => *this = *goal_evaluation.state.unwrap(), + DebugSolver::CanonicalGoalEvaluationStep(_) => { + assert!(goal_evaluation.state.is_none()) } + _ => unreachable!(), } } @@ -340,26 +340,27 @@ impl, I: Interner> ProofTreeBuilder { } pub(crate) fn goal_evaluation_step(&mut self, goal_evaluation_step: ProofTreeBuilder) { - if let Some(this) = self.as_mut() { - match (this, *goal_evaluation_step.state.unwrap()) { - ( - DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluations), - DebugSolver::CanonicalGoalEvaluationStep(goal_evaluation_step), - ) => { - canonical_goal_evaluations.final_revision = Some(goal_evaluation_step); - } - _ => unreachable!(), + let Some(this) = self.as_mut() else { return }; + + match (this, *goal_evaluation_step.state.unwrap()) { + ( + DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluations), + DebugSolver::CanonicalGoalEvaluationStep(goal_evaluation_step), + ) => { + canonical_goal_evaluations.final_revision = Some(goal_evaluation_step); } + _ => unreachable!(), } } pub(crate) fn add_var_value>(&mut self, arg: T) { - match self.as_mut() { - None => {} - Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { + let Some(s) = self.as_mut() else { return }; + + match s { + DebugSolver::CanonicalGoalEvaluationStep(state) => { state.var_values.push(arg.into()); } - Some(s) => panic!("tried to add var values to {s:?}"), + s => panic!("tried to add var values to {s:?}"), } } @@ -501,22 +502,19 @@ impl, I: Interner> ProofTreeBuilder { } pub(crate) fn query_result(&mut self, result: QueryResult) { - if let Some(this) = self.as_mut() { - match this { - DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => { - assert_eq!(canonical_goal_evaluation.result.replace(result), None); - } - DebugSolver::CanonicalGoalEvaluationStep(evaluation_step) => { - assert_eq!( - evaluation_step - .evaluation - .kind - .replace(inspect::ProbeKind::Root { result }), - None - ); - } - _ => unreachable!(), + let Some(this) = self.as_mut() else { return }; + + match this { + DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => { + assert_eq!(canonical_goal_evaluation.result.replace(result), None); + } + DebugSolver::CanonicalGoalEvaluationStep(evaluation_step) => { + assert_eq!( + evaluation_step.evaluation.kind.replace(inspect::ProbeKind::Root { result }), + None + ); } + _ => unreachable!(), } } } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs index 8ad0bf5cdf9a4..21871b8707070 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs @@ -14,14 +14,15 @@ where &mut self, goal: Goal>, ) -> QueryResult { - if let Some(normalized_const) = self.evaluate_const( + let certainty = if let Some(normalized_const) = self.evaluate_const( goal.param_env, ty::UnevaluatedConst::new(goal.predicate.alias.def_id, goal.predicate.alias.args), ) { self.instantiate_normalizes_to_term(goal, normalized_const.into()); - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + Certainty::Yes } else { - self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) - } + Certainty::AMBIGUOUS + }; + self.evaluate_added_goals_and_make_canonical_response(certainty) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 76cbe5758b23a..9c122f553beed 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -150,43 +150,42 @@ where assumption: I::Clause, then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult, ) -> Result, NoSolution> { - if let Some(projection_pred) = assumption.as_projection_clause() { - if projection_pred.item_def_id() == goal.predicate.def_id() { - let cx = ecx.cx(); - if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( - goal.predicate.alias.args, - projection_pred.skip_binder().projection_term.args, - ) { - return Err(NoSolution); - } - ecx.probe_trait_candidate(source).enter(|ecx| { - let assumption_projection_pred = - ecx.instantiate_binder_with_infer(projection_pred); - ecx.eq( - goal.param_env, - goal.predicate.alias, - assumption_projection_pred.projection_term, - )?; - - ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term); - - // Add GAT where clauses from the trait's definition - // FIXME: We don't need these, since these are the type's own WF obligations. - ecx.add_goals( - GoalSource::Misc, - cx.own_predicates_of(goal.predicate.def_id()) - .iter_instantiated(cx, goal.predicate.alias.args) - .map(|pred| goal.with(cx, pred)), - ); - - then(ecx) - }) - } else { - Err(NoSolution) - } - } else { - Err(NoSolution) + let Some(projection_pred) = assumption.as_projection_clause() else { + return Err(NoSolution); + }; + + if projection_pred.item_def_id() != goal.predicate.def_id() + || !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( + goal.predicate.alias.args, + projection_pred.skip_binder().projection_term.args, + ) + { + return Err(NoSolution); } + + let cx = ecx.cx(); + + ecx.probe_trait_candidate(source).enter(|ecx| { + let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred); + ecx.eq( + goal.param_env, + goal.predicate.alias, + assumption_projection_pred.projection_term, + )?; + + ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term); + + // Add GAT where clauses from the trait's definition + // FIXME: We don't need these, since these are the type's own WF obligations. + ecx.add_goals( + GoalSource::Misc, + cx.own_predicates_of(goal.predicate.def_id()) + .iter_instantiated(cx, goal.predicate.alias.args) + .map(|pred| goal.with(cx, pred)), + ); + + then(ecx) + }) } fn consider_additional_alias_assumptions( @@ -378,17 +377,15 @@ where goal_kind: ty::ClosureKind, ) -> Result, NoSolution> { let cx = ecx.cx(); - let tupled_inputs_and_output = - match structural_traits::extract_tupled_inputs_and_output_from_callable( + let Some(tupled_inputs_and_output) = + structural_traits::extract_tupled_inputs_and_output_from_callable( cx, goal.predicate.self_ty(), goal_kind, - )? { - Some(tupled_inputs_and_output) => tupled_inputs_and_output, - None => { - return ecx.forced_ambiguity(MaybeCause::Ambiguity); - } - }; + )? + else { + return ecx.forced_ambiguity(MaybeCause::Ambiguity); + }; // A built-in `Fn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 513fc9355c8b5..3c307214678f8 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -130,6 +130,7 @@ where assumption: I::Clause, then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult, ) -> Result, NoSolution> { + // ... if let Some(trait_clause) = assumption.as_trait_clause() { if trait_clause.def_id() == goal.predicate.def_id() && trait_clause.polarity() == goal.predicate.polarity @@ -253,27 +254,20 @@ where let self_ty = goal.predicate.self_ty(); match goal.predicate.polarity { // impl FnPtr for FnPtr {} - ty::PredicatePolarity::Positive => { - if self_ty.is_fn_ptr() { - ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }) - } else { - Err(NoSolution) - } - } - // impl !FnPtr for T where T != FnPtr && T is rigid {} - ty::PredicatePolarity::Negative => { + ty::PredicatePolarity::Positive if self_ty.is_fn_ptr() => ecx + .probe_builtin_trait_candidate(BuiltinImplSource::Misc) + .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)), + // impl !FnPtr for T where T != FnPtr && T is rigid {} + ty::PredicatePolarity::Negative // If a type is rigid and not a fn ptr, then we know for certain // that it does *not* implement `FnPtr`. - if !self_ty.is_fn_ptr() && self_ty.is_known_rigid() { - ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }) - } else { - Err(NoSolution) - } + if !self_ty.is_fn_ptr() && self_ty.is_known_rigid() => + { + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } + _ => Err(NoSolution), } } @@ -287,17 +281,15 @@ where } let cx = ecx.cx(); - let tupled_inputs_and_output = - match structural_traits::extract_tupled_inputs_and_output_from_callable( + let Some(tupled_inputs_and_output) = + structural_traits::extract_tupled_inputs_and_output_from_callable( cx, goal.predicate.self_ty(), goal_kind, - )? { - Some(a) => a, - None => { - return ecx.forced_ambiguity(MaybeCause::Ambiguity); - } - }; + )? + else { + return ecx.forced_ambiguity(MaybeCause::Ambiguity); + }; // A built-in `Fn` impl only holds if the output is sized. // (FIXME: technically we only need to check this if the type is a fn ptr...) @@ -403,12 +395,12 @@ where return Err(NoSolution); } - if let ty::Tuple(..) = goal.predicate.self_ty().kind() { - ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) - .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) - } else { - Err(NoSolution) - } + let ty::Tuple(..) = goal.predicate.self_ty().kind() else { + return Err(NoSolution); + }; + + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) + .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } fn consider_builtin_pointee_candidate( @@ -637,10 +629,8 @@ where return vec![]; } - let result_to_single = |result| match result { - Ok(resp) => vec![resp], - Err(NoSolution) => vec![], - }; + let result_to_single = + |result: Result<_, _>| result.map(|resp| vec![resp]).unwrap_or_default(); ecx.probe(|_| ProbeKind::UnsizeAssembly).enter(|ecx| { let a_ty = goal.predicate.self_ty(); @@ -726,12 +716,11 @@ where let cx = self.cx(); let Goal { predicate: (a_ty, _b_ty), .. } = goal; - let mut responses = vec![]; // If the principal def ids match (or are both none), then we're not doing // trait upcasting. We're just removing auto traits (or shortening the lifetime). let b_principal_def_id = b_data.principal_def_id(); if a_data.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() { - responses.extend(self.consider_builtin_upcast_to_principal( + self.consider_builtin_upcast_to_principal( goal, CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), a_data, @@ -739,28 +728,30 @@ where b_data, b_region, a_data.principal(), - )); + ) + .into_iter() + .collect() } else if let Some(a_principal) = a_data.principal() { - for (idx, new_a_principal) in - elaborate::supertraits(self.cx(), a_principal.with_self_ty(cx, a_ty)) - .enumerate() - .skip(1) - { - responses.extend(self.consider_builtin_upcast_to_principal( - goal, - CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting(idx)), - a_data, - a_region, - b_data, - b_region, - Some(new_a_principal.map_bound(|trait_ref| { - ty::ExistentialTraitRef::erase_self_ty(cx, trait_ref) - })), - )); - } + elaborate::supertraits(self.cx(), a_principal.with_self_ty(cx, a_ty)) + .enumerate() + .skip(1) + .flat_map(|(idx, new_a_principal)| { + self.consider_builtin_upcast_to_principal( + goal, + CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting(idx)), + a_data, + a_region, + b_data, + b_region, + Some(new_a_principal.map_bound(|trait_ref| { + ty::ExistentialTraitRef::erase_self_ty(cx, trait_ref) + })), + ) + }) + .collect() + } else { + vec![] } - - responses } fn consider_builtin_unsize_to_dyn_candidate( diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index eec9e9a851503..30c0c8dd8012b 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -522,7 +522,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { debug!("build_reduced_graph_for_use_tree: prefix={:?}", prefix); let empty_for_self = |prefix: &[Segment]| { - prefix.is_empty() || prefix.len() == 1 && prefix[0].ident.name == kw::PathRoot + matches!(prefix, [] | [Segment { ident: Ident { name: kw::PathRoot, .. }, .. }]) }; match use_tree.kind { ast::UseTreeKind::Simple(rename) => { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 8dc752c2cb38d..bd93088717d3f 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1,3 +1,5 @@ +use std::cmp; + use rustc_ast::expand::StrippedCfgItem; use rustc_ast::ptr::P; use rustc_ast::visit::{self, Visitor}; @@ -1094,7 +1096,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } Scope::ExternPrelude => { - suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| { + suggestions.extend(this.extern_prelude.keys().filter_map(|ident| { let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id()); filter_fn(res).then_some(TypoSuggestion::typo_from_ident(*ident, res)) })); @@ -1307,12 +1309,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let is_extern_crate_that_also_appears_in_prelude = name_binding.is_extern_crate() && lookup_ident.span.at_least_rust_2018(); - if !is_extern_crate_that_also_appears_in_prelude || alias_import { + if (!is_extern_crate_that_also_appears_in_prelude || alias_import) // add the module to the lookup - if seen_modules.insert(module.def_id()) { - if via_import { &mut worklist_via_import } else { &mut worklist } - .push((module, path_segments, child_accessible, child_doc_visible)); - } + && seen_modules.insert(module.def_id()) + { + if via_import { &mut worklist_via_import } else { &mut worklist }.push(( + module, + path_segments, + child_accessible, + child_doc_visible, + )); } } }) @@ -1889,9 +1895,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { match binding.kind { NameBindingKind::Import { import, .. } => { - for segment in import.module_path.iter().skip(1) { - path.push(segment.ident.to_string()); - } + path.extend( + import.module_path.iter().skip(1).map(|segment| segment.ident.to_string()), + ); sugg_paths.push(( path.iter() .cloned() @@ -1931,25 +1937,23 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; err.subdiagnostic(note); } - // We prioritize shorter paths, non-core imports and direct imports over the alternatives. - sugg_paths.sort_by_key(|(p, reexport)| (p.len(), p[0] == "core", *reexport)); - for (sugg, reexport) in sugg_paths { - if not_publicly_reexported { - break; - } - if sugg.len() <= 1 { + if !not_publicly_reexported { + // We prioritize shorter paths, non-core imports and direct imports over the alternatives. + sugg_paths.sort_by_key(|(p, reexport)| (p.len(), p[0] == "core", *reexport)); + + if let Some((sugg, reexport)) = sugg_paths.into_iter().find(|(sugg, _)| { // A single path segment suggestion is wrong. This happens on circular imports. // `tests/ui/imports/issue-55884-2.rs` - continue; + sugg.len() > 1 + }) { + let path = sugg.join("::"); + let sugg = if reexport { + errors::ImportIdent::ThroughReExport { span: dedup_span, ident, path } + } else { + errors::ImportIdent::Directly { span: dedup_span, ident, path } + }; + err.subdiagnostic(sugg); } - let path = sugg.join("::"); - let sugg = if reexport { - errors::ImportIdent::ThroughReExport { span: dedup_span, ident, path } - } else { - errors::ImportIdent::Directly { span: dedup_span, ident, path } - }; - err.subdiagnostic(sugg); - break; } err.emit(); @@ -1966,11 +1970,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .map(|ident| ident.name) .chain( self.module_map - .iter() - .filter(|(_, module)| { + .values() + .filter(|module| { current_module.is_ancestor_of(**module) && current_module != **module }) - .flat_map(|(_, module)| module.kind.name()), + .flat_map(|module| module.kind.name()), ) .filter(|c| !c.to_string().is_empty()) .collect::>(); @@ -2260,13 +2264,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { mut path: Vec, parent_scope: &ParentScope<'ra>, ) -> Option<(Vec, Option)> { - match (path.get(0), path.get(1)) { + match path[..] { // `{{root}}::ident::...` on both editions. // On 2015 `{{root}}` is usually added implicitly. - (Some(fst), Some(snd)) + [fst, snd, ..] if fst.ident.name == kw::PathRoot && !snd.ident.is_path_segment_keyword() => {} // `ident::...` on 2018. - (Some(fst), _) + [fst, ..] if fst.ident.span.at_least_rust_2018() && !fst.ident.is_path_segment_keyword() => { // Insert a placeholder that's later replaced by `self`/`super`/etc. @@ -2378,19 +2382,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // 2) `std` suggestions before `core` suggestions. let mut extern_crate_names = self.extern_prelude.keys().map(|ident| ident.name).collect::>(); - extern_crate_names.sort_by(|a, b| b.as_str().partial_cmp(a.as_str()).unwrap()); - - for name in extern_crate_names.into_iter() { - // Replace first ident with a crate name and check if that is valid. - path[0].ident.name = name; - let result = self.maybe_resolve_path(&path, None, parent_scope, None); - debug!(?path, ?name, ?result); - if let PathResult::Module(..) = result { - return Some((path, None)); - } - } - - None + extern_crate_names.sort_by(|a, b| a.cmp(&b)); + + extern_crate_names + .into_iter() + .any(|name| { + // Replace first ident with a crate name and check if that is valid. + path[0].ident.name = name; + let result = self.maybe_resolve_path(&path, None, parent_scope, None); + debug!(?path, ?name, ?result); + matches!(result, PathResult::Module(..)) + }) + .then_some((path, None)) } /// Suggests importing a macro from the root of the crate rather than a module within @@ -3081,20 +3084,21 @@ impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder { } fn search_for_any_use_in_items(items: &[P]) -> Option { - for item in items { - if let ItemKind::Use(..) = item.kind - && is_span_suitable_for_use_injection(item.span) - { - let mut lo = item.span.lo(); - for attr in &item.attrs { - if attr.span.eq_ctxt(item.span) { - lo = std::cmp::min(lo, attr.span.lo()); - } - } - return Some(Span::new(lo, lo, item.span.ctxt(), item.span.parent())); - } - } - None + items + .iter() + .find(|item| { + matches!(item.kind, ItemKind::Use(..)) && is_span_suitable_for_use_injection(item.span) + }) + .map(|item| { + let lo = item + .attrs + .iter() + .filter(|attr| attr.span.eq_ctxt(item.span)) + .map(|attr| attr.span.lo()) + .fold(item.span.lo(), cmp::min); + + Span::new(lo, lo, item.span.ctxt(), item.span.parent()) + }) } fn is_span_suitable_for_use_injection(s: Span) -> bool { diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index d49f8d3093db7..ca11035340f7f 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -1,4 +1,4 @@ -use tracing::debug; +use tracing::{debug, instrument}; use super::{ ExpectedFound, RelateResult, StructurallyRelateAliases, TypeRelation, @@ -57,7 +57,7 @@ where match (a.kind(), b.kind()) { (ty::Error(e), _) | (_, ty::Error(e)) => { infcx.set_tainted_by_errors(e); - return Ok(Ty::new_error(infcx.cx(), e)); + Ok(Ty::new_error(infcx.cx(), e)) } // Relate integral variables to other types @@ -146,6 +146,7 @@ where } } +#[instrument(fields(R = std::any::type_name::()), skip(infcx, relation))] pub fn super_combine_consts( infcx: &Infcx, relation: &mut R, @@ -157,7 +158,6 @@ where I: Interner, R: PredicateEmittingRelation, { - debug!("super_combine_consts::<{}>({:?}, {:?})", std::any::type_name::(), a, b); debug_assert!(!a.has_escaping_bound_vars()); debug_assert!(!b.has_escaping_bound_vars()); diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index a1b1748c85b53..5884945965fa1 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -68,14 +68,12 @@ pub fn submodule_path_of(builder: &Builder<'_>, path: &str) -> Option { } fn is_aix_shared_archive(path: &Path) -> bool { - let file = match fs::File::open(path) { - Ok(file) => file, - Err(_) => return false, + let Ok(file) = fs::File::open(path) else { + return false; }; let reader = object::ReadCache::new(file); - let archive = match ArchiveFile::parse(&reader) { - Ok(result) => result, - Err(_) => return false, + let Ok(archive) = ArchiveFile::parse(&reader) else { + return false; }; archive @@ -99,10 +97,7 @@ pub fn libdir(target: TargetSelection) -> &'static str { /// Adds a list of lookup paths to `cmd`'s dynamic library lookup path. /// If the dylib_path_var is already set for this cmd, the old value will be overwritten! pub fn add_dylib_path(path: Vec, cmd: &mut BootstrapCommand) { - let mut list = dylib_path(); - for path in path { - list.insert(0, path); - } + let list = path.into_iter().rev().chain(dylib_path()); cmd.env(dylib_path_var(), t!(env::join_paths(list))); } @@ -156,7 +151,7 @@ pub fn move_file, Q: AsRef>(from: P, to: Q) -> io::Result<( } pub fn forcing_clang_based_tests() -> bool { - if let Some(var) = env::var_os("RUSTBUILD_FORCE_CLANG_BASED_TESTS") { + env::var_os("RUSTBUILD_FORCE_CLANG_BASED_TESTS").is_some_and(|var| { match &var.to_string_lossy().to_lowercase()[..] { "1" | "yes" | "on" => true, "0" | "no" | "off" => false, @@ -168,9 +163,7 @@ pub fn forcing_clang_based_tests() -> bool { ) } } - } else { - false - } + }) } pub fn use_host_linker(target: TargetSelection) -> bool { @@ -206,10 +199,7 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef>( builder: &Builder<'_>, ) -> Option<&'a str> { let suite_path = suite_path.as_ref(); - let path = match path.strip_prefix(".") { - Ok(p) => p, - Err(_) => path, - }; + let path = path.strip_prefix(".").unwrap_or(path); if !path.starts_with(suite_path) { return None; } @@ -227,20 +217,15 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef>( // Therefore, we need to filter these out, as only the first --test-args // flag is respected, so providing an empty --test-args conflicts with // any following it. - match path.strip_prefix(suite_path).ok().and_then(|p| p.to_str()) { - Some(s) if !s.is_empty() => Some(s), - _ => None, - } + path.strip_prefix(suite_path).ok().and_then(|p| p.to_str()).filter(|s| !s.is_empty()) } // FIXME: get rid of this function pub fn check_run(cmd: &mut BootstrapCommand, print_cmd_on_fail: bool) -> bool { - let status = match cmd.as_command_mut().status() { - Ok(status) => status, - Err(e) => { - println!("failed to execute command: {cmd:?}\nERROR: {e}"); - return false; - } + let Ok(status) = cmd.as_command_mut().status().inspect_err(|e| { + println!("failed to execute command: {cmd:?}\nERROR: {e}"); + }) else { + return false; }; if !status.success() && print_cmd_on_fail { println!( @@ -512,16 +497,15 @@ where pub fn check_cfg_arg(name: &str, values: Option<&[&str]>) -> String { // Creating a string of the values by concatenating each value: // ',values("tvos","watchos")' or '' (nothing) when there are no values. - let next = match values { - Some(values) => { + let next = values + .map(|values| { let mut tmp = values.iter().flat_map(|val| [",", "\"", val, "\""]).collect::(); tmp.insert_str(1, "values("); tmp.push(')'); tmp - } - None => "".to_string(), - }; + }) + .unwrap_or_default(); format!("--check-cfg=cfg({name}{next})") } diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs index 6b3e40b91150d..903b6d28db5ca 100644 --- a/src/tools/rustfmt/src/spanned.rs +++ b/src/tools/rustfmt/src/spanned.rs @@ -27,10 +27,10 @@ impl Spanned for source_map::Spanned { macro_rules! span_with_attrs_lo_hi { ($this:ident, $lo:expr, $hi:expr) => {{ let attrs = outer_attributes(&$this.attrs); - if attrs.is_empty() { - mk_sp($lo, $hi) + if let Some(attr) = attrs.first() { + mk_sp(attr.span.lo(), $hi) } else { - mk_sp(attrs[0].span.lo(), $hi) + mk_sp($lo, $hi) } }}; } @@ -68,10 +68,10 @@ impl Spanned for ast::Stmt { mk_sp(expr.span().lo(), self.span.hi()) } ast::StmtKind::MacCall(ref mac_stmt) => { - if mac_stmt.attrs.is_empty() { - self.span + if let Some(attr) = mac_stmt.attrs.first() { + mk_sp(attr.span.lo(), self.span.hi()) } else { - mk_sp(mac_stmt.attrs[0].span.lo(), self.span.hi()) + self.span } } ast::StmtKind::Empty => self.span, @@ -93,10 +93,10 @@ impl Spanned for ast::Ty { impl Spanned for ast::Arm { fn span(&self) -> Span { - let lo = if self.attrs.is_empty() { - self.pat.span.lo() + let lo = if let Some(attr) = self.attrs.first() { + attr.span.lo() } else { - self.attrs[0].span.lo() + self.pat.span.lo() }; let hi = if let Some(body) = &self.body { body.span.hi() @@ -119,15 +119,15 @@ impl Spanned for ast::Param { impl Spanned for ast::GenericParam { fn span(&self) -> Span { - let lo = match self.kind { - _ if !self.attrs.is_empty() => self.attrs[0].span.lo(), - ast::GenericParamKind::Const { kw_span, .. } => kw_span.lo(), + let lo = match (&self.kind, self.attrs.first()) { + (_, Some(attr)) => attr.span.lo(), + (ast::GenericParamKind::Const { kw_span, .. }, _) => kw_span.lo(), _ => self.ident.span.lo(), }; - let hi = if self.bounds.is_empty() { - self.ident.span.hi() + let hi = if let Some(bound) = self.bounds.last() { + bound.span().hi() } else { - self.bounds.last().unwrap().span().hi() + self.ident.span.hi() }; let ty_hi = if let ast::GenericParamKind::Type { default: Some(ref ty),