From 470b49bac9ca58e48a92a0f69aef2745413fe9b4 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 2 Nov 2021 13:34:26 +0100 Subject: [PATCH 01/22] Clarify how to quote and respond to the target tier policy requirements Several times, people have seemed unclear on how to respond to some of the policy requirements, particularly those that just state things the target developers must *not* do (e.g. not posting to PRs that break the target). Add a note that such requirements just need acknowledgement, nothing more. Make quoting and responding a "must" rather than an "is encouraged to", since it's easier to review the requirements that way. --- src/doc/rustc/src/target-tier-policy.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc/src/target-tier-policy.md b/src/doc/rustc/src/target-tier-policy.md index cc02b294b4469..191021dea97fc 100644 --- a/src/doc/rustc/src/target-tier-policy.md +++ b/src/doc/rustc/src/target-tier-policy.md @@ -62,8 +62,10 @@ not preclude an existing target's maintainers using issues (on the Rust repository or otherwise) to track requirements that have not yet been met, as appropriate; however, before officially proposing the introduction or promotion of a target, it should meet all of the necessary requirements. A target -proposal is encouraged to quote the corresponding requirements verbatim as part -of explaining how the target meets those requirements. +proposal must quote the corresponding requirements verbatim and respond to them +as part of explaining how the target meets those requirements. (For the +requirements that simply state that the target or the target developers must +not do something, it suffices to acknowledge the requirement.) For a list of all supported targets and their corresponding tiers ("tier 3", "tier 2", "tier 2 with host tools", "tier 1", or "tier 1 with host tools"), see From 9a016badfae61b7527f94168c2829e775d83401b Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 2 Nov 2021 13:38:51 +0100 Subject: [PATCH 02/22] Clarify dependency requirements in the face of cross-compilation The requirement on dependencies was phrased in terms of "host tools", but it was also intended to apply equally to targets that only support cross-compilation. Only the exception (for libraries commonly needed for binaries on the target) was intended to apply to host tools. Reword the requirement to talk about the dependencies required for "compiling, linking,and emitting functional binaries, libraries, or other code for the target", rather than generically in terms of dependencies for rustc/cargo. This doesn't change the net effect of the requirements, since other requirements already stated that the target can't make the Rust toolchain depend on proprietary libraries. However, this should make the requirements clearer. --- src/doc/rustc/src/target-tier-policy.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/doc/rustc/src/target-tier-policy.md b/src/doc/rustc/src/target-tier-policy.md index 191021dea97fc..025f7e3984e25 100644 --- a/src/doc/rustc/src/target-tier-policy.md +++ b/src/doc/rustc/src/target-tier-policy.md @@ -141,17 +141,19 @@ approved by the appropriate team for that shared code before acceptance. or binary. In other words, the introduction of the target must not cause a user installing or running a version of Rust or the Rust tools to be subject to any new license requirements. - - If the target supports building host tools (such as `rustc` or `cargo`), - those host tools must not depend on proprietary (non-FOSS) libraries, other - than ordinary runtime libraries supplied by the platform and commonly used - by other binaries built for the target. For instance, `rustc` built for the - target may depend on a common proprietary C runtime library or console - output library, but must not depend on a proprietary code generation - library or code optimization library. Rust's license permits such - combinations, but the Rust project has no interest in maintaining such - combinations within the scope of Rust itself, even at tier 3. - - Targets should not require proprietary (non-FOSS) components to link a - functional binary or library. + - Compiling, linking, and emitting functional binaries, libraries, or other + code for the target (whether hosted on the target itself or cross-compiling + from another target) must not depend on proprietary (non-FOSS) libraries. + Host tools built for the target itself may depend on the ordinary runtime + libraries supplied by the platform and commonly used by other applications + built for the target, but those libraries must not be required for code + generation for the target; cross-compilation to the target must not require + such libraries at all. For instance, `rustc` built for the target may + depend on a common proprietary C runtime library or console output library, + but must not depend on a proprietary code generation library or code + optimization library. Rust's license permits such combinations, but the + Rust project has no interest in maintaining such combinations within the + scope of Rust itself, even at tier 3. - "onerous" here is an intentionally subjective term. At a minimum, "onerous" legal/licensing terms include but are *not* limited to: non-disclosure requirements, non-compete requirements, contributor license agreements From 1aeb3f9cadd940825e1e0ce167a8852e0681c20d Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 2 Nov 2021 13:47:08 +0100 Subject: [PATCH 03/22] Clarify documentation about running binaries The requirement for target documentation talks about "running tests", but tier 3 targets often don't support running the full testsuite, and in practice the documentation for how to run an individual binary may be more useful. Change "running tests" to "running binaries, or running tests". --- src/doc/rustc/src/target-tier-policy.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc/src/target-tier-policy.md b/src/doc/rustc/src/target-tier-policy.md index 025f7e3984e25..5f22ad2b16f1a 100644 --- a/src/doc/rustc/src/target-tier-policy.md +++ b/src/doc/rustc/src/target-tier-policy.md @@ -188,9 +188,9 @@ approved by the appropriate team for that shared code before acceptance. target not implementing those portions. - The target must provide documentation for the Rust community explaining how to build for the target, using cross-compilation if possible. If the target - supports running tests (even if they do not pass), the documentation must - explain how to run tests for the target, using emulation if possible or - dedicated hardware if necessary. + supports running binaries, or running tests (even if they do not pass), the + documentation must explain how to run such binaries or tests for the target, + using emulation if possible or dedicated hardware if necessary. - Tier 3 targets must not impose burden on the authors of pull requests, or other developers in the community, to maintain the target. In particular, do not post comments (automated or manual) on a PR that derail or suggest a From 10420ef94514b6319ab87442bfbc7fd465c3394b Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 2 Nov 2021 13:52:39 +0100 Subject: [PATCH 04/22] Point to platform-support/ for target-specific documentation Explain that target-specific documentation should appear in a subdirectory of platform-support, with a link from the target's entry on the platform-support page. --- src/doc/rustc/src/target-tier-policy.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/doc/rustc/src/target-tier-policy.md b/src/doc/rustc/src/target-tier-policy.md index 5f22ad2b16f1a..f82a8edd10866 100644 --- a/src/doc/rustc/src/target-tier-policy.md +++ b/src/doc/rustc/src/target-tier-policy.md @@ -71,6 +71,12 @@ For a list of all supported targets and their corresponding tiers ("tier 3", "tier 2", "tier 2 with host tools", "tier 1", or "tier 1 with host tools"), see [platform support](platform-support.md). +Several parts of this policy require providing target-specific documentation. +Such documentation should typically appear in a subdirectory of the +platform-support section of this rustc manual, with a link from the target's +entry in [platform support](platform-support.md). See other documentation in +that directory for examples. + Note that a target must have already received approval for the next lower tier, and spent a reasonable amount of time at that tier, before making a proposal for promotion to the next higher tier; this is true even if a target meets the From f863e4cc301c7ab7c97b86ad142474989789badc Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 2 Nov 2021 14:07:52 +0100 Subject: [PATCH 05/22] Add a template for target-specific documentation --- src/doc/rustc/src/SUMMARY.md | 1 + .../rustc/src/platform-support/TEMPLATE.md | 52 +++++++++++++++++++ src/doc/rustc/src/target-tier-policy.md | 5 +- 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 src/doc/rustc/src/platform-support/TEMPLATE.md diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 8c41835183797..0bf5c9b3de31e 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -13,6 +13,7 @@ - [JSON Output](json.md) - [Tests](tests/index.md) - [Platform Support](platform-support.md) + - [Template for target-specific documentation](platform-support/TEMPLATE.md) - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md) - [\*-kmc-solid_\*](platform-support/kmc-solid.md) - [Target Tier Policy](target-tier-policy.md) diff --git a/src/doc/rustc/src/platform-support/TEMPLATE.md b/src/doc/rustc/src/platform-support/TEMPLATE.md new file mode 100644 index 0000000000000..e64783fcf194a --- /dev/null +++ b/src/doc/rustc/src/platform-support/TEMPLATE.md @@ -0,0 +1,52 @@ +# `target-name-here` + +**Tier: 3** + +One-sentence description of the target (e.g. CPU, OS) + +## Target maintainers + +- Some Person, `email@example.org`, https://github.com/... + +## Requirements + +Does the target support host tools, or only cross-compilation? Does the target +support std, or alloc (either with a default allocator, or if the user supplies +an allocator)? + +Document the expectations of binaries built for the target. Do they assume +specific minimum features beyond the baseline of the CPU/environment/etc? What +version of the OS or environment do they expect? + +Are there notable `#[target_feature(...)]` or `-C target-feature=` values that +programs may wish to use? + +What calling convention does `extern "C"` use on the target? + +What format do binaries use by default? ELF, PE, something else? + +## Building the target + +If Rust doesn't build the target by default, how can users build it? Can users +just add it to the `target` list in `config.toml`? + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for +this target, you will either need to build Rust with the target enabled (see +"Building the target" above), or build your own copy of `core` by using +`build-std` or similar. + +## Testing + +Does the target support running binaries, or do binaries have varying +expectations that prevent having a standard way to run them? If users can run +binaries, can they do so in some common emulator, or do they need native +hardware? Does the target support running the Rust testsuite? + +## Cross-compilation toolchains and C code + +Does the target support C code? If so, what toolchain target should users use +to build compatible C code? (This may match the target triple, or it may be a +toolchain for a different target triple, potentially with specific options or +caveats.) diff --git a/src/doc/rustc/src/target-tier-policy.md b/src/doc/rustc/src/target-tier-policy.md index f82a8edd10866..53d0470fa8135 100644 --- a/src/doc/rustc/src/target-tier-policy.md +++ b/src/doc/rustc/src/target-tier-policy.md @@ -74,8 +74,9 @@ For a list of all supported targets and their corresponding tiers ("tier 3", Several parts of this policy require providing target-specific documentation. Such documentation should typically appear in a subdirectory of the platform-support section of this rustc manual, with a link from the target's -entry in [platform support](platform-support.md). See other documentation in -that directory for examples. +entry in [platform support](platform-support.md). Use +[TEMPLATE.md](platform-support/TEMPLATE.md) as a base, and see other +documentation in that directory for examples. Note that a target must have already received approval for the next lower tier, and spent a reasonable amount of time at that tier, before making a proposal From 5ab40c8f99607a28441c921690b4498f0186c701 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 21 Dec 2021 18:40:50 +0300 Subject: [PATCH 06/22] Implement `#[rustc_must_implement_one_of]` attribute --- compiler/rustc_feature/src/builtin_attrs.rs | 6 ++ compiler/rustc_metadata/src/rmeta/decoder.rs | 2 + compiler/rustc_metadata/src/rmeta/encoder.rs | 1 + compiler/rustc_metadata/src/rmeta/mod.rs | 1 + compiler/rustc_middle/src/ty/trait_def.rs | 8 +- compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_typeck/src/check/check.rs | 23 +++++ compiler/rustc_typeck/src/check/mod.rs | 25 ++++++ compiler/rustc_typeck/src/collect.rs | 83 ++++++++++++++++++- src/test/ui/rustc_must_implement_one_of.rs | 44 ++++++++++ .../ui/rustc_must_implement_one_of.stderr | 15 ++++ 11 files changed, 205 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/rustc_must_implement_one_of.rs create mode 100644 src/test/ui/rustc_must_implement_one_of.stderr diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index f25b2d8f566c0..6f119d5ab8892 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -677,6 +677,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "the `#[rustc_skip_array_during_method_dispatch]` attribute is used to exclude a trait \ from method dispatch when the receiver is an array, for compatibility in editions < 2021." ), + rustc_attr!( + rustc_must_implement_one_of, Normal, template!(List: "method1, method2, ..."), ErrorFollowing, + "the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete \ + definition of a trait, it's currently in experimental form and should be changed before \ + being exposed outside of the std" + ), // ========================================================================== // Internal attributes, Testing: diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 603b21d400578..2cdbdfdd99b89 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -820,6 +820,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { data.skip_array_during_method_dispatch, data.specialization_kind, self.def_path_hash(item_id), + data.must_implement_one_of, ) } EntryKind::TraitAlias => ty::TraitDef::new( @@ -831,6 +832,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { false, ty::trait_def::TraitSpecializationKind::None, self.def_path_hash(item_id), + None, ), _ => bug!("def-index does not refer to trait or trait alias"), } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 8a74aef60ddaf..c2c231d5cf90e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1514,6 +1514,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { is_marker: trait_def.is_marker, skip_array_during_method_dispatch: trait_def.skip_array_during_method_dispatch, specialization_kind: trait_def.specialization_kind, + must_implement_one_of: trait_def.must_implement_one_of.clone(), }; EntryKind::Trait(self.lazy(data)) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 432ca547de6cd..c7e5a7c5d2c7c 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -378,6 +378,7 @@ struct TraitData { is_marker: bool, skip_array_during_method_dispatch: bool, specialization_kind: ty::trait_def::TraitSpecializationKind, + must_implement_one_of: Option>, } #[derive(TyEncodable, TyDecodable)] diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 34d059f4ec849..c4c75434980d2 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -1,7 +1,7 @@ use crate::traits::specialization_graph; use crate::ty::fast_reject::{self, SimplifiedType, SimplifyParams, StripReferences}; use crate::ty::fold::TypeFoldable; -use crate::ty::{Ty, TyCtxt}; +use crate::ty::{Ident, Ty, TyCtxt}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::definitions::DefPathHash; @@ -44,6 +44,10 @@ pub struct TraitDef { /// The ICH of this trait's DefPath, cached here so it doesn't have to be /// recomputed all the time. pub def_path_hash: DefPathHash, + + /// List of methods from `#[rustc_must_implement_one_of]` attribute one of which + /// must be implemented. + pub must_implement_one_of: Option>, } /// Whether this trait is treated specially by the standard library @@ -87,6 +91,7 @@ impl<'tcx> TraitDef { skip_array_during_method_dispatch: bool, specialization_kind: TraitSpecializationKind, def_path_hash: DefPathHash, + must_implement_one_of: Option>, ) -> TraitDef { TraitDef { def_id, @@ -97,6 +102,7 @@ impl<'tcx> TraitDef { skip_array_during_method_dispatch, specialization_kind, def_path_hash, + must_implement_one_of, } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 84cf8878af809..483171917ddf4 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1136,6 +1136,7 @@ symbols! { rustc_macro_transparency, rustc_main, rustc_mir, + rustc_must_implement_one_of, rustc_nonnull_optimization_guaranteed, rustc_object_lifetime_default, rustc_on_unimplemented, diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index dcf42e1aefebc..ff1031595662d 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -979,6 +979,10 @@ fn check_impl_items_against_trait<'tcx>( if let Ok(ancestors) = trait_def.ancestors(tcx, impl_id.to_def_id()) { // Check for missing items from trait let mut missing_items = Vec::new(); + + let mut must_implement_one_of: Option> = + trait_def.must_implement_one_of.as_deref().map(|slice| slice.iter().copied().collect()); + for &trait_item_id in tcx.associated_item_def_ids(impl_trait_ref.def_id) { let is_implemented = ancestors .leaf_def(tcx, trait_item_id) @@ -987,12 +991,31 @@ fn check_impl_items_against_trait<'tcx>( if !is_implemented && tcx.impl_defaultness(impl_id).is_final() { missing_items.push(tcx.associated_item(trait_item_id)); } + + if let Some(required_items) = &must_implement_one_of { + let trait_item = tcx.associated_item(trait_item_id); + + if is_implemented && required_items.contains(&trait_item.ident) { + must_implement_one_of = None; + } + } } if !missing_items.is_empty() { let impl_span = tcx.sess.source_map().guess_head_span(full_impl_span); missing_items_err(tcx, impl_span, &missing_items, full_impl_span); } + + if let Some(missing_items) = must_implement_one_of { + let impl_span = tcx.sess.source_map().guess_head_span(full_impl_span); + let attr_span = tcx + .get_attrs(impl_trait_ref.def_id) + .iter() + .find(|attr| attr.has_name(sym::rustc_must_implement_one_of)) + .map(|attr| attr.span); + + missing_items_must_implement_one_of_err(tcx, impl_span, &missing_items, attr_span); + } } } diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index d576154ff9073..17c4bc1b3014f 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -641,6 +641,31 @@ fn missing_items_err( err.emit(); } +fn missing_items_must_implement_one_of_err( + tcx: TyCtxt<'_>, + impl_span: Span, + missing_items: &FxHashSet, + annotation_span: Option, +) { + let missing_items_msg = + missing_items.iter().map(Ident::to_string).collect::>().join("`, `"); + + let mut err = struct_span_err!( + tcx.sess, + impl_span, + E0046, + "not all trait items implemented, missing one of: `{}`", + missing_items_msg + ); + err.span_label(impl_span, format!("missing one of `{}` in implementation", missing_items_msg)); + + if let Some(annotation_span) = annotation_span { + err.span_note(annotation_span, "required because of this annotation"); + } + + err.emit(); +} + /// Resugar `ty::GenericPredicates` in a way suitable to be used in structured suggestions. fn bounds_from_generic_predicates<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index d4d4baa3f71da..50613ef7104da 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1198,9 +1198,11 @@ fn super_predicates_that_define_assoc_type( fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { let item = tcx.hir().expect_item(def_id.expect_local()); - let (is_auto, unsafety) = match item.kind { - hir::ItemKind::Trait(is_auto, unsafety, ..) => (is_auto == hir::IsAuto::Yes, unsafety), - hir::ItemKind::TraitAlias(..) => (false, hir::Unsafety::Normal), + let (is_auto, unsafety, items) = match item.kind { + hir::ItemKind::Trait(is_auto, unsafety, .., items) => { + (is_auto == hir::IsAuto::Yes, unsafety, items) + } + hir::ItemKind::TraitAlias(..) => (false, hir::Unsafety::Normal, &[][..]), _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"), }; @@ -1227,6 +1229,80 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { ty::trait_def::TraitSpecializationKind::None }; let def_path_hash = tcx.def_path_hash(def_id); + + let must_implement_one_of = tcx + .get_attrs(def_id) + .iter() + .find(|attr| attr.has_name(sym::rustc_must_implement_one_of)) + // Check that there are at least 2 arguments of `#[rustc_must_implement_one_of]` + // and that they are all identifiers + .and_then(|attr| match attr.meta_item_list() { + Some(items) if items.len() < 2 => { + tcx.sess + .struct_span_err( + attr.span, + "the `#[rustc_must_implement_one_of]` attribute must be \ + used with at least 2 args", + ) + .emit(); + + None + } + Some(items) => items + .into_iter() + .map(|item| item.ident().ok_or(item.span())) + .collect::, _>>() + .map_err(|span| { + tcx.sess.struct_span_err(span, "must be an identifier of a method").emit(); + }) + .ok() + .zip(Some(attr.span)), + // Error is reported by `rustc_attr!` + None => None, + }) + // Check that all arguments of `#[rustc_must_implement_one_of]` reference + // methods in the trait with default implementations + .and_then(|(list, attr_span)| { + let errors = list.iter().filter_map(|ident| { + let item = items.iter().find(|item| item.ident == *ident); + + match item { + Some(item) if matches!(item.kind, hir::AssocItemKind::Fn { .. }) => { + if !item.defaultness.has_value() { + tcx.sess + .struct_span_err( + item.span, + "This method doesn't have a default implementation", + ) + .span_note(attr_span, "required by this annotation") + .emit(); + + return Some(()); + } + + return None; + } + Some(item) => tcx + .sess + .struct_span_err(item.span, "Not a method") + .span_note(attr_span, "required by this annotation") + .note( + "All `#[rustc_must_implement_one_of]` arguments \ + must be method identifiers", + ) + .emit(), + None => tcx + .sess + .struct_span_err(ident.span, "Method not found in this trait") + .emit(), + } + + Some(()) + }); + + (errors.count() == 0).then_some(list) + }); + ty::TraitDef::new( def_id, unsafety, @@ -1236,6 +1312,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { skip_array_during_method_dispatch, spec_kind, def_path_hash, + must_implement_one_of, ) } diff --git a/src/test/ui/rustc_must_implement_one_of.rs b/src/test/ui/rustc_must_implement_one_of.rs new file mode 100644 index 0000000000000..f98d3bdc3fa5e --- /dev/null +++ b/src/test/ui/rustc_must_implement_one_of.rs @@ -0,0 +1,44 @@ +#![feature(rustc_attrs)] + +#[rustc_must_implement_one_of(eq, neq)] +trait Equal { + fn eq(&self, other: &Self) -> bool { + !self.neq(other) + } + + fn neq(&self, other: &Self) -> bool { + !self.eq(other) + } +} + +struct T0; +struct T1; +struct T2; +struct T3; + +impl Equal for T0 { + fn eq(&self, _other: &Self) -> bool { + true + } +} + +impl Equal for T1 { + fn neq(&self, _other: &Self) -> bool { + false + } +} + +impl Equal for T2 { + fn eq(&self, _other: &Self) -> bool { + true + } + + fn neq(&self, _other: &Self) -> bool { + false + } +} + +impl Equal for T3 {} +//~^ not all trait items implemented, missing one of: `neq`, `eq` + +fn main() {} diff --git a/src/test/ui/rustc_must_implement_one_of.stderr b/src/test/ui/rustc_must_implement_one_of.stderr new file mode 100644 index 0000000000000..53c4e71cf8b43 --- /dev/null +++ b/src/test/ui/rustc_must_implement_one_of.stderr @@ -0,0 +1,15 @@ +error[E0046]: not all trait items implemented, missing one of: `neq`, `eq` + --> $DIR/rustc_must_implement_one_of.rs:41:1 + | +LL | impl Equal for T3 {} + | ^^^^^^^^^^^^^^^^^ missing one of `neq`, `eq` in implementation + | +note: required because of this annotation + --> $DIR/rustc_must_implement_one_of.rs:3:1 + | +LL | #[rustc_must_implement_one_of(eq, neq)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. From e6bc0ac6f365cca5aaec5cf7fe8d6adb15e973a7 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 3 Jan 2022 16:42:13 +0300 Subject: [PATCH 07/22] Add test for misused `#[rustc_must_implement_one_of]` --- .../ui/rustc_must_implement_one_of_misuse.rs | 38 +++++++++ .../rustc_must_implement_one_of_misuse.stderr | 82 +++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 src/test/ui/rustc_must_implement_one_of_misuse.rs create mode 100644 src/test/ui/rustc_must_implement_one_of_misuse.stderr diff --git a/src/test/ui/rustc_must_implement_one_of_misuse.rs b/src/test/ui/rustc_must_implement_one_of_misuse.rs new file mode 100644 index 0000000000000..161e94273f8cb --- /dev/null +++ b/src/test/ui/rustc_must_implement_one_of_misuse.rs @@ -0,0 +1,38 @@ +#![feature(rustc_attrs)] + +#[rustc_must_implement_one_of(a, b)] +//~^ Method not found in this trait +//~| Method not found in this trait +trait Tr0 {} + +#[rustc_must_implement_one_of(a, b)] +//~^ Method not found in this trait +trait Tr1 { + fn a() {} +} + +#[rustc_must_implement_one_of(a)] +//~^ the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args +trait Tr2 { + fn a() {} +} + +#[rustc_must_implement_one_of] +//~^ malformed `rustc_must_implement_one_of` attribute input +trait Tr3 {} + +#[rustc_must_implement_one_of(A, B)] +trait Tr4 { + const A: u8 = 1; //~ Not a method + + type B; //~ Not a method +} + +#[rustc_must_implement_one_of(a, b)] +trait Tr5 { + fn a(); //~ This method doesn't have a default implementation + + fn b(); //~ This method doesn't have a default implementation +} + +fn main() {} diff --git a/src/test/ui/rustc_must_implement_one_of_misuse.stderr b/src/test/ui/rustc_must_implement_one_of_misuse.stderr new file mode 100644 index 0000000000000..b5428cf331028 --- /dev/null +++ b/src/test/ui/rustc_must_implement_one_of_misuse.stderr @@ -0,0 +1,82 @@ +error: malformed `rustc_must_implement_one_of` attribute input + --> $DIR/rustc_must_implement_one_of_misuse.rs:20:1 + | +LL | #[rustc_must_implement_one_of] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_must_implement_one_of(method1, method2, ...)]` + +error: Method not found in this trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:3:31 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^ + +error: Method not found in this trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:3:34 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^ + +error: Method not found in this trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:8:34 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^ + +error: the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args + --> $DIR/rustc_must_implement_one_of_misuse.rs:14:1 + | +LL | #[rustc_must_implement_one_of(a)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Not a method + --> $DIR/rustc_must_implement_one_of_misuse.rs:26:5 + | +LL | const A: u8 = 1; + | ^^^^^^^^^^^^^^^^ + | +note: required by this annotation + --> $DIR/rustc_must_implement_one_of_misuse.rs:24:1 + | +LL | #[rustc_must_implement_one_of(A, B)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: All `#[rustc_must_implement_one_of]` arguments must be method identifiers + +error: Not a method + --> $DIR/rustc_must_implement_one_of_misuse.rs:28:5 + | +LL | type B; + | ^^^^^^^ + | +note: required by this annotation + --> $DIR/rustc_must_implement_one_of_misuse.rs:24:1 + | +LL | #[rustc_must_implement_one_of(A, B)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: All `#[rustc_must_implement_one_of]` arguments must be method identifiers + +error: This method doesn't have a default implementation + --> $DIR/rustc_must_implement_one_of_misuse.rs:33:5 + | +LL | fn a(); + | ^^^^^^^ + | +note: required by this annotation + --> $DIR/rustc_must_implement_one_of_misuse.rs:31:1 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: This method doesn't have a default implementation + --> $DIR/rustc_must_implement_one_of_misuse.rs:35:5 + | +LL | fn b(); + | ^^^^^^^ + | +note: required by this annotation + --> $DIR/rustc_must_implement_one_of_misuse.rs:31:1 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors + From 268ae9a232372dcdff59830310d353d8539acb35 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 3 Jan 2022 16:48:18 +0300 Subject: [PATCH 08/22] Move `#[rustc_must_implement_one_of]` tests to fix tidy check --- .../ui/{ => traits/default-method}/rustc_must_implement_one_of.rs | 0 .../default-method}/rustc_must_implement_one_of.stderr | 0 .../default-method}/rustc_must_implement_one_of_misuse.rs | 0 .../default-method}/rustc_must_implement_one_of_misuse.stderr | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{ => traits/default-method}/rustc_must_implement_one_of.rs (100%) rename src/test/ui/{ => traits/default-method}/rustc_must_implement_one_of.stderr (100%) rename src/test/ui/{ => traits/default-method}/rustc_must_implement_one_of_misuse.rs (100%) rename src/test/ui/{ => traits/default-method}/rustc_must_implement_one_of_misuse.stderr (100%) diff --git a/src/test/ui/rustc_must_implement_one_of.rs b/src/test/ui/traits/default-method/rustc_must_implement_one_of.rs similarity index 100% rename from src/test/ui/rustc_must_implement_one_of.rs rename to src/test/ui/traits/default-method/rustc_must_implement_one_of.rs diff --git a/src/test/ui/rustc_must_implement_one_of.stderr b/src/test/ui/traits/default-method/rustc_must_implement_one_of.stderr similarity index 100% rename from src/test/ui/rustc_must_implement_one_of.stderr rename to src/test/ui/traits/default-method/rustc_must_implement_one_of.stderr diff --git a/src/test/ui/rustc_must_implement_one_of_misuse.rs b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs similarity index 100% rename from src/test/ui/rustc_must_implement_one_of_misuse.rs rename to src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs diff --git a/src/test/ui/rustc_must_implement_one_of_misuse.stderr b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr similarity index 100% rename from src/test/ui/rustc_must_implement_one_of_misuse.stderr rename to src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr From 96b2f8ac3268f0aee4d10868f9e31a5f7b66641b Mon Sep 17 00:00:00 2001 From: Waffle Maybe Date: Tue, 4 Jan 2022 13:21:56 +0300 Subject: [PATCH 09/22] Apply suggestions from code review Use "(associated) function" terminology instead of "method". Co-authored-by: Daniel Henry-Mantilla --- compiler/rustc_feature/src/builtin_attrs.rs | 2 +- compiler/rustc_middle/src/ty/trait_def.rs | 2 +- compiler/rustc_typeck/src/collect.rs | 14 +++++++------ .../rustc_must_implement_one_of_misuse.rs | 14 ++++++------- .../rustc_must_implement_one_of_misuse.stderr | 20 +++++++++---------- 5 files changed, 27 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 6f119d5ab8892..3e1605aabfdc2 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -678,7 +678,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ from method dispatch when the receiver is an array, for compatibility in editions < 2021." ), rustc_attr!( - rustc_must_implement_one_of, Normal, template!(List: "method1, method2, ..."), ErrorFollowing, + rustc_must_implement_one_of, Normal, template!(List: "function1, function2, ..."), ErrorFollowing, "the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete \ definition of a trait, it's currently in experimental form and should be changed before \ being exposed outside of the std" diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index c4c75434980d2..9f8053d4a4eac 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -45,7 +45,7 @@ pub struct TraitDef { /// recomputed all the time. pub def_path_hash: DefPathHash, - /// List of methods from `#[rustc_must_implement_one_of]` attribute one of which + /// List of functions from `#[rustc_must_implement_one_of]` attribute one of which /// must be implemented. pub must_implement_one_of: Option>, } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 50613ef7104da..b95a2b6fa498c 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1253,7 +1253,9 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { .map(|item| item.ident().ok_or(item.span())) .collect::, _>>() .map_err(|span| { - tcx.sess.struct_span_err(span, "must be an identifier of a method").emit(); + tcx.sess + .struct_span_err(span, "must be a name of an associated function") + .emit(); }) .ok() .zip(Some(attr.span)), @@ -1261,7 +1263,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { None => None, }) // Check that all arguments of `#[rustc_must_implement_one_of]` reference - // methods in the trait with default implementations + // functions in the trait with default implementations .and_then(|(list, attr_span)| { let errors = list.iter().filter_map(|ident| { let item = items.iter().find(|item| item.ident == *ident); @@ -1272,7 +1274,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { tcx.sess .struct_span_err( item.span, - "This method doesn't have a default implementation", + "This function doesn't have a default implementation", ) .span_note(attr_span, "required by this annotation") .emit(); @@ -1284,16 +1286,16 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { } Some(item) => tcx .sess - .struct_span_err(item.span, "Not a method") + .struct_span_err(item.span, "Not a function") .span_note(attr_span, "required by this annotation") .note( "All `#[rustc_must_implement_one_of]` arguments \ - must be method identifiers", + must be associated function names", ) .emit(), None => tcx .sess - .struct_span_err(ident.span, "Method not found in this trait") + .struct_span_err(ident.span, "Function not found in this trait") .emit(), } diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs index 161e94273f8cb..1089e5f9c4ab9 100644 --- a/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs @@ -1,12 +1,12 @@ #![feature(rustc_attrs)] #[rustc_must_implement_one_of(a, b)] -//~^ Method not found in this trait -//~| Method not found in this trait +//~^ Function not found in this trait +//~| Function not found in this trait trait Tr0 {} #[rustc_must_implement_one_of(a, b)] -//~^ Method not found in this trait +//~^ Function not found in this trait trait Tr1 { fn a() {} } @@ -23,16 +23,16 @@ trait Tr3 {} #[rustc_must_implement_one_of(A, B)] trait Tr4 { - const A: u8 = 1; //~ Not a method + const A: u8 = 1; //~ Not a function - type B; //~ Not a method + type B; //~ Not a function } #[rustc_must_implement_one_of(a, b)] trait Tr5 { - fn a(); //~ This method doesn't have a default implementation + fn a(); //~ This function doesn't have a default implementation - fn b(); //~ This method doesn't have a default implementation + fn b(); //~ This function doesn't have a default implementation } fn main() {} diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr index b5428cf331028..74a6dc8fec97c 100644 --- a/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr @@ -2,21 +2,21 @@ error: malformed `rustc_must_implement_one_of` attribute input --> $DIR/rustc_must_implement_one_of_misuse.rs:20:1 | LL | #[rustc_must_implement_one_of] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_must_implement_one_of(method1, method2, ...)]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_must_implement_one_of(function1, function2, ...)]` -error: Method not found in this trait +error: Function not found in this trait --> $DIR/rustc_must_implement_one_of_misuse.rs:3:31 | LL | #[rustc_must_implement_one_of(a, b)] | ^ -error: Method not found in this trait +error: Function not found in this trait --> $DIR/rustc_must_implement_one_of_misuse.rs:3:34 | LL | #[rustc_must_implement_one_of(a, b)] | ^ -error: Method not found in this trait +error: Function not found in this trait --> $DIR/rustc_must_implement_one_of_misuse.rs:8:34 | LL | #[rustc_must_implement_one_of(a, b)] @@ -28,7 +28,7 @@ error: the `#[rustc_must_implement_one_of]` attribute must be used with at least LL | #[rustc_must_implement_one_of(a)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Not a method +error: Not a function --> $DIR/rustc_must_implement_one_of_misuse.rs:26:5 | LL | const A: u8 = 1; @@ -39,9 +39,9 @@ note: required by this annotation | LL | #[rustc_must_implement_one_of(A, B)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: All `#[rustc_must_implement_one_of]` arguments must be method identifiers + = note: All `#[rustc_must_implement_one_of]` arguments must be associated function names -error: Not a method +error: Not a function --> $DIR/rustc_must_implement_one_of_misuse.rs:28:5 | LL | type B; @@ -52,9 +52,9 @@ note: required by this annotation | LL | #[rustc_must_implement_one_of(A, B)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: All `#[rustc_must_implement_one_of]` arguments must be method identifiers + = note: All `#[rustc_must_implement_one_of]` arguments must be associated function names -error: This method doesn't have a default implementation +error: This function doesn't have a default implementation --> $DIR/rustc_must_implement_one_of_misuse.rs:33:5 | LL | fn a(); @@ -66,7 +66,7 @@ note: required by this annotation LL | #[rustc_must_implement_one_of(a, b)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: This method doesn't have a default implementation +error: This function doesn't have a default implementation --> $DIR/rustc_must_implement_one_of_misuse.rs:35:5 | LL | fn b(); From f64daff0c6e400819c997c888ac2aca32168dd53 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 10 Jan 2022 12:54:04 +0300 Subject: [PATCH 10/22] Fix `#[rustc_must_implement_one_of]` This adds the old, pre 90639 `is_implemented` that previously only was true if the implementation of the item was from the given impl block and not from the trait default. --- compiler/rustc_typeck/src/check/check.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index ff1031595662d..a49c6bd2e8038 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -993,10 +993,16 @@ fn check_impl_items_against_trait<'tcx>( } if let Some(required_items) = &must_implement_one_of { - let trait_item = tcx.associated_item(trait_item_id); - - if is_implemented && required_items.contains(&trait_item.ident) { - must_implement_one_of = None; + // true if this item is specifically implemented in this impl + let is_implemented_here = ancestors + .leaf_def(tcx, trait_item_id) + .map_or(false, |node_item| !node_item.defining_node.is_from_trait()); + + if is_implemented_here { + let trait_item = tcx.associated_item(trait_item_id); + if required_items.contains(&trait_item.ident) { + must_implement_one_of = None; + } } } } From 4ccfa97021abbe228dbf9dcc36c76ce7489b08b3 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 11 Jan 2022 03:39:43 +0300 Subject: [PATCH 11/22] Add a test for ungated `#[rustc_must_implement_one_of]` This test checks that `#[rustc_must_implement_one_of]` is gated behind `#![feature(rustc_attrs)]`. --- .../rustc_must_implement_one_of_gated.rs | 13 +++++++++++++ .../rustc_must_implement_one_of_gated.stderr | 11 +++++++++++ 2 files changed, 24 insertions(+) create mode 100644 src/test/ui/traits/default-method/rustc_must_implement_one_of_gated.rs create mode 100644 src/test/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_gated.rs b/src/test/ui/traits/default-method/rustc_must_implement_one_of_gated.rs new file mode 100644 index 0000000000000..ec2995872de02 --- /dev/null +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_gated.rs @@ -0,0 +1,13 @@ +#[rustc_must_implement_one_of(eq, neq)] +//~^ the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete definition of a trait, it's currently in experimental form and should be changed before being exposed outside of the std +trait Equal { + fn eq(&self, other: &Self) -> bool { + !self.neq(other) + } + + fn neq(&self, other: &Self) -> bool { + !self.eq(other) + } +} + +fn main() {} diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr b/src/test/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr new file mode 100644 index 0000000000000..228bc3e35c21d --- /dev/null +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr @@ -0,0 +1,11 @@ +error[E0658]: the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete definition of a trait, it's currently in experimental form and should be changed before being exposed outside of the std + --> $DIR/rustc_must_implement_one_of_gated.rs:1:1 + | +LL | #[rustc_must_implement_one_of(eq, neq)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. From 842bf71fdad1aaf6d56deff86beac97ece148355 Mon Sep 17 00:00:00 2001 From: James R T Date: Tue, 11 Jan 2022 10:42:51 +0800 Subject: [PATCH 12/22] fix(compiler): correct minor typos in some long error code explanations --- compiler/rustc_error_codes/src/error_codes/E0038.md | 4 ++-- compiler/rustc_error_codes/src/error_codes/E0183.md | 4 ++-- compiler/rustc_error_codes/src/error_codes/E0521.md | 2 +- compiler/rustc_error_codes/src/error_codes/E0581.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0038.md b/compiler/rustc_error_codes/src/error_codes/E0038.md index ca2eaa54057fa..584b78554ef88 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0038.md +++ b/compiler/rustc_error_codes/src/error_codes/E0038.md @@ -15,7 +15,7 @@ Two general aspects of trait object types give rise to the restrictions: these types can only be accessed through pointers, such as `&dyn Trait` or `Box`. The size of such a pointer is known, but the size of the `dyn Trait` object pointed-to by the pointer is _opaque_ to code working - with it, and different tait objects with the same trait object type may + with it, and different trait objects with the same trait object type may have different sizes. 2. The pointer used to access a trait object is paired with an extra pointer @@ -167,7 +167,7 @@ implementation on-demand. If you call `foo()` with a `bool` parameter, the compiler will only generate code for `foo::()`. When we have additional type parameters, the number of monomorphized implementations the compiler generates does not grow drastically, since the compiler will only generate an -implementation if the function is called with unparametrized substitutions +implementation if the function is called with unparameterized substitutions (i.e., substitutions where none of the substituted types are themselves parameterized). diff --git a/compiler/rustc_error_codes/src/error_codes/E0183.md b/compiler/rustc_error_codes/src/error_codes/E0183.md index 7e1d08daae1f2..92fa4c7c21e72 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0183.md +++ b/compiler/rustc_error_codes/src/error_codes/E0183.md @@ -1,4 +1,4 @@ -Manual implemetation of a `Fn*` trait. +Manual implementation of a `Fn*` trait. Erroneous code example: @@ -33,7 +33,7 @@ impl FnOnce<()> for MyClosure { // ok! } ``` -The argumements must be a tuple representing the argument list. +The arguments must be a tuple representing the argument list. For more info, see the [tracking issue][iss29625]: [iss29625]: https://github.com/rust-lang/rust/issues/29625 diff --git a/compiler/rustc_error_codes/src/error_codes/E0521.md b/compiler/rustc_error_codes/src/error_codes/E0521.md index 65dcac983acd5..fedf6365fb559 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0521.md +++ b/compiler/rustc_error_codes/src/error_codes/E0521.md @@ -10,7 +10,7 @@ let _add = |el: &str| { }; ``` -A type anotation of a closure parameter implies a new lifetime declaration. +A type annotation of a closure parameter implies a new lifetime declaration. Consider to drop it, the compiler is reliably able to infer them. ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0581.md b/compiler/rustc_error_codes/src/error_codes/E0581.md index 89f6e3269ec36..02468dd946646 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0581.md +++ b/compiler/rustc_error_codes/src/error_codes/E0581.md @@ -10,7 +10,7 @@ fn main() { } ``` -The problem here is that the lifetime isn't contrained by any of the arguments, +The problem here is that the lifetime isn't constrained by any of the arguments, making it impossible to determine how long it's supposed to live. To fix this issue, either use the lifetime in the arguments, or use the From 68515cb6687a58b8fedd78660e9256970d20f214 Mon Sep 17 00:00:00 2001 From: pierwill Date: Wed, 12 Jan 2022 15:31:26 -0600 Subject: [PATCH 13/22] Rename environment variable for overriding rustc version --- compiler/rustc_incremental/src/persist/file_format.rs | 2 +- compiler/rustc_span/src/def_id.rs | 4 ++-- src/test/incremental/cache_file_headers.rs | 2 +- src/test/run-make-fulldeps/crate-hash-rustc-version/Makefile | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs index 392c5bdc15ad2..68180a2214a50 100644 --- a/compiler/rustc_incremental/src/persist/file_format.rs +++ b/compiler/rustc_incremental/src/persist/file_format.rs @@ -190,7 +190,7 @@ fn report_format_mismatch(report_incremental_info: bool, file: &Path, message: & fn rustc_version(nightly_build: bool) -> String { if nightly_build { - if let Some(val) = env::var_os("RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER") { + if let Some(val) = env::var_os("RUSTC_FORCE_RUSTC_VERSION") { return val.to_string_lossy().into_owned(); } } diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index 0bba918994c51..5390eed89fadc 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -176,9 +176,9 @@ impl StableCrateId { // and no -Cmetadata, symbols from the same crate compiled with different versions of // rustc are named the same. // - // RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER is used to inject rustc version information + // RUSTC_FORCE_RUSTC_VERSION is used to inject rustc version information // during testing. - if let Some(val) = std::env::var_os("RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER") { + if let Some(val) = std::env::var_os("RUSTC_FORCE_RUSTC_VERSION") { hasher.write(val.to_string_lossy().into_owned().as_bytes()) } else { hasher.write(option_env!("CFG_VERSION").unwrap_or("unknown version").as_bytes()); diff --git a/src/test/incremental/cache_file_headers.rs b/src/test/incremental/cache_file_headers.rs index 7f1ef886ac831..9cf611c3379e8 100644 --- a/src/test/incremental/cache_file_headers.rs +++ b/src/test/incremental/cache_file_headers.rs @@ -7,7 +7,7 @@ // The `l33t haxx0r` Rust compiler is known to produce incr. comp. artifacts // that are outrageously incompatible with just about anything, even itself: -//[rpass1] rustc-env:RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER="l33t haxx0r rustc 2.1 LTS" +//[rpass1] rustc-env:RUSTC_FORCE_RUSTC_VERSION="l33t haxx0r rustc 2.1 LTS" // revisions:rpass1 rpass2 // compile-flags: -Z query-dep-graph diff --git a/src/test/run-make-fulldeps/crate-hash-rustc-version/Makefile b/src/test/run-make-fulldeps/crate-hash-rustc-version/Makefile index fd66702db7f2a..091508cd805b9 100644 --- a/src/test/run-make-fulldeps/crate-hash-rustc-version/Makefile +++ b/src/test/run-make-fulldeps/crate-hash-rustc-version/Makefile @@ -27,7 +27,7 @@ all: $(RUSTC) b.rs --extern a=$(TMPDIR)/liba$(EXT) --crate-type=bin -Crpath $(FLAGS) $(call RUN,b) # Now re-compile a.rs with another rustc version - RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER=deadfeed $(RUSTC) a.rs --crate-type=dylib $(FLAGS) + RUSTC_FORCE_RUSTC_VERSION=deadfeed $(RUSTC) a.rs --crate-type=dylib $(FLAGS) # After compiling with a different rustc version, write symbols to disk again. $(NM_CMD) $(call DYLIB,a) > $(TMPDIR)/symbolsafter # As a sanity check, test if the symbols changed: From 606d9c0c0e54b7ed6ec962f3eb492f335c6afe81 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Fri, 14 Jan 2022 00:10:10 +0000 Subject: [PATCH 14/22] Remove LLVMRustMarkAllFunctionsNounwind This was originally introduced in #10916 as a way to remove all landing pads when performing LTO. However this is no longer necessary today since rustc properly marks all functions and call-sites as nounwind where appropriate. In fact this is incorrect in the presence of `extern "C-unwind"` which must create a landing pad when compiled with `-C panic=abort` so that foreign exceptions are caught and properly turned into aborts. --- compiler/rustc_codegen_llvm/src/back/lto.rs | 17 ----------------- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 1 - compiler/rustc_codegen_ssa/src/back/write.rs | 4 +--- .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 19 ------------------- 4 files changed, 1 insertion(+), 40 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index ddba43cd1f16e..6afa649b6de32 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -349,13 +349,6 @@ fn fat_lto( ); save_temp_bitcode(cgcx, &module, "lto.after-restriction"); } - - if cgcx.no_landing_pads { - unsafe { - llvm::LLVMRustMarkAllFunctionsNounwind(llmod); - } - save_temp_bitcode(cgcx, &module, "lto.after-nounwind"); - } } Ok(LtoModuleCodegen::Fat { module: Some(module), _serialized_bitcode: serialized_bitcode }) @@ -770,16 +763,6 @@ pub unsafe fn optimize_thin_module( return Err(write::llvm_err(&diag_handler, msg)); } - // Like with "fat" LTO, get some better optimizations if landing pads - // are disabled by removing all landing pads. - if cgcx.no_landing_pads { - let _timer = cgcx - .prof - .generic_activity_with_arg("LLVM_thin_lto_remove_landing_pads", thin_module.name()); - llvm::LLVMRustMarkAllFunctionsNounwind(llmod); - save_temp_bitcode(cgcx, &module, "thin-lto-after-nounwind"); - } - // Up next comes the per-module local analyses that we do for Thin LTO. // Each of these functions is basically copied from the LLVM // implementation and then tailored to suit this implementation. Ideally diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index f2782f84f557b..05212ea1879d8 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2329,7 +2329,6 @@ extern "C" { pub fn LLVMRustSetNormalizedTarget(M: &Module, triple: *const c_char); pub fn LLVMRustAddAlwaysInlinePass(P: &PassManagerBuilder, AddLifetimes: bool); pub fn LLVMRustRunRestrictionPass(M: &Module, syms: *const *const c_char, len: size_t); - pub fn LLVMRustMarkAllFunctionsNounwind(M: &Module); pub fn LLVMRustOpenArchive(path: *const c_char) -> Option<&'static mut Archive>; pub fn LLVMRustArchiveIteratorNew(AR: &Archive) -> &mut ArchiveIterator<'_>; diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index bea454458c4c0..540979ce02d8f 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -32,7 +32,7 @@ use rustc_session::Session; use rustc_span::source_map::SourceMap; use rustc_span::symbol::sym; use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span}; -use rustc_target::spec::{MergeFunctions, PanicStrategy, SanitizerSet}; +use rustc_target::spec::{MergeFunctions, SanitizerSet}; use std::any::Any; use std::fs; @@ -313,7 +313,6 @@ pub struct CodegenContext { pub backend: B, pub prof: SelfProfilerRef, pub lto: Lto, - pub no_landing_pads: bool, pub save_temps: bool, pub fewer_names: bool, pub time_trace: bool, @@ -1039,7 +1038,6 @@ fn start_executing_work( crate_types: sess.crate_types().to_vec(), each_linked_rlib_for_lto, lto: sess.lto(), - no_landing_pads: sess.panic_strategy() == PanicStrategy::Abort, fewer_names: sess.fewer_names(), save_temps: sess.opts.cg.save_temps, time_trace: sess.opts.debugging_opts.llvm_time_trace, diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index f06fc3edf5859..7030fd53704dd 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -1168,25 +1168,6 @@ extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols, passes.run(*unwrap(M)); } -extern "C" void LLVMRustMarkAllFunctionsNounwind(LLVMModuleRef M) { - for (Module::iterator GV = unwrap(M)->begin(), E = unwrap(M)->end(); GV != E; - ++GV) { - GV->setDoesNotThrow(); - Function *F = dyn_cast(GV); - if (F == nullptr) - continue; - - for (Function::iterator B = F->begin(), BE = F->end(); B != BE; ++B) { - for (BasicBlock::iterator I = B->begin(), IE = B->end(); I != IE; ++I) { - if (isa(I)) { - InvokeInst *CI = cast(I); - CI->setDoesNotThrow(); - } - } - } - } -} - extern "C" void LLVMRustSetDataLayoutFromTargetMachine(LLVMModuleRef Module, LLVMTargetMachineRef TMR) { From c30ec5a6fd3ba5e742d14d0a2089b04e43ee4e32 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 14 Jan 2022 16:38:47 +0300 Subject: [PATCH 15/22] Check for duplicate arguments in `#[rustc_must_implement_one_of]` --- compiler/rustc_typeck/src/collect.rs | 26 ++++++++++++++ .../rustc_must_implement_one_of_duplicates.rs | 19 +++++++++++ ...tc_must_implement_one_of_duplicates.stderr | 34 +++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs create mode 100644 src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index b95a2b6fa498c..23b328b918622 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1303,6 +1303,32 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { }); (errors.count() == 0).then_some(list) + }) + // Check for duplicates + .and_then(|list| { + let mut set: FxHashSet<&Ident> = FxHashSet::default(); + let mut no_dups = true; + + for ident in &*list { + if let Some(dup) = set.replace(ident) { + let dup2 = set.get(&dup).copied().unwrap(); // We've just inserted it + + tcx.sess + .struct_span_err( + vec![dup.span, dup2.span], + "Functions names are duplicated", + ) + .note( + "All `#[rustc_must_implement_one_of]` arguments \ + must be unique", + ) + .emit(); + + no_dups = false; + } + } + + no_dups.then_some(list) }); ty::TraitDef::new( diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs b/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs new file mode 100644 index 0000000000000..56e8fcff0fce5 --- /dev/null +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs @@ -0,0 +1,19 @@ +#![feature(rustc_attrs)] + +#[rustc_must_implement_one_of(a, a)] +//~^ Functions names are duplicated +trait Trait { + fn a() {} +} + +#[rustc_must_implement_one_of(b, a, a, c, b, c)] +//~^ Functions names are duplicated +//~| Functions names are duplicated +//~| Functions names are duplicated +trait Trait1 { + fn a() {} + fn b() {} + fn c() {} +} + +fn main() {} diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr b/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr new file mode 100644 index 0000000000000..777beba618277 --- /dev/null +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr @@ -0,0 +1,34 @@ +error: Functions names are duplicated + --> $DIR/rustc_must_implement_one_of_duplicates.rs:3:31 + | +LL | #[rustc_must_implement_one_of(a, a)] + | ^ ^ + | + = note: All `#[rustc_must_implement_one_of]` arguments must be unique + +error: Functions names are duplicated + --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:34 + | +LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)] + | ^ ^ + | + = note: All `#[rustc_must_implement_one_of]` arguments must be unique + +error: Functions names are duplicated + --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:31 + | +LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)] + | ^ ^ + | + = note: All `#[rustc_must_implement_one_of]` arguments must be unique + +error: Functions names are duplicated + --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:40 + | +LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)] + | ^ ^ + | + = note: All `#[rustc_must_implement_one_of]` arguments must be unique + +error: aborting due to 4 previous errors + From f9174e1d80c4672c288f59aa490a28d3463fd131 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 14 Jan 2022 16:52:30 +0300 Subject: [PATCH 16/22] Do not use `HashSet` for `#[rustc_must_implement_one_of]` --- compiler/rustc_typeck/src/check/check.rs | 6 +++--- compiler/rustc_typeck/src/check/mod.rs | 2 +- .../ui/traits/default-method/rustc_must_implement_one_of.rs | 2 +- .../default-method/rustc_must_implement_one_of.stderr | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index a49c6bd2e8038..88862ea83fded 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -980,8 +980,8 @@ fn check_impl_items_against_trait<'tcx>( // Check for missing items from trait let mut missing_items = Vec::new(); - let mut must_implement_one_of: Option> = - trait_def.must_implement_one_of.as_deref().map(|slice| slice.iter().copied().collect()); + let mut must_implement_one_of: Option<&[Ident]> = + trait_def.must_implement_one_of.as_deref(); for &trait_item_id in tcx.associated_item_def_ids(impl_trait_ref.def_id) { let is_implemented = ancestors @@ -1020,7 +1020,7 @@ fn check_impl_items_against_trait<'tcx>( .find(|attr| attr.has_name(sym::rustc_must_implement_one_of)) .map(|attr| attr.span); - missing_items_must_implement_one_of_err(tcx, impl_span, &missing_items, attr_span); + missing_items_must_implement_one_of_err(tcx, impl_span, missing_items, attr_span); } } } diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 17c4bc1b3014f..b26c4c89d6f2f 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -644,7 +644,7 @@ fn missing_items_err( fn missing_items_must_implement_one_of_err( tcx: TyCtxt<'_>, impl_span: Span, - missing_items: &FxHashSet, + missing_items: &[Ident], annotation_span: Option, ) { let missing_items_msg = diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of.rs b/src/test/ui/traits/default-method/rustc_must_implement_one_of.rs index f98d3bdc3fa5e..5ba2f5ce33426 100644 --- a/src/test/ui/traits/default-method/rustc_must_implement_one_of.rs +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of.rs @@ -39,6 +39,6 @@ impl Equal for T2 { } impl Equal for T3 {} -//~^ not all trait items implemented, missing one of: `neq`, `eq` +//~^ not all trait items implemented, missing one of: `eq`, `neq` fn main() {} diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of.stderr b/src/test/ui/traits/default-method/rustc_must_implement_one_of.stderr index 53c4e71cf8b43..5a4dd1388b2e0 100644 --- a/src/test/ui/traits/default-method/rustc_must_implement_one_of.stderr +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of.stderr @@ -1,8 +1,8 @@ -error[E0046]: not all trait items implemented, missing one of: `neq`, `eq` +error[E0046]: not all trait items implemented, missing one of: `eq`, `neq` --> $DIR/rustc_must_implement_one_of.rs:41:1 | LL | impl Equal for T3 {} - | ^^^^^^^^^^^^^^^^^ missing one of `neq`, `eq` in implementation + | ^^^^^^^^^^^^^^^^^ missing one of `eq`, `neq` in implementation | note: required because of this annotation --> $DIR/rustc_must_implement_one_of.rs:3:1 From 28edd7ac090d621ad8fd0ebe220d897d9df386a9 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sat, 15 Jan 2022 02:04:58 +0300 Subject: [PATCH 17/22] Use `Symbol` for dup check in `#[rustc_must_implement_one_of]` --- compiler/rustc_typeck/src/collect.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 23b328b918622..84315cb682718 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1306,18 +1306,13 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { }) // Check for duplicates .and_then(|list| { - let mut set: FxHashSet<&Ident> = FxHashSet::default(); + let mut set: FxHashMap = FxHashMap::default(); let mut no_dups = true; for ident in &*list { - if let Some(dup) = set.replace(ident) { - let dup2 = set.get(&dup).copied().unwrap(); // We've just inserted it - + if let Some(dup) = set.insert(ident.name, ident.span) { tcx.sess - .struct_span_err( - vec![dup.span, dup2.span], - "Functions names are duplicated", - ) + .struct_span_err(vec![dup, ident.span], "Functions names are duplicated") .note( "All `#[rustc_must_implement_one_of]` arguments \ must be unique", From 4d5a6c90b1df5590c1c1801baf51903520af012c Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Tue, 11 Jan 2022 17:36:52 -0800 Subject: [PATCH 18/22] Enable wrapping words by default Faced with a very long word, browsers will let it overflow its box horizontally rather than break it in the middle. We essentially never want that behavior. We would rather break the word and keep it inside its horizontal limits. So we apply a default overflow-wrap: break-word/anywhere to the document as a while. In some contexts we would rather add a horizontal scrollbar (code blocks), or elide the excess text with an ellipsis (sidebar). Those still work as expected. --- src/librustdoc/html/static/css/rustdoc.css | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index d7f33d6131c84..7cc0e74a79bcb 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -111,6 +111,12 @@ body { font: 1rem/1.4 "Source Serif 4", NanumBarunGothic, serif; margin: 0; position: relative; + /* We use overflow-wrap: break-word for Safari, which doesn't recognize + `anywhere`: https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-wrap */ + overflow-wrap: break-word; + /* Then override it with `anywhere`, which is required to make non-Safari browsers break + more aggressively when we want them to. */ + overflow-wrap: anywhere; -webkit-font-feature-settings: "kern", "liga"; -moz-font-feature-settings: "kern", "liga"; @@ -446,6 +452,7 @@ nav.sub { text-align: center; border-bottom: 1px solid; overflow-wrap: break-word; + overflow-wrap: anywhere; word-wrap: break-word; /* deprecated */ word-break: break-word; /* Chrome, non-standard */ } @@ -576,6 +583,7 @@ nav.sub { } .docblock-short { + overflow-wrap: break-word; overflow-wrap: anywhere; } .docblock-short p { @@ -641,6 +649,7 @@ nav.sub { flex-grow: 1; margin: 0px; padding: 0px; + overflow-wrap: break-word; overflow-wrap: anywhere; } @@ -669,6 +678,7 @@ nav.sub { margin: .5em 0; width: calc(100% - 2px); overflow-x: auto; + overflow-wrap: normal; display: block; } @@ -1495,6 +1505,7 @@ pre.rust { padding: 4px 8px; text-align: center; background: rgba(0,0,0,0); + overflow-wrap: normal; } #theme-choices > button:not(:first-child) { @@ -2099,9 +2110,14 @@ details.rustdoc-toggle[open] > summary.hideme::after { } .docblock code { + overflow-wrap: break-word; overflow-wrap: anywhere; } + .docblock table code { + overflow-wrap: normal; + } + .sub-container { flex-direction: column; } From 07fd90e2a22604690f370a68f5a47bfab19f4895 Mon Sep 17 00:00:00 2001 From: Roc Yu Date: Sat, 15 Jan 2022 12:03:17 -0500 Subject: [PATCH 19/22] Remove `collect` --- src/librustdoc/html/markdown.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 3fd9c0a194485..a9a3a0af276b1 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -923,9 +923,7 @@ impl LangString { data.original = string.to_owned(); - let tokens = Self::tokens(string).collect::>(); - - for token in tokens { + for token in Self::tokens(string) { match token { "should_panic" => { data.should_panic = true; From 3dfcc66d487bc0dbc9f35326d58fe145fa9fd586 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 15 Jan 2022 17:14:13 -0800 Subject: [PATCH 20/22] Add `log2` and `log10` to `NonZeroU*` This version is nice in that it doesn't need to worry about zeros, and thus doesn't have any error cases. --- library/core/src/num/int_log10.rs | 247 ++++++++++++++-------------- library/core/src/num/int_macros.rs | 6 +- library/core/src/num/mod.rs | 16 +- library/core/src/num/nonzero.rs | 52 +++++- library/core/src/num/uint_macros.rs | 17 +- 5 files changed, 197 insertions(+), 141 deletions(-) diff --git a/library/core/src/num/int_log10.rs b/library/core/src/num/int_log10.rs index a8455fb355b3c..cc26c04a5d42a 100644 --- a/library/core/src/num/int_log10.rs +++ b/library/core/src/num/int_log10.rs @@ -1,141 +1,140 @@ -mod unchecked { - // 0 < val <= u8::MAX - #[inline] - pub const fn u8(val: u8) -> u32 { - let val = val as u32; - - // For better performance, avoid branches by assembling the solution - // in the bits above the low 8 bits. - - // Adding c1 to val gives 10 in the top bits for val < 10, 11 for val >= 10 - const C1: u32 = 0b11_00000000 - 10; // 758 - // Adding c2 to val gives 01 in the top bits for val < 100, 10 for val >= 100 - const C2: u32 = 0b10_00000000 - 100; // 412 - - // Value of top bits: - // +c1 +c2 1&2 - // 0..=9 10 01 00 = 0 - // 10..=99 11 01 01 = 1 - // 100..=255 11 10 10 = 2 - ((val + C1) & (val + C2)) >> 8 - } +/// These functions compute the integer logarithm of their type, assuming +/// that someone has already checked that the the value is strictly positive. + +// 0 < val <= u8::MAX +#[inline] +pub const fn u8(val: u8) -> u32 { + let val = val as u32; + + // For better performance, avoid branches by assembling the solution + // in the bits above the low 8 bits. + + // Adding c1 to val gives 10 in the top bits for val < 10, 11 for val >= 10 + const C1: u32 = 0b11_00000000 - 10; // 758 + // Adding c2 to val gives 01 in the top bits for val < 100, 10 for val >= 100 + const C2: u32 = 0b10_00000000 - 100; // 412 + + // Value of top bits: + // +c1 +c2 1&2 + // 0..=9 10 01 00 = 0 + // 10..=99 11 01 01 = 1 + // 100..=255 11 10 10 = 2 + ((val + C1) & (val + C2)) >> 8 +} - // 0 < val < 100_000 - #[inline] - const fn less_than_5(val: u32) -> u32 { - // Similar to u8, when adding one of these constants to val, - // we get two possible bit patterns above the low 17 bits, - // depending on whether val is below or above the threshold. - const C1: u32 = 0b011_00000000000000000 - 10; // 393206 - const C2: u32 = 0b100_00000000000000000 - 100; // 524188 - const C3: u32 = 0b111_00000000000000000 - 1000; // 916504 - const C4: u32 = 0b100_00000000000000000 - 10000; // 514288 - - // Value of top bits: - // +c1 +c2 1&2 +c3 +c4 3&4 ^ - // 0..=9 010 011 010 110 011 010 000 = 0 - // 10..=99 011 011 011 110 011 010 001 = 1 - // 100..=999 011 100 000 110 011 010 010 = 2 - // 1000..=9999 011 100 000 111 011 011 011 = 3 - // 10000..=99999 011 100 000 111 100 100 100 = 4 - (((val + C1) & (val + C2)) ^ ((val + C3) & (val + C4))) >> 17 - } +// 0 < val < 100_000 +#[inline] +const fn less_than_5(val: u32) -> u32 { + // Similar to u8, when adding one of these constants to val, + // we get two possible bit patterns above the low 17 bits, + // depending on whether val is below or above the threshold. + const C1: u32 = 0b011_00000000000000000 - 10; // 393206 + const C2: u32 = 0b100_00000000000000000 - 100; // 524188 + const C3: u32 = 0b111_00000000000000000 - 1000; // 916504 + const C4: u32 = 0b100_00000000000000000 - 10000; // 514288 + + // Value of top bits: + // +c1 +c2 1&2 +c3 +c4 3&4 ^ + // 0..=9 010 011 010 110 011 010 000 = 0 + // 10..=99 011 011 011 110 011 010 001 = 1 + // 100..=999 011 100 000 110 011 010 010 = 2 + // 1000..=9999 011 100 000 111 011 011 011 = 3 + // 10000..=99999 011 100 000 111 100 100 100 = 4 + (((val + C1) & (val + C2)) ^ ((val + C3) & (val + C4))) >> 17 +} - // 0 < val <= u16::MAX - #[inline] - pub const fn u16(val: u16) -> u32 { - less_than_5(val as u32) - } +// 0 < val <= u16::MAX +#[inline] +pub const fn u16(val: u16) -> u32 { + less_than_5(val as u32) +} - // 0 < val <= u32::MAX - #[inline] - pub const fn u32(mut val: u32) -> u32 { - let mut log = 0; - if val >= 100_000 { - val /= 100_000; - log += 5; - } - log + less_than_5(val) +// 0 < val <= u32::MAX +#[inline] +pub const fn u32(mut val: u32) -> u32 { + let mut log = 0; + if val >= 100_000 { + val /= 100_000; + log += 5; } + log + less_than_5(val) +} - // 0 < val <= u64::MAX - #[inline] - pub const fn u64(mut val: u64) -> u32 { - let mut log = 0; - if val >= 10_000_000_000 { - val /= 10_000_000_000; - log += 10; - } - if val >= 100_000 { - val /= 100_000; - log += 5; - } - log + less_than_5(val as u32) +// 0 < val <= u64::MAX +#[inline] +pub const fn u64(mut val: u64) -> u32 { + let mut log = 0; + if val >= 10_000_000_000 { + val /= 10_000_000_000; + log += 10; } - - // 0 < val <= u128::MAX - #[inline] - pub const fn u128(mut val: u128) -> u32 { - let mut log = 0; - if val >= 100_000_000_000_000_000_000_000_000_000_000 { - val /= 100_000_000_000_000_000_000_000_000_000_000; - log += 32; - return log + u32(val as u32); - } - if val >= 10_000_000_000_000_000 { - val /= 10_000_000_000_000_000; - log += 16; - } - log + u64(val as u64) + if val >= 100_000 { + val /= 100_000; + log += 5; } + log + less_than_5(val as u32) +} - // 0 < val <= i8::MAX - #[inline] - pub const fn i8(val: i8) -> u32 { - u8(val as u8) +// 0 < val <= u128::MAX +#[inline] +pub const fn u128(mut val: u128) -> u32 { + let mut log = 0; + if val >= 100_000_000_000_000_000_000_000_000_000_000 { + val /= 100_000_000_000_000_000_000_000_000_000_000; + log += 32; + return log + u32(val as u32); } - - // 0 < val <= i16::MAX - #[inline] - pub const fn i16(val: i16) -> u32 { - u16(val as u16) + if val >= 10_000_000_000_000_000 { + val /= 10_000_000_000_000_000; + log += 16; } + log + u64(val as u64) +} - // 0 < val <= i32::MAX - #[inline] - pub const fn i32(val: i32) -> u32 { - u32(val as u32) - } +#[cfg(target_pointer_width = "16")] +#[inline] +pub const fn usize(val: usize) -> u32 { + u16(val as _) +} - // 0 < val <= i64::MAX - #[inline] - pub const fn i64(val: i64) -> u32 { - u64(val as u64) - } +#[cfg(target_pointer_width = "32")] +#[inline] +pub const fn usize(val: usize) -> u32 { + u32(val as _) +} - // 0 < val <= i128::MAX - #[inline] - pub const fn i128(val: i128) -> u32 { - u128(val as u128) - } +#[cfg(target_pointer_width = "64")] +#[inline] +pub const fn usize(val: usize) -> u32 { + u64(val as _) +} + +// 0 < val <= i8::MAX +#[inline] +pub const fn i8(val: i8) -> u32 { + u8(val as u8) } -macro_rules! impl_checked { - ($T:ident) => { - #[inline] - pub const fn $T(val: $T) -> Option { - if val > 0 { Some(unchecked::$T(val)) } else { None } - } - }; +// 0 < val <= i16::MAX +#[inline] +pub const fn i16(val: i16) -> u32 { + u16(val as u16) } -impl_checked! { u8 } -impl_checked! { u16 } -impl_checked! { u32 } -impl_checked! { u64 } -impl_checked! { u128 } -impl_checked! { i8 } -impl_checked! { i16 } -impl_checked! { i32 } -impl_checked! { i64 } -impl_checked! { i128 } +// 0 < val <= i32::MAX +#[inline] +pub const fn i32(val: i32) -> u32 { + u32(val as u32) +} + +// 0 < val <= i64::MAX +#[inline] +pub const fn i64(val: i64) -> u32 { + u64(val as u64) +} + +// 0 < val <= i128::MAX +#[inline] +pub const fn i128(val: i128) -> u32 { + u128(val as u128) +} diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 6f7c5a6d11994..79436c8e8ede4 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -2362,7 +2362,11 @@ macro_rules! int_impl { without modifying the original"] #[inline] pub const fn checked_log10(self) -> Option { - int_log10::$ActualT(self as $ActualT) + if self > 0 { + Some(int_log10::$ActualT(self as $ActualT)) + } else { + None + } } /// Computes the absolute value of `self`. diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index e3eab07b9df6d..721c030b410ae 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -264,7 +264,7 @@ const ASCII_CASE_MASK: u8 = 0b0010_0000; #[lang = "u8"] impl u8 { - uint_impl! { u8, u8, i8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", + uint_impl! { u8, u8, i8, NonZeroU8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", "[0x12]", "", "" } widening_impl! { u8, u16, 8, unsigned } @@ -813,21 +813,21 @@ impl u8 { #[lang = "u16"] impl u16 { - uint_impl! { u16, u16, i16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", + uint_impl! { u16, u16, i16, NonZeroU16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } widening_impl! { u16, u32, 16, unsigned } } #[lang = "u32"] impl u32 { - uint_impl! { u32, u32, i32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", + uint_impl! { u32, u32, i32, NonZeroU32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } widening_impl! { u32, u64, 32, unsigned } } #[lang = "u64"] impl u64 { - uint_impl! { u64, u64, i64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", + uint_impl! { u64, u64, i64, NonZeroU64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", @@ -837,7 +837,7 @@ impl u64 { #[lang = "u128"] impl u128 { - uint_impl! { u128, u128, i128, 128, 340282366920938463463374607431768211455, 16, + uint_impl! { u128, u128, i128, NonZeroU128, 128, 340282366920938463463374607431768211455, 16, "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012", "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48", "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ @@ -850,7 +850,7 @@ impl u128 { #[cfg(target_pointer_width = "16")] #[lang = "usize"] impl usize { - uint_impl! { usize, u16, isize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", + uint_impl! { usize, u16, isize, NonZeroUsize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } widening_impl! { usize, u32, 16, unsigned } @@ -858,7 +858,7 @@ impl usize { #[cfg(target_pointer_width = "32")] #[lang = "usize"] impl usize { - uint_impl! { usize, u32, isize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", + uint_impl! { usize, u32, isize, NonZeroUsize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } widening_impl! { usize, u64, 32, unsigned } @@ -867,7 +867,7 @@ impl usize { #[cfg(target_pointer_width = "64")] #[lang = "usize"] impl usize { - uint_impl! { usize, u64, isize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", + uint_impl! { usize, u64, isize, NonZeroUsize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 8f895c33a6328..e21ae48917953 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -302,7 +302,7 @@ nonzero_integers_div! { // A bunch of methods for unsigned nonzero types only. macro_rules! nonzero_unsigned_operations { - ( $( $Ty: ident($Int: ty); )+ ) => { + ( $( $Ty: ident($Int: ident); )+ ) => { $( impl $Ty { /// Add an unsigned integer to a non-zero value. @@ -442,6 +442,56 @@ macro_rules! nonzero_unsigned_operations { None } } + + /// Returns the base 2 logarithm of the number, rounded down. + /// + /// This is the same operation as + #[doc = concat!("[`", stringify!($Int), "::log2`],")] + /// except that it has no failure cases to worry about + /// since this value can never be zero. + /// + /// # Examples + /// + /// ``` + /// #![feature(int_log)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(7).unwrap().log2(), 2);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(8).unwrap().log2(), 3);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(9).unwrap().log2(), 3);")] + /// ``` + #[unstable(feature = "int_log", issue = "70887")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn log2(self) -> u32 { + <$Int>::BITS - 1 - self.leading_zeros() + } + + /// Returns the base 10 logarithm of the number, rounded down. + /// + /// This is the same operation as + #[doc = concat!("[`", stringify!($Int), "::log10`],")] + /// except that it has no failure cases to worry about + /// since this value can never be zero. + /// + /// # Examples + /// + /// ``` + /// #![feature(int_log)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(99).unwrap().log10(), 1);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(100).unwrap().log10(), 2);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(101).unwrap().log10(), 2);")] + /// ``` + #[unstable(feature = "int_log", issue = "70887")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn log10(self) -> u32 { + super::int_log10::$Int(self.0) + } } )+ } diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 1dd8b0a18ab1b..0bb654977764d 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1,5 +1,6 @@ macro_rules! uint_impl { - ($SelfT:ty, $ActualT:ident, $SignedT:ident, $BITS:expr, $MaxV:expr, + ($SelfT:ty, $ActualT:ident, $SignedT:ident, $NonZeroT:ident, + $BITS:expr, $MaxV:expr, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr, $reversed:expr, $le_bytes:expr, $be_bytes:expr, $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => { @@ -839,12 +840,10 @@ macro_rules! uint_impl { without modifying the original"] #[inline] pub const fn checked_log2(self) -> Option { - if self <= 0 { - None + if let Some(x) = <$NonZeroT>::new(self) { + Some(x.log2()) } else { - // SAFETY: We just checked that this number is positive - let log = (Self::BITS - 1) - unsafe { intrinsics::ctlz_nonzero(self) as u32 }; - Some(log) + None } } @@ -863,7 +862,11 @@ macro_rules! uint_impl { without modifying the original"] #[inline] pub const fn checked_log10(self) -> Option { - int_log10::$ActualT(self as $ActualT) + if let Some(x) = <$NonZeroT>::new(self) { + Some(x.log10()) + } else { + None + } } /// Checked negation. Computes `-self`, returning `None` unless `self == From e0e15c9747a0b5be0419a86d1b46ddf27c82820b Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 15 Jan 2022 20:22:34 -0800 Subject: [PATCH 21/22] Use `carrying_{mul|add}` in `num::bignum` Now that we have (unstable) methods for this, we don't need the bespoke trait methods for it in the `bignum` implementation. --- library/core/src/num/bignum.rs | 42 ++++------------------------------ 1 file changed, 5 insertions(+), 37 deletions(-) diff --git a/library/core/src/num/bignum.rs b/library/core/src/num/bignum.rs index 98d8a8a1d74ae..de85fdd6ed246 100644 --- a/library/core/src/num/bignum.rs +++ b/library/core/src/num/bignum.rs @@ -19,18 +19,8 @@ )] #![macro_use] -use crate::intrinsics; - /// Arithmetic operations required by bignums. pub trait FullOps: Sized { - /// Returns `(carry', v')` such that `carry' * 2^W + v' = self + other + carry`, - /// where `W` is the number of bits in `Self`. - fn full_add(self, other: Self, carry: bool) -> (bool /* carry */, Self); - - /// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + carry`, - /// where `W` is the number of bits in `Self`. - fn full_mul(self, other: Self, carry: Self) -> (Self /* carry */, Self); - /// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + other2 + carry`, /// where `W` is the number of bits in `Self`. fn full_mul_add(self, other: Self, other2: Self, carry: Self) -> (Self /* carry */, Self); @@ -45,22 +35,6 @@ macro_rules! impl_full_ops { ($($ty:ty: add($addfn:path), mul/div($bigty:ident);)*) => ( $( impl FullOps for $ty { - fn full_add(self, other: $ty, carry: bool) -> (bool, $ty) { - // This cannot overflow; the output is between `0` and `2 * 2^nbits - 1`. - // FIXME: will LLVM optimize this into ADC or similar? - let (v, carry1) = intrinsics::add_with_overflow(self, other); - let (v, carry2) = intrinsics::add_with_overflow(v, if carry {1} else {0}); - (carry1 || carry2, v) - } - - fn full_mul(self, other: $ty, carry: $ty) -> ($ty, $ty) { - // This cannot overflow; - // the output is between `0` and `2^nbits * (2^nbits - 1)`. - // FIXME: will LLVM optimize this into ADC or similar? - let v = (self as $bigty) * (other as $bigty) + (carry as $bigty); - ((v >> <$ty>::BITS) as $ty, v as $ty) - } - fn full_mul_add(self, other: $ty, other2: $ty, carry: $ty) -> ($ty, $ty) { // This cannot overflow; // the output is between `0` and `2^nbits * (2^nbits - 1)`. @@ -173,12 +147,11 @@ macro_rules! define_bignum { pub fn add<'a>(&'a mut self, other: &$name) -> &'a mut $name { use crate::cmp; use crate::iter; - use crate::num::bignum::FullOps; let mut sz = cmp::max(self.size, other.size); let mut carry = false; for (a, b) in iter::zip(&mut self.base[..sz], &other.base[..sz]) { - let (c, v) = (*a).full_add(*b, carry); + let (v, c) = (*a).carrying_add(*b, carry); *a = v; carry = c; } @@ -191,13 +164,11 @@ macro_rules! define_bignum { } pub fn add_small(&mut self, other: $ty) -> &mut $name { - use crate::num::bignum::FullOps; - - let (mut carry, v) = self.base[0].full_add(other, false); + let (v, mut carry) = self.base[0].carrying_add(other, false); self.base[0] = v; let mut i = 1; while carry { - let (c, v) = self.base[i].full_add(0, carry); + let (v, c) = self.base[i].carrying_add(0, carry); self.base[i] = v; carry = c; i += 1; @@ -212,12 +183,11 @@ macro_rules! define_bignum { pub fn sub<'a>(&'a mut self, other: &$name) -> &'a mut $name { use crate::cmp; use crate::iter; - use crate::num::bignum::FullOps; let sz = cmp::max(self.size, other.size); let mut noborrow = true; for (a, b) in iter::zip(&mut self.base[..sz], &other.base[..sz]) { - let (c, v) = (*a).full_add(!*b, noborrow); + let (v, c) = (*a).carrying_add(!*b, noborrow); *a = v; noborrow = c; } @@ -229,12 +199,10 @@ macro_rules! define_bignum { /// Multiplies itself by a digit-sized `other` and returns its own /// mutable reference. pub fn mul_small(&mut self, other: $ty) -> &mut $name { - use crate::num::bignum::FullOps; - let mut sz = self.size; let mut carry = 0; for a in &mut self.base[..sz] { - let (c, v) = (*a).full_mul(other, carry); + let (v, c) = (*a).carrying_mul(other, carry); *a = v; carry = c; } From 9a79ab6c0b50e993408e0afd33a5c5085e1fffc1 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 10 Jan 2022 15:59:52 +0100 Subject: [PATCH 22/22] rustc_codegen_llvm: Remove (almost) unused span parameter from many functions in metadata.rs. --- .../src/debuginfo/metadata.rs | 162 +++++------------- .../rustc_codegen_llvm/src/debuginfo/mod.rs | 19 +- 2 files changed, 51 insertions(+), 130 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 5c02e3d0fa7c7..3d5fd2f354e55 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -27,18 +27,18 @@ use rustc_fs_util::path_to_c_string; use rustc_hir::def::CtorKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_index::vec::{Idx, IndexVec}; +use rustc_middle::bug; use rustc_middle::mir::{self, GeneratorLayout}; use rustc_middle::ty::layout::{self, IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout}; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{ self, AdtKind, GeneratorSubsts, Instance, ParamEnv, Ty, TyCtxt, COMMON_VTABLE_ENTRIES, }; -use rustc_middle::{bug, span_bug}; use rustc_query_system::ich::NodeIdHashingMode; use rustc_session::config::{self, DebugInfo}; use rustc_span::symbol::Symbol; use rustc_span::FileNameDisplayPreference; -use rustc_span::{self, SourceFile, SourceFileHash, Span}; +use rustc_span::{self, SourceFile, SourceFileHash}; use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, TagEncoding}; use rustc_target::abi::{Int, Pointer, F32, F64}; use rustc_target::abi::{Primitive, Size, VariantIdx, Variants}; @@ -381,9 +381,8 @@ fn fixed_vec_metadata<'ll, 'tcx>( unique_type_id: UniqueTypeId, array_or_slice_type: Ty<'tcx>, element_type: Ty<'tcx>, - span: Span, ) -> MetadataCreationResult<'ll> { - let element_type_metadata = type_metadata(cx, element_type, span); + let element_type_metadata = type_metadata(cx, element_type); return_if_metadata_created_in_meantime!(cx, unique_type_id); @@ -416,11 +415,10 @@ fn vec_slice_metadata<'ll, 'tcx>( slice_ptr_type: Ty<'tcx>, element_type: Ty<'tcx>, unique_type_id: UniqueTypeId, - span: Span, ) -> MetadataCreationResult<'ll> { let data_ptr_type = cx.tcx.mk_imm_ptr(element_type); - let data_ptr_metadata = type_metadata(cx, data_ptr_type, span); + let data_ptr_metadata = type_metadata(cx, data_ptr_type); return_if_metadata_created_in_meantime!(cx, unique_type_id); @@ -442,7 +440,7 @@ fn vec_slice_metadata<'ll, 'tcx>( }, MemberDescription { name: "length".to_owned(), - type_metadata: type_metadata(cx, cx.tcx.types.usize, span), + type_metadata: type_metadata(cx, cx.tcx.types.usize), offset: pointer_size, size: usize_size, align: usize_align, @@ -452,8 +450,6 @@ fn vec_slice_metadata<'ll, 'tcx>( }, ]; - let file_metadata = unknown_file_metadata(cx); - let metadata = composite_type_metadata( cx, slice_ptr_type, @@ -461,8 +457,6 @@ fn vec_slice_metadata<'ll, 'tcx>( unique_type_id, member_descriptions, NO_SCOPE_METADATA, - file_metadata, - span, ); MetadataCreationResult::new(metadata, false) } @@ -471,7 +465,6 @@ fn subroutine_type_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, unique_type_id: UniqueTypeId, signature: ty::PolyFnSig<'tcx>, - span: Span, ) -> MetadataCreationResult<'ll> { let signature = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), signature); @@ -480,12 +473,12 @@ fn subroutine_type_metadata<'ll, 'tcx>( // return type match signature.output().kind() { ty::Tuple(tys) if tys.is_empty() => None, - _ => Some(type_metadata(cx, signature.output(), span)), + _ => Some(type_metadata(cx, signature.output())), }, ) .chain( // regular arguments - signature.inputs().iter().map(|argument_type| Some(type_metadata(cx, argument_type, span))), + signature.inputs().iter().map(|argument_type| Some(type_metadata(cx, argument_type))), ) .collect(); @@ -541,8 +534,6 @@ fn trait_pointer_metadata<'ll, 'tcx>( None => (NO_SCOPE_METADATA, compute_debuginfo_type_name(cx.tcx, trait_type, true)), }; - let file_metadata = unknown_file_metadata(cx); - let layout = cx.layout_of(cx.tcx.mk_mut_ptr(trait_type)); assert_eq!(abi::FAT_PTR_ADDR, 0); @@ -553,11 +544,7 @@ fn trait_pointer_metadata<'ll, 'tcx>( let member_descriptions = vec![ MemberDescription { name: "pointer".to_owned(), - type_metadata: type_metadata( - cx, - cx.tcx.mk_mut_ptr(cx.tcx.types.u8), - rustc_span::DUMMY_SP, - ), + type_metadata: type_metadata(cx, cx.tcx.mk_mut_ptr(cx.tcx.types.u8)), offset: layout.fields.offset(0), size: data_ptr_field.size, align: data_ptr_field.align.abi, @@ -567,7 +554,7 @@ fn trait_pointer_metadata<'ll, 'tcx>( }, MemberDescription { name: "vtable".to_owned(), - type_metadata: type_metadata(cx, vtable_field.ty, rustc_span::DUMMY_SP), + type_metadata: type_metadata(cx, vtable_field.ty), offset: layout.fields.offset(1), size: vtable_field.size, align: vtable_field.align.abi, @@ -584,16 +571,10 @@ fn trait_pointer_metadata<'ll, 'tcx>( unique_type_id, member_descriptions, containing_scope, - file_metadata, - rustc_span::DUMMY_SP, ) } -pub fn type_metadata<'ll, 'tcx>( - cx: &CodegenCx<'ll, 'tcx>, - t: Ty<'tcx>, - usage_site_span: Span, -) -> &'ll DIType { +pub fn type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { // Get the unique type ID of this type. let unique_type_id = { let mut type_map = debug_context(cx).type_map.borrow_mut(); @@ -630,14 +611,14 @@ pub fn type_metadata<'ll, 'tcx>( debug!("type_metadata: {:?}", t); let ptr_metadata = |ty: Ty<'tcx>| match *ty.kind() { - ty::Slice(typ) => Ok(vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span)), - ty::Str => Ok(vec_slice_metadata(cx, t, cx.tcx.types.u8, unique_type_id, usage_site_span)), + ty::Slice(typ) => Ok(vec_slice_metadata(cx, t, typ, unique_type_id)), + ty::Str => Ok(vec_slice_metadata(cx, t, cx.tcx.types.u8, unique_type_id)), ty::Dynamic(..) => Ok(MetadataCreationResult::new( trait_pointer_metadata(cx, ty, Some(t), unique_type_id), false, )), _ => { - let pointee_metadata = type_metadata(cx, ty, usage_site_span); + let pointee_metadata = type_metadata(cx, ty); if let Some(metadata) = debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id) @@ -656,10 +637,8 @@ pub fn type_metadata<'ll, 'tcx>( ty::Tuple(elements) if elements.is_empty() => { MetadataCreationResult::new(basic_type_metadata(cx, t), false) } - ty::Array(typ, _) | ty::Slice(typ) => { - fixed_vec_metadata(cx, unique_type_id, t, typ, usage_site_span) - } - ty::Str => fixed_vec_metadata(cx, unique_type_id, t, cx.tcx.types.i8, usage_site_span), + ty::Array(typ, _) | ty::Slice(typ) => fixed_vec_metadata(cx, unique_type_id, t, typ), + ty::Str => fixed_vec_metadata(cx, unique_type_id, t, cx.tcx.types.i8), ty::Dynamic(..) => { MetadataCreationResult::new(trait_pointer_metadata(cx, t, None, unique_type_id), false) } @@ -710,8 +689,7 @@ pub fn type_metadata<'ll, 'tcx>( type_map.borrow_mut().register_type_with_metadata(t, temp_type); let fn_metadata = - subroutine_type_metadata(cx, unique_type_id, t.fn_sig(cx.tcx), usage_site_span) - .metadata; + subroutine_type_metadata(cx, unique_type_id, t.fn_sig(cx.tcx)).metadata; type_map.borrow_mut().remove_type(t); @@ -721,15 +699,8 @@ pub fn type_metadata<'ll, 'tcx>( ty::Closure(def_id, substs) => { let upvar_tys: Vec<_> = substs.as_closure().upvar_tys().collect(); let containing_scope = get_namespace_for_item(cx, def_id); - prepare_tuple_metadata( - cx, - t, - &upvar_tys, - unique_type_id, - usage_site_span, - Some(containing_scope), - ) - .finalize(cx) + prepare_tuple_metadata(cx, t, &upvar_tys, unique_type_id, Some(containing_scope)) + .finalize(cx) } ty::Generator(def_id, substs, _) => { let upvar_tys: Vec<_> = substs @@ -737,25 +708,18 @@ pub fn type_metadata<'ll, 'tcx>( .prefix_tys() .map(|t| cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)) .collect(); - prepare_enum_metadata(cx, t, def_id, unique_type_id, usage_site_span, upvar_tys) - .finalize(cx) + prepare_enum_metadata(cx, t, def_id, unique_type_id, upvar_tys).finalize(cx) } ty::Adt(def, ..) => match def.adt_kind() { - AdtKind::Struct => { - prepare_struct_metadata(cx, t, unique_type_id, usage_site_span).finalize(cx) - } - AdtKind::Union => { - prepare_union_metadata(cx, t, unique_type_id, usage_site_span).finalize(cx) - } + AdtKind::Struct => prepare_struct_metadata(cx, t, unique_type_id).finalize(cx), + AdtKind::Union => prepare_union_metadata(cx, t, unique_type_id).finalize(cx), AdtKind::Enum => { - prepare_enum_metadata(cx, t, def.did, unique_type_id, usage_site_span, vec![]) - .finalize(cx) + prepare_enum_metadata(cx, t, def.did, unique_type_id, vec![]).finalize(cx) } }, ty::Tuple(elements) => { let tys: Vec<_> = elements.iter().map(|k| k.expect_ty()).collect(); - prepare_tuple_metadata(cx, t, &tys, unique_type_id, usage_site_span, NO_SCOPE_METADATA) - .finalize(cx) + prepare_tuple_metadata(cx, t, &tys, unique_type_id, NO_SCOPE_METADATA).finalize(cx) } // Type parameters from polymorphized functions. ty::Param(_) => MetadataCreationResult::new(param_type_metadata(cx, t), false), @@ -770,8 +734,7 @@ pub fn type_metadata<'ll, 'tcx>( let metadata_for_uid = match type_map.find_metadata_for_unique_id(unique_type_id) { Some(metadata) => metadata, None => { - span_bug!( - usage_site_span, + bug!( "expected type metadata for unique \ type ID '{}' to already be in \ the `debuginfo::TypeMap` but it \ @@ -785,8 +748,7 @@ pub fn type_metadata<'ll, 'tcx>( match type_map.find_metadata_for_type(t) { Some(metadata) => { if metadata != metadata_for_uid { - span_bug!( - usage_site_span, + bug!( "mismatch between `Ty` and \ `UniqueTypeId` maps in \ `debuginfo::TypeMap`. \ @@ -1283,7 +1245,6 @@ impl<'ll, 'tcx> MemberDescriptionFactory<'ll, 'tcx> { struct StructMemberDescriptionFactory<'tcx> { ty: Ty<'tcx>, variant: &'tcx ty::VariantDef, - span: Span, } impl<'tcx> StructMemberDescriptionFactory<'tcx> { @@ -1305,7 +1266,7 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> { let field = layout.field(cx, i); MemberDescription { name, - type_metadata: type_metadata(cx, field.ty, self.span), + type_metadata: type_metadata(cx, field.ty), offset: layout.fields.offset(i), size: field.size, align: field.align.abi, @@ -1322,7 +1283,6 @@ fn prepare_struct_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, struct_type: Ty<'tcx>, unique_type_id: UniqueTypeId, - span: Span, ) -> RecursiveTypeDescription<'ll, 'tcx> { let struct_name = compute_debuginfo_type_name(cx.tcx, struct_type, false); @@ -1348,7 +1308,7 @@ fn prepare_struct_metadata<'ll, 'tcx>( unique_type_id, struct_metadata_stub, struct_metadata_stub, - StructMDF(StructMemberDescriptionFactory { ty: struct_type, variant, span }), + StructMDF(StructMemberDescriptionFactory { ty: struct_type, variant }), ) } @@ -1385,7 +1345,6 @@ fn closure_saved_names_of_captured_variables(tcx: TyCtxt<'_>, def_id: DefId) -> struct TupleMemberDescriptionFactory<'tcx> { ty: Ty<'tcx>, component_types: Vec>, - span: Span, } impl<'tcx> TupleMemberDescriptionFactory<'tcx> { @@ -1412,7 +1371,7 @@ impl<'tcx> TupleMemberDescriptionFactory<'tcx> { }; MemberDescription { name, - type_metadata: type_metadata(cx, component_type, self.span), + type_metadata: type_metadata(cx, component_type), offset: layout.fields.offset(i), size, align, @@ -1430,7 +1389,6 @@ fn prepare_tuple_metadata<'ll, 'tcx>( tuple_type: Ty<'tcx>, component_types: &[Ty<'tcx>], unique_type_id: UniqueTypeId, - span: Span, containing_scope: Option<&'ll DIScope>, ) -> RecursiveTypeDescription<'ll, 'tcx> { let tuple_name = compute_debuginfo_type_name(cx.tcx, tuple_type, false); @@ -1453,7 +1411,6 @@ fn prepare_tuple_metadata<'ll, 'tcx>( TupleMDF(TupleMemberDescriptionFactory { ty: tuple_type, component_types: component_types.to_vec(), - span, }), ) } @@ -1465,7 +1422,6 @@ fn prepare_tuple_metadata<'ll, 'tcx>( struct UnionMemberDescriptionFactory<'tcx> { layout: TyAndLayout<'tcx>, variant: &'tcx ty::VariantDef, - span: Span, } impl<'tcx> UnionMemberDescriptionFactory<'tcx> { @@ -1481,7 +1437,7 @@ impl<'tcx> UnionMemberDescriptionFactory<'tcx> { let field = self.layout.field(cx, i); MemberDescription { name: f.name.to_string(), - type_metadata: type_metadata(cx, field.ty, self.span), + type_metadata: type_metadata(cx, field.ty), offset: Size::ZERO, size: field.size, align: field.align.abi, @@ -1498,7 +1454,6 @@ fn prepare_union_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, union_type: Ty<'tcx>, unique_type_id: UniqueTypeId, - span: Span, ) -> RecursiveTypeDescription<'ll, 'tcx> { let union_name = compute_debuginfo_type_name(cx.tcx, union_type, false); @@ -1518,7 +1473,7 @@ fn prepare_union_metadata<'ll, 'tcx>( unique_type_id, union_metadata_stub, union_metadata_stub, - UnionMDF(UnionMemberDescriptionFactory { layout: cx.layout_of(union_type), variant, span }), + UnionMDF(UnionMemberDescriptionFactory { layout: cx.layout_of(union_type), variant }), ) } @@ -1573,7 +1528,6 @@ struct EnumMemberDescriptionFactory<'ll, 'tcx> { layout: TyAndLayout<'tcx>, tag_type_metadata: Option<&'ll DIType>, common_members: Vec>, - span: Span, } impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { @@ -1605,7 +1559,7 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { // msvc, then we need to use a different, fallback encoding of the debuginfo. let fallback = cpp_like_debuginfo(cx.tcx); // This will always find the metadata in the type map. - let self_metadata = type_metadata(cx, self.enum_type, self.span); + let self_metadata = type_metadata(cx, self.enum_type); match self.layout.variants { Variants::Single { index } => { @@ -1617,7 +1571,7 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { let variant_info = variant_info_for(index); let (variant_type_metadata, member_description_factory) = - describe_enum_variant(cx, self.layout, variant_info, self_metadata, self.span); + describe_enum_variant(cx, self.layout, variant_info, self_metadata); let member_descriptions = member_description_factory.create_member_descriptions(cx); @@ -1682,13 +1636,8 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { .map(|(i, _)| { let variant = self.layout.for_variant(cx, i); let variant_info = variant_info_for(i); - let (variant_type_metadata, member_desc_factory) = describe_enum_variant( - cx, - variant, - variant_info, - self_metadata, - self.span, - ); + let (variant_type_metadata, member_desc_factory) = + describe_enum_variant(cx, variant, variant_info, self_metadata); let member_descriptions = member_desc_factory.create_member_descriptions(cx); @@ -1807,7 +1756,7 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { tag.value.size(cx).bits(), tag.value.align(cx).abi.bits() as u32, create_DIArray(DIB(cx), &tags), - type_metadata(cx, discr_enum_ty, self.span), + type_metadata(cx, discr_enum_ty), true, ) }; @@ -1818,7 +1767,6 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { dataful_variant_layout, variant_info, self_metadata, - self.span, ); let member_descriptions = member_desc_factory.create_member_descriptions(cx); @@ -1864,13 +1812,7 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { let variant = self.layout.for_variant(cx, i); let variant_info = variant_info_for(i); let (variant_type_metadata, member_desc_factory) = - describe_enum_variant( - cx, - variant, - variant_info, - self_metadata, - self.span, - ); + describe_enum_variant(cx, variant, variant_info, self_metadata); let member_descriptions = member_desc_factory.create_member_descriptions(cx); @@ -1908,7 +1850,6 @@ struct VariantMemberDescriptionFactory<'tcx> { /// Cloned from the `layout::Struct` describing the variant. offsets: Vec, args: Vec<(String, Ty<'tcx>)>, - span: Span, } impl<'tcx> VariantMemberDescriptionFactory<'tcx> { @@ -1923,7 +1864,7 @@ impl<'tcx> VariantMemberDescriptionFactory<'tcx> { let (size, align) = cx.size_and_align_of(ty); MemberDescription { name: name.to_string(), - type_metadata: type_metadata(cx, ty, self.span), + type_metadata: type_metadata(cx, ty), offset: self.offsets[i], size, align, @@ -2011,7 +1952,6 @@ fn describe_enum_variant<'ll, 'tcx>( layout: layout::TyAndLayout<'tcx>, variant: VariantInfo<'_, 'tcx>, containing_scope: &'ll DIScope, - span: Span, ) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) { let metadata_stub = variant.map_struct_name(|variant_name| { let unique_type_id = debug_context(cx) @@ -2033,8 +1973,7 @@ fn describe_enum_variant<'ll, 'tcx>( .map(|i| (variant.field_name(i), layout.field(cx, i).ty)) .collect(); - let member_description_factory = - VariantMDF(VariantMemberDescriptionFactory { offsets, args, span }); + let member_description_factory = VariantMDF(VariantMemberDescriptionFactory { offsets, args }); (metadata_stub, member_description_factory) } @@ -2044,7 +1983,6 @@ fn prepare_enum_metadata<'ll, 'tcx>( enum_type: Ty<'tcx>, enum_def_id: DefId, unique_type_id: UniqueTypeId, - span: Span, outer_field_tys: Vec>, ) -> RecursiveTypeDescription<'ll, 'tcx> { let tcx = cx.tcx; @@ -2109,8 +2047,7 @@ fn prepare_enum_metadata<'ll, 'tcx>( Some(discriminant_type_metadata) => discriminant_type_metadata, None => { let (discriminant_size, discriminant_align) = (discr.size(cx), discr.align(cx)); - let discriminant_base_type_metadata = - type_metadata(cx, discr.to_ty(tcx), rustc_span::DUMMY_SP); + let discriminant_base_type_metadata = type_metadata(cx, discr.to_ty(tcx)); let item_name; let discriminant_name = match enum_type.kind() { @@ -2202,7 +2139,6 @@ fn prepare_enum_metadata<'ll, 'tcx>( layout, tag_type_metadata: discriminant_type_metadata, common_members: vec![], - span, }), ); } @@ -2272,11 +2208,8 @@ fn prepare_enum_metadata<'ll, 'tcx>( let outer_fields = match layout.variants { Variants::Single { .. } => vec![], Variants::Multiple { .. } => { - let tuple_mdf = TupleMemberDescriptionFactory { - ty: enum_type, - component_types: outer_field_tys, - span, - }; + let tuple_mdf = + TupleMemberDescriptionFactory { ty: enum_type, component_types: outer_field_tys }; tuple_mdf .create_member_descriptions(cx) .into_iter() @@ -2352,7 +2285,6 @@ fn prepare_enum_metadata<'ll, 'tcx>( layout, tag_type_metadata: None, common_members: outer_fields, - span, }), ) } @@ -2368,11 +2300,6 @@ fn composite_type_metadata<'ll, 'tcx>( composite_type_unique_id: UniqueTypeId, member_descriptions: Vec>, containing_scope: Option<&'ll DIScope>, - - // Ignore source location information as long as it - // can't be reconstructed for non-local crates. - _file_metadata: &'ll DIFile, - _definition_span: Span, ) -> &'ll DICompositeType { // Create the (empty) struct metadata node ... let composite_type_metadata = create_struct_stub( @@ -2450,8 +2377,7 @@ fn compute_type_parameters<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) - if let GenericArgKind::Type(ty) = kind.unpack() { let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); - let actual_type_metadata = - type_metadata(cx, actual_type, rustc_span::DUMMY_SP); + let actual_type_metadata = type_metadata(cx, actual_type); let name = name.as_str(); Some(unsafe { Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( @@ -2593,7 +2519,7 @@ pub fn create_global_var_metadata<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, g let is_local_to_unit = is_node_local_to_unit(cx, def_id); let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, ty::ParamEnv::reveal_all()); - let type_metadata = type_metadata(cx, variable_type, span); + let type_metadata = type_metadata(cx, variable_type); let var_name = tcx.item_name(def_id); let var_name = var_name.as_str(); let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id)).name; @@ -2648,7 +2574,7 @@ fn vtable_type_metadata<'ll, 'tcx>( // things simple instead of adding some ad-hoc disambiguation scheme. let vtable_type = tcx.mk_array(tcx.mk_imm_ptr(tcx.types.unit), vtable_entries.len() as u64); - type_metadata(cx, vtable_type, rustc_span::DUMMY_SP) + type_metadata(cx, vtable_type) } /// Creates debug information for the given vtable, which is for the diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index d1cea147a7a70..61e49fab6ff88 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -390,7 +390,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { signature.push(if fn_abi.ret.is_ignore() { None } else { - Some(type_metadata(cx, fn_abi.ret.layout.ty, rustc_span::DUMMY_SP)) + Some(type_metadata(cx, fn_abi.ret.layout.ty)) }); // Arguments types @@ -415,15 +415,11 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { } _ => t, }; - Some(type_metadata(cx, t, rustc_span::DUMMY_SP)) + Some(type_metadata(cx, t)) })); } else { - signature.extend( - fn_abi - .args - .iter() - .map(|arg| Some(type_metadata(cx, arg.layout.ty, rustc_span::DUMMY_SP))), - ); + signature + .extend(fn_abi.args.iter().map(|arg| Some(type_metadata(cx, arg.layout.ty)))); } create_DIArray(DIB(cx), &signature[..]) @@ -453,8 +449,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { if let GenericArgKind::Type(ty) = kind.unpack() { let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); - let actual_type_metadata = - type_metadata(cx, actual_type, rustc_span::DUMMY_SP); + let actual_type_metadata = type_metadata(cx, actual_type); let name = name.as_str(); Some(unsafe { Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( @@ -509,7 +504,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { if cx.sess().opts.debuginfo == DebugInfo::Full && !impl_self_ty.needs_subst() { - Some(type_metadata(cx, impl_self_ty, rustc_span::DUMMY_SP)) + Some(type_metadata(cx, impl_self_ty)) } else { Some(namespace::item_namespace(cx, def.did)) } @@ -584,7 +579,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { let loc = self.lookup_debug_loc(span.lo()); let file_metadata = file_metadata(self, &loc.file); - let type_metadata = type_metadata(self, variable_type, span); + let type_metadata = type_metadata(self, variable_type); let (argument_index, dwarf_tag) = match variable_kind { ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),