From 7d9fe91ccbf350613dd20a39133ad9984999a20b Mon Sep 17 00:00:00 2001 From: Caio Date: Tue, 21 Jan 2025 17:54:16 -0300 Subject: [PATCH 01/11] [cfg_match] Document the use of expressions --- library/core/src/macros/mod.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 5c04e5a40df09..01a3c9d2ada72 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -313,6 +313,17 @@ pub macro cfg_match { /// } /// } /// ``` +/// +/// If desired, it is possible to return expressions through the use of surrounding braces: +/// +/// ``` +/// #![feature(cfg_match)] +/// +/// let _some_string = cfg_match! {{ +/// unix => { "With great power comes great electricity bills" } +/// _ => { "Behind every successful diet is an unwatched pizza" } +/// }}; +/// ``` #[cfg(not(bootstrap))] #[unstable(feature = "cfg_match", issue = "115585")] #[rustc_diagnostic_item = "cfg_match"] From 1ee75825455328c287cb2ad1bdbd855656f09871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sun, 26 Jan 2025 17:18:07 +0000 Subject: [PATCH 02/11] add NLL region graph to the polonius MIR dump --- compiler/rustc_borrowck/src/polonius/dump.rs | 84 +++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index 40e801d03885c..11b00fdd44aaa 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -1,14 +1,17 @@ use std::io; +use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir::pretty::{ PassWhere, PrettyPrintMirOptions, create_dump_file, dump_enabled, dump_mir_to_writer, }; use rustc_middle::mir::{Body, ClosureRegionRequirements}; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_session::config::MirIncludeSpans; use crate::borrow_set::BorrowSet; +use crate::constraints::OutlivesConstraint; use crate::polonius::{LocalizedOutlivesConstraint, LocalizedOutlivesConstraintSet}; +use crate::type_check::Locations; use crate::{BorrowckInferCtxt, RegionInferenceContext}; /// `-Zdump-mir=polonius` dumps MIR annotated with NLL and polonius specific information. @@ -50,6 +53,7 @@ pub(crate) fn dump_polonius_mir<'tcx>( /// - the NLL MIR /// - the list of polonius localized constraints /// - a mermaid graph of the CFG +/// - a mermaid graph of the NLL regions and the constraints between them fn emit_polonius_dump<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, @@ -89,6 +93,14 @@ fn emit_polonius_dump<'tcx>( writeln!(out, "")?; writeln!(out, "")?; + // Section 3: mermaid visualization of the NLL region graph. + writeln!(out, "
")?; + writeln!(out, "NLL regions")?; + writeln!(out, "
")?;
+    emit_mermaid_nll_regions(regioncx, out)?;
+    writeln!(out, "
")?; + writeln!(out, "
")?; + // Finalize the dump with the HTML epilogue. writeln!( out, @@ -261,3 +273,73 @@ fn emit_mermaid_cfg(body: &Body<'_>, out: &mut dyn io::Write) -> io::Result<()> Ok(()) } + +/// Emits a region's label: index, universe, external name. +fn render_region( + region: RegionVid, + regioncx: &RegionInferenceContext<'_>, + out: &mut dyn io::Write, +) -> io::Result<()> { + let def = regioncx.region_definition(region); + let universe = def.universe; + + write!(out, "'{}", region.as_usize())?; + if !universe.is_root() { + write!(out, "/{universe:?}")?; + } + if let Some(name) = def.external_name.and_then(|e| e.get_name()) { + write!(out, " ({name})")?; + } + Ok(()) +} + +/// Emits a mermaid flowchart of the NLL regions and the outlives constraints between them, similar +/// to the graphviz version. +fn emit_mermaid_nll_regions<'tcx>( + regioncx: &RegionInferenceContext<'tcx>, + out: &mut dyn io::Write, +) -> io::Result<()> { + // The mermaid chart type: a top-down flowchart. + writeln!(out, "flowchart TD")?; + + // Emit the region nodes. + for region in regioncx.var_infos.indices() { + write!(out, "{}[\"", region.as_usize())?; + render_region(region, regioncx, out)?; + writeln!(out, "\"]")?; + } + + // Get a set of edges to check for the reverse edge being present. + let edges: FxHashSet<_> = regioncx.outlives_constraints().map(|c| (c.sup, c.sub)).collect(); + + // Order (and deduplicate) edges for traversal, to display them in a generally increasing order. + let constraint_key = |c: &OutlivesConstraint<'_>| { + let min = c.sup.min(c.sub); + let max = c.sup.max(c.sub); + (min, max) + }; + let mut ordered_edges: Vec<_> = regioncx.outlives_constraints().collect(); + ordered_edges.sort_by_key(|c| constraint_key(c)); + ordered_edges.dedup_by_key(|c| constraint_key(c)); + + for outlives in ordered_edges { + // Source node. + write!(out, "{} ", outlives.sup.as_usize())?; + + // The kind of arrow: bidirectional if the opposite edge exists in the set. + if edges.contains(&(outlives.sub, outlives.sup)) { + write!(out, "<")?; + } + write!(out, "-- ")?; + + // Edge label from its `Locations`. + match outlives.locations { + Locations::All(_) => write!(out, "All")?, + Locations::Single(location) => write!(out, "{:?}", location)?, + } + + // Target node. + writeln!(out, " --> {}", outlives.sub.as_usize())?; + } + Ok(()) +} From 052e9b430651f5cb89b511d131d1d7a47a28d215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sun, 26 Jan 2025 21:13:32 +0000 Subject: [PATCH 03/11] add NLL SCCs to polonius MIR dump --- compiler/rustc_borrowck/src/polonius/dump.rs | 49 ++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index 11b00fdd44aaa..944b5b1d4a7df 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -1,6 +1,7 @@ use std::io; use rustc_data_structures::fx::FxHashSet; +use rustc_index::IndexVec; use rustc_middle::mir::pretty::{ PassWhere, PrettyPrintMirOptions, create_dump_file, dump_enabled, dump_mir_to_writer, }; @@ -54,6 +55,7 @@ pub(crate) fn dump_polonius_mir<'tcx>( /// - the list of polonius localized constraints /// - a mermaid graph of the CFG /// - a mermaid graph of the NLL regions and the constraints between them +/// - a mermaid graph of the NLL SCCs and the constraints between them fn emit_polonius_dump<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, @@ -101,6 +103,14 @@ fn emit_polonius_dump<'tcx>( writeln!(out, "")?; writeln!(out, "")?; + // Section 4: mermaid visualization of the NLL SCC graph. + writeln!(out, "
")?; + writeln!(out, "NLL SCCs")?; + writeln!(out, "
")?;
+    emit_mermaid_nll_sccs(regioncx, out)?;
+    writeln!(out, "
")?; + writeln!(out, "
")?; + // Finalize the dump with the HTML epilogue. writeln!( out, @@ -343,3 +353,42 @@ fn emit_mermaid_nll_regions<'tcx>( } Ok(()) } + +/// Emits a mermaid flowchart of the NLL SCCs and the outlives constraints between them, similar +/// to the graphviz version. +fn emit_mermaid_nll_sccs<'tcx>( + regioncx: &RegionInferenceContext<'tcx>, + out: &mut dyn io::Write, +) -> io::Result<()> { + // The mermaid chart type: a top-down flowchart. + writeln!(out, "flowchart TD")?; + + // Gather and emit the SCC nodes. + let mut nodes_per_scc: IndexVec<_, _> = + regioncx.constraint_sccs().all_sccs().map(|_| Vec::new()).collect(); + for region in regioncx.var_infos.indices() { + let scc = regioncx.constraint_sccs().scc(region); + nodes_per_scc[scc].push(region); + } + for (scc, regions) in nodes_per_scc.iter_enumerated() { + // The node label: the regions contained in the SCC. + write!(out, "{scc}[\"SCC({scc}) = {{", scc = scc.as_usize())?; + for (idx, ®ion) in regions.iter().enumerate() { + render_region(region, regioncx, out)?; + if idx < regions.len() - 1 { + write!(out, ",")?; + } + } + writeln!(out, "}}\"]")?; + } + + // Emit the edges between SCCs. + let edges = regioncx.constraint_sccs().all_sccs().flat_map(|source| { + regioncx.constraint_sccs().successors(source).iter().map(move |&target| (source, target)) + }); + for (source, target) in edges { + writeln!(out, "{} --> {}", source.as_usize(), target.as_usize())?; + } + + Ok(()) +} From 6bdc2dc3cf7534a8066a8f937698f4a7520b85aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sun, 26 Jan 2025 21:22:46 +0000 Subject: [PATCH 04/11] tidy up html structure - invert pre/code which was an invalid combination, that works fine in practice - remove unneeded code wrapper for graphs --- compiler/rustc_borrowck/src/polonius/dump.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index 944b5b1d4a7df..f71e6f3e6f3a6 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -74,7 +74,7 @@ fn emit_polonius_dump<'tcx>( // Section 1: the NLL + Polonius MIR. writeln!(out, "
")?; writeln!(out, "Raw MIR dump")?; - writeln!(out, "
")?;
+    writeln!(out, "
")?;
     emit_html_mir(
         tcx,
         body,
@@ -84,15 +84,15 @@ fn emit_polonius_dump<'tcx>(
         closure_region_requirements,
         out,
     )?;
-    writeln!(out, "
")?; + writeln!(out, "
")?; writeln!(out, "
")?; // Section 2: mermaid visualization of the CFG. writeln!(out, "
")?; writeln!(out, "Control-flow graph")?; - writeln!(out, "
")?;
+    writeln!(out, "
")?;
     emit_mermaid_cfg(body, out)?;
-    writeln!(out, "
")?; + writeln!(out, "
")?; writeln!(out, "
")?; // Section 3: mermaid visualization of the NLL region graph. From cedd3e22a64ad7a1097414f314cf444dbd115949 Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 27 Jan 2025 12:00:59 -0500 Subject: [PATCH 05/11] Update books --- src/doc/book | 2 +- src/doc/edition-guide | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/book b/src/doc/book index 82a4a49789bc9..fa312a343fbff 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 82a4a49789bc96db1a1b2a210b4c5ed7c9ef0c0d +Subproject commit fa312a343fbff01bc6cef393e326817f70719813 diff --git a/src/doc/edition-guide b/src/doc/edition-guide index d56e0f3a0656b..4ed5a1a4a2a7e 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit d56e0f3a0656b7702ca466d4b191e16c28262b82 +Subproject commit 4ed5a1a4a2a7ecc2e529a5baaef04f7bc7917eda diff --git a/src/doc/nomicon b/src/doc/nomicon index 625b200e5b33a..bc22988655446 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 625b200e5b33a5af35589db0bc454203a3d46d20 +Subproject commit bc2298865544695c63454fc1f9f98a3dc22e9948 diff --git a/src/doc/reference b/src/doc/reference index 293af99100377..93b921c7d3213 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 293af991003772bdccf2d6b980182d84dd055942 +Subproject commit 93b921c7d3213d38d920f7f905a3bec093d2217d From 93ee180cfa12cfca5e0ce79bb3d9a3eaf91cf7b5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 27 Jan 2025 18:30:17 +0100 Subject: [PATCH 06/11] ABI-required target features: warn when they are missing in base CPU (rather than silently enabling them) --- compiler/rustc_codegen_gcc/src/gcc_util.rs | 50 +---------------- compiler/rustc_codegen_gcc/src/lib.rs | 5 +- compiler/rustc_codegen_llvm/src/llvm_util.rs | 56 ++----------------- compiler/rustc_interface/messages.ftl | 5 ++ compiler/rustc_interface/src/errors.rs | 9 +++ compiler/rustc_interface/src/interface.rs | 2 + compiler/rustc_interface/src/util.rs | 38 ++++++++++++- .../x86/intrinsics-x86-pause-without-sse2.rs | 4 +- tests/codegen/target-feature-overrides.rs | 8 +-- tests/codegen/tied-features-strength.rs | 5 +- tests/ui-fulldeps/codegen-backend/hotplug.rs | 4 ++ .../feature-hierarchy.aarch64-sve2.stderr | 7 --- ...target-feature-flag-disable-implied.stderr | 2 +- ...at-target-feature-flag-disable-neon.stderr | 2 +- ...rdfloat-target-feature-flag-disable.stderr | 10 ++-- 15 files changed, 80 insertions(+), 127 deletions(-) delete mode 100644 tests/ui/target-feature/feature-hierarchy.aarch64-sve2.stderr diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs index 560aff43d6538..4e8c8aaaf5c8a 100644 --- a/compiler/rustc_codegen_gcc/src/gcc_util.rs +++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs @@ -1,10 +1,8 @@ -use std::iter::FromIterator; - #[cfg(feature = "master")] use gccjit::Context; use rustc_codegen_ssa::codegen_attrs::check_tied_features; use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::unord::UnordSet; use rustc_session::Session; use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES; @@ -45,12 +43,6 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec Vec Vec sess.target .rust_target_features() .iter() - .filter(|(_, gate, _)| gate.in_cfg()) .filter(|(feature, _, _)| { // skip checking special features, as LLVM may not understand them if RUSTC_SPECIAL_FEATURES.contains(feature) { @@ -388,9 +387,13 @@ pub fn target_features_cfg(sess: &Session, allow_unstable: bool) -> Vec sess.target .rust_target_features() .iter() - .filter(|(_, gate, _)| gate.in_cfg()) .filter_map(|(feature, gate, _)| { - if sess.is_nightly_build() || allow_unstable || gate.requires_nightly().is_none() { + // The `allow_unstable` set is used by rustc internally to determined which target + // features are truly available, so we want to return even perma-unstable "forbidden" + // features. + if allow_unstable + || (gate.in_cfg() && (sess.is_nightly_build() || gate.requires_nightly().is_none())) + { Some(*feature) } else { None @@ -670,12 +673,6 @@ pub(crate) fn global_llvm_features( // Will only be filled when `diagnostics` is set! let mut featsmap = FxHashMap::default(); - // Ensure that all ABI-required features are enabled, and the ABI-forbidden ones - // are disabled. - let abi_feature_constraints = sess.target.abi_required_features(); - let abi_incompatible_set = - FxHashSet::from_iter(abi_feature_constraints.incompatible.iter().copied()); - // Compute implied features let mut all_rust_features = vec![]; for feature in sess.opts.cg.target_feature.split(',') { @@ -746,52 +743,11 @@ pub(crate) fn global_llvm_features( } } - // Ensure that the features we enable/disable are compatible with the ABI. - if enable { - if abi_incompatible_set.contains(feature) { - sess.dcx().emit_warn(ForbiddenCTargetFeature { - feature, - enabled: "enabled", - reason: "this feature is incompatible with the target ABI", - }); - } - } else { - // FIXME: we have to request implied features here since - // negative features do not handle implied features above. - for &required in abi_feature_constraints.required.iter() { - let implied = - sess.target.implied_target_features(std::iter::once(required)); - if implied.contains(feature) { - sess.dcx().emit_warn(ForbiddenCTargetFeature { - feature, - enabled: "disabled", - reason: "this feature is required by the target ABI", - }); - } - } - } - // FIXME(nagisa): figure out how to not allocate a full hashset here. featsmap.insert(feature, enable); } } - // To be sure the ABI-relevant features are all in the right state, we explicitly - // (un)set them here. This means if the target spec sets those features wrong, - // we will silently correct them rather than silently producing wrong code. - // (The target sanity check tries to catch this, but we can't know which features are - // enabled in LLVM by default so we can't be fully sure about that check.) - // We add these at the beginning of the list so that `-Ctarget-features` can - // still override it... that's unsound, but more compatible with past behavior. - all_rust_features.splice( - 0..0, - abi_feature_constraints - .required - .iter() - .map(|&f| (true, f)) - .chain(abi_feature_constraints.incompatible.iter().map(|&f| (false, f))), - ); - // Translate this into LLVM features. let feats = all_rust_features .iter() diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl index 47dfbc1d7fbf1..31123625369bd 100644 --- a/compiler/rustc_interface/messages.ftl +++ b/compiler/rustc_interface/messages.ftl @@ -1,3 +1,8 @@ +interface_abi_required_feature = + target feature `{$feature}` must be {$enabled} to ensure that the ABI of the current target can be implemented correctly + .note = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +interface_abi_required_feature_issue = for more information, see issue #116344 + interface_cant_emit_mir = could not emit MIR: {$error} diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index 939980a932fdb..b62950d670964 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -103,3 +103,12 @@ pub struct IgnoringOutDir; #[derive(Diagnostic)] #[diag(interface_multiple_output_types_to_stdout)] pub struct MultipleOutputTypesToStdout; + +#[derive(Diagnostic)] +#[diag(interface_abi_required_feature)] +#[note] +#[note(interface_abi_required_feature_issue)] +pub(crate) struct AbiRequiredTargetFeature<'a> { + pub feature: &'a str, + pub enabled: &'a str, +} diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 2113345eda3ac..d9803236f85cf 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -492,6 +492,8 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se } sess.lint_store = Some(Lrc::new(lint_store)); + util::check_abi_required_features(&sess); + let compiler = Compiler { sess, codegen_backend, diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 984b8104f539f..e900ec14fcab6 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -18,21 +18,25 @@ use rustc_session::{EarlyDiagCtxt, Session, filesearch}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::source_map::SourceMapInputs; -use rustc_span::sym; +use rustc_span::{Symbol, sym}; use rustc_target::spec::Target; use tracing::info; use crate::errors; /// Function pointer type that constructs a new CodegenBackend. -pub type MakeBackendFn = fn() -> Box; +type MakeBackendFn = fn() -> Box; /// Adds `target_feature = "..."` cfgs for a variety of platform /// specific features (SSE, NEON etc.). /// /// This is performed by checking whether a set of permitted features /// is available on the target machine, by querying the codegen backend. -pub fn add_configuration(cfg: &mut Cfg, sess: &mut Session, codegen_backend: &dyn CodegenBackend) { +pub(crate) fn add_configuration( + cfg: &mut Cfg, + sess: &mut Session, + codegen_backend: &dyn CodegenBackend, +) { let tf = sym::target_feature; let unstable_target_features = codegen_backend.target_features_cfg(sess, true); @@ -48,6 +52,34 @@ pub fn add_configuration(cfg: &mut Cfg, sess: &mut Session, codegen_backend: &dy } } +/// Ensures that all target features required by the ABI are present. +/// Must be called after `unstable_target_features` has been populated! +pub(crate) fn check_abi_required_features(sess: &Session) { + let abi_feature_constraints = sess.target.abi_required_features(); + // We check this against `unstable_target_features` as that is conveniently already + // back-translated to rustc feature names, taking into account `-Ctarget-cpu` and `-Ctarget-feature`. + // Just double-check that the features we care about are actually on our list. + for feature in + abi_feature_constraints.required.iter().chain(abi_feature_constraints.incompatible.iter()) + { + assert!( + sess.target.rust_target_features().iter().any(|(name, ..)| feature == name), + "target feature {feature} is required/incompatible for the current ABI but not a recognized feature for this target" + ); + } + + for feature in abi_feature_constraints.required { + if !sess.unstable_target_features.contains(&Symbol::intern(feature)) { + sess.dcx().emit_warn(errors::AbiRequiredTargetFeature { feature, enabled: "enabled" }); + } + } + for feature in abi_feature_constraints.incompatible { + if sess.unstable_target_features.contains(&Symbol::intern(feature)) { + sess.dcx().emit_warn(errors::AbiRequiredTargetFeature { feature, enabled: "disabled" }); + } + } +} + pub static STACK_SIZE: OnceLock = OnceLock::new(); pub const DEFAULT_STACK_SIZE: usize = 8 * 1024 * 1024; diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pause-without-sse2.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pause-without-sse2.rs index 4d5ddd75f385a..6ca53c0eb6fca 100644 --- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pause-without-sse2.rs +++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pause-without-sse2.rs @@ -1,5 +1,5 @@ -// We're testing x86 target specific features -//@only-target: x86_64 i686 +// We're testing x86-32 target specific features. SSE always exists on x86-64. +//@only-target: i686 //@compile-flags: -C target-feature=-sse2 #[cfg(target_arch = "x86")] diff --git a/tests/codegen/target-feature-overrides.rs b/tests/codegen/target-feature-overrides.rs index e7f70a1e24ab7..f38a1ae72de5d 100644 --- a/tests/codegen/target-feature-overrides.rs +++ b/tests/codegen/target-feature-overrides.rs @@ -39,8 +39,8 @@ pub unsafe fn banana() -> u32 { } // CHECK: attributes [[APPLEATTRS]] -// COMPAT-SAME: "target-features"="+x87,+sse2,+avx,+avx2,{{.*}}" -// INCOMPAT-SAME: "target-features"="+x87,+sse2,-avx2,-avx,+avx,{{.*}}" +// COMPAT-SAME: "target-features"="+avx,+avx2,{{.*}}" +// INCOMPAT-SAME: "target-features"="-avx2,-avx,+avx,{{.*}}" // CHECK: attributes [[BANANAATTRS]] -// COMPAT-SAME: "target-features"="+x87,+sse2,+avx,+avx2,{{.*}}" -// INCOMPAT-SAME: "target-features"="+x87,+sse2,-avx2,-avx" +// COMPAT-SAME: "target-features"="+avx,+avx2,{{.*}}" +// INCOMPAT-SAME: "target-features"="-avx2,-avx" diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs index 6daa5cd7d5e26..1b2b63c3d1ac4 100644 --- a/tests/codegen/tied-features-strength.rs +++ b/tests/codegen/tied-features-strength.rs @@ -11,11 +11,10 @@ // ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(\+sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } //@ [DISABLE_SVE] compile-flags: -C target-feature=-sve -Copt-level=0 -// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } +// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-sve,?)|(\+neon,?))*}}" } //@ [DISABLE_NEON] compile-flags: -C target-feature=-neon -Copt-level=0 -// `neon` and `fp-armv8` get enabled as target base features, but then disabled again at the end of the list. -// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fp-armv8,?)|(\+neon,?))*}},-neon,-fp-armv8{{(,\+fpmr)?}}" } +// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-fp-armv8,?)|(-neon,?))*}}" } //@ [ENABLE_NEON] compile-flags: -C target-feature=+neon -Copt-level=0 // ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" } diff --git a/tests/ui-fulldeps/codegen-backend/hotplug.rs b/tests/ui-fulldeps/codegen-backend/hotplug.rs index 917b20fcdb56e..ce310ba3e315e 100644 --- a/tests/ui-fulldeps/codegen-backend/hotplug.rs +++ b/tests/ui-fulldeps/codegen-backend/hotplug.rs @@ -6,6 +6,10 @@ //@ normalize-stdout: "libthe_backend.dylib" -> "libthe_backend.so" //@ normalize-stdout: "the_backend.dll" -> "libthe_backend.so" +// Pick a target that requires no target features, so that no warning is shown +// about missing target features. +//@ compile-flags: --target arm-unknown-linux-gnueabi +//@ needs-llvm-components: arm //@ revisions: normal dep bindep //@ compile-flags: --crate-type=lib //@ [normal] compile-flags: --emit=link=- diff --git a/tests/ui/target-feature/feature-hierarchy.aarch64-sve2.stderr b/tests/ui/target-feature/feature-hierarchy.aarch64-sve2.stderr deleted file mode 100644 index b6c3ccdedfb00..0000000000000 --- a/tests/ui/target-feature/feature-hierarchy.aarch64-sve2.stderr +++ /dev/null @@ -1,7 +0,0 @@ -warning: target feature `neon` cannot be disabled with `-Ctarget-feature`: this feature is required by the target ABI - | - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #116344 - -warning: 1 warning emitted - diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.stderr b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.stderr index 72b2d03fe2036..7ec8b04cfce01 100644 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.stderr +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.stderr @@ -1,4 +1,4 @@ -warning: target feature `sse` cannot be disabled with `-Ctarget-feature`: this feature is required by the target ABI +warning: target feature `sse2` must be enabled to ensure that the ABI of the current target can be implemented correctly | = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #116344 diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-neon.stderr b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-neon.stderr index b6c3ccdedfb00..b1186d5d5dc78 100644 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-neon.stderr +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-neon.stderr @@ -1,4 +1,4 @@ -warning: target feature `neon` cannot be disabled with `-Ctarget-feature`: this feature is required by the target ABI +warning: target feature `neon` must be enabled to ensure that the ABI of the current target can be implemented correctly | = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #116344 diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.stderr b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.stderr index 6191681286a36..02398d27501c8 100644 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.stderr +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable.stderr @@ -1,11 +1,11 @@ -warning: unstable feature specified for `-Ctarget-feature`: `x87` - | - = note: this feature is not stably supported; its behavior can change in the future - -warning: target feature `x87` cannot be disabled with `-Ctarget-feature`: this feature is required by the target ABI +warning: target feature `x87` must be enabled to ensure that the ABI of the current target can be implemented correctly | = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #116344 +warning: unstable feature specified for `-Ctarget-feature`: `x87` + | + = note: this feature is not stably supported; its behavior can change in the future + warning: 2 warnings emitted From 3f6ffa1462d8f9d4f6f645a330872b172074a2c5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 27 Jan 2025 20:17:39 +0100 Subject: [PATCH 07/11] update comments --- compiler/rustc_target/src/target_features.rs | 24 +++++++++----------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 9fd07c8634aa1..3bc4b92987f1c 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -108,21 +108,19 @@ impl Stability { // per-function level, since we would then allow safe calls from functions with `+soft-float` to // functions without that feature! // -// It is important for soundness that features allowed here do *not* change the function call ABI. -// For example, disabling the `x87` feature on x86 changes how scalar floats are passed as -// arguments, so enabling toggling that feature would be unsound. In fact, since `-Ctarget-feature` -// will just allow unknown features (with a warning), we have to explicitly list features that change -// the ABI as `Forbidden` to ensure using them causes an error. Note that this is only effective if -// such features can never be toggled via `-Ctarget-cpu`! If that is ever a possibility, we will need -// extra checks ensuring that the LLVM-computed target features for a CPU did not (un)set a -// `Forbidden` feature. See https://github.com/rust-lang/rust/issues/116344 for some more context. -// FIXME: add such "forbidden" features for non-x86 targets. +// It is important for soundness to consider the interaction of targets features and the function +// call ABI. For example, disabling the `x87` feature on x86 changes how scalar floats are passed as +// arguments, so letting people toggle that feature would be unsound. To this end, the +// `abi_required_features` function computes which target features must and must not be enabled for +// any given target, and individual features can also be marked as `Forbidden`. +// See https://github.com/rust-lang/rust/issues/116344 for some more context. // // The one exception to features that change the ABI is features that enable larger vector -// registers. Those are permitted to be listed here. This is currently unsound (see -// https://github.com/rust-lang/rust/issues/116558); in the future we will have to ensure that -// functions can only use such vectors as arguments/return types if the corresponding target feature -// is enabled. +// registers. Those are permitted to be listed here. The `*_FOR_CORRECT_VECTOR_ABI` arrays store +// information about which target feature is ABI-required for which vector size; this is used to +// ensure that vectors can only be passed via `extern "C"` when the right feature is enabled. (For +// the "Rust" ABI we generally pass vectors by-ref exactly to avoid these issues.) +// Also see https://github.com/rust-lang/rust/issues/116558. // // Stabilizing a target feature requires t-lang approval. From 3026545ab50e65fcd1c888b77272032000e36147 Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Thu, 23 Jan 2025 10:16:08 +0100 Subject: [PATCH 08/11] parse_format optimize import use --- compiler/rustc_builtin_macros/src/asm.rs | 2 +- compiler/rustc_builtin_macros/src/format.rs | 2 +- compiler/rustc_parse_format/src/lib.rs | 41 ++++++++----------- compiler/rustc_parse_format/src/tests.rs | 18 ++++---- .../traits/on_unimplemented.rs | 4 +- .../crates/hir-def/src/body/lower/asm.rs | 2 +- .../crates/hir-def/src/hir/format_args.rs | 2 +- 7 files changed, 33 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 5062cf55bb9ad..eb5b345e49ecd 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -651,7 +651,7 @@ fn expand_preparsed_asm( .map(|span| template_span.from_inner(InnerSpan::new(span.start, span.end))); for piece in unverified_pieces { match piece { - parse::Piece::String(s) => { + parse::Piece::Lit(s) => { template.push(ast::InlineAsmTemplatePiece::String(s.to_string().into())) } parse::Piece::NextArgument(arg) => { diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 5202fe26c401e..a0ab6375a666b 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -406,7 +406,7 @@ fn make_format_args( for piece in &pieces { match *piece { - parse::Piece::String(s) => { + parse::Piece::Lit(s) => { unfinished_literal.push_str(s); } parse::Piece::NextArgument(box parse::Argument { position, position_span, format }) => { diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 5418f054bebd2..09c88e7f83bb6 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -16,11 +16,8 @@ #![warn(unreachable_pub)] // tidy-alphabetical-end -use std::{iter, str, string}; - pub use Alignment::*; pub use Count::*; -pub use Piece::*; pub use Position::*; use rustc_lexer::unescape; @@ -86,7 +83,7 @@ impl InnerOffset { #[derive(Clone, Debug, PartialEq)] pub enum Piece<'a> { /// A literal string which should directly be emitted - String(&'a str), + Lit(&'a str), /// This describes that formatting should process the next argument (as /// specified inside) for emission. NextArgument(Box>), @@ -205,11 +202,11 @@ pub enum Count<'a> { } pub struct ParseError { - pub description: string::String, - pub note: Option, - pub label: string::String, + pub description: String, + pub note: Option, + pub label: String, pub span: InnerSpan, - pub secondary_label: Option<(string::String, InnerSpan)>, + pub secondary_label: Option<(String, InnerSpan)>, pub suggestion: Suggestion, } @@ -225,7 +222,7 @@ pub enum Suggestion { /// `format!("{foo:?#}")` -> `format!("{foo:#?}")` /// `format!("{foo:?x}")` -> `format!("{foo:x?}")` /// `format!("{foo:?X}")` -> `format!("{foo:X?}")` - ReorderFormatParameter(InnerSpan, string::String), + ReorderFormatParameter(InnerSpan, String), } /// The parser structure for interpreting the input format string. This is @@ -237,7 +234,7 @@ pub enum Suggestion { pub struct Parser<'a> { mode: ParseMode, input: &'a str, - cur: iter::Peekable>, + cur: std::iter::Peekable>, /// Error messages accumulated during parsing pub errors: Vec, /// Current position of implicit positional argument pointer @@ -278,7 +275,7 @@ impl<'a> Iterator for Parser<'a> { if self.consume('{') { self.last_opening_brace = curr_last_brace; - Some(String(self.string(pos + 1))) + Some(Piece::Lit(self.string(pos + 1))) } else { let arg = self.argument(lbrace_end); if let Some(rbrace_pos) = self.consume_closing_brace(&arg) { @@ -299,13 +296,13 @@ impl<'a> Iterator for Parser<'a> { _ => self.suggest_positional_arg_instead_of_captured_arg(arg), } } - Some(NextArgument(Box::new(arg))) + Some(Piece::NextArgument(Box::new(arg))) } } '}' => { self.cur.next(); if self.consume('}') { - Some(String(self.string(pos + 1))) + Some(Piece::Lit(self.string(pos + 1))) } else { let err_pos = self.to_span_index(pos); self.err_with_note( @@ -317,7 +314,7 @@ impl<'a> Iterator for Parser<'a> { None } } - _ => Some(String(self.string(pos))), + _ => Some(Piece::Lit(self.string(pos))), } } else { if self.is_source_literal { @@ -336,7 +333,7 @@ impl<'a> Parser<'a> { pub fn new( s: &'a str, style: Option, - snippet: Option, + snippet: Option, append_newline: bool, mode: ParseMode, ) -> Parser<'a> { @@ -366,7 +363,7 @@ impl<'a> Parser<'a> { /// Notifies of an error. The message doesn't actually need to be of type /// String, but I think it does when this eventually uses conditions so it /// might as well start using it now. - fn err, S2: Into>( + fn err, S2: Into>( &mut self, description: S1, label: S2, @@ -385,11 +382,7 @@ impl<'a> Parser<'a> { /// Notifies of an error. The message doesn't actually need to be of type /// String, but I think it does when this eventually uses conditions so it /// might as well start using it now. - fn err_with_note< - S1: Into, - S2: Into, - S3: Into, - >( + fn err_with_note, S2: Into, S3: Into>( &mut self, description: S1, label: S2, @@ -968,7 +961,7 @@ impl<'a> Parser<'a> { /// in order to properly synthesise the intra-string `Span`s for error diagnostics. fn find_width_map_from_snippet( input: &str, - snippet: Option, + snippet: Option, str_style: Option, ) -> InputStringKind { let snippet = match snippet { @@ -1083,8 +1076,8 @@ fn find_width_map_from_snippet( InputStringKind::Literal { width_mappings } } -fn unescape_string(string: &str) -> Option { - let mut buf = string::String::new(); +fn unescape_string(string: &str) -> Option { + let mut buf = String::new(); let mut ok = true; unescape::unescape_unicode(string, unescape::Mode::Str, &mut |_, unescaped_char| { match unescaped_char { diff --git a/compiler/rustc_parse_format/src/tests.rs b/compiler/rustc_parse_format/src/tests.rs index 81e5bca0ba9fa..fbb217b16fc32 100644 --- a/compiler/rustc_parse_format/src/tests.rs +++ b/compiler/rustc_parse_format/src/tests.rs @@ -1,3 +1,5 @@ +use Piece::*; + use super::*; #[track_caller] @@ -32,12 +34,12 @@ fn musterr(s: &str) { #[test] fn simple() { - same("asdf", &[String("asdf")]); - same("a{{b", &[String("a"), String("{b")]); - same("a}}b", &[String("a"), String("}b")]); - same("a}}", &[String("a"), String("}")]); - same("}}", &[String("}")]); - same("\\}}", &[String("\\"), String("}")]); + same("asdf", &[Lit("asdf")]); + same("a{{b", &[Lit("a"), Lit("{b")]); + same("a}}b", &[Lit("a"), Lit("}b")]); + same("a}}", &[Lit("a"), Lit("}")]); + same("}}", &[Lit("}")]); + same("\\}}", &[Lit("\\"), Lit("}")]); } #[test] @@ -370,7 +372,7 @@ fn format_flags() { #[test] fn format_mixture() { same("abcd {3:x} efg", &[ - String("abcd "), + Lit("abcd "), NextArgument(Box::new(Argument { position: ArgumentIs(3), position_span: InnerSpan { start: 7, end: 8 }, @@ -390,7 +392,7 @@ fn format_mixture() { ty_span: None, }, })), - String(" efg"), + Lit(" efg"), ]); } #[test] 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 4e0b097db4c6f..3d79b0acf83a9 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 @@ -799,7 +799,7 @@ impl<'tcx> OnUnimplementedFormatString { let mut result = Ok(()); for token in &mut parser { match token { - Piece::String(_) => (), // Normal string, no need to check it + Piece::Lit(_) => (), // Normal string, no need to check it Piece::NextArgument(a) => { let format_spec = a.format; if self.is_diagnostic_namespace_variant @@ -950,7 +950,7 @@ impl<'tcx> OnUnimplementedFormatString { let item_context = (options.get(&sym::ItemContext)).unwrap_or(&empty_string); let constructed_message = (&mut parser) .map(|p| match p { - Piece::String(s) => s.to_owned(), + Piece::Lit(s) => s.to_owned(), Piece::NextArgument(a) => match a.position { Position::ArgumentNamed(arg) => { let s = Symbol::intern(arg); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs index 68c7173d1e409..994ba2aa069d3 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs @@ -229,7 +229,7 @@ impl ExprCollector<'_> { }; for piece in unverified_pieces { match piece { - rustc_parse_format::Piece::String(_) => {} + rustc_parse_format::Piece::Lit(_) => {} rustc_parse_format::Piece::NextArgument(arg) => { // let span = arg_spans.next(); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs index e64e498c17074..28c824fd31d73 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs @@ -287,7 +287,7 @@ pub(crate) fn parse( for piece in pieces { match piece { - parse::Piece::String(s) => { + parse::Piece::Lit(s) => { unfinished_literal.push_str(s); } parse::Piece::NextArgument(arg) => { From 3f8ce7c973e57c99e51df0c94ab3440be9580315 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 22 Jan 2025 21:07:10 +0000 Subject: [PATCH 09/11] Do not assume child bound assumptions for rigid alias --- compiler/rustc_middle/src/ty/context.rs | 14 +++++ .../src/solve/assembly/mod.rs | 63 ++++++++++++++----- compiler/rustc_type_ir/src/interner.rs | 10 +++ ...opy-bound-from-child-rigid.current.stderr} | 2 +- ...ee-copy-bound-from-child-rigid.next.stderr | 14 +++++ .../cant-see-copy-bound-from-child-rigid.rs | 4 ++ .../const-traits/const-impl-trait.stderr | 16 ++++- 7 files changed, 105 insertions(+), 18 deletions(-) rename tests/ui/associated-type-bounds/{cant-see-copy-bound-from-child-rigid.stderr => cant-see-copy-bound-from-child-rigid.current.stderr} (88%) create mode 100644 tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.next.stderr diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 1f0710e24152d..da4a868148201 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -345,6 +345,20 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.item_bounds(def_id).map_bound(IntoIterator::into_iter) } + fn item_self_bounds( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { + self.item_super_predicates(def_id).map_bound(IntoIterator::into_iter) + } + + fn item_non_self_bounds( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { + self.item_non_self_assumptions(def_id).map_bound(IntoIterator::into_iter) + } + fn predicates_of( self, def_id: DefId, 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 63432dc199b98..d0b01b14d6358 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -19,6 +19,11 @@ use crate::solve::{ MaybeCause, NoSolution, QueryResult, }; +enum AliasBoundKind { + SelfBounds, + NonSelfBounds, +} + /// A candidate is a possible way to prove a goal. /// /// It consists of both the `source`, which describes how that goal would be proven, @@ -510,7 +515,12 @@ where candidates: &mut Vec>, ) { let () = self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| { - ecx.assemble_alias_bound_candidates_recur(goal.predicate.self_ty(), goal, candidates); + ecx.assemble_alias_bound_candidates_recur( + goal.predicate.self_ty(), + goal, + candidates, + AliasBoundKind::SelfBounds, + ); }); } @@ -528,6 +538,7 @@ where self_ty: I::Ty, goal: Goal, candidates: &mut Vec>, + consider_self_bounds: AliasBoundKind, ) { let (kind, alias_ty) = match self_ty.kind() { ty::Bool @@ -580,16 +591,37 @@ where } }; - for assumption in - self.cx().item_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, - [], - )); + 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, + CandidateSource::AliasBound, + goal, + assumption, + [], + )); + } + } + 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(G::consider_additional_alias_assumptions(self, goal, alias_ty)); @@ -600,9 +632,12 @@ 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(next_self_ty, goal, candidates) - } + Ok(next_self_ty) => self.assemble_alias_bound_candidates_recur( + next_self_ty, + goal, + candidates, + AliasBoundKind::NonSelfBounds, + ), Err(NoSolution) => {} } } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 4fec606a83152..0c3b0758f0f95 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -203,6 +203,16 @@ pub trait Interner: def_id: Self::DefId, ) -> ty::EarlyBinder>; + fn item_self_bounds( + self, + def_id: Self::DefId, + ) -> ty::EarlyBinder>; + + fn item_non_self_bounds( + self, + def_id: Self::DefId, + ) -> ty::EarlyBinder>; + fn predicates_of( self, def_id: Self::DefId, diff --git a/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.stderr b/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.current.stderr similarity index 88% rename from tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.stderr rename to tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.current.stderr index 3ed73918de313..0d57d9d0142d1 100644 --- a/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.stderr +++ b/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.current.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `x` - --> $DIR/cant-see-copy-bound-from-child-rigid.rs:14:9 + --> $DIR/cant-see-copy-bound-from-child-rigid.rs:18:9 | LL | fn foo(x: T::Assoc) -> (T::Assoc, T::Assoc) | - move occurs because `x` has type `::Assoc`, which does not implement the `Copy` trait diff --git a/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.next.stderr b/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.next.stderr new file mode 100644 index 0000000000000..0d57d9d0142d1 --- /dev/null +++ b/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.next.stderr @@ -0,0 +1,14 @@ +error[E0382]: use of moved value: `x` + --> $DIR/cant-see-copy-bound-from-child-rigid.rs:18:9 + | +LL | fn foo(x: T::Assoc) -> (T::Assoc, T::Assoc) + | - move occurs because `x` has type `::Assoc`, which does not implement the `Copy` trait +... +LL | (x, x) + | - ^ value used here after move + | | + | value moved here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.rs b/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.rs index 6b3fd7e898d18..fe135031b3138 100644 --- a/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.rs +++ b/tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + trait Id { type This: ?Sized; } diff --git a/tests/ui/traits/const-traits/const-impl-trait.stderr b/tests/ui/traits/const-traits/const-impl-trait.stderr index 4e3200594485e..27d7957c00148 100644 --- a/tests/ui/traits/const-traits/const-impl-trait.stderr +++ b/tests/ui/traits/const-traits/const-impl-trait.stderr @@ -99,6 +99,16 @@ note: `PartialEq` can't be used with `~const` because it isn't annotated with `# --> $SRC_DIR/core/src/cmp.rs:LL:COL = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-impl-trait.rs:27:22 + | +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { + | ^^^^^^ can't be applied to `PartialEq` + | +note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-impl-trait.rs:23:22 | @@ -120,9 +130,9 @@ note: `PartialEq` can't be used with `~const` because it isn't annotated with `# = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:27:22 + --> $DIR/const-impl-trait.rs:23:22 | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; | ^^^^^^ can't be applied to `PartialEq` | note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` @@ -181,7 +191,7 @@ LL | a == a | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 20 previous errors +error: aborting due to 21 previous errors Some errors have detailed explanations: E0015, E0635. For more information about an error, try `rustc --explain E0015`. From 009d68740f660562c81c8565f5a5e6ec7ccfb4ae Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 22 Jan 2025 21:07:54 +0000 Subject: [PATCH 10/11] Make item self/non-self bound naming less whack --- compiler/rustc_hir_analysis/src/check/mod.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 14 +++--- .../src/collect/item_bounds.rs | 11 +++-- compiler/rustc_hir_typeck/src/closure.rs | 4 +- compiler/rustc_hir_typeck/src/coercion.rs | 44 +++++++++---------- .../rustc_infer/src/infer/outlives/verify.rs | 2 +- compiler/rustc_lint/src/unused.rs | 35 +++++++-------- .../src/rmeta/decoder/cstore_impl.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 12 ++--- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 6 +-- compiler/rustc_middle/src/ty/context.rs | 6 +-- .../ty/return_position_impl_trait_in_trait.rs | 2 +- .../src/error_reporting/infer/mod.rs | 2 +- .../error_reporting/infer/note_and_explain.rs | 4 +- .../src/error_reporting/traits/suggestions.rs | 33 +++++++------- .../src/traits/select/mod.rs | 4 +- .../clippy_lints/src/future_not_send.rs | 2 +- src/tools/clippy/clippy_utils/src/ty/mod.rs | 6 +-- 19 files changed, 92 insertions(+), 101 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 69b4aa47ebade..cc0b7fdd8dd1f 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -457,7 +457,7 @@ fn fn_sig_suggestion<'tcx>( let asyncness = if tcx.asyncness(assoc.def_id).is_async() { output = if let ty::Alias(_, alias_ty) = *output.kind() { - tcx.explicit_item_super_predicates(alias_ty.def_id) + tcx.explicit_item_self_bounds(alias_ty.def_id) .iter_instantiated_copied(tcx, alias_ty.args) .find_map(|(bound, _)| { bound.as_projection_clause()?.no_bound_vars()?.term.as_type() diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 447050ea7d206..cad7b2a1e57b9 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -65,9 +65,9 @@ pub fn provide(providers: &mut Providers) { type_alias_is_lazy: type_of::type_alias_is_lazy, item_bounds: item_bounds::item_bounds, explicit_item_bounds: item_bounds::explicit_item_bounds, - item_super_predicates: item_bounds::item_super_predicates, - explicit_item_super_predicates: item_bounds::explicit_item_super_predicates, - item_non_self_assumptions: item_bounds::item_non_self_assumptions, + item_self_bounds: item_bounds::item_self_bounds, + explicit_item_self_bounds: item_bounds::explicit_item_self_bounds, + item_non_self_bounds: item_bounds::item_non_self_bounds, impl_super_outlives: item_bounds::impl_super_outlives, generics_of: generics_of::generics_of, predicates_of: predicates_of::predicates_of, @@ -328,9 +328,9 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { self.tcx.ensure().generics_of(def_id); self.tcx.ensure().predicates_of(def_id); self.tcx.ensure().explicit_item_bounds(def_id); - self.tcx.ensure().explicit_item_super_predicates(def_id); + self.tcx.ensure().explicit_item_self_bounds(def_id); self.tcx.ensure().item_bounds(def_id); - self.tcx.ensure().item_super_predicates(def_id); + self.tcx.ensure().item_self_bounds(def_id); if self.tcx.is_conditionally_const(def_id) { self.tcx.ensure().explicit_implied_const_bounds(def_id); self.tcx.ensure().const_conditions(def_id); @@ -822,7 +822,7 @@ fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { hir::TraitItemKind::Type(_, Some(_)) => { tcx.ensure().item_bounds(def_id); - tcx.ensure().item_super_predicates(def_id); + tcx.ensure().item_self_bounds(def_id); tcx.ensure().type_of(def_id); // Account for `type T = _;`. let mut visitor = HirPlaceholderCollector::default(); @@ -839,7 +839,7 @@ fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { hir::TraitItemKind::Type(_, None) => { tcx.ensure().item_bounds(def_id); - tcx.ensure().item_super_predicates(def_id); + tcx.ensure().item_self_bounds(def_id); // #74612: Visit and try to find bad placeholders // even if there is no concrete type. let mut visitor = HirPlaceholderCollector::default(); diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index d3ff1f7bebe65..e37a11b684453 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -350,7 +350,7 @@ pub(super) fn explicit_item_bounds( explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::All) } -pub(super) fn explicit_item_super_predicates( +pub(super) fn explicit_item_self_bounds( tcx: TyCtxt<'_>, def_id: LocalDefId, ) -> ty::EarlyBinder<'_, &'_ [(ty::Clause<'_>, Span)]> { @@ -434,11 +434,11 @@ pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<'_, }) } -pub(super) fn item_super_predicates( +pub(super) fn item_self_bounds( tcx: TyCtxt<'_>, def_id: DefId, ) -> ty::EarlyBinder<'_, ty::Clauses<'_>> { - tcx.explicit_item_super_predicates(def_id).map_bound(|bounds| { + tcx.explicit_item_self_bounds(def_id).map_bound(|bounds| { tcx.mk_clauses_from_iter( util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound)).filter_only_self(), ) @@ -447,13 +447,12 @@ pub(super) fn item_super_predicates( /// This exists as an optimization to compute only the item bounds of the item /// that are not `Self` bounds. -pub(super) fn item_non_self_assumptions( +pub(super) fn item_non_self_bounds( tcx: TyCtxt<'_>, def_id: DefId, ) -> ty::EarlyBinder<'_, ty::Clauses<'_>> { let all_bounds: FxIndexSet<_> = tcx.item_bounds(def_id).skip_binder().iter().collect(); - let own_bounds: FxIndexSet<_> = - tcx.item_super_predicates(def_id).skip_binder().iter().collect(); + let own_bounds: FxIndexSet<_> = tcx.item_self_bounds(def_id).skip_binder().iter().collect(); if all_bounds.len() == own_bounds.len() { ty::EarlyBinder::bind(ty::ListWithCachedTypeInfo::empty()) } else { diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index b8652d82d91bc..d569d5f59c9e2 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -308,7 +308,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty, closure_kind, self.tcx - .explicit_item_super_predicates(def_id) + .explicit_item_self_bounds(def_id) .iter_instantiated_copied(self.tcx, args) .map(|(c, s)| (c.as_predicate(), s)), ), @@ -981,7 +981,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => self .tcx - .explicit_item_super_predicates(def_id) + .explicit_item_self_bounds(def_id) .iter_instantiated_copied(self.tcx, args) .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?, ty::Error(_) => return Some(ret_ty), diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 47abba1cc29c9..153fd6001bbc8 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1847,30 +1847,26 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { fcx.probe(|_| { let ocx = ObligationCtxt::new(fcx); ocx.register_obligations( - fcx.tcx.item_super_predicates(rpit_def_id).iter_identity().filter_map( - |clause| { - let predicate = clause - .kind() - .map_bound(|clause| match clause { - ty::ClauseKind::Trait(trait_pred) => Some( - ty::ClauseKind::Trait(trait_pred.with_self_ty(fcx.tcx, ty)), - ), - ty::ClauseKind::Projection(proj_pred) => { - Some(ty::ClauseKind::Projection( - proj_pred.with_self_ty(fcx.tcx, ty), - )) - } - _ => None, - }) - .transpose()?; - Some(Obligation::new( - fcx.tcx, - ObligationCause::dummy(), - fcx.param_env, - predicate, - )) - }, - ), + fcx.tcx.item_self_bounds(rpit_def_id).iter_identity().filter_map(|clause| { + let predicate = clause + .kind() + .map_bound(|clause| match clause { + ty::ClauseKind::Trait(trait_pred) => Some(ty::ClauseKind::Trait( + trait_pred.with_self_ty(fcx.tcx, ty), + )), + ty::ClauseKind::Projection(proj_pred) => Some( + ty::ClauseKind::Projection(proj_pred.with_self_ty(fcx.tcx, ty)), + ), + _ => None, + }) + .transpose()?; + Some(Obligation::new( + fcx.tcx, + ObligationCause::dummy(), + fcx.param_env, + predicate, + )) + }), ); ocx.select_where_possible().is_empty() }) diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 7a21c2883d1ac..d68f3639176f9 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -281,7 +281,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { alias_ty: ty::AliasTy<'tcx>, ) -> impl Iterator> { let tcx = self.tcx; - let bounds = tcx.item_super_predicates(alias_ty.def_id); + let bounds = tcx.item_self_bounds(alias_ty.def_id); trace!("{:#?}", bounds.skip_binder()); bounds .iter_instantiated(tcx, alias_ty.args) diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 3059adb3fda10..5696fcaed1370 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -289,25 +289,22 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { } ty::Adt(def, _) => is_def_must_use(cx, def.did(), span), ty::Alias(ty::Opaque | ty::Projection, ty::AliasTy { def_id: def, .. }) => { - elaborate( - cx.tcx, - cx.tcx.explicit_item_super_predicates(def).iter_identity_copied(), - ) - // We only care about self bounds for the impl-trait - .filter_only_self() - .find_map(|(pred, _span)| { - // We only look at the `DefId`, so it is safe to skip the binder here. - if let ty::ClauseKind::Trait(ref poly_trait_predicate) = - pred.kind().skip_binder() - { - let def_id = poly_trait_predicate.trait_ref.def_id; - - is_def_must_use(cx, def_id, span) - } else { - None - } - }) - .map(|inner| MustUsePath::Opaque(Box::new(inner))) + elaborate(cx.tcx, cx.tcx.explicit_item_self_bounds(def).iter_identity_copied()) + // We only care about self bounds for the impl-trait + .filter_only_self() + .find_map(|(pred, _span)| { + // We only look at the `DefId`, so it is safe to skip the binder here. + if let ty::ClauseKind::Trait(ref poly_trait_predicate) = + pred.kind().skip_binder() + { + let def_id = poly_trait_predicate.trait_ref.def_id; + + is_def_must_use(cx, def_id, span) + } else { + None + } + }) + .map(|inner| MustUsePath::Opaque(Box::new(inner))) } ty::Dynamic(binders, _, _) => binders.iter().find_map(|predicate| { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 527f2f10205a6..da07ad8f6c074 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -241,7 +241,7 @@ impl IntoArgs for (CrateNum, SimplifiedType) { provide! { tcx, def_id, other, cdata, explicit_item_bounds => { table_defaulted_array } - explicit_item_super_predicates => { table_defaulted_array } + explicit_item_self_bounds => { table_defaulted_array } explicit_predicates_of => { table } generics_of => { table } inferred_outlives_of => { table_defaulted_array } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index c538ab99fb54b..904409dd777ea 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1554,7 +1554,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } if let DefKind::OpaqueTy = def_kind { self.encode_explicit_item_bounds(def_id); - self.encode_explicit_item_super_predicates(def_id); + self.encode_explicit_item_self_bounds(def_id); record!(self.tables.opaque_ty_origin[def_id] <- self.tcx.opaque_ty_origin(def_id)); self.encode_precise_capturing_args(def_id); if tcx.is_conditionally_const(def_id) { @@ -1667,10 +1667,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record_defaulted_array!(self.tables.explicit_item_bounds[def_id] <- bounds); } - fn encode_explicit_item_super_predicates(&mut self, def_id: DefId) { - debug!("EncodeContext::encode_explicit_item_super_predicates({:?})", def_id); - let bounds = self.tcx.explicit_item_super_predicates(def_id).skip_binder(); - record_defaulted_array!(self.tables.explicit_item_super_predicates[def_id] <- bounds); + fn encode_explicit_item_self_bounds(&mut self, def_id: DefId) { + debug!("EncodeContext::encode_explicit_item_self_bounds({:?})", def_id); + let bounds = self.tcx.explicit_item_self_bounds(def_id).skip_binder(); + record_defaulted_array!(self.tables.explicit_item_self_bounds[def_id] <- bounds); } #[instrument(level = "debug", skip(self))] @@ -1685,7 +1685,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { AssocItemContainer::Trait => { if let ty::AssocKind::Type = item.kind { self.encode_explicit_item_bounds(def_id); - self.encode_explicit_item_super_predicates(def_id); + self.encode_explicit_item_self_bounds(def_id); if tcx.is_conditionally_const(def_id) { record_defaulted_array!(self.tables.explicit_implied_const_bounds[def_id] <- self.tcx.explicit_implied_const_bounds(def_id).skip_binder()); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 4f9cdc9a474bd..d1d356c5220a3 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -386,7 +386,7 @@ define_tables! { // corresponding DefPathHash. def_path_hashes: Table, explicit_item_bounds: Table, Span)>>, - explicit_item_super_predicates: Table, Span)>>, + explicit_item_self_bounds: Table, Span)>>, inferred_outlives_of: Table, Span)>>, explicit_super_predicates_of: Table, Span)>>, explicit_implied_predicates_of: Table, Span)>>, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index e27a98236390b..d83bc19a6a2f5 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -393,7 +393,7 @@ rustc_queries! { /// like closure signature deduction. /// /// [explicit item bounds]: Self::explicit_item_bounds - query explicit_item_super_predicates(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { + query explicit_item_self_bounds(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern @@ -427,11 +427,11 @@ rustc_queries! { desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } } - query item_super_predicates(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { + query item_self_bounds(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) } } - query item_non_self_assumptions(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { + query item_non_self_bounds(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index da4a868148201..0c22c056dab5f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -349,14 +349,14 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self, def_id: DefId, ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { - self.item_super_predicates(def_id).map_bound(IntoIterator::into_iter) + self.item_self_bounds(def_id).map_bound(IntoIterator::into_iter) } fn item_non_self_bounds( self, def_id: DefId, ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { - self.item_non_self_assumptions(def_id).map_bound(IntoIterator::into_iter) + self.item_non_self_bounds(def_id).map_bound(IntoIterator::into_iter) } fn predicates_of( @@ -2591,7 +2591,7 @@ impl<'tcx> TyCtxt<'tcx> { let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false }; let future_trait = self.require_lang_item(LangItem::Future, None); - self.explicit_item_super_predicates(def_id).skip_binder().iter().any(|&(predicate, _)| { + self.explicit_item_self_bounds(def_id).skip_binder().iter().any(|&(predicate, _)| { let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() else { return false; }; diff --git a/compiler/rustc_middle/src/ty/return_position_impl_trait_in_trait.rs b/compiler/rustc_middle/src/ty/return_position_impl_trait_in_trait.rs index 21c605f8296d1..cbc02097d827d 100644 --- a/compiler/rustc_middle/src/ty/return_position_impl_trait_in_trait.rs +++ b/compiler/rustc_middle/src/ty/return_position_impl_trait_in_trait.rs @@ -64,7 +64,7 @@ impl<'tcx> TyCtxt<'tcx> { args: ty::GenericArgsRef<'tcx>, ) -> &'tcx ty::List> { let mut bounds: Vec<_> = self - .item_super_predicates(def_id) + .item_self_bounds(def_id) .iter_instantiated(self, args) .filter_map(|clause| { clause diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index bcb6ac13b8faf..5f3f65e46963b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -196,7 +196,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0]; self.tcx - .explicit_item_super_predicates(def_id) + .explicit_item_self_bounds(def_id) .iter_instantiated_copied(self.tcx, args) .find_map(|(predicate, _)| { predicate diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index 1dd09fe7aafa2..e8d14b89d698e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -293,7 +293,7 @@ impl Trait for X { (ty::Dynamic(t, _, ty::DynKind::Dyn), ty::Alias(ty::Opaque, alias)) if let Some(def_id) = t.principal_def_id() && tcx - .explicit_item_super_predicates(alias.def_id) + .explicit_item_self_bounds(alias.def_id) .skip_binder() .iter() .any(|(pred, _span)| match pred.kind().skip_binder() { @@ -422,7 +422,7 @@ impl Trait for X { ty::Alias(..) => values.expected, _ => values.found, }; - let preds = tcx.explicit_item_super_predicates(opaque_ty.def_id); + let preds = tcx.explicit_item_self_bounds(opaque_ty.def_id); for (pred, _span) in preds.skip_binder() { let ty::ClauseKind::Trait(trait_predicate) = pred.kind().skip_binder() else { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 471105773e2b0..f9cda83a57544 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1087,28 +1087,27 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { sig_parts.map_bound(|sig| sig.tupled_inputs_ty.tuple_fields().as_slice()), )) } - ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => self - .tcx - .item_super_predicates(def_id) - .instantiate(self.tcx, args) - .iter() - .find_map(|pred| { - if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder() + ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { + self.tcx.item_self_bounds(def_id).instantiate(self.tcx, args).iter().find_map( + |pred| { + if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder() && self .tcx .is_lang_item(proj.projection_term.def_id, LangItem::FnOnceOutput) // args tuple will always be args[1] && let ty::Tuple(args) = proj.projection_term.args.type_at(1).kind() - { - Some(( - DefIdOrName::DefId(def_id), - pred.kind().rebind(proj.term.expect_type()), - pred.kind().rebind(args.as_slice()), - )) - } else { - None - } - }), + { + Some(( + DefIdOrName::DefId(def_id), + pred.kind().rebind(proj.term.expect_type()), + pred.kind().rebind(args.as_slice()), + )) + } else { + None + } + }, + ) + } ty::Dynamic(data, _, ty::Dyn) => data.iter().find_map(|pred| { if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder() && self.tcx.is_lang_item(proj.def_id, LangItem::FnOnceOutput) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 0cc0d7f786b0f..6b6e0b32385c4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1620,9 +1620,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // projections, we will never be able to equate, e.g. `::A` // with `<::A as Tr>::A`. let relevant_bounds = if in_parent_alias_type { - self.tcx().item_non_self_assumptions(alias_ty.def_id) + self.tcx().item_non_self_bounds(alias_ty.def_id) } else { - self.tcx().item_super_predicates(alias_ty.def_id) + self.tcx().item_self_bounds(alias_ty.def_id) }; for bound in relevant_bounds.instantiate(self.tcx(), alias_ty.args) { diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs index bb2dc9995df7e..3ccfa51ab70b7 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -79,7 +79,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { && let Some(future_trait) = cx.tcx.lang_items().future_trait() && let Some(send_trait) = cx.tcx.get_diagnostic_item(sym::Send) { - let preds = cx.tcx.explicit_item_super_predicates(def_id); + let preds = cx.tcx.explicit_item_self_bounds(def_id); let is_future = preds.iter_instantiated_copied(cx.tcx, args).any(|(p, _)| { p.as_trait_clause() .is_some_and(|trait_pred| trait_pred.skip_binder().trait_ref.def_id == future_trait) diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index 32e7c2bbf7cb6..607d762010283 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -96,7 +96,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' return false; } - for (predicate, _span) in cx.tcx.explicit_item_super_predicates(def_id).iter_identity_copied() { + for (predicate, _span) in cx.tcx.explicit_item_self_bounds(def_id).iter_identity_copied() { match predicate.kind().skip_binder() { // For `impl Trait`, it will register a predicate of `T: Trait`, so we go through // and check substitutions to find `U`. @@ -322,7 +322,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { }, ty::Tuple(args) => args.iter().any(|ty| is_must_use_ty(cx, ty)), ty::Alias(ty::Opaque, AliasTy { def_id, .. }) => { - for (predicate, _) in cx.tcx.explicit_item_super_predicates(def_id).skip_binder() { + for (predicate, _) in cx.tcx.explicit_item_self_bounds(def_id).skip_binder() { if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() { if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) { return true; @@ -712,7 +712,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option sig_from_bounds( cx, ty, - cx.tcx.item_super_predicates(def_id).iter_instantiated(cx.tcx, args), + cx.tcx.item_self_bounds(def_id).iter_instantiated(cx.tcx, args), cx.tcx.opt_parent(def_id), ), ty::FnPtr(sig_tys, hdr) => Some(ExprFnSig::Sig(sig_tys.with(hdr), None)), From c22a27130dde7d7ccf5d76fd021476ddbfdecfa0 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Mon, 27 Jan 2025 16:30:02 -0800 Subject: [PATCH 11/11] Refactor FnKind variant to hold &Fn --- compiler/rustc_ast/src/mut_visit.rs | 36 ++++++++----------- compiler/rustc_ast/src/visit.rs | 25 +++++++------ compiler/rustc_ast_lowering/src/expr.rs | 4 +-- .../rustc_ast_passes/src/ast_validation.rs | 22 ++++++------ .../rustc_ast_pretty/src/pprust/state/item.rs | 28 +++++---------- compiler/rustc_lint/src/builtin.rs | 8 +++-- compiler/rustc_resolve/src/def_collector.rs | 9 +++-- compiler/rustc_resolve/src/late.rs | 6 ++-- .../rustc_resolve/src/late/diagnostics.rs | 10 +++--- .../src/multiple_bound_locations.rs | 4 +-- src/tools/rustfmt/src/items.rs | 17 ++++----- src/tools/rustfmt/src/visitor.rs | 15 ++++++-- 12 files changed, 93 insertions(+), 91 deletions(-) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 3459d39131ac7..7caf7c4c35687 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -954,8 +954,14 @@ fn walk_coroutine_kind(vis: &mut T, coroutine_kind: &mut Coroutin fn walk_fn(vis: &mut T, kind: FnKind<'_>) { match kind { - FnKind::Fn(_ctxt, _ident, FnSig { header, decl, span }, _visibility, generics, body) => { + FnKind::Fn( + _ctxt, + _ident, + _vis, + Fn { defaultness, generics, body, sig: FnSig { header, decl, span } }, + ) => { // Identifier and visibility are visited as a part of the item. + visit_defaultness(vis, defaultness); vis.visit_fn_header(header); vis.visit_generics(generics); vis.visit_fn_decl(decl); @@ -1205,13 +1211,8 @@ impl WalkItemKind for ItemKind { ItemKind::Const(item) => { visit_const_item(item, vis); } - ItemKind::Fn(box Fn { defaultness, generics, sig, body }) => { - visit_defaultness(vis, defaultness); - vis.visit_fn( - FnKind::Fn(FnCtxt::Free, ident, sig, visibility, generics, body), - span, - id, - ); + ItemKind::Fn(func) => { + vis.visit_fn(FnKind::Fn(FnCtxt::Free, ident, visibility, &mut *func), span, id); } ItemKind::Mod(safety, mod_kind) => { visit_safety(vis, safety); @@ -1329,10 +1330,9 @@ impl WalkItemKind for AssocItemKind { AssocItemKind::Const(item) => { visit_const_item(item, visitor); } - AssocItemKind::Fn(box Fn { defaultness, generics, sig, body }) => { - visit_defaultness(visitor, defaultness); + AssocItemKind::Fn(func) => { visitor.visit_fn( - FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, visibility, generics, body), + FnKind::Fn(FnCtxt::Assoc(ctxt), ident, visibility, &mut *func), span, id, ); @@ -1476,10 +1476,9 @@ impl WalkItemKind for ForeignItemKind { visitor.visit_ty(ty); visit_opt(expr, |expr| visitor.visit_expr(expr)); } - ForeignItemKind::Fn(box Fn { defaultness, generics, sig, body }) => { - visit_defaultness(visitor, defaultness); + ForeignItemKind::Fn(func) => { visitor.visit_fn( - FnKind::Fn(FnCtxt::Foreign, ident, sig, visibility, generics, body), + FnKind::Fn(FnCtxt::Foreign, ident, visibility, &mut *func), span, id, ); @@ -1965,14 +1964,7 @@ impl DummyAstNode for crate::ast_traits::AstNo #[derive(Debug)] pub enum FnKind<'a> { /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`. - Fn( - FnCtxt, - &'a mut Ident, - &'a mut FnSig, - &'a mut Visibility, - &'a mut Generics, - &'a mut Option>, - ), + Fn(FnCtxt, &'a mut Ident, &'a mut Visibility, &'a mut Fn), /// E.g., `|x, y| body`. Closure( diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 1d6d7330757de..232fd546de9a3 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -65,7 +65,7 @@ impl BoundKind { #[derive(Copy, Clone, Debug)] pub enum FnKind<'a> { /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`. - Fn(FnCtxt, &'a Ident, &'a FnSig, &'a Visibility, &'a Generics, &'a Option>), + Fn(FnCtxt, &'a Ident, &'a Visibility, &'a Fn), /// E.g., `|x, y| body`. Closure(&'a ClosureBinder, &'a Option, &'a FnDecl, &'a Expr), @@ -74,7 +74,7 @@ pub enum FnKind<'a> { impl<'a> FnKind<'a> { pub fn header(&self) -> Option<&'a FnHeader> { match *self { - FnKind::Fn(_, _, sig, _, _, _) => Some(&sig.header), + FnKind::Fn(_, _, _, Fn { sig, .. }) => Some(&sig.header), FnKind::Closure(..) => None, } } @@ -88,7 +88,7 @@ impl<'a> FnKind<'a> { pub fn decl(&self) -> &'a FnDecl { match self { - FnKind::Fn(_, _, sig, _, _, _) => &sig.decl, + FnKind::Fn(_, _, _, Fn { sig, .. }) => &sig.decl, FnKind::Closure(_, _, decl, _) => decl, } } @@ -374,8 +374,8 @@ impl WalkItemKind for ItemKind { try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); } - ItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => { - let kind = FnKind::Fn(FnCtxt::Free, ident, sig, vis, generics, body); + ItemKind::Fn(func) => { + let kind = FnKind::Fn(FnCtxt::Free, ident, vis, &*func); try_visit!(visitor.visit_fn(kind, span, id)); } ItemKind::Mod(_unsafety, mod_kind) => match mod_kind { @@ -715,8 +715,8 @@ impl WalkItemKind for ForeignItemKind { try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); } - ForeignItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => { - let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, generics, body); + ForeignItemKind::Fn(func) => { + let kind = FnKind::Fn(FnCtxt::Foreign, ident, vis, &*func); try_visit!(visitor.visit_fn(kind, span, id)); } ForeignItemKind::TyAlias(box TyAlias { @@ -858,7 +858,12 @@ pub fn walk_fn_decl<'a, V: Visitor<'a>>( pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Result { match kind { - FnKind::Fn(_ctxt, _ident, FnSig { header, decl, span: _ }, _vis, generics, body) => { + FnKind::Fn( + _ctxt, + _ident, + _vis, + Fn { defaultness: _, sig: FnSig { header, decl, span: _ }, generics, body }, + ) => { // Identifier and visibility are visited as a part of the item. try_visit!(visitor.visit_fn_header(header)); try_visit!(visitor.visit_generics(generics)); @@ -892,8 +897,8 @@ impl WalkItemKind for AssocItemKind { try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); } - AssocItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => { - let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body); + AssocItemKind::Fn(func) => { + let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, vis, &*func); try_visit!(visitor.visit_fn(kind, span, id)); } AssocItemKind::Type(box TyAlias { diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index f31e2c65c792a..b932915dc298c 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -2125,7 +2125,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.arena.alloc(self.expr_call_mut(span, e, args)) } - fn expr_call_lang_item_fn_mut( + pub(super) fn expr_call_lang_item_fn_mut( &mut self, span: Span, lang_item: hir::LangItem, @@ -2135,7 +2135,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.expr_call_mut(span, path, args) } - fn expr_call_lang_item_fn( + pub(super) fn expr_call_lang_item_fn( &mut self, span: Span, lang_item: hir::LangItem, diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 236ca7ba70357..ea1f4a6559ac8 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -917,7 +917,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { walk_list!(self, visit_attribute, &item.attrs); return; // Avoid visiting again. } - ItemKind::Fn(box Fn { defaultness, sig, generics, body }) => { + ItemKind::Fn(func @ box Fn { defaultness, generics: _, sig, body }) => { self.check_defaultness(item.span, *defaultness); let is_intrinsic = @@ -947,7 +947,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.visit_vis(&item.vis); self.visit_ident(&item.ident); - let kind = FnKind::Fn(FnCtxt::Free, &item.ident, sig, &item.vis, generics, body); + let kind = FnKind::Fn(FnCtxt::Free, &item.ident, &item.vis, &*func); self.visit_fn(kind, item.span, item.id); walk_list!(self, visit_attribute, &item.attrs); return; // Avoid visiting again. @@ -1348,19 +1348,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } if let FnKind::Fn( - _, - _, - FnSig { header: FnHeader { ext: Extern::Implicit(extern_span), .. }, .. }, _, _, _, + Fn { + sig: FnSig { header: FnHeader { ext: Extern::Implicit(extern_span), .. }, .. }, + .. + }, ) = fk { self.maybe_lint_missing_abi(*extern_span, id); } // Functions without bodies cannot have patterns. - if let FnKind::Fn(ctxt, _, sig, _, _, None) = fk { + if let FnKind::Fn(ctxt, _, _, Fn { body: None, sig, .. }) = fk { Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| { if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) { if let Some(ident) = ident { @@ -1394,7 +1395,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .is_some(); let disallowed = (!tilde_const_allowed).then(|| match fk { - FnKind::Fn(_, ident, _, _, _, _) => TildeConstReason::Function { ident: ident.span }, + FnKind::Fn(_, ident, _, _) => TildeConstReason::Function { ident: ident.span }, FnKind::Closure(..) => TildeConstReason::Closure, }); self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk)); @@ -1470,15 +1471,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.outer_trait_or_trait_impl.as_ref().and_then(TraitOrTraitImpl::constness).is_some(); match &item.kind { - AssocItemKind::Fn(box Fn { sig, generics, body, .. }) + AssocItemKind::Fn(func) if parent_is_const || ctxt == AssocCtxt::Trait - || matches!(sig.header.constness, Const::Yes(_)) => + || matches!(func.sig.header.constness, Const::Yes(_)) => { self.visit_vis(&item.vis); self.visit_ident(&item.ident); - let kind = - FnKind::Fn(FnCtxt::Assoc(ctxt), &item.ident, sig, &item.vis, generics, body); + let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), &item.ident, &item.vis, &*func); walk_list!(self, visit_attribute, &item.attrs); self.visit_fn(kind, item.span, item.id); } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 897c275d850c2..4cfcaa95233da 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -34,8 +34,8 @@ impl<'a> State<'a> { self.maybe_print_comment(span.lo()); self.print_outer_attributes(attrs); match kind { - ast::ForeignItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => { - self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs); + ast::ForeignItemKind::Fn(func) => { + self.print_fn_full(ident, vis, attrs, &*func); } ast::ForeignItemKind::Static(box ast::StaticItem { ty, mutability, expr, safety }) => { self.print_item_const( @@ -199,16 +199,8 @@ impl<'a> State<'a> { *defaultness, ); } - ast::ItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => { - self.print_fn_full( - sig, - item.ident, - generics, - &item.vis, - *defaultness, - body.as_deref(), - &item.attrs, - ); + ast::ItemKind::Fn(func) => { + self.print_fn_full(item.ident, &item.vis, &item.attrs, &*func); } ast::ItemKind::Mod(safety, mod_kind) => { self.head(Self::to_string(|s| { @@ -542,8 +534,8 @@ impl<'a> State<'a> { self.maybe_print_comment(span.lo()); self.print_outer_attributes(attrs); match kind { - ast::AssocItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => { - self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs); + ast::AssocItemKind::Fn(func) => { + self.print_fn_full(ident, vis, attrs, &*func); } ast::AssocItemKind::Const(box ast::ConstItem { defaultness, generics, ty, expr }) => { self.print_item_const( @@ -653,19 +645,17 @@ impl<'a> State<'a> { fn print_fn_full( &mut self, - sig: &ast::FnSig, name: Ident, - generics: &ast::Generics, vis: &ast::Visibility, - defaultness: ast::Defaultness, - body: Option<&ast::Block>, attrs: &[ast::Attribute], + func: &ast::Fn, ) { + let ast::Fn { defaultness, generics, sig, body } = func; if body.is_some() { self.head(""); } self.print_visibility(vis); - self.print_defaultness(defaultness); + self.print_defaultness(*defaultness); self.print_fn(&sig.decl, sig.header, Some(name), generics); if let Some(body) = body { self.nbsp(); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index c03de687a338b..e8a4e9a84c467 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -330,10 +330,12 @@ impl EarlyLintPass for UnsafeCode { if let FnKind::Fn( ctxt, _, - ast::FnSig { header: ast::FnHeader { safety: ast::Safety::Unsafe(_), .. }, .. }, _, - _, - body, + ast::Fn { + sig: ast::FnSig { header: ast::FnHeader { safety: ast::Safety::Unsafe(_), .. }, .. }, + body, + .. + }, ) = fk { let decorator = match ctxt { diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 87024c487df71..16c0a345f8791 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -170,9 +170,12 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) { match fn_kind { - FnKind::Fn(_ctxt, _ident, FnSig { header, decl, span: _ }, _vis, generics, body) - if let Some(coroutine_kind) = header.coroutine_kind => - { + FnKind::Fn( + _ctxt, + _ident, + _vis, + Fn { sig: FnSig { header, decl, span: _ }, generics, body, .. }, + ) if let Some(coroutine_kind) = header.coroutine_kind => { self.visit_fn_header(header); self.visit_generics(generics); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 68d3351f174ca..4842cbd556c37 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -986,8 +986,8 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r match fn_kind { // Bail if the function is foreign, and thus cannot validly have // a body, or if there's no body for some other reason. - FnKind::Fn(FnCtxt::Foreign, _, sig, _, generics, _) - | FnKind::Fn(_, _, sig, _, generics, None) => { + FnKind::Fn(FnCtxt::Foreign, _, _, Fn { sig, generics, .. }) + | FnKind::Fn(_, _, _, Fn { sig, generics, body: None, .. }) => { self.visit_fn_header(&sig.header); self.visit_generics(generics); self.with_lifetime_rib( @@ -1019,7 +1019,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r // Create a label rib for the function. this.with_label_rib(RibKind::FnOrCoroutine, |this| { match fn_kind { - FnKind::Fn(_, _, sig, _, generics, body) => { + FnKind::Fn(_, _, _, Fn { sig, generics, body, .. }) => { this.visit_generics(generics); let declaration = &sig.decl; diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 2db8087fd8327..57679d595da3e 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -224,7 +224,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let suggestion = if self.current_trait_ref.is_none() && let Some((fn_kind, _)) = self.diag_metadata.current_function && let Some(FnCtxt::Assoc(_)) = fn_kind.ctxt() - && let FnKind::Fn(_, _, sig, ..) = fn_kind + && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = fn_kind && let Some(items) = self.diag_metadata.current_impl_items && let Some(item) = items.iter().find(|i| { i.ident.name == item_str.name @@ -560,7 +560,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { Applicability::MaybeIncorrect, ); if !self.self_value_is_available(path[0].ident.span) { - if let Some((FnKind::Fn(_, _, sig, ..), fn_span)) = + if let Some((FnKind::Fn(_, _, _, ast::Fn { sig, .. }), fn_span)) = &self.diag_metadata.current_function { let (span, sugg) = if let Some(param) = sig.decl.inputs.get(0) { @@ -3249,7 +3249,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { { let pre = if lt.kind == MissingLifetimeKind::Ampersand && let Some((kind, _span)) = self.diag_metadata.current_function - && let FnKind::Fn(_, _, sig, _, _, _) = kind + && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = kind && !sig.decl.inputs.is_empty() && let sugg = sig .decl @@ -3290,7 +3290,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } else if (lt.kind == MissingLifetimeKind::Ampersand || lt.kind == MissingLifetimeKind::Underscore) && let Some((kind, _span)) = self.diag_metadata.current_function - && let FnKind::Fn(_, _, sig, _, _, _) = kind + && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = kind && let ast::FnRetTy::Ty(ret_ty) = &sig.decl.output && !sig.decl.inputs.is_empty() && let arg_refs = sig @@ -3350,7 +3350,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let mut owned_sugg = lt.kind == MissingLifetimeKind::Ampersand; let mut sugg = vec![(lt.span, String::new())]; if let Some((kind, _span)) = self.diag_metadata.current_function - && let FnKind::Fn(_, _, sig, _, _, _) = kind + && let FnKind::Fn(_, _, _, ast::Fn { sig, .. }) = kind && let ast::FnRetTy::Ty(ty) = &sig.decl.output { let mut lt_finder = diff --git a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs index 882ab2dda7aaa..0e1980a6acb61 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs @@ -1,5 +1,5 @@ use rustc_ast::visit::FnKind; -use rustc_ast::{NodeId, WherePredicateKind}; +use rustc_ast::{Fn, NodeId, WherePredicateKind}; use rustc_data_structures::fx::FxHashMap; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::declare_lint_pass; @@ -39,7 +39,7 @@ declare_lint_pass!(MultipleBoundLocations => [MULTIPLE_BOUND_LOCATIONS]); impl EarlyLintPass for MultipleBoundLocations { fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, _: Span, _: NodeId) { - if let FnKind::Fn(_, _, _, _, generics, _) = kind + if let FnKind::Fn(_, _, _, Fn { generics, .. }) = kind && !generics.params.is_empty() && !generics.where_clause.predicates.is_empty() { diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index e7d0fba048b43..457d0afe3b5b7 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -333,19 +333,19 @@ impl<'a> FnSig<'a> { defaultness: ast::Defaultness, ) -> FnSig<'a> { match *fn_kind { - visit::FnKind::Fn(visit::FnCtxt::Assoc(..), _, fn_sig, vis, generics, _) => { - let mut fn_sig = FnSig::from_method_sig(fn_sig, generics, vis); + visit::FnKind::Fn(visit::FnCtxt::Assoc(..), _, vis, ast::Fn { sig, generics, .. }) => { + let mut fn_sig = FnSig::from_method_sig(sig, generics, vis); fn_sig.defaultness = defaultness; fn_sig } - visit::FnKind::Fn(_, _, fn_sig, vis, generics, _) => FnSig { + visit::FnKind::Fn(_, _, vis, ast::Fn { sig, generics, .. }) => FnSig { decl, generics, - ext: fn_sig.header.ext, - constness: fn_sig.header.constness, - coroutine_kind: Cow::Borrowed(&fn_sig.header.coroutine_kind), + ext: sig.header.ext, + constness: sig.header.constness, + coroutine_kind: Cow::Borrowed(&sig.header.coroutine_kind), defaultness, - safety: fn_sig.header.safety, + safety: sig.header.safety, visibility: vis, }, _ => unreachable!(), @@ -3453,6 +3453,7 @@ impl Rewrite for ast::ForeignItem { ref sig, ref generics, ref body, + .. } = **fn_kind; if body.is_some() { let mut visitor = FmtVisitor::from_context(context); @@ -3461,7 +3462,7 @@ impl Rewrite for ast::ForeignItem { let inner_attrs = inner_attributes(&self.attrs); let fn_ctxt = visit::FnCtxt::Foreign; visitor.visit_fn( - visit::FnKind::Fn(fn_ctxt, &self.ident, sig, &self.vis, generics, body), + visit::FnKind::Fn(fn_ctxt, &self.ident, &self.vis, fn_kind), &sig.decl, self.span, defaultness, diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 805e13b780367..bdcb619153d89 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -386,7 +386,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let indent = self.block_indent; let block; let rewrite = match fk { - visit::FnKind::Fn(_, ident, _, _, _, Some(ref b)) => { + visit::FnKind::Fn( + _, + ident, + _, + ast::Fn { + body: Some(ref b), .. + }, + ) => { block = b; self.rewrite_fn_before_block( indent, @@ -539,6 +546,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ref sig, ref generics, ref body, + .. } = **fn_kind; if body.is_some() { let inner_attrs = inner_attributes(&item.attrs); @@ -547,7 +555,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { _ => visit::FnCtxt::Foreign, }; self.visit_fn( - visit::FnKind::Fn(fn_ctxt, &item.ident, sig, &item.vis, generics, body), + visit::FnKind::Fn(fn_ctxt, &item.ident, &item.vis, fn_kind), &sig.decl, item.span, defaultness, @@ -640,12 +648,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ref sig, ref generics, ref body, + .. } = **fn_kind; if body.is_some() { let inner_attrs = inner_attributes(&ai.attrs); let fn_ctxt = visit::FnCtxt::Assoc(assoc_ctxt); self.visit_fn( - visit::FnKind::Fn(fn_ctxt, &ai.ident, sig, &ai.vis, generics, body), + visit::FnKind::Fn(fn_ctxt, &ai.ident, &ai.vis, fn_kind), &sig.decl, ai.span, defaultness,