diff --git a/.mailmap b/.mailmap index c29f6a66f5d7d..fa30f07ad7310 100644 --- a/.mailmap +++ b/.mailmap @@ -260,6 +260,7 @@ Grzegorz Bartoszek Guanqun Lu Guillaume Gomez Guillaume Gomez Guillaume Gomez +Guillaume Gomez ggomez Guillaume Gomez ggomez Guillaume Gomez Guillaume Gomez Guillaume Gomez Guillaume Gomez diff --git a/compiler/rustc_attr_parsing/src/attributes/autodiff.rs b/compiler/rustc_attr_parsing/src/attributes/autodiff.rs index 34fd7c8e7f046..dc63767462201 100644 --- a/compiler/rustc_attr_parsing/src/attributes/autodiff.rs +++ b/compiler/rustc_attr_parsing/src/attributes/autodiff.rs @@ -52,10 +52,7 @@ impl SingleAttributeParser for RustcAutodiffParser { cx.adcx().expected_identifier(mode.span()); return None; }; - let Ok(()) = mode.args().no_args() else { - cx.adcx().expected_identifier(mode.span()); - return None; - }; + cx.expect_no_args(mode.args())?; let Some(mode) = mode.path().word() else { cx.adcx().expected_identifier(mode.span()); return None; @@ -85,11 +82,7 @@ impl SingleAttributeParser for RustcAutodiffParser { .expected_specific_argument(activity.span(), DiffActivity::all_activities()); return None; }; - let Ok(()) = activity.args().no_args() else { - cx.adcx() - .expected_specific_argument(activity.span(), DiffActivity::all_activities()); - return None; - }; + cx.expect_no_args(activity.args())?; let Some(activity) = activity.path().word() else { cx.adcx() .expected_specific_argument(activity.span(), DiffActivity::all_activities()); diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index a6cf25330b557..2651d97cf63e0 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -195,10 +195,9 @@ pub(crate) struct NakedParser { impl AttributeParser for NakedParser { const ATTRIBUTES: AcceptMapping = &[(&[sym::naked], template!(Word), |this, cx, args| { - if let Err(span) = args.no_args() { - cx.adcx().expected_no_args(span); + let Some(()) = cx.expect_no_args(args) else { return; - } + }; if let Some(earlier) = this.span { let span = cx.attr_span; diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs index 070b0e385b024..75c777f1a9c4e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs +++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs @@ -294,11 +294,9 @@ impl CombineAttributeParser for FeatureParser { cx.adcx().expected_identifier(elem.span()); continue; }; - if let Err(arg_span) = elem.args().no_args() { - cx.adcx().expected_no_args(arg_span); + let Some(()) = cx.expect_no_args(elem.args()) else { continue; - } - + }; let path = elem.path(); let Some(ident) = path.word() else { cx.adcx().expected_identifier(path.span()); @@ -340,10 +338,9 @@ impl CombineAttributeParser for RegisterToolParser { cx.adcx().expected_identifier(elem.span()); continue; }; - if let Err(arg_span) = elem.args().no_args() { - cx.adcx().expected_no_args(arg_span); + let Some(()) = cx.expect_no_args(elem.args()) else { continue; - } + }; let path = elem.path(); let Some(ident) = path.word() else { diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs index 816d51a6ba395..9b4ffc7ea27f6 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs @@ -3,8 +3,8 @@ use std::ops::Range; use rustc_errors::E0232; use rustc_hir::AttrPath; use rustc_hir::attrs::diagnostic::{ - Directive, FilterFormatString, Flag, FormatArg, FormatString, LitOrArg, Name, NameValue, - OnUnimplementedCondition, Piece, Predicate, + Directive, Filter, FilterFormatString, Flag, FormatArg, FormatString, LitOrArg, Name, + NameValue, Piece, Predicate, }; use rustc_macros::Diagnostic; use rustc_parse_format::{ @@ -201,12 +201,11 @@ fn parse_directive_items<'p>( items: impl Iterator, is_root: bool, ) -> Option { - let condition = None; let mut message: Option<(Span, _)> = None; let mut label: Option<(Span, _)> = None; let mut notes = ThinVec::new(); let mut parent_label = None; - let mut subcommands = ThinVec::new(); + let mut filters = ThinVec::new(); for item in items { let span = item.span(); @@ -330,7 +329,7 @@ fn parse_directive_items<'p>( if is_root { let items = or_malformed!(item.args().as_list()?); let mut iter = items.mixed(); - let condition: &MetaItemOrLitParser = match iter.next() { + let filter: &MetaItemOrLitParser = match iter.next() { Some(c) => c, None => { cx.emit_err(InvalidOnClause::Empty { span }); @@ -338,21 +337,19 @@ fn parse_directive_items<'p>( } }; - let condition = parse_condition(condition); + let filter = parse_filter(filter); if items.len() < 2 { // Something like `#[rustc_on_unimplemented(on(.., /* nothing */))]` - // There's a condition but no directive behind it, this is a mistake. + // There's a filter but no directive behind it, this is a mistake. malformed!(); } - let mut directive = - or_malformed!(parse_directive_items(cx, mode, iter, false)?); - - match condition { - Ok(c) => { - directive.condition = Some(c); - subcommands.push(directive); + match filter { + Ok(filter) => { + let directive = + or_malformed!(parse_directive_items(cx, mode, iter, false)?); + filters.push((filter, directive)); } Err(e) => { cx.emit_err(e); @@ -371,8 +368,7 @@ fn parse_directive_items<'p>( Some(Directive { is_rustc_attr: matches!(mode, Mode::RustcOnUnimplemented), - condition, - subcommands, + filters, message, label, notes, @@ -513,12 +509,10 @@ fn slice_span(input: Span, Range { start, end }: Range, is_source_literal if is_source_literal { input.from_inner(InnerSpan { start, end }) } else { input } } -pub(crate) fn parse_condition( - input: &MetaItemOrLitParser, -) -> Result { +pub(crate) fn parse_filter(input: &MetaItemOrLitParser) -> Result { let span = input.span(); let pred = parse_predicate(input)?; - Ok(OnUnimplementedCondition { span, pred }) + Ok(Filter { span, pred }) } fn parse_predicate(input: &MetaItemOrLitParser) -> Result { @@ -553,7 +547,7 @@ fn parse_predicate(input: &MetaItemOrLitParser) -> Result Name { } } -fn parse_filter(input: Symbol) -> FilterFormatString { +fn parse_filter_format(input: Symbol) -> FilterFormatString { let pieces = Parser::new(input.as_str(), None, None, false, ParseMode::Diagnostic) .map(|p| match p { RpfPiece::Lit(s) => LitOrArg::Lit(Symbol::intern(s)), diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index 63c86f3ee9ef6..10232a7c55a5f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -150,7 +150,7 @@ impl DocParser { match path.word_sym() { Some(sym::no_crate_inject) => { - if let Err(span) = args.no_args() { + if let Err(span) = args.as_no_args() { expected_no_args(cx, span); return; } @@ -280,7 +280,7 @@ impl DocParser { args: &ArgParser, inline: DocInline, ) { - if let Err(span) = args.no_args() { + if let Err(span) = args.as_no_args() { expected_no_args(cx, span); return; } @@ -426,7 +426,7 @@ impl DocParser { macro_rules! no_args { ($ident: ident) => {{ - if let Err(span) = args.no_args() { + if let Err(span) = args.as_no_args() { expected_no_args(cx, span); return; } @@ -445,7 +445,7 @@ impl DocParser { } macro_rules! no_args_and_not_crate_level { ($ident: ident) => {{ - if let Err(span) = args.no_args() { + if let Err(span) = args.as_no_args() { expected_no_args(cx, span); return; } @@ -461,7 +461,7 @@ impl DocParser { no_args_and_crate_level!($ident, |span| {}); }}; ($ident: ident, |$span:ident| $extra_validation:block) => {{ - if let Err(span) = args.no_args() { + if let Err(span) = args.as_no_args() { expected_no_args(cx, span); return; } diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs index 36ee18d5bbe8d..80555053174f7 100644 --- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs @@ -86,10 +86,9 @@ impl AttributeParser for MacroUseParser { cx.adcx().expected_identifier(item.span()); continue; }; - if let Err(err_span) = item.args().no_args() { - cx.adcx().expected_no_args(err_span); + let Some(()) = cx.expect_no_args(item.args()) else { continue; - } + }; let Some(item) = item.path().word() else { cx.adcx().expected_identifier(item.span()); continue; @@ -179,9 +178,7 @@ impl SingleAttributeParser for CollapseDebugInfoParser { cx.adcx().expected_not_literal(single.span()); return None; }; - if let Err(err) = mi.args().no_args() { - cx.adcx().expected_no_args(err); - } + let _ = cx.expect_no_args(mi.args()); let path = mi.path().word_sym(); let info = match path { Some(sym::yes) => CollapseMacroDebuginfo::Yes, diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index af90bd0fe58cc..42c6828ef57b7 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -258,9 +258,7 @@ impl SingleAttributeParser for WithoutArgs { const TEMPLATE: AttributeTemplate = template!(Word); fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { - if let Err(span) = args.no_args() { - cx.adcx().expected_no_args(span); - } + let _ = cx.expect_no_args(args); Some(T::CREATE(cx.attr_span)) } } diff --git a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs index 88253041ed6e0..d7bc60153f269 100644 --- a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs @@ -58,7 +58,7 @@ fn parse_derive_like( ) -> Option<(Option, ThinVec)> { let Some(list) = args.as_list() else { // For #[rustc_builtin_macro], it is permitted to leave out the trait name - if args.no_args().is_ok() && !trait_name_mandatory { + if args.as_no_args().is_ok() && !trait_name_mandatory { return Some((None, ThinVec::new())); } let attr_span = cx.attr_span; @@ -84,10 +84,7 @@ fn parse_derive_like( cx.adcx().expected_identifier(trait_ident.span); return None; } - if let Err(e) = trait_attr.args().no_args() { - cx.adcx().expected_no_args(e); - return None; - }; + cx.expect_no_args(trait_attr.args())?; // Parse optional attributes let mut attributes = ThinVec::new(); @@ -108,10 +105,7 @@ fn parse_derive_like( cx.adcx().expected_identifier(attr.span()); return None; }; - if let Err(e) = attr.args().no_args() { - cx.adcx().expected_no_args(e); - return None; - }; + cx.expect_no_args(attr.args())?; let Some(ident) = attr.path().word() else { cx.adcx().expected_identifier(attr.path().span()); return None; diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs index 1158f1c5acf4c..8d507065dbdb6 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs @@ -36,10 +36,7 @@ impl SingleAttributeParser for RustcDumpDefPathParser { ]); const TEMPLATE: AttributeTemplate = template!(Word); fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { - if let Err(span) = args.no_args() { - cx.adcx().expected_no_args(span); - return None; - } + cx.expect_no_args(args)?; Some(AttributeKind::RustcDumpDefPath(cx.attr_span)) } } @@ -203,10 +200,7 @@ impl SingleAttributeParser for RustcDumpSymbolNameParser { ]); const TEMPLATE: AttributeTemplate = template!(Word); fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { - if let Err(span) = args.no_args() { - cx.adcx().expected_no_args(span); - return None; - } + cx.expect_no_args(args)?; Some(AttributeKind::RustcDumpSymbolName(cx.attr_span)) } } diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 835af97358ac4..697d3f8cc2a23 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -555,7 +555,7 @@ impl SingleAttributeParser for RustcScalableVectorParser { const TEMPLATE: AttributeTemplate = template!(Word, List: &["count"]); fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { - if args.no_args().is_ok() { + if args.as_no_args().is_ok() { return Some(AttributeKind::RustcScalableVector { element_count: None, span: cx.attr_span, diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index 4ed10b0ff1ac3..89f5e3747c1d6 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -30,7 +30,7 @@ impl SingleAttributeParser for IgnoreParser { ArgParser::List(list) => { let help = list.as_single().and_then(|item| item.meta_item()).and_then(|item| { - item.args().no_args().ok()?; + item.args().as_no_args().ok()?; Some(item.path().to_string()) }); cx.adcx().warn_ill_formed_attribute_input_with_help( diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs index 546bb0364bddc..fe5af66f2a9cb 100644 --- a/compiler/rustc_attr_parsing/src/attributes/traits.rs +++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs @@ -27,9 +27,7 @@ impl SingleAttributeParser for RustcSkipDuringMethodDispatchParser { cx.adcx().expected_not_literal(arg.span()); continue; }; - if let Err(span) = arg.args().no_args() { - cx.adcx().expected_no_args(span); - } + let _ = cx.expect_no_args(arg.args()); let path = arg.path(); let (key, skip): (Symbol, &mut bool) = match path.word_sym() { Some(key @ sym::array) => (key, &mut array), diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 9c82e6208c24c..9fc7c3c8f1320 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -562,6 +562,16 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> { { arg.expect_name_value(self, span, name) } + + /// Assert that an [`ArgParser`] has no args, or emits an error and return `None`. + pub(crate) fn expect_no_args<'arg>(&mut self, arg: &'arg ArgParser) -> Option<()> { + if let Err(span) = arg.as_no_args() { + self.adcx().expected_no_args(span); + return None; + } + + Some(()) + } } pub(crate) trait ExpectNameValue { diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index de505cc8c7ac8..845f1394cc3de 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -202,7 +202,7 @@ impl ArgParser { /// Assert that there were no args. /// If there were, get a span to the arguments /// (to pass to [`AttributeDiagnosticContext::expected_no_args`](crate::context::AttributeDiagnosticContext::expected_no_args)). - pub fn no_args(&self) -> Result<(), Span> { + pub fn as_no_args(&self) -> Result<(), Span> { match self { Self::NoArgs => Ok(()), Self::List(args) => Err(args.span), diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index f7d35f3ff3b4b..86184e913262e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -47,7 +47,6 @@ use super::{DescribePlaceOpt, RegionName, RegionNameSource, UseSpans}; use crate::borrow_set::{BorrowData, TwoPhaseActivation}; use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead; use crate::diagnostics::{CapturedMessageOpt, call_kind, find_all_local_uses}; -use crate::prefixes::IsPrefixOf; use crate::{InitializationRequiringAction, MirBorrowckCtxt, WriteKind, borrowck_errors}; #[derive(Debug)] diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs index 9e51264d8edcb..7ac63e02e318d 100644 --- a/compiler/rustc_borrowck/src/prefixes.rs +++ b/compiler/rustc_borrowck/src/prefixes.rs @@ -8,18 +8,6 @@ use rustc_middle::mir::{PlaceRef, ProjectionElem}; use super::MirBorrowckCtxt; -pub(crate) trait IsPrefixOf<'tcx> { - fn is_prefix_of(&self, other: PlaceRef<'tcx>) -> bool; -} - -impl<'tcx> IsPrefixOf<'tcx> for PlaceRef<'tcx> { - fn is_prefix_of(&self, other: PlaceRef<'tcx>) -> bool { - self.local == other.local - && self.projection.len() <= other.projection.len() - && self.projection == &other.projection[..self.projection.len()] - } -} - pub(super) struct Prefixes<'tcx> { kind: PrefixSet, next: Option>, diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index c1fed1260340f..6a0d70790cfef 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -426,19 +426,13 @@ impl ToElementIndex<'_> for RegionVid { } impl<'tcx> ToElementIndex<'tcx> for ty::PlaceholderRegion<'tcx> { - fn add_to_row(self, values: &mut RegionValues<'tcx, N>, row: N) -> bool - where - Self: Into>, - { + fn add_to_row(self, values: &mut RegionValues<'tcx, N>, row: N) -> bool { let placeholder: ty::PlaceholderRegion<'tcx> = self.into(); let index = values.placeholder_indices.lookup_index(placeholder); values.placeholders.insert(row, index) } - fn contained_in_row(self, values: &RegionValues<'tcx, N>, row: N) -> bool - where - Self: Into>, - { + fn contained_in_row(self, values: &RegionValues<'tcx, N>, row: N) -> bool { let placeholder: ty::PlaceholderRegion<'tcx> = self.into(); let index = values.placeholder_indices.lookup_index(placeholder); values.placeholders.contains(row, index) diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 2e6a2962b8760..64c5f5f0c560b 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -176,7 +176,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } // In MIR, argument N is stored in local N+1. - let local = Local::from_usize(argument_index + 1); + let local = Local::arg(argument_index); let mir_input_ty = self.body.local_decls[local].ty; diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 2967db9df787c..55001d85211a4 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -522,7 +522,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if self.fn_abi.c_variadic { // The `VaList` "spoofed" argument is just after all the real arguments. let va_list_arg_idx = self.fn_abi.args.len(); - match self.locals[mir::Local::from_usize(1 + va_list_arg_idx)] { + match self.locals[mir::Local::arg(va_list_arg_idx)] { LocalRef::Place(va_list) => { bx.va_end(va_list.val.llval); diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index bbcda7bce2177..0111080bc2ee4 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -268,10 +268,7 @@ pub fn fluent_value_from_str_list_sep_by_and(l: Vec>) -> FluentValu type Args = (); type Error = (); - fn construct(lang: LanguageIdentifier, _args: Self::Args) -> Result - where - Self: Sized, - { + fn construct(lang: LanguageIdentifier, _args: Self::Args) -> Result { let locale = icu_locale_from_unic_langid(lang) .unwrap_or_else(|| rustc_baked_icu_data::supported_locales::EN); let list_formatter = icu_list::ListFormatter::try_new_and_unstable( diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 377d96b73e9b8..2fbb90b770261 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -143,10 +143,7 @@ impl<'a, F: FnOnce(&mut Diag<'_, ()>)> Diagnostic<'a, ()> for DiagDecorator { /// Trait implemented by error types. This should not be implemented manually. Instead, use /// `#[derive(Subdiagnostic)]` -- see [rustc_macros::Subdiagnostic]. #[rustc_diagnostic_item = "Subdiagnostic"] -pub trait Subdiagnostic -where - Self: Sized, -{ +pub trait Subdiagnostic { /// Add a subdiagnostic to an existing diagnostic. fn add_to_diag(self, diag: &mut Diag<'_, G>); } diff --git a/compiler/rustc_hir/src/attrs/diagnostic.rs b/compiler/rustc_hir/src/attrs/diagnostic.rs index 9d38125c678b9..7a833a06a7eb6 100644 --- a/compiler/rustc_hir/src/attrs/diagnostic.rs +++ b/compiler/rustc_hir/src/attrs/diagnostic.rs @@ -2,7 +2,6 @@ use std::fmt; use std::fmt::Debug; -pub use rustc_ast::attr::data_structures::*; use rustc_macros::{Decodable, Encodable, HashStable, PrintAttribute}; use rustc_span::{DesugaringKind, Span, Symbol, kw}; use thin_vec::ThinVec; @@ -13,8 +12,9 @@ use crate::attrs::PrintAttribute; #[derive(Clone, Default, Debug, HashStable, Encodable, Decodable, PrintAttribute)] pub struct Directive { pub is_rustc_attr: bool, - pub condition: Option, - pub subcommands: ThinVec, + /// This is never nested more than once, i.e. the directives in this + /// thinvec have no filters of their own. + pub filters: ThinVec<(Filter, Directive)>, pub message: Option<(Span, FormatString)>, pub label: Option<(Span, FormatString)>, pub notes: ThinVec, @@ -28,11 +28,8 @@ impl Directive { /// We can't check this while parsing the attribute because `rustc_attr_parsing` doesn't have /// access to the item an attribute is on. Instead we later call this function in `check_attr`. pub fn visit_params(&self, visit: &mut impl FnMut(Symbol, Span)) { - if let Some(condition) = &self.condition { - condition.visit_params(visit); - } - - for subcommand in &self.subcommands { + for (filter, subcommand) in &self.filters { + filter.visit_params(visit); subcommand.visit_params(visit); } @@ -54,61 +51,33 @@ impl Directive { pub fn eval( &self, - condition_options: Option<&ConditionOptions>, + filter_options: Option<&FilterOptions>, args: &FormatArgs, ) -> CustomDiagnostic { let this = &args.this; debug!( - "Directive::eval({self:?}, this={this}, options={condition_options:?}, args ={args:?})" + "Directive::eval({self:?}, this={this}, options={filter_options:?}, args ={args:?})" ); - let Some(condition_options) = condition_options else { + let mut ret = CustomDiagnostic::default(); + + if let Some(filter_options) = filter_options { + for (filter, directive) in &self.filters { + if filter.matches_predicate(filter_options) { + debug!("eval: {filter:?} succeeded"); + ret.update(directive, args); + } else { + debug!("eval: skipping {filter:?} due to {filter_options:?}"); + } + } + } else { debug_assert!( !self.is_rustc_attr, - "Directive::eval called for `rustc_on_unimplemented` without `condition_options`" + "Directive::eval called for `rustc_on_unimplemented` without `filter_options`" ); - return CustomDiagnostic { - label: self.label.as_ref().map(|l| l.1.format(args)), - message: self.message.as_ref().map(|m| m.1.format(args)), - notes: self.notes.iter().map(|n| n.format(args)).collect(), - parent_label: None, - }; }; - let mut message = None; - let mut label = None; - let mut notes = Vec::new(); - let mut parent_label = None; - - for command in self.subcommands.iter().chain(Some(self)).rev() { - debug!(?command); - if let Some(ref condition) = command.condition - && !condition.matches_predicate(condition_options) - { - debug!("eval: skipping {command:?} due to condition"); - continue; - } - debug!("eval: {command:?} succeeded"); - if let Some(ref message_) = command.message { - message = Some(message_.clone()); - } - - if let Some(ref label_) = command.label { - label = Some(label_.clone()); - } - - notes.extend(command.notes.clone()); - - if let Some(ref parent_label_) = command.parent_label { - parent_label = Some(parent_label_.clone()); - } - } - - CustomDiagnostic { - label: label.map(|l| l.1.format(args)), - message: message.map(|m| m.1.format(args)), - notes: notes.into_iter().map(|n| n.format(args)).collect(), - parent_label: parent_label.map(|e_s| e_s.format(args)), - } + ret.update(self, args); + ret } } @@ -121,6 +90,22 @@ pub struct CustomDiagnostic { pub parent_label: Option, } +impl CustomDiagnostic { + fn update(&mut self, di: &Directive, args: &FormatArgs) { + if self.message.is_none() { + self.message = di.message.as_ref().map(|m| m.1.format(args)); + } + if self.label.is_none() { + self.label = di.label.as_ref().map(|l| l.1.format(args)); + } + if self.parent_label.is_none() { + self.parent_label = di.parent_label.as_ref().map(|p| p.format(args)); + } + + self.notes.extend(di.notes.iter().map(|n| n.format(args))) + } +} + /// Like [std::fmt::Arguments] this is a string that has been parsed into "pieces", /// either as string pieces or dynamic arguments. #[derive(Clone, Debug, HashStable, Encodable, Decodable, PrintAttribute)] @@ -252,12 +237,12 @@ pub enum FormatArg { /// Represents the `on` filter in `#[rustc_on_unimplemented]`. #[derive(Clone, Debug, HashStable, Encodable, Decodable, PrintAttribute)] -pub struct OnUnimplementedCondition { +pub struct Filter { pub span: Span, pub pred: Predicate, } -impl OnUnimplementedCondition { - pub fn matches_predicate(self: &OnUnimplementedCondition, options: &ConditionOptions) -> bool { +impl Filter { + pub fn matches_predicate(&self, options: &FilterOptions) -> bool { self.pred.eval(&mut |p| match p { FlagOrNv::Flag(b) => options.has_flag(*b), FlagOrNv::NameValue(NameValue { name, value }) => { @@ -272,7 +257,7 @@ impl OnUnimplementedCondition { } } -/// Predicate(s) in `#[rustc_on_unimplemented]`'s `on` filter. See [`OnUnimplementedCondition`]. +/// Predicate(s) in `#[rustc_on_unimplemented]`'s `on` filter. See [`Filter`]. /// /// It is similar to the predicate in the `cfg` attribute, /// and may contain nested predicates. @@ -406,8 +391,7 @@ pub enum LitOrArg { Arg(Symbol), } -/// Used with `OnUnimplementedCondition::matches_predicate` to evaluate the -/// [`OnUnimplementedCondition`]. +/// Used with `Filter::matches_predicate` to evaluate the [`Filter`]. /// /// For example, given a /// ```rust,ignore (just an example) @@ -433,7 +417,7 @@ pub enum LitOrArg { /// it will look like this: /// /// ```rust,ignore (just an example) -/// ConditionOptions { +/// FilterOptions { /// self_types: ["u32", "{integral}"], /// from_desugaring: Some("QuestionMark"), /// cause: None, @@ -446,7 +430,7 @@ pub enum LitOrArg { /// } /// ``` #[derive(Debug)] -pub struct ConditionOptions { +pub struct FilterOptions { /// All the self types that may apply. pub self_types: Vec, // The kind of compiler desugaring. @@ -460,7 +444,7 @@ pub struct ConditionOptions { pub generic_args: Vec<(Symbol, String)>, } -impl ConditionOptions { +impl FilterOptions { pub fn has_flag(&self, name: Flag) -> bool { match name { Flag::CrateLocal => self.crate_local, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index e93059f752223..68d8c12ec099c 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -71,11 +71,6 @@ use rustc_span::{Ident, Span, Symbol}; use crate::hir::*; -pub trait IntoVisitor<'hir> { - type Visitor: Visitor<'hir>; - fn into_visitor(&self) -> Self::Visitor; -} - #[derive(Copy, Clone, Debug)] pub enum FnKind<'a> { /// `#[xxx] pub async/const/extern "Abi" fn foo()` diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 3ce363e1e9c7e..4dfbbc6c6350c 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -211,8 +211,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> { let diverging_roots: UnordSet = self .diverging_type_vars .borrow() - .items() - .map(|&ty| self.shallow_resolve(ty)) + .iter() + .map(|&ty_id| self.shallow_resolve(Ty::new_var(self.tcx, ty_id))) .filter_map(|ty| ty.ty_vid()) .map(|vid| self.root_var(vid)) .collect(); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 9a54d651fe73a..360236f048dec 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -321,8 +321,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for a in &adj { match a.kind { Adjust::NeverToAny => { - if a.target.is_ty_var() { - self.diverging_type_vars.borrow_mut().insert(a.target); + if let ty::Infer(ty::TyVar(a_id)) = a.target.kind() { + self.diverging_type_vars.borrow_mut().push(*a_id); debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target); } } diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs index ff2fc66e1d477..e4dcead1f7954 100644 --- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs +++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs @@ -1,12 +1,11 @@ use std::cell::{Cell, RefCell}; use std::ops::Deref; -use rustc_data_structures::unord::UnordSet; use rustc_hir::def_id::LocalDefId; use rustc_hir::{self as hir, HirId, HirIdMap}; use rustc_infer::infer::{InferCtxt, InferOk, OpaqueTypeStorageEntries, TyCtxtInferExt}; use rustc_middle::span_bug; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode}; +use rustc_middle::ty::{self, Ty, TyCtxt, TyVid, TypeVisitableExt, TypingMode}; use rustc_span::Span; use rustc_span::def_id::LocalDefIdMap; use rustc_trait_selection::traits::{self, FulfillmentError, TraitEngine, TraitEngineExt as _}; @@ -66,7 +65,7 @@ pub(crate) struct TypeckRootCtxt<'tcx> { /// Whenever we introduce an adjustment from `!` into a type variable, /// we record that type variable here. This is later used to inform /// fallback. See the `fallback` module for details. - pub(super) diverging_type_vars: RefCell>>, + pub(super) diverging_type_vars: RefCell>, } impl<'tcx> Deref for TypeckRootCtxt<'tcx> { diff --git a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs index 19212c99ae43b..a10026f2f77c7 100644 --- a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs +++ b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs @@ -126,7 +126,6 @@ where fn extend(&mut self, undos: J) where - Self: Sized, J: IntoIterator, { if self.in_snapshot() { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index d5795e64089bc..9485f08bb2837 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -845,6 +845,16 @@ rustc_index::newtype_index! { } } +impl Local { + /// Makes a `Local` for the `i`-th argument to a function. + /// + /// `Local(0)` is the [`RETURN_PLACE`], with the arguments after that, + /// so `arg(i)` will give `Local(i + 1)`. + pub const fn arg(i: usize) -> Local { + Local::from_usize(i + 1) + } +} + impl Atom for Local { fn index(self) -> usize { Idx::index(self) diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index c55d49c12b4b8..02bbcf1c9e6cb 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -478,6 +478,12 @@ impl From for Place<'_> { } impl<'tcx> PlaceRef<'tcx> { + pub fn is_prefix_of(&self, other: PlaceRef<'tcx>) -> bool { + self.local == other.local + && self.projection.len() <= other.projection.len() + && self.projection == &other.projection[..self.projection.len()] + } + /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or /// a single deref of a local. pub fn local_or_deref_local(&self) -> Option { diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index ce6f87668beff..e8d5f1a912d21 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -17,7 +17,7 @@ use crate::{mir, ty}; /// Captures are represented using fields inside a structure. /// This represents accessing self in the closure structure -pub const CAPTURE_STRUCT_LOCAL: mir::Local = mir::Local::from_u32(1); +pub const CAPTURE_STRUCT_LOCAL: mir::Local = mir::Local::arg(0); #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] #[derive(TypeFoldable, TypeVisitable)] diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 8e51ab7d4edb1..5a33963b2b654 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -1068,7 +1068,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Bind the argument patterns for (index, param) in arguments.iter().enumerate() { // Function arguments always get the first Local indices after the return place - let local = Local::new(index + 1); + let local = Local::arg(index); let place = Place::from(local); // Make sure we drop (parts of) the argument even when not matched on. diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 652fd00d54d02..807fe771d0ea2 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -168,8 +168,8 @@ fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtx tracing::trace!(?place); } -const SELF_ARG: Local = Local::from_u32(1); -const CTX_ARG: Local = Local::from_u32(2); +const SELF_ARG: Local = Local::arg(0); +const CTX_ARG: Local = Local::arg(1); /// A `yield` point in the coroutine. struct SuspensionPoint<'tcx> { diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 89423bf885c84..39d5eef844559 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -358,8 +358,8 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) let mut body = new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span); - // The first argument (index 0), but add 1 for the return value. - let dropee_ptr = Place::from(Local::new(1 + 0)); + // The first argument (index 0), but local 1 (after the return place). + let dropee_ptr = Place::from(Local::arg(0)); let dropee_ptr = dropee_emit_retag(tcx, &mut body, dropee_ptr, span); if ty.is_some() { @@ -538,7 +538,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) - let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty); let dest = Place::return_place(); - let src = tcx.mk_place_deref(Place::from(Local::new(1 + 0))); + let src = tcx.mk_place_deref(Place::from(Local::arg(0))); match self_ty.kind() { ty::FnDef(..) | ty::FnPtr(..) => builder.copy_shim(), @@ -624,7 +624,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { } fn copy_shim(&mut self) { - let rcvr = self.tcx.mk_place_deref(Place::from(Local::new(1 + 0))); + let rcvr = self.tcx.mk_place_deref(Place::from(Local::arg(0))); let ret_statement = self.make_statement(StatementKind::Assign(Box::new(( Place::return_place(), Rvalue::Use(Operand::Copy(rcvr)), @@ -879,7 +879,7 @@ fn build_call_shim<'tcx>( let rcvr_place = || { assert!(rcvr_adjustment.is_some()); - Place::from(Local::new(1)) + Place::from(Local::arg(0)) }; let mut statements = vec![]; @@ -938,11 +938,11 @@ fn build_call_shim<'tcx>( } // Pass all of the non-special arguments directly. - args.extend(arg_range.map(|i| Operand::Move(Place::from(Local::new(1 + i))))); + args.extend(arg_range.map(|i| Operand::Move(Place::from(Local::arg(i))))); // Untuple the last argument, if we have to. if let Some(untuple_args) = untuple_args { - let tuple_arg = Local::new(1 + (sig.inputs().len() - 1)); + let tuple_arg = Local::arg(sig.inputs().len() - 1); args.extend(untuple_args.iter().enumerate().map(|(i, ity)| { Operand::Move(tcx.mk_place_field(Place::from(tuple_arg), FieldIdx::new(i), *ity)) })); @@ -1074,7 +1074,7 @@ pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { Rvalue::Aggregate( Box::new(kind), (0..variant.fields.len()) - .map(|idx| Operand::Move(Place::from(Local::new(idx + 1)))) + .map(|idx| Operand::Move(Place::from(Local::arg(idx)))) .collect(), ), ))), @@ -1125,7 +1125,7 @@ fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'t // provenance. let rvalue = Rvalue::Cast( CastKind::FnPtrToPtr, - Operand::Move(Place::from(Local::new(1))), + Operand::Move(Place::from(Local::arg(0))), Ty::new_imm_ptr(tcx, tcx.types.unit), ); let stmt = Statement::new( @@ -1148,7 +1148,7 @@ fn build_construct_coroutine_by_move_shim<'tcx>( receiver_by_ref: bool, ) -> Body<'tcx> { let mut self_ty = tcx.type_of(coroutine_closure_def_id).instantiate_identity().skip_norm_wip(); - let mut self_local: Place<'tcx> = Local::from_usize(1).into(); + let mut self_local: Place<'tcx> = Local::arg(0).into(); let ty::CoroutineClosure(_, args) = *self_ty.kind() else { bug!(); }; @@ -1190,7 +1190,7 @@ fn build_construct_coroutine_by_move_shim<'tcx>( // Move all of the closure args. for idx in 1..sig.inputs().len() { - fields.push(Operand::Move(Local::from_usize(idx + 1).into())); + fields.push(Operand::Move(Local::arg(idx).into())); } for (idx, ty) in args.as_coroutine_closure().upvar_tys().iter().enumerate() { diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index 5038afffcd8d2..0897aecb17e0a 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -74,8 +74,8 @@ pub(super) fn build_async_drop_shim<'tcx>( let span = tcx.def_span(def_id); let source_info = SourceInfo::outermost(span); - // The first argument (index 0), but add 1 for the return value. - let coroutine_layout = Place::from(Local::new(1 + 0)); + // The first argument (index 0) which will be local 1 (after the return value). + let coroutine_layout = Place::from(Local::arg(0)); let coroutine_layout_dropee = tcx.mk_place_field(coroutine_layout, FieldIdx::new(0), drop_ptr_ty); diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs index 91e040d5cbc89..5d0008f9e7472 100644 --- a/compiler/rustc_mir_transform/src/single_use_consts.rs +++ b/compiler/rustc_mir_transform/src/single_use_consts.rs @@ -35,7 +35,7 @@ impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts { locals_in_debug_info: DenseBitSet::new_empty(body.local_decls.len()), }; - finder.ineligible_locals.insert_range(..=Local::from_usize(body.arg_count)); + finder.ineligible_locals.insert_range(..Local::arg(body.arg_count)); finder.visit_body(body); diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index f9ab5f3551221..0fe20e6a46acc 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -87,7 +87,7 @@ fn escaping_locals<'tcx>( }; let mut set = DenseBitSet::new_empty(body.local_decls.len()); - set.insert_range(RETURN_PLACE..=Local::from_usize(body.arg_count)); + set.insert_range(RETURN_PLACE..Local::arg(body.arg_count)); for (local, decl) in body.local_decls().iter_enumerated() { if excluded.contains(local) || is_excluded_ty(decl.ty) { set.insert(local); diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 059bf47c579c8..e1883e7df815e 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -25,9 +25,6 @@ pub use rustc_index::{Idx, IndexVec}; // re-exported to avoid rustc_index versio use crate::constructor::{Constructor, ConstructorSet, IntRange}; use crate::pat::DeconstructedPat; -pub trait Captures<'a> {} -impl<'a, T: ?Sized> Captures<'a> for T {} - /// `bool` newtype that indicates whether this is a privately uninhabited field that we should skip /// during analysis. #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index a65e612b93e9c..b15f528b7261e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -1,7 +1,7 @@ use std::path::PathBuf; use rustc_hir as hir; -use rustc_hir::attrs::diagnostic::{ConditionOptions, CustomDiagnostic, FormatArgs}; +use rustc_hir::attrs::diagnostic::{CustomDiagnostic, FilterOptions, FormatArgs}; use rustc_hir::def_id::LocalDefId; use rustc_hir::find_attr; use rustc_middle::ty::print::PrintTraitRefExt; @@ -40,11 +40,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if trait_pred.polarity() != ty::PredicatePolarity::Positive { return CustomDiagnostic::default(); } - let (condition_options, format_args) = + let (filter_options, format_args) = self.on_unimplemented_components(trait_pred, obligation, long_ty_path); if let Some(command) = find_attr!(self.tcx, trait_pred.def_id(), OnUnimplemented {directive, ..} => directive.as_deref()).flatten() { command.eval( - Some(&condition_options), + Some(&filter_options), &format_args, ) } else { @@ -57,7 +57,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { trait_pred: ty::PolyTraitPredicate<'tcx>, obligation: &PredicateObligation<'tcx>, long_ty_path: &mut Option, - ) -> (ConditionOptions, FormatArgs) { + ) -> (FilterOptions, FormatArgs) { let (def_id, args) = (trait_pred.def_id(), trait_pred.skip_binder().trait_ref.args); let trait_pred = trait_pred.skip_binder(); @@ -219,14 +219,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let this = self.tcx.def_path_str(trait_pred.trait_ref.def_id); let this_sugared = trait_pred.trait_ref.print_trait_sugared().to_string(); - let condition_options = ConditionOptions { - self_types, - from_desugaring, - cause, - crate_local, - direct, - generic_args, - }; + let filter_options = + FilterOptions { self_types, from_desugaring, cause, crate_local, direct, generic_args }; // Unlike the generic_args earlier, // this one is *not* collected under `with_no_trimmed_paths!` @@ -256,6 +250,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .collect(); let format_args = FormatArgs { this, this_sugared, generic_args, item_context }; - (condition_options, format_args) + (filter_options, format_args) } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b42f2f92c52bd..3afe367a45ed3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -62,12 +62,15 @@ pub(crate) use self::types::*; pub(crate) use self::utils::{krate, register_res, synthesize_auto_trait_and_blanket_impls}; use crate::core::DocContext; use crate::formats::item_type::ItemType; -use crate::visit_ast::Module as DocModule; +use crate::visit_ast; -pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<'tcx>) -> Item { +pub(crate) fn clean_doc_module<'tcx>( + doc: &visit_ast::Module<'tcx>, + cx: &mut DocContext<'tcx>, +) -> Item { let mut items: Vec = vec![]; let mut inserted = FxHashSet::default(); - items.extend(doc.foreigns.iter().map(|(item, renamed, import_id)| { + items.extend(doc.foreigns.iter().map(|visit_ast::Foreign { item, renamed, import_id }| { let item = clean_maybe_renamed_foreign_item(cx, item, *renamed, *import_id); if let Some(name) = item.name && (cx.document_hidden() || !item.is_doc_hidden()) @@ -95,52 +98,56 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< // This covers the case where somebody does an import which should pull in an item, // but there's already an item with the same namespace and same name. Rust gives // priority to the not-imported one, so we should, too. - items.extend(doc.items.values().flat_map(|entry| { - // First, lower everything other than glob imports. - let item = entry.item; - if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) { - return Vec::new(); - } - let v = clean_maybe_renamed_item(cx, item, entry.renamed, &entry.import_ids); - for item in &v { - if let Some(name) = item.name - && (cx.document_hidden() || !item.is_doc_hidden()) - { - inserted.insert((item.type_(), name)); + items.extend(doc.items.values().flat_map( + |visit_ast::ItemEntry { item, renamed, import_ids }| { + // First, lower everything other than glob imports. + if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) { + return Vec::new(); } - } - v - })); - items.extend(doc.inlined_foreigns.iter().flat_map(|((_, renamed), (res, local_import_id))| { - let Some(def_id) = res.opt_def_id() else { return Vec::new() }; - let name = renamed.unwrap_or_else(|| cx.tcx.item_name(def_id)); - let import = cx.tcx.hir_expect_item(*local_import_id); - match import.kind { - hir::ItemKind::Use(path, kind) => { - let hir::UsePath { segments, span, .. } = *path; - let path = hir::Path { segments, res: *res, span }; - clean_use_statement_inner( - import, - Some(name), - &path, - kind, - cx, - &mut Default::default(), - ) + let v = clean_maybe_renamed_item(cx, item, *renamed, import_ids); + for item in &v { + if let Some(name) = item.name + && (cx.document_hidden() || !item.is_doc_hidden()) + { + inserted.insert((item.type_(), name)); + } } - _ => unreachable!(), - } - })); - items.extend(doc.items.values().flat_map(|entry| { - // Now we actually lower the imports, skipping everything else. - let item = entry.item; - if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind { - clean_use_statement(item, entry.renamed, path, hir::UseKind::Glob, cx, &mut inserted) - } else { - // skip everything else - Vec::new() - } - })); + v + }, + )); + items.extend(doc.inlined_foreigns.iter().flat_map( + |((_, renamed), visit_ast::InlinedForeign { res, import_id })| { + let Some(def_id) = res.opt_def_id() else { return Vec::new() }; + let name = renamed.unwrap_or_else(|| cx.tcx.item_name(def_id)); + let import = cx.tcx.hir_expect_item(*import_id); + match import.kind { + hir::ItemKind::Use(path, kind) => { + let hir::UsePath { segments, span, .. } = *path; + let path = hir::Path { segments, res: *res, span }; + clean_use_statement_inner( + import, + Some(name), + &path, + kind, + cx, + &mut Default::default(), + ) + } + _ => unreachable!(), + } + }, + )); + items.extend(doc.items.values().flat_map( + |visit_ast::ItemEntry { item, renamed, import_ids: _ }| { + // Now we actually lower the imports, skipping everything else. + if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind { + clean_use_statement(item, *renamed, path, hir::UseKind::Glob, cx, &mut inserted) + } else { + // skip everything else + Vec::new() + } + }, + )); // determine if we should display the inner contents or // the outer `mod` item for the source code. diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 5f119c23841e3..9e989bbd5fd9e 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -32,8 +32,7 @@ pub(crate) struct Module<'hir> { pub(crate) def_id: LocalDefId, pub(crate) renamed: Option, pub(crate) import_id: Option, - /// The key is the item `ItemId`. - /// We use `FxIndexMap` to keep the insert order. + /// The key is the item `ItemId`. We use `FxIndexMap` to keep the insert order. /// /// `import_id` needs to be a `Vec` because we live in a dark world where you can have code /// like: @@ -54,7 +53,7 @@ pub(crate) struct Module<'hir> { /// shadowed or not. pub(crate) items: FxIndexMap<(LocalDefId, Option), ItemEntry<'hir>>, - /// (def_id, renamed) -> (res, local_import_id) + /// The key is `(def_id, renamed)`. /// /// `inlined_foreigns` only contains `extern` items /// that are cross-crate inlined. @@ -62,9 +61,9 @@ pub(crate) struct Module<'hir> { /// Locally inlined `extern` items are /// stored in `foreigns` with the `import_id` set, /// analogous to how `items` is. - pub(crate) inlined_foreigns: FxIndexMap<(DefId, Option), (Res, LocalDefId)>, + pub(crate) inlined_foreigns: FxIndexMap<(DefId, Option), InlinedForeign>, /// (item, renamed, import_id) - pub(crate) foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option, Option)>, + pub(crate) foreigns: Vec>, } #[derive(Debug)] @@ -74,6 +73,19 @@ pub(crate) struct ItemEntry<'hir> { pub(crate) import_ids: Vec, } +#[derive(Debug)] +pub(crate) struct InlinedForeign { + pub(crate) res: Res, + pub(crate) import_id: LocalDefId, +} + +#[derive(Debug)] +pub(crate) struct Foreign<'hir> { + pub(crate) item: &'hir hir::ForeignItem<'hir>, + pub(crate) renamed: Option, + pub(crate) import_id: Option, +} + impl Module<'_> { pub(crate) fn new( name: Symbol, @@ -283,7 +295,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { .last_mut() .unwrap() .inlined_foreigns - .insert((ori_res_did, renamed), (res, def_id)); + .insert((ori_res_did, renamed), InlinedForeign { res, import_id: def_id }); return true; }; @@ -575,7 +587,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { ) { // If inlining we only want to include public functions. if !self.inlining || self.cx.tcx.visibility(item.owner_id).is_public() { - self.modules.last_mut().unwrap().foreigns.push((item, renamed, import_id)); + self.modules.last_mut().unwrap().foreigns.push(Foreign { item, renamed, import_id }); } } diff --git a/tests/ui/abi/bad-custom.stderr b/tests/ui/abi/bad-custom.stderr index 372ef71375c58..d7c9cae35c7b3 100644 --- a/tests/ui/abi/bad-custom.stderr +++ b/tests/ui/abi/bad-custom.stderr @@ -194,8 +194,8 @@ LL | f | - return type was inferred to be `unsafe extern "custom" fn()` here | = help: the trait `Fn()` is not implemented for `unsafe extern "custom" fn()` - = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe extern "custom" fn()` in a closure with no arguments: `|| { /* code */ }` + = note: unsafe function cannot be called generically without an unsafe block error: items with the "custom" ABI can only be declared externally or defined via naked functions --> $DIR/bad-custom.rs:25:1 diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr index 1c6e3905abb11..52543caad37db 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr @@ -78,8 +78,8 @@ LL | call(foo_unsafe); | required by a bound introduced by this call | = help: the trait `Fn()` is not implemented for fn item `unsafe fn() {foo_unsafe}` - = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` + = note: unsafe function cannot be called generically without an unsafe block = note: `#[target_feature]` functions do not implement the `Fn` traits = note: try casting the function to a `fn` pointer or wrapping it in a closure note: required by a bound in `call` @@ -97,8 +97,8 @@ LL | call_mut(foo_unsafe); | required by a bound introduced by this call | = help: the trait `FnMut()` is not implemented for fn item `unsafe fn() {foo_unsafe}` - = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` + = note: unsafe function cannot be called generically without an unsafe block = note: `#[target_feature]` functions do not implement the `Fn` traits = note: try casting the function to a `fn` pointer or wrapping it in a closure note: required by a bound in `call_mut` @@ -116,8 +116,8 @@ LL | call_once(foo_unsafe); | required by a bound introduced by this call | = help: the trait `FnOnce()` is not implemented for fn item `unsafe fn() {foo_unsafe}` - = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` + = note: unsafe function cannot be called generically without an unsafe block = note: `#[target_feature]` functions do not implement the `Fn` traits = note: try casting the function to a `fn` pointer or wrapping it in a closure note: required by a bound in `call_once` diff --git a/tests/ui/suggestions/path-display.stderr b/tests/ui/suggestions/path-display.stderr index df9e855bb714d..3594be2efcc47 100644 --- a/tests/ui/suggestions/path-display.stderr +++ b/tests/ui/suggestions/path-display.stderr @@ -7,8 +7,8 @@ LL | println!("{}", path); | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `Path` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: required for `&Path` to implement `std::fmt::Display` error[E0277]: `PathBuf` doesn't implement `std::fmt::Display` @@ -20,8 +20,8 @@ LL | println!("{}", path); | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `PathBuf` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead error: aborting due to 2 previous errors diff --git a/tests/ui/traits/next-solver/fn-trait.stderr b/tests/ui/traits/next-solver/fn-trait.stderr index 00243fd905950..77c834f377852 100644 --- a/tests/ui/traits/next-solver/fn-trait.stderr +++ b/tests/ui/traits/next-solver/fn-trait.stderr @@ -7,8 +7,8 @@ LL | require_fn(f as unsafe fn() -> i32); | required by a bound introduced by this call | = help: the trait `Fn()` is not implemented for `unsafe fn() -> i32` - = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe fn() -> i32` in a closure with no arguments: `|| { /* code */ }` + = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `require_fn` --> $DIR/fn-trait.rs:3:23 | @@ -56,8 +56,8 @@ LL | require_fn(h); | required by a bound introduced by this call | = help: the trait `Fn()` is not implemented for fn item `unsafe fn() -> i32 {h}` - = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe fn() -> i32 {h}` in a closure with no arguments: `|| { /* code */ }` + = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `require_fn` --> $DIR/fn-trait.rs:3:23 | diff --git a/tests/ui/unpretty/diagnostic-attr.stdout b/tests/ui/unpretty/diagnostic-attr.stdout index 4dc0c54633d72..b5e0269410fb7 100644 --- a/tests/ui/unpretty/diagnostic-attr.stdout +++ b/tests/ui/unpretty/diagnostic-attr.stdout @@ -7,7 +7,7 @@ use ::std::prelude::rust_2015::*; //@ edition: 2015 #[attr = OnUnimplemented {directive: Directive {is_rustc_attr: false, -subcommands: [], +filters: [], message: FormatString {input: "My Message for `ImportantTrait<{A}>` implemented for `{Self}`", pieces: [Lit("My Message for `ImportantTrait<"), Arg(GenericParam {generic_param: "A"}), Lit(">` implemented for `"), @@ -22,7 +22,7 @@ impl ImportantTrait for T where T: Clone { } struct X; -#[attr = OnConst {directive: Directive {is_rustc_attr: false, subcommands: [], +#[attr = OnConst {directive: Directive {is_rustc_attr: false, filters: [], message: FormatString {input: "My Message for `ImportantTrait` implemented for `{Self}`", pieces: [Lit("My Message for `ImportantTrait` implemented for `"), Arg(SelfUpper), Lit("`")]}, label: FormatString {input: "My Label",