From 09195d38225a478d4b10f535a80ca7ab9d5173e8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 10 Apr 2022 17:21:58 +0300 Subject: [PATCH 1/8] resolve: Create dummy bindings for all unresolved imports --- compiler/rustc_resolve/src/imports.rs | 58 +++++++++---------- .../intra-doc/unresolved-import-recovery.rs | 6 ++ .../unresolved-import-recovery.stderr | 11 ++++ src/test/ui/use/use-super-global-path.rs | 2 +- src/test/ui/use/use-super-global-path.stderr | 16 +---- 5 files changed, 48 insertions(+), 45 deletions(-) create mode 100644 src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.rs create mode 100644 src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 02abdbaa98354..1512d2d49f732 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -583,18 +583,23 @@ impl<'a> Resolver<'a> { t } - // Define a "dummy" resolution containing a Res::Err as a placeholder for a - // failed resolution + // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed resolution, + // also mark such failed imports as used to avoid duplicate diagnostics. fn import_dummy_binding(&mut self, import: &'a Import<'a>) { - if let ImportKind::Single { target, .. } = import.kind { + if let ImportKind::Single { target, ref target_bindings, .. } = import.kind { + if target_bindings.iter().any(|binding| binding.get().is_some()) { + return; // Has resolution, do not create the dummy binding + } let dummy_binding = self.dummy_binding; let dummy_binding = self.import(dummy_binding, import); self.per_ns(|this, ns| { let key = this.new_key(target, ns); let _ = this.try_define(import.parent_scope.module, key, dummy_binding); }); - // Consider erroneous imports used to avoid duplicate diagnostics. self.record_use(target, dummy_binding, false); + } else if import.imported_module.get().is_none() { + import.used.set(true); + self.used_imports.insert(import.id); } } } @@ -659,7 +664,13 @@ impl<'a, 'b> ImportResolver<'a, 'b> { .map(|i| (false, i)) .chain(indeterminate_imports.into_iter().map(|i| (true, i))) { - if let Some(err) = self.finalize_import(import) { + let unresolved_import_error = self.finalize_import(import); + + // If this import is unresolved then create a dummy import + // resolution for it so that later resolve stages won't complain. + self.r.import_dummy_binding(import); + + if let Some(err) = unresolved_import_error { if let ImportKind::Single { source, ref source_bindings, .. } = import.kind { if source.name == kw::SelfLower { // Silence `unresolved import` error if E0429 is already emitted @@ -669,9 +680,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } } - // If the error is a single failed import then create a "fake" import - // resolution for it so that later resolve stages won't complain. - self.r.import_dummy_binding(import); if prev_root_id.as_u32() != 0 && prev_root_id.as_u32() != import.root_id.as_u32() && !errors.is_empty() @@ -691,8 +699,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> { prev_root_id = import.root_id; } } else if is_indeterminate { - // Consider erroneous imports used to avoid duplicate diagnostics. - self.r.used_imports.insert(import.id); let path = import_path_to_string( &import.module_path.iter().map(|seg| seg.ident).collect::>(), &import.kind, @@ -824,26 +830,23 @@ impl<'a, 'b> ImportResolver<'a, 'b> { Err(Undetermined) => indeterminate = true, // Don't update the resolution, because it was never added. Err(Determined) if target.name == kw::Underscore => {} - Err(Determined) => { + Ok(binding) if binding.is_importable() => { + let imported_binding = this.import(binding, import); + target_bindings[ns].set(Some(imported_binding)); + this.define(parent, target, ns, imported_binding); + } + source_binding @ (Ok(..) | Err(Determined)) => { + if source_binding.is_ok() { + let msg = format!("`{}` is not directly importable", target); + struct_span_err!(this.session, import.span, E0253, "{}", &msg) + .span_label(import.span, "cannot be imported directly") + .emit(); + } let key = this.new_key(target, ns); this.update_resolution(parent, key, |_, resolution| { resolution.single_imports.remove(&Interned::new_unchecked(import)); }); } - Ok(binding) if !binding.is_importable() => { - let msg = format!("`{}` is not directly importable", target); - struct_span_err!(this.session, import.span, E0253, "{}", &msg) - .span_label(import.span, "cannot be imported directly") - .emit(); - // Do not import this illegal binding. Import a dummy binding and pretend - // everything is fine - this.import_dummy_binding(import); - } - Ok(binding) => { - let imported_binding = this.import(binding, import); - target_bindings[ns].set(Some(imported_binding)); - this.define(parent, target, ns, imported_binding); - } } } }); @@ -876,10 +879,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> { self.r.unusable_binding = orig_unusable_binding; } import.vis.set(orig_vis); - if let PathResult::Failed { .. } | PathResult::NonModule(..) = path_res { - // Consider erroneous imports used to avoid duplicate diagnostics. - self.r.used_imports.insert(import.id); - } let module = match path_res { PathResult::Module(module) => { // Consistency checks, analogous to `finalize_macro_resolutions`. @@ -1144,7 +1143,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> { }) } else { // `resolve_ident_in_module` reported a privacy error. - self.r.import_dummy_binding(import); None }; } diff --git a/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.rs b/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.rs new file mode 100644 index 0000000000000..c71e5bee12ead --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.rs @@ -0,0 +1,6 @@ +// Regression test for issue #95879. + +use unresolved_crate::module::Name; //~ ERROR failed to resolve + +/// [Name] +pub struct S; diff --git a/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr b/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr new file mode 100644 index 0000000000000..b60ab6050d79c --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr @@ -0,0 +1,11 @@ +error[E0433]: failed to resolve: maybe a missing crate `unresolved_crate`? + --> $DIR/unresolved-import-recovery.rs:3:5 + | +LL | use unresolved_crate::module::Name; + | ^^^^^^^^^^^^^^^^ maybe a missing crate `unresolved_crate`? + +error: Compilation failed, aborting rustdoc + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/use/use-super-global-path.rs b/src/test/ui/use/use-super-global-path.rs index 27a4a653b4903..64bfd14b7e7da 100644 --- a/src/test/ui/use/use-super-global-path.rs +++ b/src/test/ui/use/use-super-global-path.rs @@ -9,7 +9,7 @@ mod foo { pub fn g() { use ::super::main; //~ ERROR global paths cannot start with `super` - main(); //~ ERROR cannot find function `main` in this scope + main(); } } diff --git a/src/test/ui/use/use-super-global-path.stderr b/src/test/ui/use/use-super-global-path.stderr index edde26c1fc15d..7014a12e9ddd2 100644 --- a/src/test/ui/use/use-super-global-path.stderr +++ b/src/test/ui/use/use-super-global-path.stderr @@ -16,18 +16,6 @@ error[E0433]: failed to resolve: global paths cannot start with `super` LL | use ::super::main; | ^^^^^ global paths cannot start with `super` -error[E0425]: cannot find function `main` in this scope - --> $DIR/use-super-global-path.rs:12:9 - | -LL | main(); - | ^^^^ not found in this scope - | -help: consider importing this function - | -LL | use main; - | - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0425, E0433. -For more information about an error, try `rustc --explain E0425`. +For more information about this error, try `rustc --explain E0433`. From bbd7ce690452f28d459643d97fbae89109cf5808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 13 Apr 2022 22:18:28 +0200 Subject: [PATCH 2/8] couple of clippy::perf fixes --- .../src/debuginfo/metadata/enums/cpp_like.rs | 1 - compiler/rustc_errors/src/lib.rs | 2 +- compiler/rustc_expand/src/mbe/macro_parser.rs | 2 +- compiler/rustc_mir_build/src/thir/pattern/check_match.rs | 2 +- .../src/traits/error_reporting/suggestions.rs | 4 ++-- src/librustdoc/passes/html_tags.rs | 2 +- 6 files changed, 6 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index 31bb9ed318589..d6e2c8ccdf44a 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -372,7 +372,6 @@ fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>( // Build the type node for each field. let variant_field_infos: SmallVec> = variant_range - .clone() .map(|variant_index| { let variant_struct_type_di_node = super::build_generator_variant_struct_type_di_node( cx, diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index c927fcb2109cb..4c1a39318649a 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1208,7 +1208,7 @@ impl HandlerInner { (0, 0) => return, (0, _) => self.emitter.emit_diagnostic(&Diagnostic::new( Level::Warning, - DiagnosticMessage::Str(warnings.to_owned()), + DiagnosticMessage::Str(warnings), )), (_, 0) => { let _ = self.fatal(&errors); diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index b5f56d7d6dc84..cda3d0fd2bfb6 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -589,7 +589,7 @@ impl TtParser { (_, 0) => { // Dump all possible `next_mps` into `cur_mps` for the next iteration. Then // process the next token. - self.cur_mps.extend(self.next_mps.drain(..)); + self.cur_mps.append(&mut self.next_mps); parser.to_mut().bump(); } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 44caa2ac076f2..58e484e413dab 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -844,7 +844,7 @@ fn non_exhaustive_match<'p, 'tcx>( format!( "{}{}{} => todo!()", comma, - snippet.strip_prefix(",").unwrap_or(&snippet), + snippet.strip_prefix(',').unwrap_or(&snippet), pattern ), )); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index ead1f0126c465..7485c082f4eaf 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2724,9 +2724,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &format!( "consider annotating `{}` with `#[derive({})]`", trait_pred.skip_binder().self_ty(), - diagnostic_name.to_string(), + diagnostic_name, ), - format!("#[derive({})]\n", diagnostic_name.to_string()), + format!("#[derive({})]\n", diagnostic_name), Applicability::MaybeIncorrect, ); } diff --git a/src/librustdoc/passes/html_tags.rs b/src/librustdoc/passes/html_tags.rs index 00e10c6d5a7c7..a620ffa987860 100644 --- a/src/librustdoc/passes/html_tags.rs +++ b/src/librustdoc/passes/html_tags.rs @@ -215,7 +215,7 @@ impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> { // We don't try to detect stuff `` because that's not valid HTML, // and we don't try to detect stuff `` because that's not valid Rust. if let Some(Some(generics_start)) = (is_open_tag - && dox[..range.end].ends_with(">")) + && dox[..range.end].ends_with('>')) .then(|| extract_path_backwards(&dox, range.start)) { let generics_sp = match super::source_span_for_markdown_range( From f6d957701f8113d8c05e6a2397b93ad6fc450400 Mon Sep 17 00:00:00 2001 From: Boyd Kane <33420535+beyarkay@users.noreply.github.com> Date: Thu, 14 Apr 2022 09:51:47 +0200 Subject: [PATCH 3/8] docs: add link from zip to unzip The docs for `Iterator::unzip` explain that it is kind of an inverse operation to `Iterator::zip` and guide the reader to the `zip` docs, but the `zip` docs don't let the user know that they can undo the `zip` operation with `unzip`. This change modifies the docs to help the user find `unzip`. --- library/core/src/iter/traits/iterator.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 53fbe4cbc42f5..eae29278f5572 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -469,6 +469,10 @@ pub trait Iterator { /// If the zipped iterator has no more elements to return then each further attempt to advance /// it will first try to advance the first iterator at most one time and if it still yielded an item /// try to advance the second iterator at most one time. + /// + /// To 'undo' the result of zipping up two iterators, see [`unzip`]. + /// + /// [`unzip`]: Iterator::unzip /// /// # Examples /// From d73e32867f45690720c17422b83c8abc8ceff645 Mon Sep 17 00:00:00 2001 From: Boyd Kane <33420535+beyarkay@users.noreply.github.com> Date: Thu, 14 Apr 2022 11:19:49 +0200 Subject: [PATCH 4/8] Remove trailing whitespace Co-authored-by: Mara Bos --- library/core/src/iter/traits/iterator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index eae29278f5572..69f06fb06ef5d 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -469,7 +469,7 @@ pub trait Iterator { /// If the zipped iterator has no more elements to return then each further attempt to advance /// it will first try to advance the first iterator at most one time and if it still yielded an item /// try to advance the second iterator at most one time. - /// + /// /// To 'undo' the result of zipping up two iterators, see [`unzip`]. /// /// [`unzip`]: Iterator::unzip From 1e78a47faec4c45af8f99bfda091d17b3b668a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Thu, 14 Apr 2022 15:42:13 +0300 Subject: [PATCH 5/8] :arrow_up: rust-analyzer --- src/tools/rust-analyzer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index 46d7ee68f2628..24cf957627d5e 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit 46d7ee68f26285db26b2640f2c07d6332380c756 +Subproject commit 24cf957627d5ede1b395f92ff871fd7a281d49a4 From 9d319f370134afc9c46965f2b9af23dc5d625124 Mon Sep 17 00:00:00 2001 From: Keita Nonaka Date: Wed, 13 Apr 2022 22:37:41 -0700 Subject: [PATCH 6/8] update: actions/checkout@v2 to actions/checkout@v3 update: actions/checkout@v2 to actions/checkout@v3 for all yaml files Revert "update: actions/checkout@v2 to actions/checkout@v3 for all yaml files" This reverts commit 7445e582b900f0f56f5f2bd9036aacab97ef28e9. change GitHub Actions version v2 to v3 change GitHub Actions --- .github/workflows/ci.yml | 8 ++++---- src/ci/github-actions/ci.yml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ff3a832631530..451116f320d64 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: - name: disable git crlf conversion run: git config --global core.autocrlf false - name: checkout the source code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 2 - name: configure the PR in which the error message will be posted @@ -454,7 +454,7 @@ jobs: - name: disable git crlf conversion run: git config --global core.autocrlf false - name: checkout the source code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 2 - name: configure the PR in which the error message will be posted @@ -567,7 +567,7 @@ jobs: - name: disable git crlf conversion run: git config --global core.autocrlf false - name: checkout the source code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 2 - name: configure the PR in which the error message will be posted @@ -670,7 +670,7 @@ jobs: if: "github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'rust-lang-ci/rust'" steps: - name: checkout the source code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 2 - name: publish toolstate diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 5622422d50f52..173ee170c9f58 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -99,7 +99,7 @@ x--expand-yaml-anchors--remove: run: git config --global core.autocrlf false - name: checkout the source code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 2 @@ -703,7 +703,7 @@ jobs: if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'rust-lang-ci/rust' steps: - name: checkout the source code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 2 From 753d567989e9cd8f6b1a2b707c231d70838b7819 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Thu, 14 Apr 2022 19:03:56 -0400 Subject: [PATCH 7/8] clarify doc(cfg) wording The current "This is supported" wording implies that it's possible to still use the item on other configurations, but in an unsupported way. Changing this to "Available" removes this ambiguity. --- .../src/language-features/doc-cfg.md | 2 +- src/librustdoc/clean/cfg.rs | 9 ++--- src/librustdoc/clean/cfg/tests.rs | 40 ++++++++----------- src/test/rustdoc-gui/item-info-overflow.goml | 4 +- src/test/rustdoc-gui/item-info-width.goml | 2 +- src/test/rustdoc/doc-cfg.rs | 22 +++++----- src/test/rustdoc/duplicate-cfg.rs | 18 ++++----- 7 files changed, 43 insertions(+), 54 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/doc-cfg.md b/src/doc/unstable-book/src/language-features/doc-cfg.md index e75f1aea99229..b15f5ee66aba1 100644 --- a/src/doc/unstable-book/src/language-features/doc-cfg.md +++ b/src/doc/unstable-book/src/language-features/doc-cfg.md @@ -7,7 +7,7 @@ The tracking issue for this feature is: [#43781] The `doc_cfg` feature allows an API be documented as only available in some specific platforms. This attribute has two effects: -1. In the annotated item's documentation, there will be a message saying "This is supported on +1. In the annotated item's documentation, there will be a message saying "Available on (platform) only". 2. The item's doc-tests will only run on the specific platform. diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index b72d262417755..0d213a5a2dee9 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -171,11 +171,8 @@ impl Cfg { pub(crate) fn render_long_html(&self) -> String { let on = if self.should_use_with_in_description() { "with" } else { "on" }; - let mut msg = format!( - "This is supported {} {}", - on, - Display(self, Format::LongHtml) - ); + let mut msg = + format!("Available {on} {}", Display(self, Format::LongHtml)); if self.should_append_only_to_description() { msg.push_str(" only"); } @@ -187,7 +184,7 @@ impl Cfg { pub(crate) fn render_long_plain(&self) -> String { let on = if self.should_use_with_in_description() { "with" } else { "on" }; - let mut msg = format!("This is supported {} {}", on, Display(self, Format::LongPlain)); + let mut msg = format!("Available {on} {}", Display(self, Format::LongPlain)); if self.should_append_only_to_description() { msg.push_str(" only"); } diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs index 275d1b3ebd938..ece3fcb18b6f3 100644 --- a/src/librustdoc/clean/cfg/tests.rs +++ b/src/librustdoc/clean/cfg/tests.rs @@ -359,81 +359,73 @@ fn test_render_short_html() { #[test] fn test_render_long_html() { create_default_session_globals_then(|| { - assert_eq!( - word_cfg("unix").render_long_html(), - "This is supported on Unix only." - ); + assert_eq!(word_cfg("unix").render_long_html(), "Available on Unix only."); assert_eq!( name_value_cfg("target_os", "macos").render_long_html(), - "This is supported on macOS only." + "Available on macOS only." ); assert_eq!( name_value_cfg("target_os", "wasi").render_long_html(), - "This is supported on WASI only." + "Available on WASI only." ); assert_eq!( name_value_cfg("target_pointer_width", "16").render_long_html(), - "This is supported on 16-bit only." + "Available on 16-bit only." ); assert_eq!( name_value_cfg("target_endian", "little").render_long_html(), - "This is supported on little-endian only." + "Available on little-endian only." ); assert_eq!( (!word_cfg("windows")).render_long_html(), - "This is supported on non-Windows only." + "Available on non-Windows only." ); assert_eq!( (word_cfg("unix") & word_cfg("windows")).render_long_html(), - "This is supported on Unix and Windows only." + "Available on Unix and Windows only." ); assert_eq!( (word_cfg("unix") | word_cfg("windows")).render_long_html(), - "This is supported on Unix or Windows only." + "Available on Unix or Windows only." ); assert_eq!( (word_cfg("unix") & word_cfg("windows") & word_cfg("debug_assertions")) .render_long_html(), - "This is supported on Unix and Windows and debug-assertions enabled\ - only." + "Available on Unix and Windows and debug-assertions enabled only." ); assert_eq!( (word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions")) .render_long_html(), - "This is supported on Unix or Windows or debug-assertions enabled\ - only." + "Available on Unix or Windows or debug-assertions enabled only." ); assert_eq!( (!(word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions"))) .render_long_html(), - "This is supported on neither Unix nor Windows nor debug-assertions \ - enabled." + "Available on neither Unix nor Windows nor debug-assertions enabled." ); assert_eq!( ((word_cfg("unix") & name_value_cfg("target_arch", "x86_64")) | (word_cfg("windows") & name_value_cfg("target_pointer_width", "64"))) .render_long_html(), - "This is supported on Unix and x86-64, or Windows and 64-bit only." + "Available on Unix and x86-64, or Windows and 64-bit only." ); assert_eq!( (!(word_cfg("unix") & word_cfg("windows"))).render_long_html(), - "This is supported on not (Unix and Windows)." + "Available on not (Unix and Windows)." ); assert_eq!( ((word_cfg("debug_assertions") | word_cfg("windows")) & word_cfg("unix")) .render_long_html(), - "This is supported on (debug-assertions enabled or Windows) and Unix\ - only." + "Available on (debug-assertions enabled or Windows) and Unix only." ); assert_eq!( name_value_cfg("target_feature", "sse2").render_long_html(), - "This is supported with target feature sse2 only." + "Available with target feature sse2 only." ); assert_eq!( (name_value_cfg("target_arch", "x86_64") & name_value_cfg("target_feature", "sse2")) .render_long_html(), - "This is supported on x86-64 and target feature \ - sse2 only." + "Available on x86-64 and target feature sse2 only." ); }) } diff --git a/src/test/rustdoc-gui/item-info-overflow.goml b/src/test/rustdoc-gui/item-info-overflow.goml index 4ff719bfb7ddc..d6385e2acb8e6 100644 --- a/src/test/rustdoc-gui/item-info-overflow.goml +++ b/src/test/rustdoc-gui/item-info-overflow.goml @@ -8,7 +8,7 @@ assert-property: (".item-info", {"scrollWidth": "890"}) // Just to be sure we're comparing the correct "item-info": assert-text: ( ".item-info", - "This is supported on Android or Linux or Emscripten or DragonFly BSD", + "Available on Android or Linux or Emscripten or DragonFly BSD", STARTS_WITH, ) @@ -23,6 +23,6 @@ assert-property: ("#impl-SimpleTrait .item-info", {"scrollWidth": "866"}) // Just to be sure we're comparing the correct "item-info": assert-text: ( "#impl-SimpleTrait .item-info", - "This is supported on Android or Linux or Emscripten or DragonFly BSD", + "Available on Android or Linux or Emscripten or DragonFly BSD", STARTS_WITH, ) diff --git a/src/test/rustdoc-gui/item-info-width.goml b/src/test/rustdoc-gui/item-info-width.goml index 7a32d9029103a..8b6d355a8f1a7 100644 --- a/src/test/rustdoc-gui/item-info-width.goml +++ b/src/test/rustdoc-gui/item-info-width.goml @@ -4,5 +4,5 @@ goto: file://|DOC_PATH|/lib2/struct.Foo.html size: (1100, 800) // We check that ".item-info" is bigger than its content. assert-css: (".item-info", {"width": "790px"}) -assert-css: (".item-info .stab", {"width": "340px"}) +assert-css: (".item-info .stab", {"width": "289px"}) assert-position: (".item-info .stab", {"x": 295}) diff --git a/src/test/rustdoc/doc-cfg.rs b/src/test/rustdoc/doc-cfg.rs index 9465c8a35c886..4cddb0b76d410 100644 --- a/src/test/rustdoc/doc-cfg.rs +++ b/src/test/rustdoc/doc-cfg.rs @@ -4,21 +4,21 @@ // @has doc_cfg/struct.Portable.html // @!has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' '' // @has - '//*[@id="method.unix_and_arm_only_function"]' 'fn unix_and_arm_only_function()' -// @has - '//*[@class="stab portability"]' 'This is supported on Unix and ARM only.' +// @has - '//*[@class="stab portability"]' 'Available on Unix and ARM only.' // @has - '//*[@id="method.wasi_and_wasm32_only_function"]' 'fn wasi_and_wasm32_only_function()' -// @has - '//*[@class="stab portability"]' 'This is supported on WASI and WebAssembly only.' +// @has - '//*[@class="stab portability"]' 'Available on WASI and WebAssembly only.' pub struct Portable; // @has doc_cfg/unix_only/index.html \ // '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \ -// 'This is supported on Unix only.' +// 'Available on Unix only.' // @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\AARM\Z' // @count - '//*[@class="stab portability"]' 2 #[doc(cfg(unix))] pub mod unix_only { // @has doc_cfg/unix_only/fn.unix_only_function.html \ // '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \ - // 'This is supported on Unix only.' + // 'Available on Unix only.' // @count - '//*[@class="stab portability"]' 1 pub fn unix_only_function() { content::should::be::irrelevant(); @@ -26,7 +26,7 @@ pub mod unix_only { // @has doc_cfg/unix_only/trait.ArmOnly.html \ // '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \ - // 'This is supported on Unix and ARM only.' + // 'Available on Unix and ARM only.' // @count - '//*[@class="stab portability"]' 1 #[doc(cfg(target_arch = "arm"))] pub trait ArmOnly { @@ -41,14 +41,14 @@ pub mod unix_only { // @has doc_cfg/wasi_only/index.html \ // '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \ -// 'This is supported on WASI only.' +// 'Available on WASI only.' // @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\AWebAssembly\Z' // @count - '//*[@class="stab portability"]' 2 #[doc(cfg(target_os = "wasi"))] pub mod wasi_only { // @has doc_cfg/wasi_only/fn.wasi_only_function.html \ // '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \ - // 'This is supported on WASI only.' + // 'Available on WASI only.' // @count - '//*[@class="stab portability"]' 1 pub fn wasi_only_function() { content::should::be::irrelevant(); @@ -56,7 +56,7 @@ pub mod wasi_only { // @has doc_cfg/wasi_only/trait.Wasm32Only.html \ // '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \ - // 'This is supported on WASI and WebAssembly only.' + // 'Available on WASI and WebAssembly only.' // @count - '//*[@class="stab portability"]' 1 #[doc(cfg(target_arch = "wasm32"))] pub trait Wasm32Only { @@ -78,7 +78,7 @@ pub mod wasi_only { // @has doc_cfg/fn.uses_target_feature.html // @has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \ -// 'This is supported with target feature avx only.' +// 'Available with target feature avx only.' #[target_feature(enable = "avx")] pub unsafe fn uses_target_feature() { content::should::be::irrelevant(); @@ -86,7 +86,7 @@ pub unsafe fn uses_target_feature() { // @has doc_cfg/fn.uses_cfg_target_feature.html // @has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \ -// 'This is supported with target feature avx only.' +// 'Available with target feature avx only.' #[doc(cfg(target_feature = "avx"))] pub fn uses_cfg_target_feature() { uses_target_feature(); @@ -95,7 +95,7 @@ pub fn uses_cfg_target_feature() { // multiple attributes should be allowed // @has doc_cfg/fn.multiple_attrs.html \ // '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \ -// 'This is supported on x and y and z only.' +// 'Available on x and y and z only.' #[doc(cfg(x))] #[doc(cfg(y), cfg(z))] pub fn multiple_attrs() {} diff --git a/src/test/rustdoc/duplicate-cfg.rs b/src/test/rustdoc/duplicate-cfg.rs index 886ec6750304a..18f3900b263b0 100644 --- a/src/test/rustdoc/duplicate-cfg.rs +++ b/src/test/rustdoc/duplicate-cfg.rs @@ -3,7 +3,7 @@ // @has 'foo/index.html' // @matches '-' '//*[@class="item-left module-item"]//*[@class="stab portability"]' '^sync$' -// @has '-' '//*[@class="item-left module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate feature `sync` only' +// @has '-' '//*[@class="item-left module-item"]//*[@class="stab portability"]/@title' 'Available on crate feature `sync` only' // @has 'foo/struct.Foo.html' // @has '-' '//*[@class="stab portability"]' 'sync' @@ -13,41 +13,41 @@ pub struct Foo; // @has 'foo/bar/index.html' -// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.' +// @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync only.' #[doc(cfg(feature = "sync"))] pub mod bar { // @has 'foo/bar/struct.Bar.html' - // @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.' + // @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync only.' #[doc(cfg(feature = "sync"))] pub struct Bar; } // @has 'foo/baz/index.html' -// @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.' +// @has '-' '//*[@class="stab portability"]' 'Available on crate features sync and send only.' #[doc(cfg(all(feature = "sync", feature = "send")))] pub mod baz { // @has 'foo/baz/struct.Baz.html' - // @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.' + // @has '-' '//*[@class="stab portability"]' 'Available on crate features sync and send only.' #[doc(cfg(feature = "sync"))] pub struct Baz; } // @has 'foo/qux/index.html' -// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.' +// @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync only.' #[doc(cfg(feature = "sync"))] pub mod qux { // @has 'foo/qux/struct.Qux.html' - // @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.' + // @has '-' '//*[@class="stab portability"]' 'Available on crate features sync and send only.' #[doc(cfg(all(feature = "sync", feature = "send")))] pub struct Qux; } // @has 'foo/quux/index.html' -// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync and crate feature send and foo only.' +// @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync and crate feature send and foo only.' #[doc(cfg(all(feature = "sync", feature = "send", foo)))] pub mod quux { // @has 'foo/quux/struct.Quux.html' - // @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync and crate feature send and foo and bar only.' + // @has '-' '//*[@class="stab portability"]' 'Available on crate feature sync and crate feature send and foo and bar only.' #[doc(cfg(all(feature = "send", feature = "sync", bar)))] pub struct Quux; } From 93ae6f80e37797ae82cc5d5c1875972fd76d0177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Fri, 15 Apr 2022 16:59:40 +0200 Subject: [PATCH 8/8] Make some `usize`-typed masks definition agnostic to the size of `usize` Some masks where defined as ```rust const NONASCII_MASK: usize = 0x80808080_80808080u64 as usize; ``` where it was assumed that `usize` is never wider than 64, which is currently true. To make those constants valid in a hypothetical 128-bit target, these constants have been redefined in an `usize`-width-agnostic way ```rust const NONASCII_MASK: usize = usize::from_ne_bytes([0x80; size_of::()]); ``` There are already some cases where Rust anticipates the possibility of supporting 128-bit targets, such as not implementing `From` for `u64`. --- library/core/benches/ascii/is_ascii.rs | 2 +- library/core/src/num/mod.rs | 21 +++++++++++++++++++++ library/core/src/slice/ascii.rs | 2 +- library/core/src/slice/memchr.rs | 8 ++------ library/core/src/str/count.rs | 6 +++--- library/core/src/str/validations.rs | 3 +-- 6 files changed, 29 insertions(+), 13 deletions(-) diff --git a/library/core/benches/ascii/is_ascii.rs b/library/core/benches/ascii/is_ascii.rs index 729b0a04eb6ba..a42a1dcfe3988 100644 --- a/library/core/benches/ascii/is_ascii.rs +++ b/library/core/benches/ascii/is_ascii.rs @@ -77,6 +77,6 @@ fn is_ascii_align_to_unrolled(bytes: &[u8]) -> bool { #[inline] fn contains_nonascii(v: usize) -> bool { - const NONASCII_MASK: usize = 0x80808080_80808080u64 as usize; + const NONASCII_MASK: usize = usize::from_ne_bytes([0x80; core::mem::size_of::()]); (NONASCII_MASK & v) != 0 } diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 8b93cd39d5df3..66193eaf5da73 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -890,6 +890,27 @@ impl usize { widening_impl! { usize, u128, 64, unsigned } } +impl usize { + /// Returns an `usize` where every byte is equal to `x`. + #[inline] + pub(crate) const fn repeat_u8(x: u8) -> usize { + usize::from_ne_bytes([x; mem::size_of::()]) + } + + /// Returns an `usize` where every byte pair is equal to `x`. + #[inline] + pub(crate) const fn repeat_u16(x: u16) -> usize { + let mut r = 0usize; + let mut i = 0; + while i < mem::size_of::() { + // Use `wrapping_shl` to make it work on targets with 16-bit `usize` + r = r.wrapping_shl(16) | (x as usize); + i += 2; + } + r + } +} + /// A classification of floating point numbers. /// /// This `enum` is used as the return type for [`f32::classify`] and [`f64::classify`]. See diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 9aa5c88a62c8e..63715a6b86b97 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -235,7 +235,7 @@ impl<'a> fmt::Debug for EscapeAscii<'a> { /// from `../str/mod.rs`, which does something similar for utf8 validation. #[inline] fn contains_nonascii(v: usize) -> bool { - const NONASCII_MASK: usize = 0x80808080_80808080u64 as usize; + const NONASCII_MASK: usize = usize::repeat_u8(0x80); (NONASCII_MASK & v) != 0 } diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs index 6da99055f2d5a..dffeaf6a834e7 100644 --- a/library/core/src/slice/memchr.rs +++ b/library/core/src/slice/memchr.rs @@ -4,12 +4,8 @@ use crate::cmp; use crate::mem; -const LO_U64: u64 = 0x0101010101010101; -const HI_U64: u64 = 0x8080808080808080; - -// Use truncation. -const LO_USIZE: usize = LO_U64 as usize; -const HI_USIZE: usize = HI_U64 as usize; +const LO_USIZE: usize = usize::repeat_u8(0x01); +const HI_USIZE: usize = usize::repeat_u8(0x80); const USIZE_BYTES: usize = mem::size_of::(); /// Returns `true` if `x` contains any zero byte. diff --git a/library/core/src/str/count.rs b/library/core/src/str/count.rs index 5abc2b34c075a..28567a7e753aa 100644 --- a/library/core/src/str/count.rs +++ b/library/core/src/str/count.rs @@ -112,7 +112,7 @@ fn do_count_chars(s: &str) -> usize { // true) #[inline] fn contains_non_continuation_byte(w: usize) -> usize { - const LSB: usize = 0x0101_0101_0101_0101u64 as usize; + const LSB: usize = usize::repeat_u8(0x01); ((!w >> 7) | (w >> 6)) & LSB } @@ -120,8 +120,8 @@ fn contains_non_continuation_byte(w: usize) -> usize { // more efficient. #[inline] fn sum_bytes_in_usize(values: usize) -> usize { - const LSB_SHORTS: usize = 0x0001_0001_0001_0001_u64 as usize; - const SKIP_BYTES: usize = 0x00ff_00ff_00ff_00ff_u64 as usize; + const LSB_SHORTS: usize = usize::repeat_u16(0x0001); + const SKIP_BYTES: usize = usize::repeat_u16(0x00ff); let pair_sum: usize = (values & SKIP_BYTES) + ((values >> 8) & SKIP_BYTES); pair_sum.wrapping_mul(LSB_SHORTS) >> ((USIZE_SIZE - 2) * 8) diff --git a/library/core/src/str/validations.rs b/library/core/src/str/validations.rs index 0d3dc856be577..04bc665233e38 100644 --- a/library/core/src/str/validations.rs +++ b/library/core/src/str/validations.rs @@ -112,8 +112,7 @@ where Some(ch) } -// use truncation to fit u64 into usize -const NONASCII_MASK: usize = 0x80808080_80808080u64 as usize; +const NONASCII_MASK: usize = usize::repeat_u8(0x80); /// Returns `true` if any byte in the word `x` is nonascii (>= 128). #[inline]