+++ /dev/null
----
-name: Diagnostic issue
-about: Create a bug report or feature request for a change to `rustc`'s error output
-labels: A-diagnostics, T-compiler
----
-<!--
-Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
-along with any information you feel relevant to replicating the bug.
-
-If you cannot produce a minimal reproduction case (something that would work in
-isolation), please provide the steps or even link to a repository that causes
-the problematic output to occur.
--->
-
-Given the following code: <!-- Please provide a link to play.rust-lang.org -->
-
-```rust
-<code>
-```
-
-The current output is:
-
-```
-<rustc output>
-```
-
-<!-- The following is not always necessary. -->
-Ideally the output should look like:
-
-```
-<proposed output>
-```
-
-<!--
-If the problem is not self-explanatory, please provide a rationale for the
-change.
--->
-
-<!--
-If dramatically different output is caused by small changes, consider also
-adding them here.
-
-If you're using the stable version of the compiler, you should also check if the
-bug also exists in the beta or nightly versions. The output might also be
-different depending on the Edition.
--->
--- /dev/null
+name: Diagnostic issue
+description: Create a bug report or feature request for a change to `rustc`'s error output
+labels: ["A-diagnostics", "T-compiler"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thank you for filing a diagnostics bug report! 🐛
+
+ Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug.
+
+ If you cannot produce a minimal reproduction case (something that would work in isolation), please provide the steps or even link to a repository that causes the problematic output to occur.
+ - type: textarea
+ id: code
+ attributes:
+ label: Code
+ description: Please provide code that can reproduce the problem
+ placeholder: code
+ render: Rust
+ validations:
+ required: true
+ - type: textarea
+ id: output
+ attributes:
+ label: Current output
+ description: Please provide the `rustc` output you see
+ placeholder: rustc output
+ render: Shell
+ validations:
+ required: true
+ - type: textarea
+ id: desired-output
+ attributes:
+ label: Desired output
+ description: Please provide what the output *should* be
+ placeholder: proposed output
+ render: Shell
+ validations:
+ required: false
+ - type: textarea
+ id: rationale
+ attributes:
+ label: Rationale and extra context
+ description: If the problem is not self-explanatory, please provide a rationale for the change.
+ validations:
+ required: false
+ - type: textarea
+ id: other-output
+ attributes:
+ label: Other cases
+ description: If dramatically different output is caused by small changes, consider also adding them here.
+ render: Rust
+ validations:
+ required: false
+ - type: markdown
+ attributes:
+ value: |
+ If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. The output might also be different depending on the Edition.
+ - type: textarea
+ id: extra
+ attributes:
+ label: Anything else?
+ description: If you have more details you want to give us to reproduce this issue, please add it here
+ validations:
+ required: false
\ No newline at end of file
+++ /dev/null
----
-name: Documentation problem
-about: Create a report for a documentation problem.
-labels: A-docs
----
-<!--
-
-Thank you for finding a documentation problem! 📚
-
-Documentation problems might be grammatical issues, typos, or unclear wording, please provide details regarding the documentation including where it is present.
-
-Note: If your issue is for one of these, please use their dedicated issue tracker instead:
-
-- The Rust Book: https://github.com/rust-lang/book/issues
-- Rust by Example: https://github.com/rust-lang/rust-by-example/issues
-- The Edition Guide: https://github.com/rust-lang/edition-guide/issues
-- The Cargo Book: https://github.com/rust-lang/cargo/issues
-- The Clippy Book: https://github.com/rust-lang/rust-clippy/issues
-- The Reference: https://github.com/rust-lang/reference/issues
-- The Rustonomicon: https://github.com/rust-lang/nomicon/issues
-- The Embedded Book: https://github.com/rust-embedded/book/issues
-
-All other documentation issues should be filed here.
-
-Or, if you find an issue related to rustdoc (e.g. doctest, rustdoc UI), please use the bug report or blank issue template instead.
-
--->
-
-### Location
-
-### Summary
--- /dev/null
+name: Documentation problem
+description: Create a report for a documentation problem.
+labels: ["A-docs"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thank you for finding a documentation problem! 📚
+
+ Documentation problems might be grammatical issues, typos, or unclear wording, please provide details regarding the documentation including where it is present.
+
+ Note: If your issue is for one of these, please use their dedicated issue tracker instead:
+ - [The Rust Book](https://github.com/rust-lang/book/issues)
+ - [Rust by Example](https://github.com/rust-lang/rust-by-example/issues)
+ - [The Edition Guide](https://github.com/rust-lang/edition-guide/issues)
+ - [The Cargo Book](https://github.com/rust-lang/cargo/issues)
+ - [The Clippy Book](https://github.com/rust-lang/rust-clippy/issues)
+ - [The Reference](https://github.com/rust-lang/reference/issues)
+ - [The Rustonomicon](https://github.com/rust-lang/nomicon/issues)
+ - [The Embedded Book](https://github.com/rust-embedded/book/issues)
+
+ All other documentation issues should be filed here.
+
+ Or, if you find an issue related to rustdoc (e.g. doctest, rustdoc UI), please use the bug report or blank issue template instead.
+
+ - type: textarea
+ id: location
+ attributes:
+ label: Location
+ validations:
+ required: true
+
+ - type: textarea
+ id: summary
+ attributes:
+ label: Summary
+ validations:
+ required: true
\ No newline at end of file
+++ /dev/null
----
-name: Internal Compiler Error
-about: Create a report for an internal compiler error in rustc.
-labels: C-bug, I-ICE, T-compiler
----
-<!--
-Thank you for finding an Internal Compiler Error! 🧊 If possible, try to provide
-a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for
-how to create smaller examples.
-
-http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/
-
--->
-
-### Code
-
-```Rust
-<code>
-```
-
-
-### Meta
-<!--
-If you're using the stable version of the compiler, you should also check if the
-bug also exists in the beta or nightly versions.
--->
-
-`rustc --version --verbose`:
-```
-<version>
-```
-
-### Error output
-
-```
-<output>
-```
-
-<!--
-Include a backtrace in the code block by setting `RUST_BACKTRACE=1` in your
-environment. E.g. `RUST_BACKTRACE=1 cargo build`.
--->
-<details><summary><strong>Backtrace</strong></summary>
-<p>
-
-```
-<backtrace>
-```
-
-</p>
-</details>
-
--- /dev/null
+name: Internal Compiler Error
+description: Create a report for an internal compiler error in `rustc`
+labels: ["C-bug", "I-ICE", "T-compiler"]
+title: "[ICE]: "
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thank you for finding an Internal Compiler Error! 🧊
+
+ If possible, try to provide a minimal verifiable example.
+
+ You can read "[Rust Bug Minimization Patterns](http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/)" for how to create smaller examples.
+
+ - type: textarea
+ id: code
+ attributes:
+ label: Code
+ description: Please provide code or a link to a repository that can reproduce the problem
+ placeholder: code
+ render: Rust
+ validations:
+ required: false
+
+ - type: checkboxes
+ attributes:
+ label: Affected release channels
+ description: If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions
+ options:
+ - label: Previous Stable
+ required: false
+ - label: Current Stable
+ required: false
+ - label: Current Beta
+ required: false
+ - label: Current Nightly
+ required: false
+
+ - type: textarea
+ id: version
+ attributes:
+ label: Rust Version
+ description: Please provide the `rustc` version, `rustc --version --verbose`
+ placeholder: |
+ $ rustc --version --verbose
+ rustc 1.XX.Y (SHORTHASH DATE)
+ binary: rustc
+ commit-hash: LONGHASHVALUE
+ commit-date: DATE
+ host: PLATFORMTRIPLE
+ release: 1.XX.Y
+ LLVM version: XX.YY.ZZ
+ render: Shell
+ validations:
+ required: true
+
+ - type: textarea
+ id: output
+ attributes:
+ label: Current error output
+ description: Please provide the `rustc` output you see
+ placeholder: output
+ render: Shell
+ validations:
+ required: false
+
+ - type: textarea
+ id: backtrace
+ attributes:
+ label: Backtrace
+ description: Include a backtrace in the code block by setting `RUST_BACKTRACE=full` in your environment, e.g. `RUST_BACKTRACE=full cargo build`
+ render: Shell
+ validations:
+ required: true
+
+ - type: textarea
+ id: extra
+ attributes:
+ label: Anything else?
+ description: If you have more details you want to give us to reproduce this issue, please add it here
+ validations:
+ required: false
\ No newline at end of file
"version_check",
]
+[[package]]
+name = "ahash"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf6ccdb167abbf410dcb915cabd428929d7f6a04980b54a11f26a39f1c7f7107"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "version_check",
+]
+
[[package]]
name = "aho-corasick"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "276881980556fdadeb88aa1ffc667e4d2e8fe72531dfabcb7a82bb3c9ea9ba31"
dependencies = [
- "object",
+ "object 0.29.0",
]
[[package]]
"cfg-if",
"libc",
"miniz_oxide",
- "object",
+ "object 0.29.0",
"rustc-demangle",
]
[[package]]
name = "gimli"
-version = "0.26.1"
+version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
+checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
dependencies = [
"compiler_builtins",
"fallible-iterator",
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
dependencies = [
- "ahash",
+ "ahash 0.7.4",
"compiler_builtins",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
]
+[[package]]
+name = "hashbrown"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038"
+dependencies = [
+ "ahash 0.8.2",
+]
+
[[package]]
name = "heck"
version = "0.4.0"
[[package]]
name = "indexmap"
-version = "1.9.1"
+version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
+checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
dependencies = [
"autocfg",
- "hashbrown",
+ "hashbrown 0.12.3",
"rustc-rayon",
"serde",
]
checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
dependencies = [
"compiler_builtins",
+ "memchr",
+ "rustc-std-workspace-alloc",
+ "rustc-std-workspace-core",
+]
+
+[[package]]
+name = "object"
+version = "0.30.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d864c91689fdc196779b98dba0aceac6118594c2df6ee5d943eb6a8df4d107a"
+dependencies = [
"crc32fast",
"flate2",
- "hashbrown",
+ "hashbrown 0.13.1",
"indexmap",
"memchr",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
]
[[package]]
[[package]]
name = "pest"
-version = "2.3.0"
+version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b0560d531d1febc25a3c9398a62a71256c0178f2e3443baedd9ad4bb8c9deb4"
+checksum = "0f6e86fb9e7026527a0d46bc308b841d73170ef8f443e1807f6ef88526a816d4"
dependencies = [
"thiserror",
"ucd-trie",
[[package]]
name = "pest_derive"
-version = "2.3.0"
+version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "905708f7f674518498c1f8d644481440f476d39ca6ecae83319bba7c6c12da91"
+checksum = "96504449aa860c8dcde14f9fba5c58dc6658688ca1fe363589d6327b8662c603"
dependencies = [
"pest",
"pest_generator",
[[package]]
name = "pest_generator"
-version = "2.3.0"
+version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5803d8284a629cc999094ecd630f55e91b561a1d1ba75e233b00ae13b91a69ad"
+checksum = "798e0220d1111ae63d66cb66a5dcb3fc2d986d520b98e49e1852bfdb11d7c5e7"
dependencies = [
"pest",
"pest_meta",
[[package]]
name = "pest_meta"
-version = "2.3.0"
+version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1538eb784f07615c6d9a8ab061089c6c54a344c5b4301db51990ca1c241e8c04"
+checksum = "984298b75898e30a843e278a9f2452c31e349a073a0ce6fd950a12a74464e065"
dependencies = [
"once_cell",
"pest",
- "sha-1",
+ "sha1",
]
[[package]]
"cstr",
"libc",
"measureme",
- "object",
+ "object 0.30.1",
"rustc-demangle",
"rustc_ast",
"rustc_attr",
"itertools",
"jobserver",
"libc",
- "object",
+ "object 0.30.1",
"pathdiff",
"regex",
"rustc_arena",
"rustc_macros",
"rustc_serialize",
"scoped-tls",
- "sha-1",
+ "sha1",
"sha2",
"tracing",
"unicode-width",
"serde",
]
-[[package]]
-name = "sha-1"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
-dependencies = [
- "cfg-if",
- "cpufeatures",
- "digest",
-]
-
[[package]]
name = "sha1"
version = "0.10.5"
"core",
"dlmalloc",
"fortanix-sgx-abi",
- "hashbrown",
+ "hashbrown 0.12.3",
"hermit-abi 0.2.6",
"libc",
"miniz_oxide",
- "object",
+ "object 0.29.0",
"panic_abort",
"panic_unwind",
"profiler_builtins",
[[package]]
name = "thiserror"
-version = "1.0.33"
+version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d0a539a918745651435ac7db7a18761589a94cd7e94cd56999f828bf73c8a57"
+checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.33"
+version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c251e90f708e16c49a16f4917dc2131e75222b72edfa9cb7f7c58ae56aae0c09"
+checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
dependencies = [
"proc-macro2",
"quote",
[[package]]
name = "thorin-dwp"
-version = "0.3.0"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6cb0c7868d7f90407531108ab03263d9452a8811b7cdd87675343a40d4aa254"
+checksum = "da8fbf660a019b6bf11ea95762041464aa9099cc293b6a66d77cea5107619671"
dependencies = [
"gimli",
- "hashbrown",
- "object",
+ "hashbrown 0.12.3",
+ "object 0.30.1",
"tracing",
]
name = "tidy"
version = "0.1.0"
dependencies = [
+ "cargo-platform 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cargo_metadata 0.14.0",
"ignore",
"lazy_static",
[[package]]
name = "ucd-trie"
-version = "0.1.3"
+version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
+checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81"
[[package]]
name = "ui_test"
[[package]]
name = "version_check"
-version = "0.9.3"
+version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "vte"
cstr = "0.2"
libc = "0.2"
measureme = "10.0.0"
-object = { version = "0.29.0", default-features = false, features = ["std", "read"] }
+object = { version = "0.30.1", default-features = false, features = [
+ "std",
+ "read",
+] }
tracing = "0.1"
rustc_middle = { path = "../rustc_middle" }
rustc-demangle = "0.1.21"
libc = "0.2.50"
jobserver = "0.1.22"
tempfile = "3.2"
-thorin-dwp = "0.3"
+thorin-dwp = "0.4"
pathdiff = "0.2.0"
serde_json = "1.0.59"
snap = "1"
rustc_const_eval = { path = "../rustc_const_eval" }
[dependencies.object]
-version = "0.29.0"
+version = "0.30.1"
default-features = false
features = ["read_core", "elf", "macho", "pe", "unaligned", "archive", "write"]
};
let architecture = match &sess.target.arch[..] {
"arm" => Architecture::Arm,
- "aarch64" => Architecture::Aarch64,
+ "aarch64" => {
+ if sess.target.pointer_width == 32 {
+ Architecture::Aarch64_Ilp32
+ } else {
+ Architecture::Aarch64
+ }
+ }
"x86" => Architecture::I386,
"s390x" => Architecture::S390x,
"mips" => Architecture::Mips,
use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId};
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{BytePos, FileName, RealFileName, Span, DUMMY_SP};
+use rustc_span::{BytePos, FileName, Span, DUMMY_SP};
use smallvec::{smallvec, SmallVec};
use std::iter;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
use std::rc::Rc;
pub(crate) use rustc_span::hygiene::MacroKind;
if let [variant] = &*enum_def.variants {
if variant.ident.name == sym::Input {
let filename = sess.source_map().span_to_filename(item.ident.span);
- if let FileName::Real(RealFileName::LocalPath(path)) = filename {
- if let Some(c) = path
+ if let FileName::Real(real) = filename {
+ if let Some(c) = real
+ .local_path()
+ .unwrap_or(Path::new(""))
.components()
.flat_map(|c| c.as_os_str().to_str())
.find(|c| c.starts_with("rental") || c.starts_with("allsorts-rental"))
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
self.check_for_range_as_method_call(err, expr, expr_ty, expected);
self.check_for_binding_assigned_block_without_tail_expression(err, expr, expr_ty, expected);
+ self.check_wrong_return_type_due_to_generic_arg(err, expr, expr_ty);
}
/// Requires that the two types unify, and prints an error message if
err.span_label(block.span, "this block is missing a tail expression");
}
}
+
+ fn check_wrong_return_type_due_to_generic_arg(
+ &self,
+ err: &mut Diagnostic,
+ expr: &hir::Expr<'_>,
+ checked_ty: Ty<'tcx>,
+ ) {
+ let Some(hir::Node::Expr(parent_expr)) = self.tcx.hir().find_parent(expr.hir_id) else { return; };
+ enum CallableKind {
+ Function,
+ Method,
+ Constructor,
+ }
+ let mut maybe_emit_help = |def_id: hir::def_id::DefId,
+ callable: rustc_span::symbol::Ident,
+ args: &[hir::Expr<'_>],
+ kind: CallableKind| {
+ let arg_idx = args.iter().position(|a| a.hir_id == expr.hir_id).unwrap();
+ let fn_ty = self.tcx.bound_type_of(def_id).0;
+ if !fn_ty.is_fn() {
+ return;
+ }
+ let fn_sig = fn_ty.fn_sig(self.tcx).skip_binder();
+ let Some(&arg) = fn_sig.inputs().get(arg_idx + if matches!(kind, CallableKind::Method) { 1 } else { 0 }) else { return; };
+ if matches!(arg.kind(), ty::Param(_))
+ && fn_sig.output().contains(arg)
+ && self.node_ty(args[arg_idx].hir_id) == checked_ty
+ {
+ let mut multi_span: MultiSpan = parent_expr.span.into();
+ multi_span.push_span_label(
+ args[arg_idx].span,
+ format!(
+ "this argument influences the {} of `{}`",
+ if matches!(kind, CallableKind::Constructor) {
+ "type"
+ } else {
+ "return type"
+ },
+ callable
+ ),
+ );
+ err.span_help(
+ multi_span,
+ format!(
+ "the {} `{}` due to the type of the argument passed",
+ match kind {
+ CallableKind::Function => "return type of this call is",
+ CallableKind::Method => "return type of this call is",
+ CallableKind::Constructor => "type constructed contains",
+ },
+ checked_ty
+ ),
+ );
+ }
+ };
+ match parent_expr.kind {
+ hir::ExprKind::Call(fun, args) => {
+ let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = fun.kind else { return; };
+ let hir::def::Res::Def(kind, def_id) = path.res else { return; };
+ let callable_kind = if matches!(kind, hir::def::DefKind::Ctor(_, _)) {
+ CallableKind::Constructor
+ } else {
+ CallableKind::Function
+ };
+ maybe_emit_help(def_id, path.segments[0].ident, args, callable_kind);
+ }
+ hir::ExprKind::MethodCall(method, _receiver, args, _span) => {
+ let Some(def_id) = self.typeck_results.borrow().type_dependent_def_id(parent_expr.hir_id) else { return; };
+ maybe_emit_help(def_id, method.ident, args, CallableKind::Method)
+ }
+ _ => return,
+ }
+ }
}
let o = self.resolve_vars_if_possible(o);
if !self.predicate_may_hold(&o) {
result = ProbeResult::NoMatch;
- possibly_unsatisfied_predicates.push((
- o.predicate,
- None,
- Some(o.cause),
- ));
+ let parent_o = o.clone();
+ let implied_obligations =
+ traits::elaborate_obligations(self.tcx, vec![o]);
+ for o in implied_obligations {
+ let parent = if o == parent_o {
+ None
+ } else {
+ if o.predicate.to_opt_poly_trait_pred().map(|p| p.def_id())
+ == self.tcx.lang_items().sized_trait()
+ {
+ // We don't care to talk about implicit `Sized` bounds.
+ continue;
+ }
+ Some(parent_o.predicate)
+ };
+ if !self.predicate_may_hold(&o) {
+ possibly_unsatisfied_predicates.push((
+ o.predicate,
+ parent,
+ Some(o.cause),
+ ));
+ }
+ }
}
}
}
}
_ => None,
};
- if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
- if let Some(g) = kind.generics() {
- let key = (
- g.tail_span_for_predicate_suggestion(),
- g.add_where_or_trailing_comma(),
- );
- type_params
- .entry(key)
- .or_insert_with(FxHashSet::default)
- .insert(obligation.to_owned());
- }
+ if let Some(hir::Node::Item(hir::Item { kind, .. })) = node
+ && let Some(g) = kind.generics()
+ {
+ let key = (
+ g.tail_span_for_predicate_suggestion(),
+ g.add_where_or_trailing_comma(),
+ );
+ type_params
+ .entry(key)
+ .or_insert_with(FxHashSet::default)
+ .insert(obligation.to_owned());
+ return true;
}
}
+ false
};
let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
let msg = format!(
"auto trait is invoked with no method error, but no error reported?",
);
}
- Some(_) => unreachable!(),
+ Some(Node::Item(hir::Item {
+ ident, kind: hir::ItemKind::Trait(..), ..
+ })) => {
+ skip_list.insert(p);
+ let entry = spanned_predicates.entry(ident.span);
+ let entry = entry.or_insert_with(|| {
+ (FxHashSet::default(), FxHashSet::default(), Vec::new())
+ });
+ entry.0.insert(cause.span);
+ entry.1.insert((ident.span, ""));
+ entry.1.insert((cause.span, "unsatisfied trait bound introduced here"));
+ entry.2.push(p);
+ }
+ Some(node) => unreachable!("encountered `{node:?}`"),
None => (),
}
}
unsatisfied_bounds = true;
}
+ let mut suggested_bounds = FxHashSet::default();
// The requirements that didn't have an `impl` span to show.
let mut bound_list = unsatisfied_predicates
.iter()
.filter_map(|(pred, parent_pred, _cause)| {
+ let mut suggested = false;
format_pred(*pred).map(|(p, self_ty)| {
- collect_type_param_suggestions(self_ty, *pred, &p);
+ if let Some(parent) = parent_pred && suggested_bounds.contains(parent) {
+ // We don't suggest `PartialEq` when we already suggest `Eq`.
+ } else if !suggested_bounds.contains(pred) {
+ if collect_type_param_suggestions(self_ty, *pred, &p) {
+ suggested = true;
+ suggested_bounds.insert(pred);
+ }
+ }
(
match parent_pred {
None => format!("`{}`", &p),
Some(parent_pred) => match format_pred(*parent_pred) {
None => format!("`{}`", &p),
Some((parent_p, _)) => {
- collect_type_param_suggestions(self_ty, *parent_pred, &p);
+ if !suggested
+ && !suggested_bounds.contains(pred)
+ && !suggested_bounds.contains(parent_pred)
+ {
+ if collect_type_param_suggestions(
+ self_ty,
+ *parent_pred,
+ &p,
+ ) {
+ suggested_bounds.insert(pred);
+ }
+ }
format!("`{}`\nwhich is required by `{}`", p, parent_p)
}
},
use smallvec::smallvec;
use crate::infer::outlives::components::{push_outlives_components, Component};
-use crate::traits::{Obligation, ObligationCause, PredicateObligation};
+use crate::traits::{self, Obligation, ObligationCause, PredicateObligation};
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_middle::ty::{self, ToPredicate, TyCtxt};
use rustc_span::symbol::Ident;
// Get predicates declared on the trait.
let predicates = tcx.super_predicates_of(data.def_id());
- let obligations = predicates.predicates.iter().map(|&(mut pred, _)| {
+ let obligations = predicates.predicates.iter().map(|&(mut pred, span)| {
// when parent predicate is non-const, elaborate it to non-const predicates.
if data.constness == ty::BoundConstness::NotConst {
pred = pred.without_const(tcx);
}
+ let cause = obligation.cause.clone().derived_cause(
+ bound_predicate.rebind(data),
+ |derived| {
+ traits::ImplDerivedObligation(Box::new(
+ traits::ImplDerivedObligationCause {
+ derived,
+ impl_def_id: data.def_id(),
+ span,
+ },
+ ))
+ },
+ );
predicate_obligation(
pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)),
obligation.param_env,
- obligation.cause.clone(),
+ cause,
)
});
debug!(?data, ?obligations, "super_predicates");
/// preceded by whitespace.
fn next_token(&mut self) -> (Token, bool) {
let mut preceded_by_whitespace = false;
-
+ let mut swallow_next_invalid = 0;
// Skip trivial (whitespace & comments) tokens
loop {
let token = self.cursor.advance_token();
rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent),
rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => {
- let c = self.str_from(start).chars().next().unwrap();
+ // Don't emit diagnostics for sequences of the same invalid token
+ if swallow_next_invalid > 0 {
+ swallow_next_invalid -= 1;
+ continue;
+ }
+ let mut it = self.str_from_to_end(start).chars();
+ let c = it.next().unwrap();
+ let repeats = it.take_while(|c1| *c1 == c).count();
let mut err =
- self.struct_err_span_char(start, self.pos, "unknown start of token", c);
+ self.struct_err_span_char(start, self.pos + Pos::from_usize(repeats * c.len_utf8()), "unknown start of token", c);
// FIXME: the lexer could be used to turn the ASCII version of unicode
// homoglyphs, instead of keeping a table in `check_for_substitution`into the
// token. Ideally, this should be inside `rustc_lexer`. However, we should
// first remove compound tokens like `<<` from `rustc_lexer`, and then add
// fancier error recovery to it, as there will be less overall work to do this
// way.
- let token = unicode_chars::check_for_substitution(self, start, c, &mut err);
+ let token = unicode_chars::check_for_substitution(self, start, c, &mut err, repeats+1);
if c == '\x00' {
err.help("source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used");
}
+ if repeats > 0 {
+ if repeats == 1 {
+ err.note(format!("character appears once more"));
+ } else {
+ err.note(format!("character appears {repeats} more times"));
+ }
+ swallow_next_invalid = repeats;
+ }
err.emit();
if let Some(token) = token {
token
&self.src[self.src_index(start)..self.src_index(end)]
}
+ /// Slice of the source text spanning from `start` until the end
+ fn str_from_to_end(&self, start: BytePos) -> &str {
+ &self.src[self.src_index(start)..]
+ }
+
fn report_raw_str_error(&self, start: BytePos, prefix_len: u32) -> ! {
match rustc_lexer::validate_raw_str(self.str_from(start), prefix_len) {
Err(RawStrError::InvalidStarter { bad_char }) => {
pos: BytePos,
ch: char,
err: &mut Diagnostic,
+ count: usize,
) -> Option<token::TokenKind> {
let &(_u_char, u_name, ascii_char) = UNICODE_ARRAY.iter().find(|&&(c, _, _)| c == ch)?;
- let span = Span::with_root_ctxt(pos, pos + Pos::from_usize(ch.len_utf8()));
+ let span = Span::with_root_ctxt(pos, pos + Pos::from_usize(ch.len_utf8() * count));
let Some((_ascii_char, ascii_name, token)) = ASCII_ARRAY.iter().find(|&&(c, _, _)| c == ascii_char) else {
let msg = format!("substitution character not found for '{}'", ch);
"Unicode character '{}' ({}) looks like '{}' ({}), but it is not",
ch, u_name, ascii_char, ascii_name
);
- err.span_suggestion(span, &msg, ascii_char, Applicability::MaybeIncorrect);
+ err.span_suggestion(
+ span,
+ &msg,
+ ascii_char.to_string().repeat(count),
+ Applicability::MaybeIncorrect,
+ );
}
token.clone()
}
pub(super) enum LhsExpr {
NotYetParsed,
AttributesParsed(AttrWrapper),
- AlreadyParsed(P<Expr>, bool), // (expr, starts_statement)
+ AlreadyParsed { expr: P<Expr>, starts_statement: bool },
}
impl From<Option<AttrWrapper>> for LhsExpr {
}
impl From<P<Expr>> for LhsExpr {
- /// Converts the `expr: P<Expr>` into `LhsExpr::AlreadyParsed(expr)`.
+ /// Converts the `expr: P<Expr>` into `LhsExpr::AlreadyParsed { expr, starts_statement: false }`.
///
/// This conversion does not allocate.
fn from(expr: P<Expr>) -> Self {
- LhsExpr::AlreadyParsed(expr, false)
+ LhsExpr::AlreadyParsed { expr, starts_statement: false }
}
}
lhs: LhsExpr,
) -> PResult<'a, P<Expr>> {
let mut starts_stmt = false;
- let mut lhs = if let LhsExpr::AlreadyParsed(expr, starts_statement) = lhs {
+ let mut lhs = if let LhsExpr::AlreadyParsed { expr, starts_statement } = lhs {
starts_stmt = starts_statement;
expr
} else {
// Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr()
match this.token.uninterpolate().kind {
- token::Not => make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Not)), // `!expr`
- token::Tilde => make_it!(this, attrs, |this, _| this.recover_tilde_expr(lo)), // `~expr`
+ // `!expr`
+ token::Not => make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Not)),
+ // `~expr`
+ token::Tilde => make_it!(this, attrs, |this, _| this.recover_tilde_expr(lo)),
+ // `-expr`
token::BinOp(token::Minus) => {
make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Neg))
- } // `-expr`
+ }
+ // `*expr`
token::BinOp(token::Star) => {
make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Deref))
- } // `*expr`
+ }
+ // `&expr` and `&&expr`
token::BinOp(token::And) | token::AndAnd => {
make_it!(this, attrs, |this, _| this.parse_borrow_expr(lo))
}
+ // `+lit`
token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
let mut err =
LeadingPlusNotSupported { span: lo, remove_plus: None, add_parentheses: None };
this.bump();
this.parse_prefix_expr(None)
- } // `+expr`
+ }
// Recover from `++x`:
token::BinOp(token::Plus)
if this.look_ahead(1, |t| *t == token::BinOp(token::Plus)) =>
Ok((span, self.mk_unary(op, expr)))
}
- // Recover on `!` suggesting for bitwise negation instead.
+ /// Recover on `~expr` in favor of `!expr`.
fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
self.sess.emit_err(TildeAsUnaryOperator(lo));
/// Recover on `not expr` in favor of `!expr`.
fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
- // Emit the error...
let negated_token = self.look_ahead(1, |t| t.clone());
let sub_diag = if negated_token.is_numeric_lit() {
),
});
- // ...and recover!
self.parse_unary_expr(lo, UnOp::Not)
}
vis.0
};
- // Suggestion involves adding a (as of time of writing this, unstable) labeled block.
+ // Suggestion involves adding a labeled block.
//
// If there are no breaks that may use this label, suggest removing the label and
// recover to the unmodified expression.
// Perform this outside of the `collect_tokens_trailing_token` closure,
// since our outer attributes do not apply to this part of the expression
let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
- this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr, true))
+ this.parse_assoc_expr_with(
+ 0,
+ LhsExpr::AlreadyParsed { expr, starts_statement: true },
+ )
})?;
Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr)))
} else {
let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
let e = self.maybe_recover_from_bad_qpath(e)?;
let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
- let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e, false))?;
+ let e = self.parse_assoc_expr_with(
+ 0,
+ LhsExpr::AlreadyParsed { expr: e, starts_statement: false },
+ )?;
StmtKind::Expr(e)
};
Ok(self.mk_stmt(lo.to(hi), kind))
unicode-width = "0.1.4"
cfg-if = "1.0"
tracing = "0.1"
-sha1 = { package = "sha-1", version = "0.10.0" }
+sha1 = "0.10.0"
sha2 = "0.10.1"
md5 = { package = "md-5", version = "0.10.0" }
})
}
}
+
impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
fn report_fulfillment_errors(
&self,
let mut suggested =
self.suggest_dereferences(&obligation, &mut err, trait_predicate);
suggested |= self.suggest_fn_call(&obligation, &mut err, trait_predicate);
+ let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
+ suggested = if let &[cand] = &impl_candidates[..] {
+ let cand = cand.trait_ref;
+ if let (ty::FnPtr(_), ty::FnDef(..)) =
+ (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind())
+ {
+ err.span_suggestion(
+ span.shrink_to_hi(),
+ format!(
+ "the trait `{}` is implemented for fn pointer `{}`, try casting using `as`",
+ cand.print_only_trait_path(),
+ cand.self_ty(),
+ ),
+ format!(" as {}", cand.self_ty()),
+ Applicability::MaybeIncorrect,
+ );
+ true
+ } else {
+ false
+ }
+ } else {
+ false
+ } || suggested;
suggested |=
self.suggest_remove_reference(&obligation, &mut err, trait_predicate);
suggested |= self.suggest_semicolon_removal(
candidates.sort();
candidates.dedup();
let len = candidates.len();
- if candidates.len() == 0 {
+ if candidates.is_empty() {
return false;
}
- if candidates.len() == 1 {
- let ty_desc = match candidates[0].self_ty().kind() {
- ty::FnPtr(_) => Some("fn pointer"),
- _ => None,
- };
- let the_desc = match ty_desc {
- Some(desc) => format!(" implemented for {} `", desc),
- None => " implemented for `".to_string(),
- };
+ if let &[cand] = &candidates[..] {
+ let (desc, mention_castable) =
+ match (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) {
+ (ty::FnPtr(_), ty::FnDef(..)) => {
+ (" implemented for fn pointer `", ", cast using `as`")
+ }
+ (ty::FnPtr(_), _) => (" implemented for fn pointer `", ""),
+ _ => (" implemented for `", ""),
+ };
err.highlighted_help(vec![
- (
- format!("the trait `{}` ", candidates[0].print_only_trait_path()),
- Style::NoStyle,
- ),
+ (format!("the trait `{}` ", cand.print_only_trait_path()), Style::NoStyle),
("is".to_string(), Style::Highlight),
- (the_desc, Style::NoStyle),
- (candidates[0].self_ty().to_string(), Style::Highlight),
+ (desc.to_string(), Style::NoStyle),
+ (cand.self_ty().to_string(), Style::Highlight),
("`".to_string(), Style::NoStyle),
+ (mention_castable.to_string(), Style::NoStyle),
]);
return true;
}
+++ /dev/null
-//! A priority queue implemented with a binary heap.
-//!
-//! Insertion and popping the largest element have *O*(log(*n*)) time complexity.
-//! Checking the largest element is *O*(1). Converting a vector to a binary heap
-//! can be done in-place, and has *O*(*n*) complexity. A binary heap can also be
-//! converted to a sorted vector in-place, allowing it to be used for an *O*(*n* * log(*n*))
-//! in-place heapsort.
-//!
-//! # Examples
-//!
-//! This is a larger example that implements [Dijkstra's algorithm][dijkstra]
-//! to solve the [shortest path problem][sssp] on a [directed graph][dir_graph].
-//! It shows how to use [`BinaryHeap`] with custom types.
-//!
-//! [dijkstra]: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
-//! [sssp]: https://en.wikipedia.org/wiki/Shortest_path_problem
-//! [dir_graph]: https://en.wikipedia.org/wiki/Directed_graph
-//!
-//! ```
-//! use std::cmp::Ordering;
-//! use std::collections::BinaryHeap;
-//!
-//! #[derive(Copy, Clone, Eq, PartialEq)]
-//! struct State {
-//! cost: usize,
-//! position: usize,
-//! }
-//!
-//! // The priority queue depends on `Ord`.
-//! // Explicitly implement the trait so the queue becomes a min-heap
-//! // instead of a max-heap.
-//! impl Ord for State {
-//! fn cmp(&self, other: &Self) -> Ordering {
-//! // Notice that the we flip the ordering on costs.
-//! // In case of a tie we compare positions - this step is necessary
-//! // to make implementations of `PartialEq` and `Ord` consistent.
-//! other.cost.cmp(&self.cost)
-//! .then_with(|| self.position.cmp(&other.position))
-//! }
-//! }
-//!
-//! // `PartialOrd` needs to be implemented as well.
-//! impl PartialOrd for State {
-//! fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-//! Some(self.cmp(other))
-//! }
-//! }
-//!
-//! // Each node is represented as a `usize`, for a shorter implementation.
-//! struct Edge {
-//! node: usize,
-//! cost: usize,
-//! }
-//!
-//! // Dijkstra's shortest path algorithm.
-//!
-//! // Start at `start` and use `dist` to track the current shortest distance
-//! // to each node. This implementation isn't memory-efficient as it may leave duplicate
-//! // nodes in the queue. It also uses `usize::MAX` as a sentinel value,
-//! // for a simpler implementation.
-//! fn shortest_path(adj_list: &Vec<Vec<Edge>>, start: usize, goal: usize) -> Option<usize> {
-//! // dist[node] = current shortest distance from `start` to `node`
-//! let mut dist: Vec<_> = (0..adj_list.len()).map(|_| usize::MAX).collect();
-//!
-//! let mut heap = BinaryHeap::new();
-//!
-//! // We're at `start`, with a zero cost
-//! dist[start] = 0;
-//! heap.push(State { cost: 0, position: start });
-//!
-//! // Examine the frontier with lower cost nodes first (min-heap)
-//! while let Some(State { cost, position }) = heap.pop() {
-//! // Alternatively we could have continued to find all shortest paths
-//! if position == goal { return Some(cost); }
-//!
-//! // Important as we may have already found a better way
-//! if cost > dist[position] { continue; }
-//!
-//! // For each node we can reach, see if we can find a way with
-//! // a lower cost going through this node
-//! for edge in &adj_list[position] {
-//! let next = State { cost: cost + edge.cost, position: edge.node };
-//!
-//! // If so, add it to the frontier and continue
-//! if next.cost < dist[next.position] {
-//! heap.push(next);
-//! // Relaxation, we have now found a better way
-//! dist[next.position] = next.cost;
-//! }
-//! }
-//! }
-//!
-//! // Goal not reachable
-//! None
-//! }
-//!
-//! fn main() {
-//! // This is the directed graph we're going to use.
-//! // The node numbers correspond to the different states,
-//! // and the edge weights symbolize the cost of moving
-//! // from one node to another.
-//! // Note that the edges are one-way.
-//! //
-//! // 7
-//! // +-----------------+
-//! // | |
-//! // v 1 2 | 2
-//! // 0 -----> 1 -----> 3 ---> 4
-//! // | ^ ^ ^
-//! // | | 1 | |
-//! // | | | 3 | 1
-//! // +------> 2 -------+ |
-//! // 10 | |
-//! // +---------------+
-//! //
-//! // The graph is represented as an adjacency list where each index,
-//! // corresponding to a node value, has a list of outgoing edges.
-//! // Chosen for its efficiency.
-//! let graph = vec![
-//! // Node 0
-//! vec![Edge { node: 2, cost: 10 },
-//! Edge { node: 1, cost: 1 }],
-//! // Node 1
-//! vec![Edge { node: 3, cost: 2 }],
-//! // Node 2
-//! vec![Edge { node: 1, cost: 1 },
-//! Edge { node: 3, cost: 3 },
-//! Edge { node: 4, cost: 1 }],
-//! // Node 3
-//! vec![Edge { node: 0, cost: 7 },
-//! Edge { node: 4, cost: 2 }],
-//! // Node 4
-//! vec![]];
-//!
-//! assert_eq!(shortest_path(&graph, 0, 1), Some(1));
-//! assert_eq!(shortest_path(&graph, 0, 3), Some(3));
-//! assert_eq!(shortest_path(&graph, 3, 0), Some(7));
-//! assert_eq!(shortest_path(&graph, 0, 4), Some(5));
-//! assert_eq!(shortest_path(&graph, 4, 0), None);
-//! }
-//! ```
-
-#![allow(missing_docs)]
-#![stable(feature = "rust1", since = "1.0.0")]
-
-use core::fmt;
-use core::iter::{FromIterator, FusedIterator, InPlaceIterable, SourceIter, TrustedLen};
-use core::mem::{self, swap, ManuallyDrop};
-use core::ops::{Deref, DerefMut};
-use core::ptr;
-
-use crate::collections::TryReserveError;
-use crate::slice;
-use crate::vec::{self, AsVecIntoIter, Vec};
-
-use super::SpecExtend;
-
-#[cfg(test)]
-mod tests;
-
-/// A priority queue implemented with a binary heap.
-///
-/// This will be a max-heap.
-///
-/// It is a logic error for an item to be modified in such a way that the
-/// item's ordering relative to any other item, as determined by the [`Ord`]
-/// trait, changes while it is in the heap. This is normally only possible
-/// through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. The
-/// behavior resulting from such a logic error is not specified, but will
-/// be encapsulated to the `BinaryHeap` that observed the logic error and not
-/// result in undefined behavior. This could include panics, incorrect results,
-/// aborts, memory leaks, and non-termination.
-///
-/// # Examples
-///
-/// ```
-/// use std::collections::BinaryHeap;
-///
-/// // Type inference lets us omit an explicit type signature (which
-/// // would be `BinaryHeap<i32>` in this example).
-/// let mut heap = BinaryHeap::new();
-///
-/// // We can use peek to look at the next item in the heap. In this case,
-/// // there's no items in there yet so we get None.
-/// assert_eq!(heap.peek(), None);
-///
-/// // Let's add some scores...
-/// heap.push(1);
-/// heap.push(5);
-/// heap.push(2);
-///
-/// // Now peek shows the most important item in the heap.
-/// assert_eq!(heap.peek(), Some(&5));
-///
-/// // We can check the length of a heap.
-/// assert_eq!(heap.len(), 3);
-///
-/// // We can iterate over the items in the heap, although they are returned in
-/// // a random order.
-/// for x in &heap {
-/// println!("{x}");
-/// }
-///
-/// // If we instead pop these scores, they should come back in order.
-/// assert_eq!(heap.pop(), Some(5));
-/// assert_eq!(heap.pop(), Some(2));
-/// assert_eq!(heap.pop(), Some(1));
-/// assert_eq!(heap.pop(), None);
-///
-/// // We can clear the heap of any remaining items.
-/// heap.clear();
-///
-/// // The heap should now be empty.
-/// assert!(heap.is_empty())
-/// ```
-///
-/// A `BinaryHeap` with a known list of items can be initialized from an array:
-///
-/// ```
-/// use std::collections::BinaryHeap;
-///
-/// let heap = BinaryHeap::from([1, 5, 2]);
-/// ```
-///
-/// ## Min-heap
-///
-/// Either [`core::cmp::Reverse`] or a custom [`Ord`] implementation can be used to
-/// make `BinaryHeap` a min-heap. This makes `heap.pop()` return the smallest
-/// value instead of the greatest one.
-///
-/// ```
-/// use std::collections::BinaryHeap;
-/// use std::cmp::Reverse;
-///
-/// let mut heap = BinaryHeap::new();
-///
-/// // Wrap values in `Reverse`
-/// heap.push(Reverse(1));
-/// heap.push(Reverse(5));
-/// heap.push(Reverse(2));
-///
-/// // If we pop these scores now, they should come back in the reverse order.
-/// assert_eq!(heap.pop(), Some(Reverse(1)));
-/// assert_eq!(heap.pop(), Some(Reverse(2)));
-/// assert_eq!(heap.pop(), Some(Reverse(5)));
-/// assert_eq!(heap.pop(), None);
-/// ```
-///
-/// # Time complexity
-///
-/// | [push] | [pop] | [peek]/[peek\_mut] |
-/// |---------|---------------|--------------------|
-/// | *O*(1)~ | *O*(log(*n*)) | *O*(1) |
-///
-/// The value for `push` is an expected cost; the method documentation gives a
-/// more detailed analysis.
-///
-/// [`core::cmp::Reverse`]: core::cmp::Reverse
-/// [`Ord`]: core::cmp::Ord
-/// [`Cell`]: core::cell::Cell
-/// [`RefCell`]: core::cell::RefCell
-/// [push]: BinaryHeap::push
-/// [pop]: BinaryHeap::pop
-/// [peek]: BinaryHeap::peek
-/// [peek\_mut]: BinaryHeap::peek_mut
-#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(not(test), rustc_diagnostic_item = "BinaryHeap")]
-pub struct BinaryHeap<T> {
- data: Vec<T>,
-}
-
-/// Structure wrapping a mutable reference to the greatest item on a
-/// `BinaryHeap`.
-///
-/// This `struct` is created by the [`peek_mut`] method on [`BinaryHeap`]. See
-/// its documentation for more.
-///
-/// [`peek_mut`]: BinaryHeap::peek_mut
-#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
-pub struct PeekMut<'a, T: 'a + Ord> {
- heap: &'a mut BinaryHeap<T>,
- sift: bool,
-}
-
-#[stable(feature = "collection_debug", since = "1.17.0")]
-impl<T: Ord + fmt::Debug> fmt::Debug for PeekMut<'_, T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_tuple("PeekMut").field(&self.heap.data[0]).finish()
- }
-}
-
-#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
-impl<T: Ord> Drop for PeekMut<'_, T> {
- fn drop(&mut self) {
- if self.sift {
- // SAFETY: PeekMut is only instantiated for non-empty heaps.
- unsafe { self.heap.sift_down(0) };
- }
- }
-}
-
-#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
-impl<T: Ord> Deref for PeekMut<'_, T> {
- type Target = T;
- fn deref(&self) -> &T {
- debug_assert!(!self.heap.is_empty());
- // SAFE: PeekMut is only instantiated for non-empty heaps
- unsafe { self.heap.data.get_unchecked(0) }
- }
-}
-
-#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
-impl<T: Ord> DerefMut for PeekMut<'_, T> {
- fn deref_mut(&mut self) -> &mut T {
- debug_assert!(!self.heap.is_empty());
- self.sift = true;
- // SAFE: PeekMut is only instantiated for non-empty heaps
- unsafe { self.heap.data.get_unchecked_mut(0) }
- }
-}
-
-impl<'a, T: Ord> PeekMut<'a, T> {
- /// Removes the peeked value from the heap and returns it.
- #[stable(feature = "binary_heap_peek_mut_pop", since = "1.18.0")]
- pub fn pop(mut this: PeekMut<'a, T>) -> T {
- let value = this.heap.pop().unwrap();
- this.sift = false;
- value
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Clone> Clone for BinaryHeap<T> {
- fn clone(&self) -> Self {
- BinaryHeap { data: self.data.clone() }
- }
-
- fn clone_from(&mut self, source: &Self) {
- self.data.clone_from(&source.data);
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Ord> Default for BinaryHeap<T> {
- /// Creates an empty `BinaryHeap<T>`.
- #[inline]
- fn default() -> BinaryHeap<T> {
- BinaryHeap::new()
- }
-}
-
-#[stable(feature = "binaryheap_debug", since = "1.4.0")]
-impl<T: fmt::Debug> fmt::Debug for BinaryHeap<T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_list().entries(self.iter()).finish()
- }
-}
-
-impl<T: Ord> BinaryHeap<T> {
- /// Creates an empty `BinaryHeap` as a max-heap.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// let mut heap = BinaryHeap::new();
- /// heap.push(4);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[must_use]
- pub fn new() -> BinaryHeap<T> {
- BinaryHeap { data: vec![] }
- }
-
- /// Creates an empty `BinaryHeap` with at least the specified capacity.
- ///
- /// The binary heap will be able to hold at least `capacity` elements without
- /// reallocating. This method is allowed to allocate for more elements than
- /// `capacity`. If `capacity` is 0, the binary heap will not allocate.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// let mut heap = BinaryHeap::with_capacity(10);
- /// heap.push(4);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[must_use]
- pub fn with_capacity(capacity: usize) -> BinaryHeap<T> {
- BinaryHeap { data: Vec::with_capacity(capacity) }
- }
-
- /// Returns a mutable reference to the greatest item in the binary heap, or
- /// `None` if it is empty.
- ///
- /// Note: If the `PeekMut` value is leaked, the heap may be in an
- /// inconsistent state.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// let mut heap = BinaryHeap::new();
- /// assert!(heap.peek_mut().is_none());
- ///
- /// heap.push(1);
- /// heap.push(5);
- /// heap.push(2);
- /// {
- /// let mut val = heap.peek_mut().unwrap();
- /// *val = 0;
- /// }
- /// assert_eq!(heap.peek(), Some(&2));
- /// ```
- ///
- /// # Time complexity
- ///
- /// If the item is modified then the worst case time complexity is *O*(log(*n*)),
- /// otherwise it's *O*(1).
- #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
- pub fn peek_mut(&mut self) -> Option<PeekMut<'_, T>> {
- if self.is_empty() { None } else { Some(PeekMut { heap: self, sift: false }) }
- }
-
- /// Removes the greatest item from the binary heap and returns it, or `None` if it
- /// is empty.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// let mut heap = BinaryHeap::from([1, 3]);
- ///
- /// assert_eq!(heap.pop(), Some(3));
- /// assert_eq!(heap.pop(), Some(1));
- /// assert_eq!(heap.pop(), None);
- /// ```
- ///
- /// # Time complexity
- ///
- /// The worst case cost of `pop` on a heap containing *n* elements is *O*(log(*n*)).
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn pop(&mut self) -> Option<T> {
- self.data.pop().map(|mut item| {
- if !self.is_empty() {
- swap(&mut item, &mut self.data[0]);
- // SAFETY: !self.is_empty() means that self.len() > 0
- unsafe { self.sift_down_to_bottom(0) };
- }
- item
- })
- }
-
- /// Pushes an item onto the binary heap.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// let mut heap = BinaryHeap::new();
- /// heap.push(3);
- /// heap.push(5);
- /// heap.push(1);
- ///
- /// assert_eq!(heap.len(), 3);
- /// assert_eq!(heap.peek(), Some(&5));
- /// ```
- ///
- /// # Time complexity
- ///
- /// The expected cost of `push`, averaged over every possible ordering of
- /// the elements being pushed, and over a sufficiently large number of
- /// pushes, is *O*(1). This is the most meaningful cost metric when pushing
- /// elements that are *not* already in any sorted pattern.
- ///
- /// The time complexity degrades if elements are pushed in predominantly
- /// ascending order. In the worst case, elements are pushed in ascending
- /// sorted order and the amortized cost per push is *O*(log(*n*)) against a heap
- /// containing *n* elements.
- ///
- /// The worst case cost of a *single* call to `push` is *O*(*n*). The worst case
- /// occurs when capacity is exhausted and needs a resize. The resize cost
- /// has been amortized in the previous figures.
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn push(&mut self, item: T) {
- let old_len = self.len();
- self.data.push(item);
- // SAFETY: Since we pushed a new item it means that
- // old_len = self.len() - 1 < self.len()
- unsafe { self.sift_up(0, old_len) };
- }
-
- /// Consumes the `BinaryHeap` and returns a vector in sorted
- /// (ascending) order.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- ///
- /// let mut heap = BinaryHeap::from([1, 2, 4, 5, 7]);
- /// heap.push(6);
- /// heap.push(3);
- ///
- /// let vec = heap.into_sorted_vec();
- /// assert_eq!(vec, [1, 2, 3, 4, 5, 6, 7]);
- /// ```
- #[must_use = "`self` will be dropped if the result is not used"]
- #[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
- pub fn into_sorted_vec(mut self) -> Vec<T> {
- let mut end = self.len();
- while end > 1 {
- end -= 1;
- // SAFETY: `end` goes from `self.len() - 1` to 1 (both included),
- // so it's always a valid index to access.
- // It is safe to access index 0 (i.e. `ptr`), because
- // 1 <= end < self.len(), which means self.len() >= 2.
- unsafe {
- let ptr = self.data.as_mut_ptr();
- ptr::swap(ptr, ptr.add(end));
- }
- // SAFETY: `end` goes from `self.len() - 1` to 1 (both included) so:
- // 0 < 1 <= end <= self.len() - 1 < self.len()
- // Which means 0 < end and end < self.len().
- unsafe { self.sift_down_range(0, end) };
- }
- self.into_vec()
- }
-
- // The implementations of sift_up and sift_down use unsafe blocks in
- // order to move an element out of the vector (leaving behind a
- // hole), shift along the others and move the removed element back into the
- // vector at the final location of the hole.
- // The `Hole` type is used to represent this, and make sure
- // the hole is filled back at the end of its scope, even on panic.
- // Using a hole reduces the constant factor compared to using swaps,
- // which involves twice as many moves.
-
- /// # Safety
- ///
- /// The caller must guarantee that `pos < self.len()`.
- unsafe fn sift_up(&mut self, start: usize, pos: usize) -> usize {
- // Take out the value at `pos` and create a hole.
- // SAFETY: The caller guarantees that pos < self.len()
- let mut hole = unsafe { Hole::new(&mut self.data, pos) };
-
- while hole.pos() > start {
- let parent = (hole.pos() - 1) / 2;
-
- // SAFETY: hole.pos() > start >= 0, which means hole.pos() > 0
- // and so hole.pos() - 1 can't underflow.
- // This guarantees that parent < hole.pos() so
- // it's a valid index and also != hole.pos().
- if hole.element() <= unsafe { hole.get(parent) } {
- break;
- }
-
- // SAFETY: Same as above
- unsafe { hole.move_to(parent) };
- }
-
- hole.pos()
- }
-
- /// Take an element at `pos` and move it down the heap,
- /// while its children are larger.
- ///
- /// # Safety
- ///
- /// The caller must guarantee that `pos < end <= self.len()`.
- unsafe fn sift_down_range(&mut self, pos: usize, end: usize) {
- // SAFETY: The caller guarantees that pos < end <= self.len().
- let mut hole = unsafe { Hole::new(&mut self.data, pos) };
- let mut child = 2 * hole.pos() + 1;
-
- // Loop invariant: child == 2 * hole.pos() + 1.
- while child <= end.saturating_sub(2) {
- // compare with the greater of the two children
- // SAFETY: child < end - 1 < self.len() and
- // child + 1 < end <= self.len(), so they're valid indexes.
- // child == 2 * hole.pos() + 1 != hole.pos() and
- // child + 1 == 2 * hole.pos() + 2 != hole.pos().
- // FIXME: 2 * hole.pos() + 1 or 2 * hole.pos() + 2 could overflow
- // if T is a ZST
- child += unsafe { hole.get(child) <= hole.get(child + 1) } as usize;
-
- // if we are already in order, stop.
- // SAFETY: child is now either the old child or the old child+1
- // We already proven that both are < self.len() and != hole.pos()
- if hole.element() >= unsafe { hole.get(child) } {
- return;
- }
-
- // SAFETY: same as above.
- unsafe { hole.move_to(child) };
- child = 2 * hole.pos() + 1;
- }
-
- // SAFETY: && short circuit, which means that in the
- // second condition it's already true that child == end - 1 < self.len().
- if child == end - 1 && hole.element() < unsafe { hole.get(child) } {
- // SAFETY: child is already proven to be a valid index and
- // child == 2 * hole.pos() + 1 != hole.pos().
- unsafe { hole.move_to(child) };
- }
- }
-
- /// # Safety
- ///
- /// The caller must guarantee that `pos < self.len()`.
- unsafe fn sift_down(&mut self, pos: usize) {
- let len = self.len();
- // SAFETY: pos < len is guaranteed by the caller and
- // obviously len = self.len() <= self.len().
- unsafe { self.sift_down_range(pos, len) };
- }
-
- /// Take an element at `pos` and move it all the way down the heap,
- /// then sift it up to its position.
- ///
- /// Note: This is faster when the element is known to be large / should
- /// be closer to the bottom.
- ///
- /// # Safety
- ///
- /// The caller must guarantee that `pos < self.len()`.
- unsafe fn sift_down_to_bottom(&mut self, mut pos: usize) {
- let end = self.len();
- let start = pos;
-
- // SAFETY: The caller guarantees that pos < self.len().
- let mut hole = unsafe { Hole::new(&mut self.data, pos) };
- let mut child = 2 * hole.pos() + 1;
-
- // Loop invariant: child == 2 * hole.pos() + 1.
- while child <= end.saturating_sub(2) {
- // SAFETY: child < end - 1 < self.len() and
- // child + 1 < end <= self.len(), so they're valid indexes.
- // child == 2 * hole.pos() + 1 != hole.pos() and
- // child + 1 == 2 * hole.pos() + 2 != hole.pos().
- // FIXME: 2 * hole.pos() + 1 or 2 * hole.pos() + 2 could overflow
- // if T is a ZST
- child += unsafe { hole.get(child) <= hole.get(child + 1) } as usize;
-
- // SAFETY: Same as above
- unsafe { hole.move_to(child) };
- child = 2 * hole.pos() + 1;
- }
-
- if child == end - 1 {
- // SAFETY: child == end - 1 < self.len(), so it's a valid index
- // and child == 2 * hole.pos() + 1 != hole.pos().
- unsafe { hole.move_to(child) };
- }
- pos = hole.pos();
- drop(hole);
-
- // SAFETY: pos is the position in the hole and was already proven
- // to be a valid index.
- unsafe { self.sift_up(start, pos) };
- }
-
- /// Rebuild assuming data[0..start] is still a proper heap.
- fn rebuild_tail(&mut self, start: usize) {
- if start == self.len() {
- return;
- }
-
- let tail_len = self.len() - start;
-
- #[inline(always)]
- fn log2_fast(x: usize) -> usize {
- (usize::BITS - x.leading_zeros() - 1) as usize
- }
-
- // `rebuild` takes O(self.len()) operations
- // and about 2 * self.len() comparisons in the worst case
- // while repeating `sift_up` takes O(tail_len * log(start)) operations
- // and about 1 * tail_len * log_2(start) comparisons in the worst case,
- // assuming start >= tail_len. For larger heaps, the crossover point
- // no longer follows this reasoning and was determined empirically.
- let better_to_rebuild = if start < tail_len {
- true
- } else if self.len() <= 2048 {
- 2 * self.len() < tail_len * log2_fast(start)
- } else {
- 2 * self.len() < tail_len * 11
- };
-
- if better_to_rebuild {
- self.rebuild();
- } else {
- for i in start..self.len() {
- // SAFETY: The index `i` is always less than self.len().
- unsafe { self.sift_up(0, i) };
- }
- }
- }
-
- fn rebuild(&mut self) {
- let mut n = self.len() / 2;
- while n > 0 {
- n -= 1;
- // SAFETY: n starts from self.len() / 2 and goes down to 0.
- // The only case when !(n < self.len()) is if
- // self.len() == 0, but it's ruled out by the loop condition.
- unsafe { self.sift_down(n) };
- }
- }
-
- /// Moves all the elements of `other` into `self`, leaving `other` empty.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- ///
- /// let mut a = BinaryHeap::from([-10, 1, 2, 3, 3]);
- /// let mut b = BinaryHeap::from([-20, 5, 43]);
- ///
- /// a.append(&mut b);
- ///
- /// assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]);
- /// assert!(b.is_empty());
- /// ```
- #[stable(feature = "binary_heap_append", since = "1.11.0")]
- pub fn append(&mut self, other: &mut Self) {
- if self.len() < other.len() {
- swap(self, other);
- }
-
- let start = self.data.len();
-
- self.data.append(&mut other.data);
-
- self.rebuild_tail(start);
- }
-
- /// Clears the binary heap, returning an iterator over the removed elements
- /// in heap order. If the iterator is dropped before being fully consumed,
- /// it drops the remaining elements in heap order.
- ///
- /// The returned iterator keeps a mutable borrow on the heap to optimize
- /// its implementation.
- ///
- /// Note:
- /// * `.drain_sorted()` is *O*(*n* \* log(*n*)); much slower than `.drain()`.
- /// You should use the latter for most cases.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// #![feature(binary_heap_drain_sorted)]
- /// use std::collections::BinaryHeap;
- ///
- /// let mut heap = BinaryHeap::from([1, 2, 3, 4, 5]);
- /// assert_eq!(heap.len(), 5);
- ///
- /// drop(heap.drain_sorted()); // removes all elements in heap order
- /// assert_eq!(heap.len(), 0);
- /// ```
- #[inline]
- #[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
- pub fn drain_sorted(&mut self) -> DrainSorted<'_, T> {
- DrainSorted { inner: self }
- }
-
- /// Retains only the elements specified by the predicate.
- ///
- /// In other words, remove all elements `e` for which `f(&e)` returns
- /// `false`. The elements are visited in unsorted (and unspecified) order.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// #![feature(binary_heap_retain)]
- /// use std::collections::BinaryHeap;
- ///
- /// let mut heap = BinaryHeap::from([-10, -5, 1, 2, 4, 13]);
- ///
- /// heap.retain(|x| x % 2 == 0); // only keep even numbers
- ///
- /// assert_eq!(heap.into_sorted_vec(), [-10, 2, 4])
- /// ```
- #[unstable(feature = "binary_heap_retain", issue = "71503")]
- pub fn retain<F>(&mut self, mut f: F)
- where
- F: FnMut(&T) -> bool,
- {
- let mut first_removed = self.len();
- let mut i = 0;
- self.data.retain(|e| {
- let keep = f(e);
- if !keep && i < first_removed {
- first_removed = i;
- }
- i += 1;
- keep
- });
- // data[0..first_removed] is untouched, so we only need to rebuild the tail:
- self.rebuild_tail(first_removed);
- }
-}
-
-impl<T> BinaryHeap<T> {
- /// Returns an iterator visiting all values in the underlying vector, in
- /// arbitrary order.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// let heap = BinaryHeap::from([1, 2, 3, 4]);
- ///
- /// // Print 1, 2, 3, 4 in arbitrary order
- /// for x in heap.iter() {
- /// println!("{x}");
- /// }
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn iter(&self) -> Iter<'_, T> {
- Iter { iter: self.data.iter() }
- }
-
- /// Returns an iterator which retrieves elements in heap order.
- /// This method consumes the original heap.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// #![feature(binary_heap_into_iter_sorted)]
- /// use std::collections::BinaryHeap;
- /// let heap = BinaryHeap::from([1, 2, 3, 4, 5]);
- ///
- /// assert_eq!(heap.into_iter_sorted().take(2).collect::<Vec<_>>(), [5, 4]);
- /// ```
- #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
- pub fn into_iter_sorted(self) -> IntoIterSorted<T> {
- IntoIterSorted { inner: self }
- }
-
- /// Returns the greatest item in the binary heap, or `None` if it is empty.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// let mut heap = BinaryHeap::new();
- /// assert_eq!(heap.peek(), None);
- ///
- /// heap.push(1);
- /// heap.push(5);
- /// heap.push(2);
- /// assert_eq!(heap.peek(), Some(&5));
- ///
- /// ```
- ///
- /// # Time complexity
- ///
- /// Cost is *O*(1) in the worst case.
- #[must_use]
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn peek(&self) -> Option<&T> {
- self.data.get(0)
- }
-
- /// Returns the number of elements the binary heap can hold without reallocating.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// let mut heap = BinaryHeap::with_capacity(100);
- /// assert!(heap.capacity() >= 100);
- /// heap.push(4);
- /// ```
- #[must_use]
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn capacity(&self) -> usize {
- self.data.capacity()
- }
-
- /// Reserves the minimum capacity for at least `additional` elements more than
- /// the current length. Unlike [`reserve`], this will not
- /// deliberately over-allocate to speculatively avoid frequent allocations.
- /// After calling `reserve_exact`, capacity will be greater than or equal to
- /// `self.len() + additional`. Does nothing if the capacity is already
- /// sufficient.
- ///
- /// [`reserve`]: BinaryHeap::reserve
- ///
- /// # Panics
- ///
- /// Panics if the new capacity overflows [`usize`].
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// let mut heap = BinaryHeap::new();
- /// heap.reserve_exact(100);
- /// assert!(heap.capacity() >= 100);
- /// heap.push(4);
- /// ```
- ///
- /// [`reserve`]: BinaryHeap::reserve
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn reserve_exact(&mut self, additional: usize) {
- self.data.reserve_exact(additional);
- }
-
- /// Reserves capacity for at least `additional` elements more than the
- /// current length. The allocator may reserve more space to speculatively
- /// avoid frequent allocations. After calling `reserve`,
- /// capacity will be greater than or equal to `self.len() + additional`.
- /// Does nothing if capacity is already sufficient.
- ///
- /// # Panics
- ///
- /// Panics if the new capacity overflows [`usize`].
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// let mut heap = BinaryHeap::new();
- /// heap.reserve(100);
- /// assert!(heap.capacity() >= 100);
- /// heap.push(4);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn reserve(&mut self, additional: usize) {
- self.data.reserve(additional);
- }
-
- /// Tries to reserve the minimum capacity for at least `additional` elements
- /// more than the current length. Unlike [`try_reserve`], this will not
- /// deliberately over-allocate to speculatively avoid frequent allocations.
- /// After calling `try_reserve_exact`, capacity will be greater than or
- /// equal to `self.len() + additional` if it returns `Ok(())`.
- /// Does nothing if the capacity is already sufficient.
- ///
- /// Note that the allocator may give the collection more space than it
- /// requests. Therefore, capacity can not be relied upon to be precisely
- /// minimal. Prefer [`try_reserve`] if future insertions are expected.
- ///
- /// [`try_reserve`]: BinaryHeap::try_reserve
- ///
- /// # Errors
- ///
- /// If the capacity overflows, or the allocator reports a failure, then an error
- /// is returned.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// use std::collections::TryReserveError;
- ///
- /// fn find_max_slow(data: &[u32]) -> Result<Option<u32>, TryReserveError> {
- /// let mut heap = BinaryHeap::new();
- ///
- /// // Pre-reserve the memory, exiting if we can't
- /// heap.try_reserve_exact(data.len())?;
- ///
- /// // Now we know this can't OOM in the middle of our complex work
- /// heap.extend(data.iter());
- ///
- /// Ok(heap.pop())
- /// }
- /// # find_max_slow(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
- /// ```
- #[stable(feature = "try_reserve_2", since = "1.63.0")]
- pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
- self.data.try_reserve_exact(additional)
- }
-
- /// Tries to reserve capacity for at least `additional` elements more than the
- /// current length. The allocator may reserve more space to speculatively
- /// avoid frequent allocations. After calling `try_reserve`, capacity will be
- /// greater than or equal to `self.len() + additional` if it returns
- /// `Ok(())`. Does nothing if capacity is already sufficient. This method
- /// preserves the contents even if an error occurs.
- ///
- /// # Errors
- ///
- /// If the capacity overflows, or the allocator reports a failure, then an error
- /// is returned.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// use std::collections::TryReserveError;
- ///
- /// fn find_max_slow(data: &[u32]) -> Result<Option<u32>, TryReserveError> {
- /// let mut heap = BinaryHeap::new();
- ///
- /// // Pre-reserve the memory, exiting if we can't
- /// heap.try_reserve(data.len())?;
- ///
- /// // Now we know this can't OOM in the middle of our complex work
- /// heap.extend(data.iter());
- ///
- /// Ok(heap.pop())
- /// }
- /// # find_max_slow(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
- /// ```
- #[stable(feature = "try_reserve_2", since = "1.63.0")]
- pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
- self.data.try_reserve(additional)
- }
-
- /// Discards as much additional capacity as possible.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// let mut heap: BinaryHeap<i32> = BinaryHeap::with_capacity(100);
- ///
- /// assert!(heap.capacity() >= 100);
- /// heap.shrink_to_fit();
- /// assert!(heap.capacity() == 0);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn shrink_to_fit(&mut self) {
- self.data.shrink_to_fit();
- }
-
- /// Discards capacity with a lower bound.
- ///
- /// The capacity will remain at least as large as both the length
- /// and the supplied value.
- ///
- /// If the current capacity is less than the lower limit, this is a no-op.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// let mut heap: BinaryHeap<i32> = BinaryHeap::with_capacity(100);
- ///
- /// assert!(heap.capacity() >= 100);
- /// heap.shrink_to(10);
- /// assert!(heap.capacity() >= 10);
- /// ```
- #[inline]
- #[stable(feature = "shrink_to", since = "1.56.0")]
- pub fn shrink_to(&mut self, min_capacity: usize) {
- self.data.shrink_to(min_capacity)
- }
-
- /// Returns a slice of all values in the underlying vector, in arbitrary
- /// order.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// #![feature(binary_heap_as_slice)]
- /// use std::collections::BinaryHeap;
- /// use std::io::{self, Write};
- ///
- /// let heap = BinaryHeap::from([1, 2, 3, 4, 5, 6, 7]);
- ///
- /// io::sink().write(heap.as_slice()).unwrap();
- /// ```
- #[must_use]
- #[unstable(feature = "binary_heap_as_slice", issue = "83659")]
- pub fn as_slice(&self) -> &[T] {
- self.data.as_slice()
- }
-
- /// Consumes the `BinaryHeap` and returns the underlying vector
- /// in arbitrary order.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// let heap = BinaryHeap::from([1, 2, 3, 4, 5, 6, 7]);
- /// let vec = heap.into_vec();
- ///
- /// // Will print in some order
- /// for x in vec {
- /// println!("{x}");
- /// }
- /// ```
- #[must_use = "`self` will be dropped if the result is not used"]
- #[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
- pub fn into_vec(self) -> Vec<T> {
- self.into()
- }
-
- /// Returns the length of the binary heap.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// let heap = BinaryHeap::from([1, 3]);
- ///
- /// assert_eq!(heap.len(), 2);
- /// ```
- #[must_use]
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn len(&self) -> usize {
- self.data.len()
- }
-
- /// Checks if the binary heap is empty.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// let mut heap = BinaryHeap::new();
- ///
- /// assert!(heap.is_empty());
- ///
- /// heap.push(3);
- /// heap.push(5);
- /// heap.push(1);
- ///
- /// assert!(!heap.is_empty());
- /// ```
- #[must_use]
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn is_empty(&self) -> bool {
- self.len() == 0
- }
-
- /// Clears the binary heap, returning an iterator over the removed elements
- /// in arbitrary order. If the iterator is dropped before being fully
- /// consumed, it drops the remaining elements in arbitrary order.
- ///
- /// The returned iterator keeps a mutable borrow on the heap to optimize
- /// its implementation.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// let mut heap = BinaryHeap::from([1, 3]);
- ///
- /// assert!(!heap.is_empty());
- ///
- /// for x in heap.drain() {
- /// println!("{x}");
- /// }
- ///
- /// assert!(heap.is_empty());
- /// ```
- #[inline]
- #[stable(feature = "drain", since = "1.6.0")]
- pub fn drain(&mut self) -> Drain<'_, T> {
- Drain { iter: self.data.drain(..) }
- }
-
- /// Drops all items from the binary heap.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// let mut heap = BinaryHeap::from([1, 3]);
- ///
- /// assert!(!heap.is_empty());
- ///
- /// heap.clear();
- ///
- /// assert!(heap.is_empty());
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn clear(&mut self) {
- self.drain();
- }
-}
-
-/// Hole represents a hole in a slice i.e., an index without valid value
-/// (because it was moved from or duplicated).
-/// In drop, `Hole` will restore the slice by filling the hole
-/// position with the value that was originally removed.
-struct Hole<'a, T: 'a> {
- data: &'a mut [T],
- elt: ManuallyDrop<T>,
- pos: usize,
-}
-
-impl<'a, T> Hole<'a, T> {
- /// Create a new `Hole` at index `pos`.
- ///
- /// Unsafe because pos must be within the data slice.
- #[inline]
- unsafe fn new(data: &'a mut [T], pos: usize) -> Self {
- debug_assert!(pos < data.len());
- // SAFE: pos should be inside the slice
- let elt = unsafe { ptr::read(data.get_unchecked(pos)) };
- Hole { data, elt: ManuallyDrop::new(elt), pos }
- }
-
- #[inline]
- fn pos(&self) -> usize {
- self.pos
- }
-
- /// Returns a reference to the element removed.
- #[inline]
- fn element(&self) -> &T {
- &self.elt
- }
-
- /// Returns a reference to the element at `index`.
- ///
- /// Unsafe because index must be within the data slice and not equal to pos.
- #[inline]
- unsafe fn get(&self, index: usize) -> &T {
- debug_assert!(index != self.pos);
- debug_assert!(index < self.data.len());
- unsafe { self.data.get_unchecked(index) }
- }
-
- /// Move hole to new location
- ///
- /// Unsafe because index must be within the data slice and not equal to pos.
- #[inline]
- unsafe fn move_to(&mut self, index: usize) {
- debug_assert!(index != self.pos);
- debug_assert!(index < self.data.len());
- unsafe {
- let ptr = self.data.as_mut_ptr();
- let index_ptr: *const _ = ptr.add(index);
- let hole_ptr = ptr.add(self.pos);
- ptr::copy_nonoverlapping(index_ptr, hole_ptr, 1);
- }
- self.pos = index;
- }
-}
-
-impl<T> Drop for Hole<'_, T> {
- #[inline]
- fn drop(&mut self) {
- // fill the hole again
- unsafe {
- let pos = self.pos;
- ptr::copy_nonoverlapping(&*self.elt, self.data.get_unchecked_mut(pos), 1);
- }
- }
-}
-
-/// An iterator over the elements of a `BinaryHeap`.
-///
-/// This `struct` is created by [`BinaryHeap::iter()`]. See its
-/// documentation for more.
-///
-/// [`iter`]: BinaryHeap::iter
-#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Iter<'a, T: 'a> {
- iter: slice::Iter<'a, T>,
-}
-
-#[stable(feature = "collection_debug", since = "1.17.0")]
-impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_tuple("Iter").field(&self.iter.as_slice()).finish()
- }
-}
-
-// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Clone for Iter<'_, T> {
- fn clone(&self) -> Self {
- Iter { iter: self.iter.clone() }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> Iterator for Iter<'a, T> {
- type Item = &'a T;
-
- #[inline]
- fn next(&mut self) -> Option<&'a T> {
- self.iter.next()
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.iter.size_hint()
- }
-
- #[inline]
- fn last(self) -> Option<&'a T> {
- self.iter.last()
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
- #[inline]
- fn next_back(&mut self) -> Option<&'a T> {
- self.iter.next_back()
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> ExactSizeIterator for Iter<'_, T> {
- fn is_empty(&self) -> bool {
- self.iter.is_empty()
- }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<T> FusedIterator for Iter<'_, T> {}
-
-/// An owning iterator over the elements of a `BinaryHeap`.
-///
-/// This `struct` is created by [`BinaryHeap::into_iter()`]
-/// (provided by the [`IntoIterator`] trait). See its documentation for more.
-///
-/// [`into_iter`]: BinaryHeap::into_iter
-/// [`IntoIterator`]: core::iter::IntoIterator
-#[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Clone)]
-pub struct IntoIter<T> {
- iter: vec::IntoIter<T>,
-}
-
-#[stable(feature = "collection_debug", since = "1.17.0")]
-impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_tuple("IntoIter").field(&self.iter.as_slice()).finish()
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Iterator for IntoIter<T> {
- type Item = T;
-
- #[inline]
- fn next(&mut self) -> Option<T> {
- self.iter.next()
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.iter.size_hint()
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> DoubleEndedIterator for IntoIter<T> {
- #[inline]
- fn next_back(&mut self) -> Option<T> {
- self.iter.next_back()
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> ExactSizeIterator for IntoIter<T> {
- fn is_empty(&self) -> bool {
- self.iter.is_empty()
- }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<T> FusedIterator for IntoIter<T> {}
-
-// In addition to the SAFETY invariants of the following three unsafe traits
-// also refer to the vec::in_place_collect module documentation to get an overview
-#[unstable(issue = "none", feature = "inplace_iteration")]
-#[doc(hidden)]
-unsafe impl<T> SourceIter for IntoIter<T> {
- type Source = IntoIter<T>;
-
- #[inline]
- unsafe fn as_inner(&mut self) -> &mut Self::Source {
- self
- }
-}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-#[doc(hidden)]
-unsafe impl<I> InPlaceIterable for IntoIter<I> {}
-
-unsafe impl<I> AsVecIntoIter for IntoIter<I> {
- type Item = I;
-
- fn as_into_iter(&mut self) -> &mut vec::IntoIter<Self::Item> {
- &mut self.iter
- }
-}
-
-#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
-#[derive(Clone, Debug)]
-pub struct IntoIterSorted<T> {
- inner: BinaryHeap<T>,
-}
-
-#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
-impl<T: Ord> Iterator for IntoIterSorted<T> {
- type Item = T;
-
- #[inline]
- fn next(&mut self) -> Option<T> {
- self.inner.pop()
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- let exact = self.inner.len();
- (exact, Some(exact))
- }
-}
-
-#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
-impl<T: Ord> ExactSizeIterator for IntoIterSorted<T> {}
-
-#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
-impl<T: Ord> FusedIterator for IntoIterSorted<T> {}
-
-#[unstable(feature = "trusted_len", issue = "37572")]
-unsafe impl<T: Ord> TrustedLen for IntoIterSorted<T> {}
-
-/// A draining iterator over the elements of a `BinaryHeap`.
-///
-/// This `struct` is created by [`BinaryHeap::drain()`]. See its
-/// documentation for more.
-///
-/// [`drain`]: BinaryHeap::drain
-#[stable(feature = "drain", since = "1.6.0")]
-#[derive(Debug)]
-pub struct Drain<'a, T: 'a> {
- iter: vec::Drain<'a, T>,
-}
-
-#[stable(feature = "drain", since = "1.6.0")]
-impl<T> Iterator for Drain<'_, T> {
- type Item = T;
-
- #[inline]
- fn next(&mut self) -> Option<T> {
- self.iter.next()
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.iter.size_hint()
- }
-}
-
-#[stable(feature = "drain", since = "1.6.0")]
-impl<T> DoubleEndedIterator for Drain<'_, T> {
- #[inline]
- fn next_back(&mut self) -> Option<T> {
- self.iter.next_back()
- }
-}
-
-#[stable(feature = "drain", since = "1.6.0")]
-impl<T> ExactSizeIterator for Drain<'_, T> {
- fn is_empty(&self) -> bool {
- self.iter.is_empty()
- }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<T> FusedIterator for Drain<'_, T> {}
-
-/// A draining iterator over the elements of a `BinaryHeap`.
-///
-/// This `struct` is created by [`BinaryHeap::drain_sorted()`]. See its
-/// documentation for more.
-///
-/// [`drain_sorted`]: BinaryHeap::drain_sorted
-#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
-#[derive(Debug)]
-pub struct DrainSorted<'a, T: Ord> {
- inner: &'a mut BinaryHeap<T>,
-}
-
-#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
-impl<'a, T: Ord> Drop for DrainSorted<'a, T> {
- /// Removes heap elements in heap order.
- fn drop(&mut self) {
- struct DropGuard<'r, 'a, T: Ord>(&'r mut DrainSorted<'a, T>);
-
- impl<'r, 'a, T: Ord> Drop for DropGuard<'r, 'a, T> {
- fn drop(&mut self) {
- while self.0.inner.pop().is_some() {}
- }
- }
-
- while let Some(item) = self.inner.pop() {
- let guard = DropGuard(self);
- drop(item);
- mem::forget(guard);
- }
- }
-}
-
-#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
-impl<T: Ord> Iterator for DrainSorted<'_, T> {
- type Item = T;
-
- #[inline]
- fn next(&mut self) -> Option<T> {
- self.inner.pop()
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- let exact = self.inner.len();
- (exact, Some(exact))
- }
-}
-
-#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
-impl<T: Ord> ExactSizeIterator for DrainSorted<'_, T> {}
-
-#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
-impl<T: Ord> FusedIterator for DrainSorted<'_, T> {}
-
-#[unstable(feature = "trusted_len", issue = "37572")]
-unsafe impl<T: Ord> TrustedLen for DrainSorted<'_, T> {}
-
-#[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
-impl<T: Ord> From<Vec<T>> for BinaryHeap<T> {
- /// Converts a `Vec<T>` into a `BinaryHeap<T>`.
- ///
- /// This conversion happens in-place, and has *O*(*n*) time complexity.
- fn from(vec: Vec<T>) -> BinaryHeap<T> {
- let mut heap = BinaryHeap { data: vec };
- heap.rebuild();
- heap
- }
-}
-
-#[stable(feature = "std_collections_from_array", since = "1.56.0")]
-impl<T: Ord, const N: usize> From<[T; N]> for BinaryHeap<T> {
- /// ```
- /// use std::collections::BinaryHeap;
- ///
- /// let mut h1 = BinaryHeap::from([1, 4, 2, 3]);
- /// let mut h2: BinaryHeap<_> = [1, 4, 2, 3].into();
- /// while let Some((a, b)) = h1.pop().zip(h2.pop()) {
- /// assert_eq!(a, b);
- /// }
- /// ```
- fn from(arr: [T; N]) -> Self {
- Self::from_iter(arr)
- }
-}
-
-#[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
-impl<T> From<BinaryHeap<T>> for Vec<T> {
- /// Converts a `BinaryHeap<T>` into a `Vec<T>`.
- ///
- /// This conversion requires no data movement or allocation, and has
- /// constant time complexity.
- fn from(heap: BinaryHeap<T>) -> Vec<T> {
- heap.data
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Ord> FromIterator<T> for BinaryHeap<T> {
- fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> BinaryHeap<T> {
- BinaryHeap::from(iter.into_iter().collect::<Vec<_>>())
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> IntoIterator for BinaryHeap<T> {
- type Item = T;
- type IntoIter = IntoIter<T>;
-
- /// Creates a consuming iterator, that is, one that moves each value out of
- /// the binary heap in arbitrary order. The binary heap cannot be used
- /// after calling this.
- ///
- /// # Examples
- ///
- /// Basic usage:
- ///
- /// ```
- /// use std::collections::BinaryHeap;
- /// let heap = BinaryHeap::from([1, 2, 3, 4]);
- ///
- /// // Print 1, 2, 3, 4 in arbitrary order
- /// for x in heap.into_iter() {
- /// // x has type i32, not &i32
- /// println!("{x}");
- /// }
- /// ```
- fn into_iter(self) -> IntoIter<T> {
- IntoIter { iter: self.data.into_iter() }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> IntoIterator for &'a BinaryHeap<T> {
- type Item = &'a T;
- type IntoIter = Iter<'a, T>;
-
- fn into_iter(self) -> Iter<'a, T> {
- self.iter()
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Ord> Extend<T> for BinaryHeap<T> {
- #[inline]
- fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
- <Self as SpecExtend<I>>::spec_extend(self, iter);
- }
-
- #[inline]
- fn extend_one(&mut self, item: T) {
- self.push(item);
- }
-
- #[inline]
- fn extend_reserve(&mut self, additional: usize) {
- self.reserve(additional);
- }
-}
-
-impl<T: Ord, I: IntoIterator<Item = T>> SpecExtend<I> for BinaryHeap<T> {
- default fn spec_extend(&mut self, iter: I) {
- self.extend_desugared(iter.into_iter());
- }
-}
-
-impl<T: Ord> SpecExtend<Vec<T>> for BinaryHeap<T> {
- fn spec_extend(&mut self, ref mut other: Vec<T>) {
- let start = self.data.len();
- self.data.append(other);
- self.rebuild_tail(start);
- }
-}
-
-impl<T: Ord> SpecExtend<BinaryHeap<T>> for BinaryHeap<T> {
- fn spec_extend(&mut self, ref mut other: BinaryHeap<T>) {
- self.append(other);
- }
-}
-
-impl<T: Ord> BinaryHeap<T> {
- fn extend_desugared<I: IntoIterator<Item = T>>(&mut self, iter: I) {
- let iterator = iter.into_iter();
- let (lower, _) = iterator.size_hint();
-
- self.reserve(lower);
-
- iterator.for_each(move |elem| self.push(elem));
- }
-}
-
-#[stable(feature = "extend_ref", since = "1.2.0")]
-impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap<T> {
- fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
- self.extend(iter.into_iter().cloned());
- }
-
- #[inline]
- fn extend_one(&mut self, &item: &'a T) {
- self.push(item);
- }
-
- #[inline]
- fn extend_reserve(&mut self, additional: usize) {
- self.reserve(additional);
- }
-}
--- /dev/null
+//! A priority queue implemented with a binary heap.
+//!
+//! Insertion and popping the largest element have *O*(log(*n*)) time complexity.
+//! Checking the largest element is *O*(1). Converting a vector to a binary heap
+//! can be done in-place, and has *O*(*n*) complexity. A binary heap can also be
+//! converted to a sorted vector in-place, allowing it to be used for an *O*(*n* * log(*n*))
+//! in-place heapsort.
+//!
+//! # Examples
+//!
+//! This is a larger example that implements [Dijkstra's algorithm][dijkstra]
+//! to solve the [shortest path problem][sssp] on a [directed graph][dir_graph].
+//! It shows how to use [`BinaryHeap`] with custom types.
+//!
+//! [dijkstra]: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
+//! [sssp]: https://en.wikipedia.org/wiki/Shortest_path_problem
+//! [dir_graph]: https://en.wikipedia.org/wiki/Directed_graph
+//!
+//! ```
+//! use std::cmp::Ordering;
+//! use std::collections::BinaryHeap;
+//!
+//! #[derive(Copy, Clone, Eq, PartialEq)]
+//! struct State {
+//! cost: usize,
+//! position: usize,
+//! }
+//!
+//! // The priority queue depends on `Ord`.
+//! // Explicitly implement the trait so the queue becomes a min-heap
+//! // instead of a max-heap.
+//! impl Ord for State {
+//! fn cmp(&self, other: &Self) -> Ordering {
+//! // Notice that the we flip the ordering on costs.
+//! // In case of a tie we compare positions - this step is necessary
+//! // to make implementations of `PartialEq` and `Ord` consistent.
+//! other.cost.cmp(&self.cost)
+//! .then_with(|| self.position.cmp(&other.position))
+//! }
+//! }
+//!
+//! // `PartialOrd` needs to be implemented as well.
+//! impl PartialOrd for State {
+//! fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+//! Some(self.cmp(other))
+//! }
+//! }
+//!
+//! // Each node is represented as a `usize`, for a shorter implementation.
+//! struct Edge {
+//! node: usize,
+//! cost: usize,
+//! }
+//!
+//! // Dijkstra's shortest path algorithm.
+//!
+//! // Start at `start` and use `dist` to track the current shortest distance
+//! // to each node. This implementation isn't memory-efficient as it may leave duplicate
+//! // nodes in the queue. It also uses `usize::MAX` as a sentinel value,
+//! // for a simpler implementation.
+//! fn shortest_path(adj_list: &Vec<Vec<Edge>>, start: usize, goal: usize) -> Option<usize> {
+//! // dist[node] = current shortest distance from `start` to `node`
+//! let mut dist: Vec<_> = (0..adj_list.len()).map(|_| usize::MAX).collect();
+//!
+//! let mut heap = BinaryHeap::new();
+//!
+//! // We're at `start`, with a zero cost
+//! dist[start] = 0;
+//! heap.push(State { cost: 0, position: start });
+//!
+//! // Examine the frontier with lower cost nodes first (min-heap)
+//! while let Some(State { cost, position }) = heap.pop() {
+//! // Alternatively we could have continued to find all shortest paths
+//! if position == goal { return Some(cost); }
+//!
+//! // Important as we may have already found a better way
+//! if cost > dist[position] { continue; }
+//!
+//! // For each node we can reach, see if we can find a way with
+//! // a lower cost going through this node
+//! for edge in &adj_list[position] {
+//! let next = State { cost: cost + edge.cost, position: edge.node };
+//!
+//! // If so, add it to the frontier and continue
+//! if next.cost < dist[next.position] {
+//! heap.push(next);
+//! // Relaxation, we have now found a better way
+//! dist[next.position] = next.cost;
+//! }
+//! }
+//! }
+//!
+//! // Goal not reachable
+//! None
+//! }
+//!
+//! fn main() {
+//! // This is the directed graph we're going to use.
+//! // The node numbers correspond to the different states,
+//! // and the edge weights symbolize the cost of moving
+//! // from one node to another.
+//! // Note that the edges are one-way.
+//! //
+//! // 7
+//! // +-----------------+
+//! // | |
+//! // v 1 2 | 2
+//! // 0 -----> 1 -----> 3 ---> 4
+//! // | ^ ^ ^
+//! // | | 1 | |
+//! // | | | 3 | 1
+//! // +------> 2 -------+ |
+//! // 10 | |
+//! // +---------------+
+//! //
+//! // The graph is represented as an adjacency list where each index,
+//! // corresponding to a node value, has a list of outgoing edges.
+//! // Chosen for its efficiency.
+//! let graph = vec![
+//! // Node 0
+//! vec![Edge { node: 2, cost: 10 },
+//! Edge { node: 1, cost: 1 }],
+//! // Node 1
+//! vec![Edge { node: 3, cost: 2 }],
+//! // Node 2
+//! vec![Edge { node: 1, cost: 1 },
+//! Edge { node: 3, cost: 3 },
+//! Edge { node: 4, cost: 1 }],
+//! // Node 3
+//! vec![Edge { node: 0, cost: 7 },
+//! Edge { node: 4, cost: 2 }],
+//! // Node 4
+//! vec![]];
+//!
+//! assert_eq!(shortest_path(&graph, 0, 1), Some(1));
+//! assert_eq!(shortest_path(&graph, 0, 3), Some(3));
+//! assert_eq!(shortest_path(&graph, 3, 0), Some(7));
+//! assert_eq!(shortest_path(&graph, 0, 4), Some(5));
+//! assert_eq!(shortest_path(&graph, 4, 0), None);
+//! }
+//! ```
+
+#![allow(missing_docs)]
+#![stable(feature = "rust1", since = "1.0.0")]
+
+use core::fmt;
+use core::iter::{FromIterator, FusedIterator, InPlaceIterable, SourceIter, TrustedLen};
+use core::mem::{self, swap, ManuallyDrop};
+use core::ops::{Deref, DerefMut};
+use core::ptr;
+
+use crate::collections::TryReserveError;
+use crate::slice;
+use crate::vec::{self, AsVecIntoIter, Vec};
+
+use super::SpecExtend;
+
+#[cfg(test)]
+mod tests;
+
+/// A priority queue implemented with a binary heap.
+///
+/// This will be a max-heap.
+///
+/// It is a logic error for an item to be modified in such a way that the
+/// item's ordering relative to any other item, as determined by the [`Ord`]
+/// trait, changes while it is in the heap. This is normally only possible
+/// through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. The
+/// behavior resulting from such a logic error is not specified, but will
+/// be encapsulated to the `BinaryHeap` that observed the logic error and not
+/// result in undefined behavior. This could include panics, incorrect results,
+/// aborts, memory leaks, and non-termination.
+///
+/// # Examples
+///
+/// ```
+/// use std::collections::BinaryHeap;
+///
+/// // Type inference lets us omit an explicit type signature (which
+/// // would be `BinaryHeap<i32>` in this example).
+/// let mut heap = BinaryHeap::new();
+///
+/// // We can use peek to look at the next item in the heap. In this case,
+/// // there's no items in there yet so we get None.
+/// assert_eq!(heap.peek(), None);
+///
+/// // Let's add some scores...
+/// heap.push(1);
+/// heap.push(5);
+/// heap.push(2);
+///
+/// // Now peek shows the most important item in the heap.
+/// assert_eq!(heap.peek(), Some(&5));
+///
+/// // We can check the length of a heap.
+/// assert_eq!(heap.len(), 3);
+///
+/// // We can iterate over the items in the heap, although they are returned in
+/// // a random order.
+/// for x in &heap {
+/// println!("{x}");
+/// }
+///
+/// // If we instead pop these scores, they should come back in order.
+/// assert_eq!(heap.pop(), Some(5));
+/// assert_eq!(heap.pop(), Some(2));
+/// assert_eq!(heap.pop(), Some(1));
+/// assert_eq!(heap.pop(), None);
+///
+/// // We can clear the heap of any remaining items.
+/// heap.clear();
+///
+/// // The heap should now be empty.
+/// assert!(heap.is_empty())
+/// ```
+///
+/// A `BinaryHeap` with a known list of items can be initialized from an array:
+///
+/// ```
+/// use std::collections::BinaryHeap;
+///
+/// let heap = BinaryHeap::from([1, 5, 2]);
+/// ```
+///
+/// ## Min-heap
+///
+/// Either [`core::cmp::Reverse`] or a custom [`Ord`] implementation can be used to
+/// make `BinaryHeap` a min-heap. This makes `heap.pop()` return the smallest
+/// value instead of the greatest one.
+///
+/// ```
+/// use std::collections::BinaryHeap;
+/// use std::cmp::Reverse;
+///
+/// let mut heap = BinaryHeap::new();
+///
+/// // Wrap values in `Reverse`
+/// heap.push(Reverse(1));
+/// heap.push(Reverse(5));
+/// heap.push(Reverse(2));
+///
+/// // If we pop these scores now, they should come back in the reverse order.
+/// assert_eq!(heap.pop(), Some(Reverse(1)));
+/// assert_eq!(heap.pop(), Some(Reverse(2)));
+/// assert_eq!(heap.pop(), Some(Reverse(5)));
+/// assert_eq!(heap.pop(), None);
+/// ```
+///
+/// # Time complexity
+///
+/// | [push] | [pop] | [peek]/[peek\_mut] |
+/// |---------|---------------|--------------------|
+/// | *O*(1)~ | *O*(log(*n*)) | *O*(1) |
+///
+/// The value for `push` is an expected cost; the method documentation gives a
+/// more detailed analysis.
+///
+/// [`core::cmp::Reverse`]: core::cmp::Reverse
+/// [`Ord`]: core::cmp::Ord
+/// [`Cell`]: core::cell::Cell
+/// [`RefCell`]: core::cell::RefCell
+/// [push]: BinaryHeap::push
+/// [pop]: BinaryHeap::pop
+/// [peek]: BinaryHeap::peek
+/// [peek\_mut]: BinaryHeap::peek_mut
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "BinaryHeap")]
+pub struct BinaryHeap<T> {
+ data: Vec<T>,
+}
+
+/// Structure wrapping a mutable reference to the greatest item on a
+/// `BinaryHeap`.
+///
+/// This `struct` is created by the [`peek_mut`] method on [`BinaryHeap`]. See
+/// its documentation for more.
+///
+/// [`peek_mut`]: BinaryHeap::peek_mut
+#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
+pub struct PeekMut<'a, T: 'a + Ord> {
+ heap: &'a mut BinaryHeap<T>,
+ sift: bool,
+}
+
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<T: Ord + fmt::Debug> fmt::Debug for PeekMut<'_, T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_tuple("PeekMut").field(&self.heap.data[0]).finish()
+ }
+}
+
+#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
+impl<T: Ord> Drop for PeekMut<'_, T> {
+ fn drop(&mut self) {
+ if self.sift {
+ // SAFETY: PeekMut is only instantiated for non-empty heaps.
+ unsafe { self.heap.sift_down(0) };
+ }
+ }
+}
+
+#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
+impl<T: Ord> Deref for PeekMut<'_, T> {
+ type Target = T;
+ fn deref(&self) -> &T {
+ debug_assert!(!self.heap.is_empty());
+ // SAFE: PeekMut is only instantiated for non-empty heaps
+ unsafe { self.heap.data.get_unchecked(0) }
+ }
+}
+
+#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
+impl<T: Ord> DerefMut for PeekMut<'_, T> {
+ fn deref_mut(&mut self) -> &mut T {
+ debug_assert!(!self.heap.is_empty());
+ self.sift = true;
+ // SAFE: PeekMut is only instantiated for non-empty heaps
+ unsafe { self.heap.data.get_unchecked_mut(0) }
+ }
+}
+
+impl<'a, T: Ord> PeekMut<'a, T> {
+ /// Removes the peeked value from the heap and returns it.
+ #[stable(feature = "binary_heap_peek_mut_pop", since = "1.18.0")]
+ pub fn pop(mut this: PeekMut<'a, T>) -> T {
+ let value = this.heap.pop().unwrap();
+ this.sift = false;
+ value
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: Clone> Clone for BinaryHeap<T> {
+ fn clone(&self) -> Self {
+ BinaryHeap { data: self.data.clone() }
+ }
+
+ fn clone_from(&mut self, source: &Self) {
+ self.data.clone_from(&source.data);
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: Ord> Default for BinaryHeap<T> {
+ /// Creates an empty `BinaryHeap<T>`.
+ #[inline]
+ fn default() -> BinaryHeap<T> {
+ BinaryHeap::new()
+ }
+}
+
+#[stable(feature = "binaryheap_debug", since = "1.4.0")]
+impl<T: fmt::Debug> fmt::Debug for BinaryHeap<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_list().entries(self.iter()).finish()
+ }
+}
+
+impl<T: Ord> BinaryHeap<T> {
+ /// Creates an empty `BinaryHeap` as a max-heap.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// let mut heap = BinaryHeap::new();
+ /// heap.push(4);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[must_use]
+ pub fn new() -> BinaryHeap<T> {
+ BinaryHeap { data: vec![] }
+ }
+
+ /// Creates an empty `BinaryHeap` with at least the specified capacity.
+ ///
+ /// The binary heap will be able to hold at least `capacity` elements without
+ /// reallocating. This method is allowed to allocate for more elements than
+ /// `capacity`. If `capacity` is 0, the binary heap will not allocate.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// let mut heap = BinaryHeap::with_capacity(10);
+ /// heap.push(4);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[must_use]
+ pub fn with_capacity(capacity: usize) -> BinaryHeap<T> {
+ BinaryHeap { data: Vec::with_capacity(capacity) }
+ }
+
+ /// Returns a mutable reference to the greatest item in the binary heap, or
+ /// `None` if it is empty.
+ ///
+ /// Note: If the `PeekMut` value is leaked, the heap may be in an
+ /// inconsistent state.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// let mut heap = BinaryHeap::new();
+ /// assert!(heap.peek_mut().is_none());
+ ///
+ /// heap.push(1);
+ /// heap.push(5);
+ /// heap.push(2);
+ /// {
+ /// let mut val = heap.peek_mut().unwrap();
+ /// *val = 0;
+ /// }
+ /// assert_eq!(heap.peek(), Some(&2));
+ /// ```
+ ///
+ /// # Time complexity
+ ///
+ /// If the item is modified then the worst case time complexity is *O*(log(*n*)),
+ /// otherwise it's *O*(1).
+ #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
+ pub fn peek_mut(&mut self) -> Option<PeekMut<'_, T>> {
+ if self.is_empty() { None } else { Some(PeekMut { heap: self, sift: false }) }
+ }
+
+ /// Removes the greatest item from the binary heap and returns it, or `None` if it
+ /// is empty.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// let mut heap = BinaryHeap::from([1, 3]);
+ ///
+ /// assert_eq!(heap.pop(), Some(3));
+ /// assert_eq!(heap.pop(), Some(1));
+ /// assert_eq!(heap.pop(), None);
+ /// ```
+ ///
+ /// # Time complexity
+ ///
+ /// The worst case cost of `pop` on a heap containing *n* elements is *O*(log(*n*)).
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn pop(&mut self) -> Option<T> {
+ self.data.pop().map(|mut item| {
+ if !self.is_empty() {
+ swap(&mut item, &mut self.data[0]);
+ // SAFETY: !self.is_empty() means that self.len() > 0
+ unsafe { self.sift_down_to_bottom(0) };
+ }
+ item
+ })
+ }
+
+ /// Pushes an item onto the binary heap.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// let mut heap = BinaryHeap::new();
+ /// heap.push(3);
+ /// heap.push(5);
+ /// heap.push(1);
+ ///
+ /// assert_eq!(heap.len(), 3);
+ /// assert_eq!(heap.peek(), Some(&5));
+ /// ```
+ ///
+ /// # Time complexity
+ ///
+ /// The expected cost of `push`, averaged over every possible ordering of
+ /// the elements being pushed, and over a sufficiently large number of
+ /// pushes, is *O*(1). This is the most meaningful cost metric when pushing
+ /// elements that are *not* already in any sorted pattern.
+ ///
+ /// The time complexity degrades if elements are pushed in predominantly
+ /// ascending order. In the worst case, elements are pushed in ascending
+ /// sorted order and the amortized cost per push is *O*(log(*n*)) against a heap
+ /// containing *n* elements.
+ ///
+ /// The worst case cost of a *single* call to `push` is *O*(*n*). The worst case
+ /// occurs when capacity is exhausted and needs a resize. The resize cost
+ /// has been amortized in the previous figures.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn push(&mut self, item: T) {
+ let old_len = self.len();
+ self.data.push(item);
+ // SAFETY: Since we pushed a new item it means that
+ // old_len = self.len() - 1 < self.len()
+ unsafe { self.sift_up(0, old_len) };
+ }
+
+ /// Consumes the `BinaryHeap` and returns a vector in sorted
+ /// (ascending) order.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ ///
+ /// let mut heap = BinaryHeap::from([1, 2, 4, 5, 7]);
+ /// heap.push(6);
+ /// heap.push(3);
+ ///
+ /// let vec = heap.into_sorted_vec();
+ /// assert_eq!(vec, [1, 2, 3, 4, 5, 6, 7]);
+ /// ```
+ #[must_use = "`self` will be dropped if the result is not used"]
+ #[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
+ pub fn into_sorted_vec(mut self) -> Vec<T> {
+ let mut end = self.len();
+ while end > 1 {
+ end -= 1;
+ // SAFETY: `end` goes from `self.len() - 1` to 1 (both included),
+ // so it's always a valid index to access.
+ // It is safe to access index 0 (i.e. `ptr`), because
+ // 1 <= end < self.len(), which means self.len() >= 2.
+ unsafe {
+ let ptr = self.data.as_mut_ptr();
+ ptr::swap(ptr, ptr.add(end));
+ }
+ // SAFETY: `end` goes from `self.len() - 1` to 1 (both included) so:
+ // 0 < 1 <= end <= self.len() - 1 < self.len()
+ // Which means 0 < end and end < self.len().
+ unsafe { self.sift_down_range(0, end) };
+ }
+ self.into_vec()
+ }
+
+ // The implementations of sift_up and sift_down use unsafe blocks in
+ // order to move an element out of the vector (leaving behind a
+ // hole), shift along the others and move the removed element back into the
+ // vector at the final location of the hole.
+ // The `Hole` type is used to represent this, and make sure
+ // the hole is filled back at the end of its scope, even on panic.
+ // Using a hole reduces the constant factor compared to using swaps,
+ // which involves twice as many moves.
+
+ /// # Safety
+ ///
+ /// The caller must guarantee that `pos < self.len()`.
+ unsafe fn sift_up(&mut self, start: usize, pos: usize) -> usize {
+ // Take out the value at `pos` and create a hole.
+ // SAFETY: The caller guarantees that pos < self.len()
+ let mut hole = unsafe { Hole::new(&mut self.data, pos) };
+
+ while hole.pos() > start {
+ let parent = (hole.pos() - 1) / 2;
+
+ // SAFETY: hole.pos() > start >= 0, which means hole.pos() > 0
+ // and so hole.pos() - 1 can't underflow.
+ // This guarantees that parent < hole.pos() so
+ // it's a valid index and also != hole.pos().
+ if hole.element() <= unsafe { hole.get(parent) } {
+ break;
+ }
+
+ // SAFETY: Same as above
+ unsafe { hole.move_to(parent) };
+ }
+
+ hole.pos()
+ }
+
+ /// Take an element at `pos` and move it down the heap,
+ /// while its children are larger.
+ ///
+ /// # Safety
+ ///
+ /// The caller must guarantee that `pos < end <= self.len()`.
+ unsafe fn sift_down_range(&mut self, pos: usize, end: usize) {
+ // SAFETY: The caller guarantees that pos < end <= self.len().
+ let mut hole = unsafe { Hole::new(&mut self.data, pos) };
+ let mut child = 2 * hole.pos() + 1;
+
+ // Loop invariant: child == 2 * hole.pos() + 1.
+ while child <= end.saturating_sub(2) {
+ // compare with the greater of the two children
+ // SAFETY: child < end - 1 < self.len() and
+ // child + 1 < end <= self.len(), so they're valid indexes.
+ // child == 2 * hole.pos() + 1 != hole.pos() and
+ // child + 1 == 2 * hole.pos() + 2 != hole.pos().
+ // FIXME: 2 * hole.pos() + 1 or 2 * hole.pos() + 2 could overflow
+ // if T is a ZST
+ child += unsafe { hole.get(child) <= hole.get(child + 1) } as usize;
+
+ // if we are already in order, stop.
+ // SAFETY: child is now either the old child or the old child+1
+ // We already proven that both are < self.len() and != hole.pos()
+ if hole.element() >= unsafe { hole.get(child) } {
+ return;
+ }
+
+ // SAFETY: same as above.
+ unsafe { hole.move_to(child) };
+ child = 2 * hole.pos() + 1;
+ }
+
+ // SAFETY: && short circuit, which means that in the
+ // second condition it's already true that child == end - 1 < self.len().
+ if child == end - 1 && hole.element() < unsafe { hole.get(child) } {
+ // SAFETY: child is already proven to be a valid index and
+ // child == 2 * hole.pos() + 1 != hole.pos().
+ unsafe { hole.move_to(child) };
+ }
+ }
+
+ /// # Safety
+ ///
+ /// The caller must guarantee that `pos < self.len()`.
+ unsafe fn sift_down(&mut self, pos: usize) {
+ let len = self.len();
+ // SAFETY: pos < len is guaranteed by the caller and
+ // obviously len = self.len() <= self.len().
+ unsafe { self.sift_down_range(pos, len) };
+ }
+
+ /// Take an element at `pos` and move it all the way down the heap,
+ /// then sift it up to its position.
+ ///
+ /// Note: This is faster when the element is known to be large / should
+ /// be closer to the bottom.
+ ///
+ /// # Safety
+ ///
+ /// The caller must guarantee that `pos < self.len()`.
+ unsafe fn sift_down_to_bottom(&mut self, mut pos: usize) {
+ let end = self.len();
+ let start = pos;
+
+ // SAFETY: The caller guarantees that pos < self.len().
+ let mut hole = unsafe { Hole::new(&mut self.data, pos) };
+ let mut child = 2 * hole.pos() + 1;
+
+ // Loop invariant: child == 2 * hole.pos() + 1.
+ while child <= end.saturating_sub(2) {
+ // SAFETY: child < end - 1 < self.len() and
+ // child + 1 < end <= self.len(), so they're valid indexes.
+ // child == 2 * hole.pos() + 1 != hole.pos() and
+ // child + 1 == 2 * hole.pos() + 2 != hole.pos().
+ // FIXME: 2 * hole.pos() + 1 or 2 * hole.pos() + 2 could overflow
+ // if T is a ZST
+ child += unsafe { hole.get(child) <= hole.get(child + 1) } as usize;
+
+ // SAFETY: Same as above
+ unsafe { hole.move_to(child) };
+ child = 2 * hole.pos() + 1;
+ }
+
+ if child == end - 1 {
+ // SAFETY: child == end - 1 < self.len(), so it's a valid index
+ // and child == 2 * hole.pos() + 1 != hole.pos().
+ unsafe { hole.move_to(child) };
+ }
+ pos = hole.pos();
+ drop(hole);
+
+ // SAFETY: pos is the position in the hole and was already proven
+ // to be a valid index.
+ unsafe { self.sift_up(start, pos) };
+ }
+
+ /// Rebuild assuming data[0..start] is still a proper heap.
+ fn rebuild_tail(&mut self, start: usize) {
+ if start == self.len() {
+ return;
+ }
+
+ let tail_len = self.len() - start;
+
+ #[inline(always)]
+ fn log2_fast(x: usize) -> usize {
+ (usize::BITS - x.leading_zeros() - 1) as usize
+ }
+
+ // `rebuild` takes O(self.len()) operations
+ // and about 2 * self.len() comparisons in the worst case
+ // while repeating `sift_up` takes O(tail_len * log(start)) operations
+ // and about 1 * tail_len * log_2(start) comparisons in the worst case,
+ // assuming start >= tail_len. For larger heaps, the crossover point
+ // no longer follows this reasoning and was determined empirically.
+ let better_to_rebuild = if start < tail_len {
+ true
+ } else if self.len() <= 2048 {
+ 2 * self.len() < tail_len * log2_fast(start)
+ } else {
+ 2 * self.len() < tail_len * 11
+ };
+
+ if better_to_rebuild {
+ self.rebuild();
+ } else {
+ for i in start..self.len() {
+ // SAFETY: The index `i` is always less than self.len().
+ unsafe { self.sift_up(0, i) };
+ }
+ }
+ }
+
+ fn rebuild(&mut self) {
+ let mut n = self.len() / 2;
+ while n > 0 {
+ n -= 1;
+ // SAFETY: n starts from self.len() / 2 and goes down to 0.
+ // The only case when !(n < self.len()) is if
+ // self.len() == 0, but it's ruled out by the loop condition.
+ unsafe { self.sift_down(n) };
+ }
+ }
+
+ /// Moves all the elements of `other` into `self`, leaving `other` empty.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ ///
+ /// let mut a = BinaryHeap::from([-10, 1, 2, 3, 3]);
+ /// let mut b = BinaryHeap::from([-20, 5, 43]);
+ ///
+ /// a.append(&mut b);
+ ///
+ /// assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]);
+ /// assert!(b.is_empty());
+ /// ```
+ #[stable(feature = "binary_heap_append", since = "1.11.0")]
+ pub fn append(&mut self, other: &mut Self) {
+ if self.len() < other.len() {
+ swap(self, other);
+ }
+
+ let start = self.data.len();
+
+ self.data.append(&mut other.data);
+
+ self.rebuild_tail(start);
+ }
+
+ /// Clears the binary heap, returning an iterator over the removed elements
+ /// in heap order. If the iterator is dropped before being fully consumed,
+ /// it drops the remaining elements in heap order.
+ ///
+ /// The returned iterator keeps a mutable borrow on the heap to optimize
+ /// its implementation.
+ ///
+ /// Note:
+ /// * `.drain_sorted()` is *O*(*n* \* log(*n*)); much slower than `.drain()`.
+ /// You should use the latter for most cases.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(binary_heap_drain_sorted)]
+ /// use std::collections::BinaryHeap;
+ ///
+ /// let mut heap = BinaryHeap::from([1, 2, 3, 4, 5]);
+ /// assert_eq!(heap.len(), 5);
+ ///
+ /// drop(heap.drain_sorted()); // removes all elements in heap order
+ /// assert_eq!(heap.len(), 0);
+ /// ```
+ #[inline]
+ #[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
+ pub fn drain_sorted(&mut self) -> DrainSorted<'_, T> {
+ DrainSorted { inner: self }
+ }
+
+ /// Retains only the elements specified by the predicate.
+ ///
+ /// In other words, remove all elements `e` for which `f(&e)` returns
+ /// `false`. The elements are visited in unsorted (and unspecified) order.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(binary_heap_retain)]
+ /// use std::collections::BinaryHeap;
+ ///
+ /// let mut heap = BinaryHeap::from([-10, -5, 1, 2, 4, 13]);
+ ///
+ /// heap.retain(|x| x % 2 == 0); // only keep even numbers
+ ///
+ /// assert_eq!(heap.into_sorted_vec(), [-10, 2, 4])
+ /// ```
+ #[unstable(feature = "binary_heap_retain", issue = "71503")]
+ pub fn retain<F>(&mut self, mut f: F)
+ where
+ F: FnMut(&T) -> bool,
+ {
+ let mut first_removed = self.len();
+ let mut i = 0;
+ self.data.retain(|e| {
+ let keep = f(e);
+ if !keep && i < first_removed {
+ first_removed = i;
+ }
+ i += 1;
+ keep
+ });
+ // data[0..first_removed] is untouched, so we only need to rebuild the tail:
+ self.rebuild_tail(first_removed);
+ }
+}
+
+impl<T> BinaryHeap<T> {
+ /// Returns an iterator visiting all values in the underlying vector, in
+ /// arbitrary order.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// let heap = BinaryHeap::from([1, 2, 3, 4]);
+ ///
+ /// // Print 1, 2, 3, 4 in arbitrary order
+ /// for x in heap.iter() {
+ /// println!("{x}");
+ /// }
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn iter(&self) -> Iter<'_, T> {
+ Iter { iter: self.data.iter() }
+ }
+
+ /// Returns an iterator which retrieves elements in heap order.
+ /// This method consumes the original heap.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(binary_heap_into_iter_sorted)]
+ /// use std::collections::BinaryHeap;
+ /// let heap = BinaryHeap::from([1, 2, 3, 4, 5]);
+ ///
+ /// assert_eq!(heap.into_iter_sorted().take(2).collect::<Vec<_>>(), [5, 4]);
+ /// ```
+ #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
+ pub fn into_iter_sorted(self) -> IntoIterSorted<T> {
+ IntoIterSorted { inner: self }
+ }
+
+ /// Returns the greatest item in the binary heap, or `None` if it is empty.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// let mut heap = BinaryHeap::new();
+ /// assert_eq!(heap.peek(), None);
+ ///
+ /// heap.push(1);
+ /// heap.push(5);
+ /// heap.push(2);
+ /// assert_eq!(heap.peek(), Some(&5));
+ ///
+ /// ```
+ ///
+ /// # Time complexity
+ ///
+ /// Cost is *O*(1) in the worst case.
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn peek(&self) -> Option<&T> {
+ self.data.get(0)
+ }
+
+ /// Returns the number of elements the binary heap can hold without reallocating.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// let mut heap = BinaryHeap::with_capacity(100);
+ /// assert!(heap.capacity() >= 100);
+ /// heap.push(4);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn capacity(&self) -> usize {
+ self.data.capacity()
+ }
+
+ /// Reserves the minimum capacity for at least `additional` elements more than
+ /// the current length. Unlike [`reserve`], this will not
+ /// deliberately over-allocate to speculatively avoid frequent allocations.
+ /// After calling `reserve_exact`, capacity will be greater than or equal to
+ /// `self.len() + additional`. Does nothing if the capacity is already
+ /// sufficient.
+ ///
+ /// [`reserve`]: BinaryHeap::reserve
+ ///
+ /// # Panics
+ ///
+ /// Panics if the new capacity overflows [`usize`].
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// let mut heap = BinaryHeap::new();
+ /// heap.reserve_exact(100);
+ /// assert!(heap.capacity() >= 100);
+ /// heap.push(4);
+ /// ```
+ ///
+ /// [`reserve`]: BinaryHeap::reserve
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn reserve_exact(&mut self, additional: usize) {
+ self.data.reserve_exact(additional);
+ }
+
+ /// Reserves capacity for at least `additional` elements more than the
+ /// current length. The allocator may reserve more space to speculatively
+ /// avoid frequent allocations. After calling `reserve`,
+ /// capacity will be greater than or equal to `self.len() + additional`.
+ /// Does nothing if capacity is already sufficient.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the new capacity overflows [`usize`].
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// let mut heap = BinaryHeap::new();
+ /// heap.reserve(100);
+ /// assert!(heap.capacity() >= 100);
+ /// heap.push(4);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn reserve(&mut self, additional: usize) {
+ self.data.reserve(additional);
+ }
+
+ /// Tries to reserve the minimum capacity for at least `additional` elements
+ /// more than the current length. Unlike [`try_reserve`], this will not
+ /// deliberately over-allocate to speculatively avoid frequent allocations.
+ /// After calling `try_reserve_exact`, capacity will be greater than or
+ /// equal to `self.len() + additional` if it returns `Ok(())`.
+ /// Does nothing if the capacity is already sufficient.
+ ///
+ /// Note that the allocator may give the collection more space than it
+ /// requests. Therefore, capacity can not be relied upon to be precisely
+ /// minimal. Prefer [`try_reserve`] if future insertions are expected.
+ ///
+ /// [`try_reserve`]: BinaryHeap::try_reserve
+ ///
+ /// # Errors
+ ///
+ /// If the capacity overflows, or the allocator reports a failure, then an error
+ /// is returned.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// use std::collections::TryReserveError;
+ ///
+ /// fn find_max_slow(data: &[u32]) -> Result<Option<u32>, TryReserveError> {
+ /// let mut heap = BinaryHeap::new();
+ ///
+ /// // Pre-reserve the memory, exiting if we can't
+ /// heap.try_reserve_exact(data.len())?;
+ ///
+ /// // Now we know this can't OOM in the middle of our complex work
+ /// heap.extend(data.iter());
+ ///
+ /// Ok(heap.pop())
+ /// }
+ /// # find_max_slow(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
+ /// ```
+ #[stable(feature = "try_reserve_2", since = "1.63.0")]
+ pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ self.data.try_reserve_exact(additional)
+ }
+
+ /// Tries to reserve capacity for at least `additional` elements more than the
+ /// current length. The allocator may reserve more space to speculatively
+ /// avoid frequent allocations. After calling `try_reserve`, capacity will be
+ /// greater than or equal to `self.len() + additional` if it returns
+ /// `Ok(())`. Does nothing if capacity is already sufficient. This method
+ /// preserves the contents even if an error occurs.
+ ///
+ /// # Errors
+ ///
+ /// If the capacity overflows, or the allocator reports a failure, then an error
+ /// is returned.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// use std::collections::TryReserveError;
+ ///
+ /// fn find_max_slow(data: &[u32]) -> Result<Option<u32>, TryReserveError> {
+ /// let mut heap = BinaryHeap::new();
+ ///
+ /// // Pre-reserve the memory, exiting if we can't
+ /// heap.try_reserve(data.len())?;
+ ///
+ /// // Now we know this can't OOM in the middle of our complex work
+ /// heap.extend(data.iter());
+ ///
+ /// Ok(heap.pop())
+ /// }
+ /// # find_max_slow(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?");
+ /// ```
+ #[stable(feature = "try_reserve_2", since = "1.63.0")]
+ pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ self.data.try_reserve(additional)
+ }
+
+ /// Discards as much additional capacity as possible.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// let mut heap: BinaryHeap<i32> = BinaryHeap::with_capacity(100);
+ ///
+ /// assert!(heap.capacity() >= 100);
+ /// heap.shrink_to_fit();
+ /// assert!(heap.capacity() == 0);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn shrink_to_fit(&mut self) {
+ self.data.shrink_to_fit();
+ }
+
+ /// Discards capacity with a lower bound.
+ ///
+ /// The capacity will remain at least as large as both the length
+ /// and the supplied value.
+ ///
+ /// If the current capacity is less than the lower limit, this is a no-op.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// let mut heap: BinaryHeap<i32> = BinaryHeap::with_capacity(100);
+ ///
+ /// assert!(heap.capacity() >= 100);
+ /// heap.shrink_to(10);
+ /// assert!(heap.capacity() >= 10);
+ /// ```
+ #[inline]
+ #[stable(feature = "shrink_to", since = "1.56.0")]
+ pub fn shrink_to(&mut self, min_capacity: usize) {
+ self.data.shrink_to(min_capacity)
+ }
+
+ /// Returns a slice of all values in the underlying vector, in arbitrary
+ /// order.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(binary_heap_as_slice)]
+ /// use std::collections::BinaryHeap;
+ /// use std::io::{self, Write};
+ ///
+ /// let heap = BinaryHeap::from([1, 2, 3, 4, 5, 6, 7]);
+ ///
+ /// io::sink().write(heap.as_slice()).unwrap();
+ /// ```
+ #[must_use]
+ #[unstable(feature = "binary_heap_as_slice", issue = "83659")]
+ pub fn as_slice(&self) -> &[T] {
+ self.data.as_slice()
+ }
+
+ /// Consumes the `BinaryHeap` and returns the underlying vector
+ /// in arbitrary order.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// let heap = BinaryHeap::from([1, 2, 3, 4, 5, 6, 7]);
+ /// let vec = heap.into_vec();
+ ///
+ /// // Will print in some order
+ /// for x in vec {
+ /// println!("{x}");
+ /// }
+ /// ```
+ #[must_use = "`self` will be dropped if the result is not used"]
+ #[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
+ pub fn into_vec(self) -> Vec<T> {
+ self.into()
+ }
+
+ /// Returns the length of the binary heap.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// let heap = BinaryHeap::from([1, 3]);
+ ///
+ /// assert_eq!(heap.len(), 2);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn len(&self) -> usize {
+ self.data.len()
+ }
+
+ /// Checks if the binary heap is empty.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// let mut heap = BinaryHeap::new();
+ ///
+ /// assert!(heap.is_empty());
+ ///
+ /// heap.push(3);
+ /// heap.push(5);
+ /// heap.push(1);
+ ///
+ /// assert!(!heap.is_empty());
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn is_empty(&self) -> bool {
+ self.len() == 0
+ }
+
+ /// Clears the binary heap, returning an iterator over the removed elements
+ /// in arbitrary order. If the iterator is dropped before being fully
+ /// consumed, it drops the remaining elements in arbitrary order.
+ ///
+ /// The returned iterator keeps a mutable borrow on the heap to optimize
+ /// its implementation.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// let mut heap = BinaryHeap::from([1, 3]);
+ ///
+ /// assert!(!heap.is_empty());
+ ///
+ /// for x in heap.drain() {
+ /// println!("{x}");
+ /// }
+ ///
+ /// assert!(heap.is_empty());
+ /// ```
+ #[inline]
+ #[stable(feature = "drain", since = "1.6.0")]
+ pub fn drain(&mut self) -> Drain<'_, T> {
+ Drain { iter: self.data.drain(..) }
+ }
+
+ /// Drops all items from the binary heap.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// let mut heap = BinaryHeap::from([1, 3]);
+ ///
+ /// assert!(!heap.is_empty());
+ ///
+ /// heap.clear();
+ ///
+ /// assert!(heap.is_empty());
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn clear(&mut self) {
+ self.drain();
+ }
+}
+
+/// Hole represents a hole in a slice i.e., an index without valid value
+/// (because it was moved from or duplicated).
+/// In drop, `Hole` will restore the slice by filling the hole
+/// position with the value that was originally removed.
+struct Hole<'a, T: 'a> {
+ data: &'a mut [T],
+ elt: ManuallyDrop<T>,
+ pos: usize,
+}
+
+impl<'a, T> Hole<'a, T> {
+ /// Create a new `Hole` at index `pos`.
+ ///
+ /// Unsafe because pos must be within the data slice.
+ #[inline]
+ unsafe fn new(data: &'a mut [T], pos: usize) -> Self {
+ debug_assert!(pos < data.len());
+ // SAFE: pos should be inside the slice
+ let elt = unsafe { ptr::read(data.get_unchecked(pos)) };
+ Hole { data, elt: ManuallyDrop::new(elt), pos }
+ }
+
+ #[inline]
+ fn pos(&self) -> usize {
+ self.pos
+ }
+
+ /// Returns a reference to the element removed.
+ #[inline]
+ fn element(&self) -> &T {
+ &self.elt
+ }
+
+ /// Returns a reference to the element at `index`.
+ ///
+ /// Unsafe because index must be within the data slice and not equal to pos.
+ #[inline]
+ unsafe fn get(&self, index: usize) -> &T {
+ debug_assert!(index != self.pos);
+ debug_assert!(index < self.data.len());
+ unsafe { self.data.get_unchecked(index) }
+ }
+
+ /// Move hole to new location
+ ///
+ /// Unsafe because index must be within the data slice and not equal to pos.
+ #[inline]
+ unsafe fn move_to(&mut self, index: usize) {
+ debug_assert!(index != self.pos);
+ debug_assert!(index < self.data.len());
+ unsafe {
+ let ptr = self.data.as_mut_ptr();
+ let index_ptr: *const _ = ptr.add(index);
+ let hole_ptr = ptr.add(self.pos);
+ ptr::copy_nonoverlapping(index_ptr, hole_ptr, 1);
+ }
+ self.pos = index;
+ }
+}
+
+impl<T> Drop for Hole<'_, T> {
+ #[inline]
+ fn drop(&mut self) {
+ // fill the hole again
+ unsafe {
+ let pos = self.pos;
+ ptr::copy_nonoverlapping(&*self.elt, self.data.get_unchecked_mut(pos), 1);
+ }
+ }
+}
+
+/// An iterator over the elements of a `BinaryHeap`.
+///
+/// This `struct` is created by [`BinaryHeap::iter()`]. See its
+/// documentation for more.
+///
+/// [`iter`]: BinaryHeap::iter
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Iter<'a, T: 'a> {
+ iter: slice::Iter<'a, T>,
+}
+
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_tuple("Iter").field(&self.iter.as_slice()).finish()
+ }
+}
+
+// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> Clone for Iter<'_, T> {
+ fn clone(&self) -> Self {
+ Iter { iter: self.iter.clone() }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> Iterator for Iter<'a, T> {
+ type Item = &'a T;
+
+ #[inline]
+ fn next(&mut self) -> Option<&'a T> {
+ self.iter.next()
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+
+ #[inline]
+ fn last(self) -> Option<&'a T> {
+ self.iter.last()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
+ #[inline]
+ fn next_back(&mut self) -> Option<&'a T> {
+ self.iter.next_back()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> ExactSizeIterator for Iter<'_, T> {
+ fn is_empty(&self) -> bool {
+ self.iter.is_empty()
+ }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<T> FusedIterator for Iter<'_, T> {}
+
+/// An owning iterator over the elements of a `BinaryHeap`.
+///
+/// This `struct` is created by [`BinaryHeap::into_iter()`]
+/// (provided by the [`IntoIterator`] trait). See its documentation for more.
+///
+/// [`into_iter`]: BinaryHeap::into_iter
+/// [`IntoIterator`]: core::iter::IntoIterator
+#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Clone)]
+pub struct IntoIter<T> {
+ iter: vec::IntoIter<T>,
+}
+
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_tuple("IntoIter").field(&self.iter.as_slice()).finish()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> Iterator for IntoIter<T> {
+ type Item = T;
+
+ #[inline]
+ fn next(&mut self) -> Option<T> {
+ self.iter.next()
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> DoubleEndedIterator for IntoIter<T> {
+ #[inline]
+ fn next_back(&mut self) -> Option<T> {
+ self.iter.next_back()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> ExactSizeIterator for IntoIter<T> {
+ fn is_empty(&self) -> bool {
+ self.iter.is_empty()
+ }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<T> FusedIterator for IntoIter<T> {}
+
+// In addition to the SAFETY invariants of the following three unsafe traits
+// also refer to the vec::in_place_collect module documentation to get an overview
+#[unstable(issue = "none", feature = "inplace_iteration")]
+#[doc(hidden)]
+unsafe impl<T> SourceIter for IntoIter<T> {
+ type Source = IntoIter<T>;
+
+ #[inline]
+ unsafe fn as_inner(&mut self) -> &mut Self::Source {
+ self
+ }
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+#[doc(hidden)]
+unsafe impl<I> InPlaceIterable for IntoIter<I> {}
+
+unsafe impl<I> AsVecIntoIter for IntoIter<I> {
+ type Item = I;
+
+ fn as_into_iter(&mut self) -> &mut vec::IntoIter<Self::Item> {
+ &mut self.iter
+ }
+}
+
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
+#[derive(Clone, Debug)]
+pub struct IntoIterSorted<T> {
+ inner: BinaryHeap<T>,
+}
+
+#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
+impl<T: Ord> Iterator for IntoIterSorted<T> {
+ type Item = T;
+
+ #[inline]
+ fn next(&mut self) -> Option<T> {
+ self.inner.pop()
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let exact = self.inner.len();
+ (exact, Some(exact))
+ }
+}
+
+#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
+impl<T: Ord> ExactSizeIterator for IntoIterSorted<T> {}
+
+#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
+impl<T: Ord> FusedIterator for IntoIterSorted<T> {}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<T: Ord> TrustedLen for IntoIterSorted<T> {}
+
+/// A draining iterator over the elements of a `BinaryHeap`.
+///
+/// This `struct` is created by [`BinaryHeap::drain()`]. See its
+/// documentation for more.
+///
+/// [`drain`]: BinaryHeap::drain
+#[stable(feature = "drain", since = "1.6.0")]
+#[derive(Debug)]
+pub struct Drain<'a, T: 'a> {
+ iter: vec::Drain<'a, T>,
+}
+
+#[stable(feature = "drain", since = "1.6.0")]
+impl<T> Iterator for Drain<'_, T> {
+ type Item = T;
+
+ #[inline]
+ fn next(&mut self) -> Option<T> {
+ self.iter.next()
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+#[stable(feature = "drain", since = "1.6.0")]
+impl<T> DoubleEndedIterator for Drain<'_, T> {
+ #[inline]
+ fn next_back(&mut self) -> Option<T> {
+ self.iter.next_back()
+ }
+}
+
+#[stable(feature = "drain", since = "1.6.0")]
+impl<T> ExactSizeIterator for Drain<'_, T> {
+ fn is_empty(&self) -> bool {
+ self.iter.is_empty()
+ }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<T> FusedIterator for Drain<'_, T> {}
+
+/// A draining iterator over the elements of a `BinaryHeap`.
+///
+/// This `struct` is created by [`BinaryHeap::drain_sorted()`]. See its
+/// documentation for more.
+///
+/// [`drain_sorted`]: BinaryHeap::drain_sorted
+#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
+#[derive(Debug)]
+pub struct DrainSorted<'a, T: Ord> {
+ inner: &'a mut BinaryHeap<T>,
+}
+
+#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
+impl<'a, T: Ord> Drop for DrainSorted<'a, T> {
+ /// Removes heap elements in heap order.
+ fn drop(&mut self) {
+ struct DropGuard<'r, 'a, T: Ord>(&'r mut DrainSorted<'a, T>);
+
+ impl<'r, 'a, T: Ord> Drop for DropGuard<'r, 'a, T> {
+ fn drop(&mut self) {
+ while self.0.inner.pop().is_some() {}
+ }
+ }
+
+ while let Some(item) = self.inner.pop() {
+ let guard = DropGuard(self);
+ drop(item);
+ mem::forget(guard);
+ }
+ }
+}
+
+#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
+impl<T: Ord> Iterator for DrainSorted<'_, T> {
+ type Item = T;
+
+ #[inline]
+ fn next(&mut self) -> Option<T> {
+ self.inner.pop()
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let exact = self.inner.len();
+ (exact, Some(exact))
+ }
+}
+
+#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
+impl<T: Ord> ExactSizeIterator for DrainSorted<'_, T> {}
+
+#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
+impl<T: Ord> FusedIterator for DrainSorted<'_, T> {}
+
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<T: Ord> TrustedLen for DrainSorted<'_, T> {}
+
+#[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
+impl<T: Ord> From<Vec<T>> for BinaryHeap<T> {
+ /// Converts a `Vec<T>` into a `BinaryHeap<T>`.
+ ///
+ /// This conversion happens in-place, and has *O*(*n*) time complexity.
+ fn from(vec: Vec<T>) -> BinaryHeap<T> {
+ let mut heap = BinaryHeap { data: vec };
+ heap.rebuild();
+ heap
+ }
+}
+
+#[stable(feature = "std_collections_from_array", since = "1.56.0")]
+impl<T: Ord, const N: usize> From<[T; N]> for BinaryHeap<T> {
+ /// ```
+ /// use std::collections::BinaryHeap;
+ ///
+ /// let mut h1 = BinaryHeap::from([1, 4, 2, 3]);
+ /// let mut h2: BinaryHeap<_> = [1, 4, 2, 3].into();
+ /// while let Some((a, b)) = h1.pop().zip(h2.pop()) {
+ /// assert_eq!(a, b);
+ /// }
+ /// ```
+ fn from(arr: [T; N]) -> Self {
+ Self::from_iter(arr)
+ }
+}
+
+#[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
+impl<T> From<BinaryHeap<T>> for Vec<T> {
+ /// Converts a `BinaryHeap<T>` into a `Vec<T>`.
+ ///
+ /// This conversion requires no data movement or allocation, and has
+ /// constant time complexity.
+ fn from(heap: BinaryHeap<T>) -> Vec<T> {
+ heap.data
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: Ord> FromIterator<T> for BinaryHeap<T> {
+ fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> BinaryHeap<T> {
+ BinaryHeap::from(iter.into_iter().collect::<Vec<_>>())
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> IntoIterator for BinaryHeap<T> {
+ type Item = T;
+ type IntoIter = IntoIter<T>;
+
+ /// Creates a consuming iterator, that is, one that moves each value out of
+ /// the binary heap in arbitrary order. The binary heap cannot be used
+ /// after calling this.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// use std::collections::BinaryHeap;
+ /// let heap = BinaryHeap::from([1, 2, 3, 4]);
+ ///
+ /// // Print 1, 2, 3, 4 in arbitrary order
+ /// for x in heap.into_iter() {
+ /// // x has type i32, not &i32
+ /// println!("{x}");
+ /// }
+ /// ```
+ fn into_iter(self) -> IntoIter<T> {
+ IntoIter { iter: self.data.into_iter() }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> IntoIterator for &'a BinaryHeap<T> {
+ type Item = &'a T;
+ type IntoIter = Iter<'a, T>;
+
+ fn into_iter(self) -> Iter<'a, T> {
+ self.iter()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: Ord> Extend<T> for BinaryHeap<T> {
+ #[inline]
+ fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
+ <Self as SpecExtend<I>>::spec_extend(self, iter);
+ }
+
+ #[inline]
+ fn extend_one(&mut self, item: T) {
+ self.push(item);
+ }
+
+ #[inline]
+ fn extend_reserve(&mut self, additional: usize) {
+ self.reserve(additional);
+ }
+}
+
+impl<T: Ord, I: IntoIterator<Item = T>> SpecExtend<I> for BinaryHeap<T> {
+ default fn spec_extend(&mut self, iter: I) {
+ self.extend_desugared(iter.into_iter());
+ }
+}
+
+impl<T: Ord> SpecExtend<Vec<T>> for BinaryHeap<T> {
+ fn spec_extend(&mut self, ref mut other: Vec<T>) {
+ let start = self.data.len();
+ self.data.append(other);
+ self.rebuild_tail(start);
+ }
+}
+
+impl<T: Ord> SpecExtend<BinaryHeap<T>> for BinaryHeap<T> {
+ fn spec_extend(&mut self, ref mut other: BinaryHeap<T>) {
+ self.append(other);
+ }
+}
+
+impl<T: Ord> BinaryHeap<T> {
+ fn extend_desugared<I: IntoIterator<Item = T>>(&mut self, iter: I) {
+ let iterator = iter.into_iter();
+ let (lower, _) = iterator.size_hint();
+
+ self.reserve(lower);
+
+ iterator.for_each(move |elem| self.push(elem));
+ }
+}
+
+#[stable(feature = "extend_ref", since = "1.2.0")]
+impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap<T> {
+ fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
+ self.extend(iter.into_iter().cloned());
+ }
+
+ #[inline]
+ fn extend_one(&mut self, &item: &'a T) {
+ self.push(item);
+ }
+
+ #[inline]
+ fn extend_reserve(&mut self, additional: usize) {
+ self.reserve(additional);
+ }
+}
/// This method should generally not be invoked manually, but rather through
/// the [`write!`] macro itself.
///
+ /// # Errors
+ ///
+ /// This function will return an instance of [`Error`] on error. Please see
+ /// [write_str](Write::write_str) for details.
+ ///
/// # Examples
///
/// ```
///
/// # Examples
///
- /// Converts an <code>Option<[String]></code> into an <code>Option<[usize]></code>, preserving
- /// the original. The [`map`] method takes the `self` argument by value, consuming the original,
- /// so this technique uses `as_ref` to first take an `Option` to a reference
- /// to the value inside the original.
+ /// Calculates the length of an <code>Option<[String]></code> as an <code>Option<[usize]></code>
+ /// without moving the [`String`]. The [`map`] method takes the `self` argument by value,
+ /// consuming the original, so this technique uses `as_ref` to first take an `Option` to a
+ /// reference to the value inside the original.
///
/// [`map`]: Option::map
/// [String]: ../../std/string/struct.String.html "String"
+ /// [`String`]: ../../std/string/struct.String.html "String"
///
/// ```
/// let text: Option<String> = Some("Hello, world!".to_string());
///
/// # Examples
///
- /// Converts an <code>Option<[String]></code> into an <code>Option<[usize]></code>, consuming
- /// the original:
+ /// Calculates the length of an <code>Option<[String]></code> as an
+ /// <code>Option<[usize]></code>, consuming the original:
///
/// [String]: ../../std/string/struct.String.html "String"
/// ```
// SAFETY: data races are prevented by atomic intrinsics.
unsafe { atomic_xor(self.p.get(), core::ptr::invalid_mut(val), order).cast() }
}
+
+ /// Returns a mutable pointer to the underlying pointer.
+ ///
+ /// Doing non-atomic reads and writes on the resulting integer can be a data race.
+ /// This method is mostly useful for FFI, where the function signature may use
+ /// `*mut *mut T` instead of `&AtomicPtr<T>`.
+ ///
+ /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
+ /// atomic types work with interior mutability. All modifications of an atomic change the value
+ /// through a shared reference, and can do so safely as long as they use atomic operations. Any
+ /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same
+ /// restriction: operations on it must be atomic.
+ ///
+ /// # Examples
+ ///
+ /// ```ignore (extern-declaration)
+ /// #![feature(atomic_mut_ptr)]
+ //// use std::sync::atomic::AtomicPtr;
+ ///
+ /// extern "C" {
+ /// fn my_atomic_op(arg: *mut *mut u32);
+ /// }
+ ///
+ /// let mut value = 17;
+ /// let atomic = AtomicPtr::new(&mut value);
+ ///
+ /// // SAFETY: Safe as long as `my_atomic_op` is atomic.
+ /// unsafe {
+ /// my_atomic_op(atomic.as_mut_ptr());
+ /// }
+ /// ```
+ #[inline]
+ #[unstable(feature = "atomic_mut_ptr", reason = "recently added", issue = "66893")]
+ pub fn as_mut_ptr(&self) -> *mut *mut T {
+ self.p.get()
+ }
}
#[cfg(target_has_atomic_load_store = "8")]
#[doc = concat!(" fn my_atomic_op(arg: *mut ", stringify!($int_type), ");")]
/// }
///
- #[doc = concat!("let mut atomic = ", stringify!($atomic_type), "::new(1);")]
+ #[doc = concat!("let atomic = ", stringify!($atomic_type), "::new(1);")]
///
- // SAFETY: Safe as long as `my_atomic_op` is atomic.
+ /// // SAFETY: Safe as long as `my_atomic_op` is atomic.
/// unsafe {
/// my_atomic_op(atomic.as_mut_ptr());
/// }
}
macro_rules! impl_cmp {
- ($lhs:ty, $rhs: ty) => {
+ (<$($life:lifetime),*> $lhs:ty, $rhs: ty) => {
#[stable(feature = "partialeq_path", since = "1.6.0")]
- impl<'a, 'b> PartialEq<$rhs> for $lhs {
+ impl<$($life),*> PartialEq<$rhs> for $lhs {
#[inline]
fn eq(&self, other: &$rhs) -> bool {
<Path as PartialEq>::eq(self, other)
}
#[stable(feature = "partialeq_path", since = "1.6.0")]
- impl<'a, 'b> PartialEq<$lhs> for $rhs {
+ impl<$($life),*> PartialEq<$lhs> for $rhs {
#[inline]
fn eq(&self, other: &$lhs) -> bool {
<Path as PartialEq>::eq(self, other)
}
#[stable(feature = "cmp_path", since = "1.8.0")]
- impl<'a, 'b> PartialOrd<$rhs> for $lhs {
+ impl<$($life),*> PartialOrd<$rhs> for $lhs {
#[inline]
fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
<Path as PartialOrd>::partial_cmp(self, other)
}
#[stable(feature = "cmp_path", since = "1.8.0")]
- impl<'a, 'b> PartialOrd<$lhs> for $rhs {
+ impl<$($life),*> PartialOrd<$lhs> for $rhs {
#[inline]
fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
<Path as PartialOrd>::partial_cmp(self, other)
};
}
-impl_cmp!(PathBuf, Path);
-impl_cmp!(PathBuf, &'a Path);
-impl_cmp!(Cow<'a, Path>, Path);
-impl_cmp!(Cow<'a, Path>, &'b Path);
-impl_cmp!(Cow<'a, Path>, PathBuf);
+impl_cmp!(<> PathBuf, Path);
+impl_cmp!(<'a> PathBuf, &'a Path);
+impl_cmp!(<'a> Cow<'a, Path>, Path);
+impl_cmp!(<'a, 'b> Cow<'a, Path>, &'b Path);
+impl_cmp!(<'a> Cow<'a, Path>, PathBuf);
macro_rules! impl_cmp_os_str {
- ($lhs:ty, $rhs: ty) => {
+ (<$($life:lifetime),*> $lhs:ty, $rhs: ty) => {
#[stable(feature = "cmp_path", since = "1.8.0")]
- impl<'a, 'b> PartialEq<$rhs> for $lhs {
+ impl<$($life),*> PartialEq<$rhs> for $lhs {
#[inline]
fn eq(&self, other: &$rhs) -> bool {
<Path as PartialEq>::eq(self, other.as_ref())
}
#[stable(feature = "cmp_path", since = "1.8.0")]
- impl<'a, 'b> PartialEq<$lhs> for $rhs {
+ impl<$($life),*> PartialEq<$lhs> for $rhs {
#[inline]
fn eq(&self, other: &$lhs) -> bool {
<Path as PartialEq>::eq(self.as_ref(), other)
}
#[stable(feature = "cmp_path", since = "1.8.0")]
- impl<'a, 'b> PartialOrd<$rhs> for $lhs {
+ impl<$($life),*> PartialOrd<$rhs> for $lhs {
#[inline]
fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
<Path as PartialOrd>::partial_cmp(self, other.as_ref())
}
#[stable(feature = "cmp_path", since = "1.8.0")]
- impl<'a, 'b> PartialOrd<$lhs> for $rhs {
+ impl<$($life),*> PartialOrd<$lhs> for $rhs {
#[inline]
fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
<Path as PartialOrd>::partial_cmp(self.as_ref(), other)
};
}
-impl_cmp_os_str!(PathBuf, OsStr);
-impl_cmp_os_str!(PathBuf, &'a OsStr);
-impl_cmp_os_str!(PathBuf, Cow<'a, OsStr>);
-impl_cmp_os_str!(PathBuf, OsString);
-impl_cmp_os_str!(Path, OsStr);
-impl_cmp_os_str!(Path, &'a OsStr);
-impl_cmp_os_str!(Path, Cow<'a, OsStr>);
-impl_cmp_os_str!(Path, OsString);
-impl_cmp_os_str!(&'a Path, OsStr);
-impl_cmp_os_str!(&'a Path, Cow<'b, OsStr>);
-impl_cmp_os_str!(&'a Path, OsString);
-impl_cmp_os_str!(Cow<'a, Path>, OsStr);
-impl_cmp_os_str!(Cow<'a, Path>, &'b OsStr);
-impl_cmp_os_str!(Cow<'a, Path>, OsString);
+impl_cmp_os_str!(<> PathBuf, OsStr);
+impl_cmp_os_str!(<'a> PathBuf, &'a OsStr);
+impl_cmp_os_str!(<'a> PathBuf, Cow<'a, OsStr>);
+impl_cmp_os_str!(<> PathBuf, OsString);
+impl_cmp_os_str!(<> Path, OsStr);
+impl_cmp_os_str!(<'a> Path, &'a OsStr);
+impl_cmp_os_str!(<'a> Path, Cow<'a, OsStr>);
+impl_cmp_os_str!(<> Path, OsString);
+impl_cmp_os_str!(<'a> &'a Path, OsStr);
+impl_cmp_os_str!(<'a, 'b> &'a Path, Cow<'b, OsStr>);
+impl_cmp_os_str!(<'a> &'a Path, OsString);
+impl_cmp_os_str!(<'a> Cow<'a, Path>, OsStr);
+impl_cmp_os_str!(<'a, 'b> Cow<'a, Path>, &'b OsStr);
+impl_cmp_os_str!(<'a> Cow<'a, Path>, OsString);
#[stable(since = "1.7.0", feature = "strip_prefix")]
impl fmt::Display for StripPrefixError {
-This directory contains the source code of the rust project, including:
+This directory contains some source code for the Rust project, including:
-- The test suite
- The bootstrapping build system
-- Various submodules for tools, like cargo, etc.
+- Various submodules for tools, like cargo, tidy, etc.
For more information on how various parts of the compiler work, see the [rustc dev guide].
git clone https://github.com/WebAssembly/wasi-libc
cd wasi-libc
-git reset --hard 8b7148f69ae241a2749b3defe4606da8143b72e0
+git reset --hard 4362b1885fd369e042a7c0ecd8df3b6cd47fb4e8
make -j$(nproc) \
CC="$bin/clang" \
NM="$bin/llvm-nm" \
python3 ../x.py test --stage 0 src/tools/compiletest && \
python3 ../x.py test --stage 0 core alloc std test proc_macro && \
# Build both public and internal documentation.
+ RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 compiler && \
RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 library/test && \
/scripts/validate-toolstate.sh && \
/scripts/validate-error-codes.sh && \
## `invalid_html_tags`
-This lint is **allowed by default** and is **nightly-only**. It detects unclosed
+This lint **warns by default**. It detects unclosed
or invalid HTML tags. For example:
```rust
write!(
buf,
"<div class=\"main-heading\">\
- <h1 class=\"fqn\">Rustdoc settings</h1>\
+ <h1>Rustdoc settings</h1>\
<span class=\"out-of-band\">\
<a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\
Back\
write!(
buf,
"<div class=\"main-heading\">\
- <h1 class=\"fqn\">Rustdoc help</h1>\
+ <h1>Rustdoc help</h1>\
<span class=\"out-of-band\">\
<a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\
Back\
}
}
- f.write_str("<h1 class=\"fqn\">List of all items</h1>");
+ f.write_str("<h1>List of all items</h1>");
// Note: print_entries does not escape the title, because we know the current set of titles
// doesn't require escaping.
print_entries(f, &self.structs, ItemSection::Structs);
let mut ids = IdMap::default();
format!(
"<div class=\"main-heading\">\
- <h1 class=\"fqn\">About scraped examples</h1>\
+ <h1>About scraped examples</h1>\
</div>\
<div>{}</div>",
Markdown {
debug!("Doc block: =====\n{}\n=====", s);
if is_collapsible {
w.write_str(
- "<details class=\"rustdoc-toggle top-doc\" open>\
+ "<details class=\"toggle top-doc\" open>\
<summary class=\"hideme\">\
<span>Expand description</span>\
</summary>",
let toggled = !doc_buffer.is_empty();
if toggled {
let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
- write!(w, "<details class=\"rustdoc-toggle{}\" open><summary>", method_toggle_class);
+ write!(w, "<details class=\"toggle{}\" open><summary>", method_toggle_class);
}
match &*item.kind {
clean::MethodItem(..) | clean::TyMethodItem(_) => {
close_tags.insert_str(0, "</details>");
write!(
w,
- "<details class=\"rustdoc-toggle implementors-toggle\"{}>",
+ "<details class=\"toggle implementors-toggle\"{}>",
if rendering_params.toggle_open_by_default { " open" } else { "" }
);
write!(w, "<summary>")
if it.peek().is_some() {
write!(
w,
- "<details class=\"rustdoc-toggle more-examples-toggle\">\
+ "<details class=\"toggle more-examples-toggle\">\
<summary class=\"hideme\">\
<span>More examples</span>\
</summary>\
fn toggle_open(w: &mut Buffer, text: impl fmt::Display) {
write!(
w,
- "<details class=\"rustdoc-toggle type-contents-toggle\">\
+ "<details class=\"toggle type-contents-toggle\">\
<summary class=\"hideme\">\
<span>Show {}</span>\
</summary>",
let toggled = !content.is_empty();
if toggled {
let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
- write!(w, "<details class=\"rustdoc-toggle{method_toggle_class}\" open><summary>");
+ write!(w, "<details class=\"toggle{method_toggle_class}\" open><summary>");
}
write!(w, "<section id=\"{}\" class=\"method has-srclink\">", id);
render_rightside(w, cx, m, t, RenderMode::Normal);
if item.is_non_exhaustive() {
write!(
w,
- "<details class=\"rustdoc-toggle non-exhaustive\">\
+ "<details class=\"toggle non-exhaustive\">\
<summary class=\"hideme\"><span>{}</span></summary>\
<div class=\"docblock\">",
{
};
let content = format!(
- "<h1 class=\"fqn\">List of all crates</h1><ul class=\"all-items\">{}</ul>",
+ "<h1>List of all crates</h1><ul class=\"all-items\">{}</ul>",
krates
.iter()
.map(|s| {
.docblock > h6:first-child {
margin-top: 0;
}
-h1.fqn {
+.main-heading h1 {
margin: 0;
padding: 0;
flex-grow: 1;
margin-right: auto;
}
-details:not(.rustdoc-toggle) summary {
+details:not(.toggle) summary {
margin-bottom: .6em;
}
Unfortunately we can't yet specify contain: content or contain: strict
because the [-]/[+] toggles extend past the boundaries of the <details>
https://developer.mozilla.org/en-US/docs/Web/CSS/contain */
-details.rustdoc-toggle {
+details.toggle {
contain: layout;
position: relative;
}
/* The hideme class is used on summary tags that contain a span with
placeholder text shown only when the toggle is closed. For instance,
"Expand description" or "Show methods". */
-details.rustdoc-toggle > summary.hideme {
+details.toggle > summary.hideme {
cursor: pointer;
font-size: 1rem;
}
-details.rustdoc-toggle > summary {
+details.toggle > summary {
list-style: none;
/* focus outline is shown on `::before` instead of this */
outline: none;
}
-details.rustdoc-toggle > summary::-webkit-details-marker,
-details.rustdoc-toggle > summary::marker {
+details.toggle > summary::-webkit-details-marker,
+details.toggle > summary::marker {
display: none;
}
-details.rustdoc-toggle > summary.hideme > span {
+details.toggle > summary.hideme > span {
margin-left: 9px;
}
-details.rustdoc-toggle > summary::before {
+details.toggle > summary::before {
background: url("toggle-plus-1092eb4930d581b0.svg") no-repeat top left;
content: "";
cursor: pointer;
filter: var(--toggle-filter);
}
-details.rustdoc-toggle > summary.hideme > span,
+details.toggle > summary.hideme > span,
.more-examples-toggle summary, .more-examples-toggle .hide-more {
color: var(--toggles-color);
}
/* Screen readers see the text version at the end the line.
Visual readers see the icon at the start of the line, but small and transparent. */
-details.rustdoc-toggle > summary::after {
+details.toggle > summary::after {
content: "Expand";
overflow: hidden;
width: 0;
position: absolute;
}
-details.rustdoc-toggle > summary.hideme::after {
+details.toggle > summary.hideme::after {
/* "hideme" toggles already have a description when they're contracted */
content: "";
}
-details.rustdoc-toggle > summary:focus::before,
-details.rustdoc-toggle > summary:hover::before {
+details.toggle > summary:focus::before,
+details.toggle > summary:hover::before {
opacity: 1;
}
-details.rustdoc-toggle > summary:focus-visible::before {
+details.toggle > summary:focus-visible::before {
/* The SVG is black, and gets turned white using a filter in the dark themes.
Do the same with the outline.
The dotted 1px style is copied from Firefox's focus ring style.
margin-bottom: 8px;
}
-details.rustdoc-toggle > summary.hideme::before {
+details.toggle > summary.hideme::before {
position: relative;
}
-details.rustdoc-toggle > summary:not(.hideme)::before {
+details.toggle > summary:not(.hideme)::before {
position: absolute;
left: -24px;
top: 4px;
}
-.impl-items > details.rustdoc-toggle > summary:not(.hideme)::before {
+.impl-items > details.toggle > summary:not(.hideme)::before {
position: absolute;
left: -24px;
}
affect the layout of the items to its right. To do that, we use
absolute positioning. Note that we also set position: relative
on the parent <details> to make this work properly. */
-details.rustdoc-toggle[open] > summary.hideme {
+details.toggle[open] > summary.hideme {
position: absolute;
}
-details.rustdoc-toggle[open] > summary.hideme > span {
+details.toggle[open] > summary.hideme > span {
display: none;
}
-details.rustdoc-toggle[open] > summary::before {
+details.toggle[open] > summary::before {
background: url("toggle-minus-31bbd6e4c77f5c96.svg") no-repeat top left;
}
-details.rustdoc-toggle[open] > summary::after {
+details.toggle[open] > summary::after {
content: "Collapse";
}
display: block;
}
- #main-content > details.rustdoc-toggle > summary::before,
- #main-content > div > details.rustdoc-toggle > summary::before {
+ #main-content > details.toggle > summary::before,
+ #main-content > div > details.toggle > summary::before {
left: -11px;
}
}
/* Position of the "[-]" element. */
- details.rustdoc-toggle:not(.top-doc) > summary {
+ details.toggle:not(.top-doc) > summary {
margin-left: 10px;
}
- .impl-items > details.rustdoc-toggle > summary:not(.hideme)::before,
- #main-content > details.rustdoc-toggle:not(.top-doc) > summary::before,
- #main-content > div > details.rustdoc-toggle > summary::before {
+ .impl-items > details.toggle > summary:not(.hideme)::before,
+ #main-content > details.toggle:not(.top-doc) > summary::before,
+ #main-content > div > details.toggle > summary::before {
left: -11px;
}
@media print {
nav.sidebar, nav.sub, .out-of-band, a.srclink, #copy-path,
- details.rustdoc-toggle[open] > summary::before, details.rustdoc-toggle > summary::before,
- details.rustdoc-toggle.top-doc > summary {
+ details.toggle[open] > summary::before, details.toggle > summary::before,
+ details.toggle.top-doc > summary {
display: none;
}
.impl,
#implementors-list > .docblock,
.impl-items > section,
-.impl-items > .rustdoc-toggle > summary,
+.impl-items > .toggle > summary,
.methods > section,
-.methods > .rustdoc-toggle > summary
+.methods > .toggle > summary
{
margin-bottom: 0.75em;
}
.variants > .docblock,
.implementors-toggle > .docblock,
-.impl-items > .rustdoc-toggle[open]:not(:last-child),
-.methods > .rustdoc-toggle[open]:not(:last-child),
+.impl-items > .toggle[open]:not(:last-child),
+.methods > .toggle[open]:not(:last-child),
.implementors-toggle[open]:not(:last-child) {
margin-bottom: 2em;
}
-#trait-implementations-list .impl-items > .rustdoc-toggle:not(:last-child),
-#synthetic-implementations-list .impl-items > .rustdoc-toggle:not(:last-child),
-#blanket-implementations-list .impl-items > .rustdoc-toggle:not(:last-child) {
+#trait-implementations-list .impl-items > .toggle:not(:last-child),
+#synthetic-implementations-list .impl-items > .toggle:not(:last-child),
+#blanket-implementations-list .impl-items > .toggle:not(:last-child) {
margin-bottom: 1em;
}
}
.setting-line .radio-line input,
-.setting-line .toggle input {
+.setting-line .settings-toggle input {
margin-right: 0.3em;
height: 1.2rem;
width: 1.2rem;
.setting-line .radio-line input {
border-radius: 50%;
}
-.setting-line .toggle input:checked {
+.setting-line .settings-toggle input:checked {
content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">\
<path d="M7,25L17,32L33,12" fill="none" stroke="black" stroke-width="5"/>\
<path d="M7,23L17,30L33,10" fill="none" stroke="white" stroke-width="5"/></svg>');
}
.setting-line .radio-line input + span,
-.setting-line .toggle span {
+.setting-line .settings-toggle span {
padding-bottom: 1px;
}
margin-left: 0.5em;
}
-.toggle {
+.settings-toggle {
position: relative;
width: 100%;
margin-right: 20px;
box-shadow: inset 0 0 0 3px var(--main-background-color);
background-color: var(--settings-input-color);
}
-.setting-line .toggle input:checked {
+.setting-line .settings-toggle input:checked {
background-color: var(--settings-input-color);
}
.setting-line .radio-line input:focus,
-.setting-line .toggle input:focus {
+.setting-line .settings-toggle input:focus {
box-shadow: 0 0 1px 1px var(--settings-input-color);
}
/* In here we combine both `:focus` and `:checked` properties. */
0 0 2px 2px var(--settings-input-color);
}
.setting-line .radio-line input:hover,
-.setting-line .toggle input:hover {
+.setting-line .settings-toggle input:hover {
border-color: var(--settings-input-color) !important;
}
}
let currentNbImpls = implementors.getElementsByClassName("impl").length;
- const traitName = document.querySelector("h1.fqn > .trait").textContent;
+ const traitName = document.querySelector(".main-heading h1 > .trait").textContent;
const baseIdName = "impl-" + traitName + "-";
const libs = Object.getOwnPropertyNames(imp);
// We don't want to include impls from this JS file, when the HTML already has them.
function expandAllDocs() {
const innerToggle = document.getElementById(toggleAllDocsId);
removeClass(innerToggle, "will-expand");
- onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => {
+ onEachLazy(document.getElementsByClassName("toggle"), e => {
if (!hasClass(e, "type-contents-toggle") && !hasClass(e, "more-examples-toggle")) {
e.open = true;
}
function collapseAllDocs() {
const innerToggle = document.getElementById(toggleAllDocsId);
addClass(innerToggle, "will-expand");
- onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => {
+ onEachLazy(document.getElementsByClassName("toggle"), e => {
if (e.parentNode.id !== "implementations-list" ||
(!hasClass(e, "implementors-toggle") &&
!hasClass(e, "type-contents-toggle"))
setImplementorsTogglesOpen("blanket-implementations-list", false);
}
- onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => {
+ onEachLazy(document.getElementsByClassName("toggle"), e => {
if (!hideLargeItemContents && hasClass(e, "type-contents-toggle")) {
e.open = true;
}
});
});
- onEachLazy(document.querySelectorAll(".rustdoc-toggle > summary:not(.hideme)"), el => {
+ onEachLazy(document.querySelectorAll(".toggle > summary:not(.hideme)"), el => {
el.addEventListener("click", e => {
if (e.target.tagName !== "SUMMARY" && e.target.tagName !== "A") {
e.preventDefault();
});
output += "</div></div>";
} else {
- // This is a toggle.
+ // This is a checkbox toggle.
const checked = setting["default"] === true ? " checked" : "";
output += `\
-<label class="toggle">\
+<label class="settings-toggle">\
<input type="checkbox" id="${js_data_name}"${checked}>\
<span class="label">${setting_name}</span>\
</label>`;
<div class="main-heading"> {#- -#}
- <h1 class="fqn"> {#- -#}
+ <h1> {#- -#}
{{-typ-}}
{#- The breadcrumbs of the item path, like std::string -#}
{%- for component in path_components -%}
}
// handled in the `strip-priv-imports` pass
- clean::ExternCrateItem { .. } => {}
- clean::ImportItem(ref imp) => {
- // Because json doesn't inline imports from private modules, we need to mark
- // the imported item as retained so it's impls won't be stripped.
- //
- // FIXME: Is it necessary to check for json output here: See
- // https://github.com/rust-lang/rust/pull/100325#discussion_r941495215
- if let Some(did) = imp.source.did && self.is_json_output {
- self.retained.insert(did.into());
- }
- }
+ clean::ExternCrateItem { .. } | clean::ImportItem(_) => {}
clean::ImplItem(..) => {}
[dependencies]
cargo_metadata = "0.14"
+cargo-platform = "0.1.2"
regex = "1"
miropt-test-tools = { path = "../miropt-test-tools" }
lazy_static = "1"
//! Checks the licenses of third-party dependencies.
-use cargo_metadata::{Metadata, Package, PackageId, Resolve};
-use std::collections::{BTreeSet, HashSet};
+use cargo_metadata::{DepKindInfo, Metadata, Package, PackageId};
+use std::collections::HashSet;
use std::path::Path;
/// These are licenses that are allowed for all crates, including the runtime,
"autocfg",
"bitflags",
"block-buffer",
- "bumpalo", // Included in Cargo's dep graph but only activated on wasm32-*-unknown.
"cc",
"cfg-if",
"chalk-derive",
"chalk-engine",
"chalk-ir",
"chalk-solve",
- "chrono",
"convert_case", // dependency of derive_more
"compiler_builtins",
"cpufeatures",
"dlmalloc",
"either",
"ena",
- "env_logger",
"expect-test",
"fallible-iterator", // dependency of `thorin`
"fastrand",
- "filetime",
"fixedbitset",
"flate2",
"fluent-bundle",
"gsgdt",
"hashbrown",
"hermit-abi",
- "humantime",
"icu_list",
"icu_locid",
"icu_provider",
"icu_provider_adapters",
"icu_provider_macros",
- "if_chain",
"indexmap",
"instant",
"intl-memoizer",
"itertools",
"itoa",
"jobserver",
- "js-sys", // Included in Cargo's dep graph but only activated on wasm32-*-unknown.
"lazy_static",
"libc",
"libloading",
"memmap2",
"memoffset",
"miniz_oxide",
- "num-integer",
- "num-traits",
"num_cpus",
"object",
"odht",
"proc-macro2",
"psm",
"punycode",
- "quick-error",
"quote",
"rand",
"rand_chacha",
"serde",
"serde_derive",
"serde_json",
- "sha-1",
+ "sha1",
"sha2",
"sharded-slab",
"smallvec",
"thiserror-impl",
"thorin-dwp",
"thread_local",
- "time",
"tinystr",
"tinyvec",
"tinyvec_macros",
"valuable",
"version_check",
"wasi",
- // vvv Included in Cargo's dep graph but only activated on wasm32-*-unknown.
- "wasm-bindgen",
- "wasm-bindgen-backend",
- "wasm-bindgen-macro",
- "wasm-bindgen-macro-support",
- "wasm-bindgen-shared",
- // ^^^ Included in Cargo's dep graph but only activated on wasm32-*-unknown.
"winapi",
"winapi-i686-pc-windows-gnu",
"winapi-util",
restricted_dependency_crates: &[&'static str],
bad: &mut bool,
) {
+ let mut deps = HashSet::new();
+ for to_check in restricted_dependency_crates {
+ let to_check = pkg_from_name(metadata, to_check);
+ use cargo_platform::Cfg;
+ use std::str::FromStr;
+ // We don't expect the compiler to ever run on wasm32, so strip
+ // out those dependencies to avoid polluting the permitted list.
+ deps_of_filtered(metadata, &to_check.id, &mut deps, &|dep_kinds| {
+ dep_kinds.iter().any(|dep_kind| {
+ dep_kind
+ .target
+ .as_ref()
+ .map(|target| {
+ !target.matches(
+ "wasm32-unknown-unknown",
+ &[
+ Cfg::from_str("target_arch=\"wasm32\"").unwrap(),
+ Cfg::from_str("target_os=\"unknown\"").unwrap(),
+ ],
+ )
+ })
+ .unwrap_or(true)
+ })
+ });
+ }
+
// Check that the PERMITTED_DEPENDENCIES does not have unused entries.
- for name in permitted_dependencies {
- if !metadata.packages.iter().any(|p| p.name == *name) {
+ for permitted in permitted_dependencies {
+ if !deps.iter().any(|dep_id| &pkg_from_id(metadata, dep_id).name == permitted) {
tidy_error!(
bad,
- "could not find allowed package `{}`\n\
+ "could not find allowed package `{permitted}`\n\
Remove from PERMITTED_DEPENDENCIES list if it is no longer used.",
- name
);
}
}
- // Get the list in a convenient form.
- let permitted_dependencies: HashSet<_> = permitted_dependencies.iter().cloned().collect();
-
- // Check dependencies.
- let mut visited = BTreeSet::new();
- let mut unapproved = BTreeSet::new();
- for &krate in restricted_dependency_crates.iter() {
- let pkg = pkg_from_name(metadata, krate);
- let mut bad =
- check_crate_dependencies(&permitted_dependencies, metadata, &mut visited, pkg);
- unapproved.append(&mut bad);
- }
-
- if !unapproved.is_empty() {
- tidy_error!(bad, "Dependencies for {} not explicitly permitted:", descr);
- for dep in unapproved {
- println!("* {dep}");
- }
- }
-}
-
-/// Checks the dependencies of the given crate from the given cargo metadata to see if they are on
-/// the list of permitted dependencies. Returns a list of disallowed dependencies.
-fn check_crate_dependencies<'a>(
- permitted_dependencies: &'a HashSet<&'static str>,
- metadata: &'a Metadata,
- visited: &mut BTreeSet<&'a PackageId>,
- krate: &'a Package,
-) -> BTreeSet<&'a PackageId> {
- // This will contain bad deps.
- let mut unapproved = BTreeSet::new();
-
- // Check if we have already visited this crate.
- if visited.contains(&krate.id) {
- return unapproved;
- }
- visited.insert(&krate.id);
+ // Get in a convenient form.
+ let permitted_dependencies: HashSet<_> = permitted_dependencies.iter().cloned().collect();
- // If this path is in-tree, we don't require it to be explicitly permitted.
- if krate.source.is_some() {
- // If this dependency is not on `PERMITTED_DEPENDENCIES`, add to bad set.
- if !permitted_dependencies.contains(krate.name.as_str()) {
- unapproved.insert(&krate.id);
+ for dep in deps {
+ let dep = pkg_from_id(metadata, dep);
+ // If this path is in-tree, we don't require it to be explicitly permitted.
+ if dep.source.is_some() {
+ if !permitted_dependencies.contains(dep.name.as_str()) {
+ tidy_error!(bad, "Dependency for {descr} not explicitly permitted: {}", dep.id);
+ }
}
}
-
- // Do a DFS in the crate graph.
- let to_check = deps_of(metadata, &krate.id);
-
- for dep in to_check {
- let mut bad = check_crate_dependencies(permitted_dependencies, metadata, visited, dep);
- unapproved.append(&mut bad);
- }
-
- unapproved
}
/// Prevents multiple versions of some expensive crates.
}
}
-/// Returns a list of dependencies for the given package.
-fn deps_of<'a>(metadata: &'a Metadata, pkg_id: &'a PackageId) -> Vec<&'a Package> {
- let resolve = metadata.resolve.as_ref().unwrap();
- let node = resolve
- .nodes
- .iter()
- .find(|n| &n.id == pkg_id)
- .unwrap_or_else(|| panic!("could not find `{pkg_id}` in resolve"));
- node.deps
- .iter()
- .map(|dep| {
- metadata.packages.iter().find(|pkg| pkg.id == dep.pkg).unwrap_or_else(|| {
- panic!("could not find dep `{}` for pkg `{}` in resolve", dep.pkg, pkg_id)
- })
- })
- .collect()
-}
-
/// Finds a package with the given name.
fn pkg_from_name<'a>(metadata: &'a Metadata, name: &'static str) -> &'a Package {
let mut i = metadata.packages.iter().filter(|p| p.name == name);
result
}
+fn pkg_from_id<'a>(metadata: &'a Metadata, id: &PackageId) -> &'a Package {
+ metadata.packages.iter().find(|p| &p.id == id).unwrap()
+}
+
/// Finds all the packages that are in the rust runtime.
fn compute_runtime_crates<'a>(metadata: &'a Metadata) -> HashSet<&'a PackageId> {
- let resolve = metadata.resolve.as_ref().unwrap();
let mut result = HashSet::new();
for name in RUNTIME_CRATES {
let id = &pkg_from_name(metadata, name).id;
- normal_deps_of_r(resolve, id, &mut result);
+ deps_of_filtered(metadata, id, &mut result, &|_| true);
}
result
}
-/// Recursively find all normal dependencies.
-fn normal_deps_of_r<'a>(
- resolve: &'a Resolve,
+/// Recursively find all dependencies.
+fn deps_of_filtered<'a>(
+ metadata: &'a Metadata,
pkg_id: &'a PackageId,
result: &mut HashSet<&'a PackageId>,
+ filter: &dyn Fn(&[DepKindInfo]) -> bool,
) {
if !result.insert(pkg_id) {
return;
}
- let node = resolve
+ let node = metadata
+ .resolve
+ .as_ref()
+ .unwrap()
.nodes
.iter()
.find(|n| &n.id == pkg_id)
.unwrap_or_else(|| panic!("could not find `{pkg_id}` in resolve"));
for dep in &node.deps {
- normal_deps_of_r(resolve, &dep.pkg, result);
+ if !filter(&dep.dep_kinds) {
+ continue;
+ }
+ deps_of_filtered(metadata, &dep.pkg, result, filter);
}
}
+fn direct_deps_of<'a>(metadata: &'a Metadata, pkg_id: &'a PackageId) -> Vec<&'a Package> {
+ let resolve = metadata.resolve.as_ref().unwrap();
+ let node = resolve.nodes.iter().find(|n| &n.id == pkg_id).unwrap();
+ node.deps.iter().map(|dep| pkg_from_id(metadata, &dep.pkg)).collect()
+}
+
fn check_rustfix(metadata: &Metadata, bad: &mut bool) {
let cargo = pkg_from_name(metadata, "cargo");
let compiletest = pkg_from_name(metadata, "compiletest");
- let cargo_deps = deps_of(metadata, &cargo.id);
- let compiletest_deps = deps_of(metadata, &compiletest.id);
+ let cargo_deps = direct_deps_of(metadata, &cargo.id);
+ let compiletest_deps = direct_deps_of(metadata, &compiletest.id);
let cargo_rustfix = cargo_deps.iter().find(|p| p.name == "rustfix").unwrap();
let compiletest_rustfix = compiletest_deps.iter().find(|p| p.name == "rustfix").unwrap();
if cargo_rustfix.version != compiletest_rustfix.version {
})
}
-static S: i32 = 5;
-static mut T: i32 = 10;
+static S: i32 = 0x05050505;
+static mut T: i32 = 0x0a0a0a0a;
// EMIT_MIR consts.statics.built.after.mir
#[custom_mir(dialect = "built")]
fn statics() {
}
alloc2 (static: T, size: 4, align: 4) {
- 0a 00 00 00 │ ....
+ 0a 0a 0a 0a │ ....
}
alloc1 (static: S, size: 4, align: 4) {
- 05 00 00 00 │ ....
+ 05 05 05 05 │ ....
}
}
alloc1 (static: STATIC, size: 4, align: 4) {
- 2a 00 00 00 │ *...
+ 42 42 42 42 │ BBBB
}
// unit-test
// compile-flags: -O
-static mut STATIC: u32 = 42;
+static mut STATIC: u32 = 0x42424242;
// EMIT_MIR mutable_variable_no_prop.main.ConstProp.diff
fn main() {
_3 = _1; // scope 2 at $DIR/issue_75439.rs:+2:47: +2:52
_2 = transmute::<[u8; 16], [u32; 4]>(move _3) -> bb1; // scope 2 at $DIR/issue_75439.rs:+2:37: +2:53
// mir::Constant
- // + span: $DIR/issue_75439.rs:7:37: 7:46
+ // + span: $DIR/issue_75439.rs:8:37: 8:46
// + literal: Const { ty: unsafe extern "rust-intrinsic" fn([u8; 16]) -> [u32; 4] {transmute::<[u8; 16], [u32; 4]>}, val: Value(<ZST>) }
}
_6 = _4; // scope 4 at $DIR/issue_75439.rs:+5:33: +5:35
_5 = transmute::<u32, [u8; 4]>(move _6) -> bb7; // scope 4 at $DIR/issue_75439.rs:+5:23: +5:36
// mir::Constant
- // + span: $DIR/issue_75439.rs:10:23: 10:32
+ // + span: $DIR/issue_75439.rs:11:23: 11:32
// + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) -> [u8; 4] {transmute::<u32, [u8; 4]>}, val: Value(<ZST>) }
}
// EMIT_MIR issue_75439.foo.MatchBranchSimplification.diff
+// ignore-endian-big
use std::mem::transmute;
define-function: (
"check-colors",
- (theme, main_color, title_color, fqn_color, fqn_type_color, src_link_color, sidebar_link_color),
+ (theme, main_color, title_color, main_heading_color, main_heading_type_color, src_link_color, sidebar_link_color),
block {
goto: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"
// This is needed to ensure that the text color is computed.
reload:
assert-css: ("#toggle-all-docs", {"color": |main_color|})
- assert-css: (".fqn a:nth-of-type(1)", {"color": |fqn_color|})
- assert-css: (".fqn a:nth-of-type(2)", {"color": |fqn_type_color|})
+ assert-css: (".main-heading h1 a:nth-of-type(1)", {"color": |main_heading_color|})
+ assert-css: (".main-heading a:nth-of-type(2)", {"color": |main_heading_type_color|})
assert-css: (
".rightside .srclink",
{"color": |src_link_color|, "text-decoration": "none solid " + |src_link_color|},
assert-css: ("#top-doc-prose-title", {"color": |title_color|})
assert-css: (".sidebar a", {"color": |sidebar_link_color|})
- assert-css: ("h1.fqn a", {"color": |title_color|})
+ assert-css: (".main-heading h1 a", {"color": |title_color|})
// We move the cursor over the "Implementations" title so the anchor is displayed.
move-cursor-to: "h2#implementations"
"theme": "ayu",
"main_color": "rgb(197, 197, 197)",
"title_color": "rgb(255, 255, 255)",
- "fqn_color": "rgb(255, 255, 255)",
- "fqn_type_color": "rgb(255, 160, 165)",
+ "main_heading_color": "rgb(255, 255, 255)",
+ "main_heading_type_color": "rgb(255, 160, 165)",
"src_link_color": "rgb(57, 175, 215)",
"sidebar_link_color": "rgb(83, 177, 219)",
},
"theme": "dark",
"main_color": "rgb(221, 221, 221)",
"title_color": "rgb(221, 221, 221)",
- "fqn_color": "rgb(221, 221, 221)",
- "fqn_type_color": "rgb(45, 191, 184)",
+ "main_heading_color": "rgb(221, 221, 221)",
+ "main_heading_type_color": "rgb(45, 191, 184)",
"src_link_color": "rgb(210, 153, 29)",
"sidebar_link_color": "rgb(253, 191, 53)",
},
"theme": "light",
"main_color": "rgb(0, 0, 0)",
"title_color": "rgb(0, 0, 0)",
- "fqn_color": "rgb(0, 0, 0)",
- "fqn_type_color": "rgb(173, 55, 138)",
+ "main_heading_color": "rgb(0, 0, 0)",
+ "main_heading_type_color": "rgb(173, 55, 138)",
"src_link_color": "rgb(56, 115, 173)",
"sidebar_link_color": "rgb(53, 109, 164)",
},
// 14px 0.875rem
goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"
-assert-css: ("h1.fqn", {"font-size": "24px"})
+assert-css: (".main-heading h1", {"font-size": "24px"})
assert-css: ("h2#top-doc-prose-title", {"font-size": "22px"})
assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"})
goto: "file://" + |DOC_PATH| + "/test_docs/enum.HeavilyDocumentedEnum.html"
-assert-css: ("h1.fqn", {"font-size": "24px"})
+assert-css: (".main-heading h1", {"font-size": "24px"})
assert-css: ("h2#top-doc-prose-title", {"font-size": "22px"})
assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"})
goto: "file://" + |DOC_PATH| + "/test_docs/union.HeavilyDocumentedUnion.html"
-assert-css: ("h1.fqn", {"font-size": "24px"})
+assert-css: (".main-heading h1", {"font-size": "24px"})
assert-css: ("h2#top-doc-prose-title", {"font-size": "22px"})
assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"})
goto: "file://" + |DOC_PATH| + "/test_docs/macro.heavily_documented_macro.html"
-assert-css: ("h1.fqn", {"font-size": "24px"})
+assert-css: (".main-heading h1", {"font-size": "24px"})
assert-css: ("h2#top-doc-prose-title", {"font-size": "22px"})
assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"})
// This test ensures that the margins on methods are coherent inside an impl block.
goto: "file://" + |DOC_PATH| + "/test_docs/trait_members/struct.HasTrait.html#impl-TraitMembers-for-HasTrait"
-assert-count: ("#trait-implementations-list > .rustdoc-toggle", 1)
+assert-count: ("#trait-implementations-list > .toggle", 1)
compare-elements-css: (
// compare margin on type with margin on method
- "#trait-implementations-list .impl-items > .rustdoc-toggle:nth-child(1) > summary",
- "#trait-implementations-list .impl-items > .rustdoc-toggle:nth-child(2) > summary",
+ "#trait-implementations-list .impl-items > .toggle:nth-child(1) > summary",
+ "#trait-implementations-list .impl-items > .toggle:nth-child(2) > summary",
["margin"]
)
compare-elements-css: (
// compare margin on type with margin on method
- "#trait-implementations-list .impl-items > .rustdoc-toggle:nth-child(1)",
- "#trait-implementations-list .impl-items > .rustdoc-toggle:nth-child(2)",
+ "#trait-implementations-list .impl-items > .toggle:nth-child(1)",
+ "#trait-implementations-list .impl-items > .toggle:nth-child(2)",
["margin"]
)
// First, we check that the first page doesn't have the string we're looking for to ensure
// that the feature is changing page as expected.
goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
-assert-text-false: (".fqn", "Struct test_docs::Foo")
+assert-text-false: (".main-heading h1", "Struct test_docs::Foo")
// We now check that we land on the search result page if "go_to_first" isn't set.
goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=struct%3AFoo"
// Waiting for the search results to appear...
wait-for: "#search-tabs"
-assert-text-false: (".fqn", "Struct test_docs::Foo")
+assert-text-false: (".main-heading h1", "Struct test_docs::Foo")
// Ensure that the search results are displayed, not the "normal" content.
assert-css: ("#main-content", {"display": "none"})
// Now we can check that the feature is working as expected!
goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=struct%3AFoo&go_to_first=true"
// Waiting for the page to load...
-wait-for-text: (".fqn", "Struct test_docs::Foo")
+wait-for-text: (".main-heading h1", "Struct test_docs::Foo")
// We now check that clicking on the toggles' text is like clicking on the checkbox.
// To test it, we use the "Disable keyboard shortcuts".
local-storage: {"rustdoc-disable-shortcuts": "false"}
-click: ".setting-line:last-child .toggle .label"
+click: ".setting-line:last-child .settings-toggle .label"
assert-local-storage: {"rustdoc-disable-shortcuts": "true"}
// Make sure that "Disable keyboard shortcuts" actually took effect.
wait-for-css: ("#settings-menu .popover", {"display": "block"})
// Now turn keyboard shortcuts back on, and see if they work.
-click: ".setting-line:last-child .toggle .label"
+click: ".setting-line:last-child .settings-toggle .label"
assert-local-storage: {"rustdoc-disable-shortcuts": "false"}
press-key: "Escape"
press-key: "?"
// This test ensures that clicking on a method summary, but not on the "[-]",
// doesn't toggle the <details>.
goto: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html"
-assert-attribute: (".impl-items .rustdoc-toggle", {"open": ""})
+assert-attribute: (".impl-items .toggle", {"open": ""})
click: "h4.code-header" // This is the position of "pub" in "pub fn a_method"
-assert-attribute: (".impl-items .rustdoc-toggle", {"open": ""})
+assert-attribute: (".impl-items .toggle", {"open": ""})
click-with-offset: (
- ".impl-items .rustdoc-toggle summary",
+ ".impl-items .toggle summary",
{"x": -24, "y": 8}, // This is the position of "[-]" next to that pub fn.
)
-assert-attribute-false: (".impl-items .rustdoc-toggle", {"open": ""})
+assert-attribute-false: (".impl-items .toggle", {"open": ""})
// Click the "Trait" part of "impl Trait" and verify it navigates.
click: "#impl-Trait-for-Foo h3 a:first-of-type"
-assert-text: (".fqn", "Trait lib2::Trait")
+assert-text: (".main-heading h1", "Trait lib2::Trait")
goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
// We first check that everything is visible.
assert-text: ("#toggle-all-docs", "[−]")
-assert-attribute: ("#implementations-list details.rustdoc-toggle", {"open": ""}, ALL)
-assert-attribute: ("#trait-implementations-list details.rustdoc-toggle", {"open": ""}, ALL)
+assert-attribute: ("#implementations-list details.toggle", {"open": ""}, ALL)
+assert-attribute: ("#trait-implementations-list details.toggle", {"open": ""}, ALL)
assert-attribute-false: (
- "#blanket-implementations-list > details.rustdoc-toggle",
+ "#blanket-implementations-list > details.toggle",
{"open": ""},
ALL,
)
click: "#toggle-all-docs"
wait-for-text: ("#toggle-all-docs", "[+]")
// We check that all <details> are collapsed (except for the impl block ones).
-assert-attribute-false: ("details.rustdoc-toggle:not(.implementors-toggle)", {"open": ""}, ALL)
+assert-attribute-false: ("details.toggle:not(.implementors-toggle)", {"open": ""}, ALL)
assert-attribute: ("#implementations-list > details.implementors-toggle", {"open": ""})
// We now check that the other impl blocks are collapsed.
assert-attribute-false: (
- "#blanket-implementations-list > details.rustdoc-toggle.implementors-toggle",
+ "#blanket-implementations-list > details.toggle.implementors-toggle",
{"open": ""},
ALL,
)
// We open them all again.
click: "#toggle-all-docs"
wait-for-text: ("#toggle-all-docs", "[−]")
-assert-attribute: ("details.rustdoc-toggle", {"open": ""}, ALL)
+assert-attribute: ("details.toggle", {"open": ""}, ALL)
// Checking the toggles style.
show-text: true
// We reload the page so the local storage settings are being used.
reload:
- assert-css: ("details.rustdoc-toggle > summary::before", {
+ assert-css: ("details.toggle > summary::before", {
"opacity": "0.5",
"filter": |filter|,
}, ALL)
- move-cursor-to: "details.rustdoc-toggle summary"
- assert-css: ("details.rustdoc-toggle > summary:hover::before", {
+ move-cursor-to: "details.toggle summary"
+ assert-css: ("details.toggle > summary:hover::before", {
"opacity": "1",
"filter": |filter|,
})
// has all the implementations toggled open by default, so users can
// find method names in those implementations with Ctrl-F.
goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
-assert-attribute: (".rustdoc-toggle.implementors-toggle", {"open": ""})
+assert-attribute: (".toggle.implementors-toggle", {"open": ""})
| ^^^
|
= note: error from rustc: unknown start of token: `
- = note: error from rustc: unknown start of token: `
- = note: error from rustc: unknown start of token: `
warning: could not parse code block as Rust code
--> $DIR/invalid-syntax.rs:64:5
#![crate_name = "foo"]
// @has foo/../index.html
-// @has - '//h1[@class="fqn"]' 'List of all crates'
+// @has - '//h1' 'List of all crates'
// @has - '//ul[@class="all-items"]//a[@href="foo/index.html"]' 'foo'
// @has - '//ul[@class="all-items"]//a[@href="all_item_types/index.html"]' 'all_item_types'
pub struct Foo;
// @!hasraw - '<span class="attr">#[outer]</span>'
// @hasraw - '#![inner]</span>'
// @!hasraw - '<span class="attr">#![inner]</span>'
-// @snapshot 'codeblock' - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]//pre/code'
+// @snapshot 'codeblock' - '//*[@class="toggle top-doc"]/*[@class="docblock"]//pre/code'
/// ```no_run
/// # # space
// @has foo/index.html '//div[@class="sidebar-elems"]//li/a' 'Keywords'
// @has foo/index.html '//div[@class="sidebar-elems"]//li/a/@href' '#keywords'
// @has foo/keyword.match.html '//a[@class="keyword"]' 'match'
-// @has foo/keyword.match.html '//h1[@class="fqn"]' 'Keyword match'
+// @has foo/keyword.match.html '//h1' 'Keyword match'
// @has foo/keyword.match.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
// @has foo/index.html '//a/@href' '../foo/index.html'
// @!has foo/foo/index.html
#![crate_name = "foo"]
// @has 'foo/fn.g.html'
-// @has - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]' \
+// @has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' \
// 'outer module inner module'
mod inner_mod {
#![crate_name = "foo"]
// @has 'foo/struct.S1.html'
-// @snapshot S1_top-doc - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]'
+// @snapshot S1_top-doc - '//details[@class="toggle top-doc"]/div[@class="docblock"]'
#[doc = "Hello world!\n\n"]
/// Goodbye!
pub struct S1;
// @has 'foo/struct.S2.html'
-// @snapshot S2_top-doc - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]'
+// @snapshot S2_top-doc - '//details[@class="toggle top-doc"]/div[@class="docblock"]'
/// Hello world!
///
pub struct S2;
// @has 'foo/struct.S3.html'
-// @snapshot S3_top-doc - '//details[@class="rustdoc-toggle top-doc"]/div[@class="docblock"]'
+// @snapshot S3_top-doc - '//details[@class="toggle top-doc"]/div[@class="docblock"]'
/** Par 1
*/ ///
/// Par 2
}
// @has 'foo/struct.Type.html'
-// @has - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]' 'foo 2 1'
+// @has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'foo 2 1'
/// foo
pub use b::Type;
// @has 'foo/struct.Whatever.html'
-// @has - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]' 'whatever 3 2 1'
+// @has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'whatever 3 2 1'
/// whatever
pub use c::Type as Whatever;
// @has 'foo/struct.Woof.html'
-// @has - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]' 'a dog 4 2 1'
+// @has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'a dog 4 2 1'
/// a dog
pub use c::Woof;
// @has - '//div[@class="sidebar-elems"]//li/a/@href' '#primitives'
// @has foo/primitive.reference.html
// @has - '//a[@class="primitive"]' 'reference'
-// @has - '//h1[@class="fqn"]' 'Primitive Type reference'
+// @has - '//h1' 'Primitive Type reference'
// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
// There should be only one implementation listed.
#![feature(rustdoc_internals)]
// @has foo/primitive.slice.html '//a[@class="primitive"]' 'slice'
-// @has - '//h1[@class="fqn"]' 'Primitive Type slice'
+// @has - '//h1' 'Primitive Type slice'
// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
// @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations'
// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Send for [T]where T: Send'
#![feature(rustdoc_internals)]
// @has foo/primitive.tuple.html '//a[@class="primitive"]' 'tuple'
-// @has - '//h1[@class="fqn"]' 'Primitive Type tuple'
+// @has - '//h1' 'Primitive Type tuple'
// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
// @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations'
// @has - '//div[@id="synthetic-implementations-list"]//h3' 'Send'
#![feature(rustdoc_internals)]
// @has foo/primitive.unit.html '//a[@class="primitive"]' 'unit'
-// @has - '//h1[@class="fqn"]' 'Primitive Type unit'
+// @has - '//h1' 'Primitive Type unit'
// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
// @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations'
// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Send for ()'
// @has foo/index.html '//div[@class="sidebar-elems"]//li/a' 'Primitive Types'
// @has foo/index.html '//div[@class="sidebar-elems"]//li/a/@href' '#primitives'
// @has foo/primitive.i32.html '//a[@class="primitive"]' 'i32'
-// @has foo/primitive.i32.html '//h1[@class="fqn"]' 'Primitive Type i32'
+// @has foo/primitive.i32.html '//h1' 'Primitive Type i32'
// @has foo/primitive.i32.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
// @has foo/index.html '//a/@href' '../foo/index.html'
// @!has foo/index.html '//span' '🔒'
// block doc comments can have their lines starting with a star.
// @has foo/fn.foo.html
-// @snapshot docblock - '//*[@class="rustdoc-toggle top-doc"]//*[@class="docblock"]'
+// @snapshot docblock - '//*[@class="toggle top-doc"]//*[@class="docblock"]'
/**
* a
*/
#![allow(unused)]
// @has 'toggle_item_contents/struct.PubStruct.html'
-// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 0
+// @count - '//details[@class="toggle type-contents-toggle"]' 0
pub struct PubStruct {
pub a: usize,
pub b: usize,
}
// @has 'toggle_item_contents/struct.BigPubStruct.html'
-// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 fields'
+// @count - '//details[@class="toggle type-contents-toggle"]' 1
+// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 13 fields'
pub struct BigPubStruct {
pub a: usize,
pub b: usize,
}
// @has 'toggle_item_contents/union.BigUnion.html'
-// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 fields'
+// @count - '//details[@class="toggle type-contents-toggle"]' 1
+// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 13 fields'
pub union BigUnion {
pub a: usize,
pub b: usize,
}
// @has 'toggle_item_contents/union.Union.html'
-// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 0
+// @count - '//details[@class="toggle type-contents-toggle"]' 0
pub union Union {
pub a: usize,
pub b: usize,
}
// @has 'toggle_item_contents/struct.PrivStruct.html'
-// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 0
+// @count - '//details[@class="toggle type-contents-toggle"]' 0
// @has - '//div[@class="item-decl"]' '/* private fields */'
pub struct PrivStruct {
a: usize,
}
// @has 'toggle_item_contents/enum.Enum.html'
-// @!has - '//details[@class="rustdoc-toggle type-contents-toggle"]' ''
+// @!has - '//details[@class="toggle type-contents-toggle"]' ''
pub enum Enum {
A, B, C,
D {
}
// @has 'toggle_item_contents/enum.EnumStructVariant.html'
-// @!has - '//details[@class="rustdoc-toggle type-contents-toggle"]' ''
+// @!has - '//details[@class="toggle type-contents-toggle"]' ''
pub enum EnumStructVariant {
A, B, C,
D {
}
// @has 'toggle_item_contents/enum.LargeEnum.html'
-// @count - '//*[@class="rust enum"]//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//*[@class="rust enum"]//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 13 variants'
+// @count - '//*[@class="rust enum"]//details[@class="toggle type-contents-toggle"]' 1
+// @has - '//*[@class="rust enum"]//details[@class="toggle type-contents-toggle"]' 'Show 13 variants'
pub enum LargeEnum {
A, B, C, D, E, F(u8), G, H, I, J, K, L, M
}
// @has 'toggle_item_contents/trait.Trait.html'
-// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 0
+// @count - '//details[@class="toggle type-contents-toggle"]' 0
pub trait Trait {
type A;
#[must_use]
}
// @has 'toggle_item_contents/trait.GinormousTrait.html'
-// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 16 associated items'
+// @count - '//details[@class="toggle type-contents-toggle"]' 1
+// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 16 associated items'
pub trait GinormousTrait {
type A;
type B;
}
// @has 'toggle_item_contents/trait.HugeTrait.html'
-// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 12 associated constants and 2 methods'
+// @count - '//details[@class="toggle type-contents-toggle"]' 1
+// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 12 associated constants and 2 methods'
pub trait HugeTrait {
type A;
const M: usize = 1;
}
// @has 'toggle_item_contents/trait.GiganticTrait.html'
-// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 1 associated constant and 1 method'
+// @count - '//details[@class="toggle type-contents-toggle"]' 1
+// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 1 associated constant and 1 method'
pub trait GiganticTrait {
type A;
type B;
}
// @has 'toggle_item_contents/trait.BigTrait.html'
-// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 1
-// @has - '//details[@class="rustdoc-toggle type-contents-toggle"]' 'Show 14 methods'
+// @count - '//details[@class="toggle type-contents-toggle"]' 1
+// @has - '//details[@class="toggle type-contents-toggle"]' 'Show 14 methods'
pub trait BigTrait {
type A;
#[must_use]
// summary. Struct methods with no documentation should not be wrapped.
//
// @has foo/struct.Foo.html
-// @has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()'
-// @has - '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented'
-// @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()'
+// @has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()'
+// @has - '//details[@class="toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented'
+// @!has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()'
pub struct Foo {
}
// summary. Trait methods with no documentation should not be wrapped.
//
// @has foo/trait.Foo.html
-// @has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'type Item'
-// @!has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'type Item2'
-// @has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()'
-// @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()'
-// @has - '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented'
-// @has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented_optional()'
-// @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented_optional()'
-// @has - '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented_optional is documented'
+// @has - '//details[@class="toggle"]//summary//h4[@class="code-header"]' 'type Item'
+// @!has - '//details[@class="toggle"]//summary//h4[@class="code-header"]' 'type Item2'
+// @has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()'
+// @!has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()'
+// @has - '//details[@class="toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented'
+// @has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented_optional()'
+// @!has - '//details[@class="toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented_optional()'
+// @has - '//details[@class="toggle method-toggle"]//*[@class="docblock"]' 'is_documented_optional is documented'
pub trait Foo {
/// is documented
type Item;
LL | type Assoc = T;
| ^ the trait `Copy` is not implemented for `T`
|
+note: required for `<T as Complete>::Assoc` to implement `Partial<T>`
+ --> $DIR/issue-43784-associated-type.rs:1:11
+ |
+LL | pub trait Partial<X: ?Sized>: Copy {
+ | ^^^^^^^
note: required by a bound in `Complete::Assoc`
--> $DIR/issue-43784-associated-type.rs:5:17
|
| |
| arguments to this struct are incorrect
|
+help: the type constructed contains `()` due to the type of the argument passed
+ --> $DIR/issue-84128.rs:13:9
+ |
+LL | Foo(())
+ | ^^^^--^
+ | |
+ | this argument influences the type of `Foo`
note: tuple struct defined here
--> $DIR/issue-84128.rs:5:8
|
| |
| arguments to this enum variant are incorrect
|
+help: the type constructed contains `()` due to the type of the argument passed
+ --> $DIR/issue-87461.rs:10:5
+ |
+LL | Ok(())
+ | ^^^--^
+ | |
+ | this argument influences the type of `Ok`
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
| |
| arguments to this enum variant are incorrect
|
+help: the type constructed contains `()` due to the type of the argument passed
+ --> $DIR/issue-87461.rs:17:5
+ |
+LL | Ok(())
+ | ^^^--^
+ | |
+ | this argument influences the type of `Ok`
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
| |
| arguments to this enum variant are incorrect
|
+help: the type constructed contains `()` due to the type of the argument passed
+ --> $DIR/issue-87461.rs:26:9
+ |
+LL | Ok(())
+ | ^^^--^
+ | |
+ | this argument influences the type of `Ok`
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
| |
| doesn't satisfy `Value: Eq`
| doesn't satisfy `Value: Hash`
+ | doesn't satisfy `Value: PartialEq`
...
LL | hs.insert(Value(0));
| ^^^^^^
|
= note: the following trait bounds were not satisfied:
`Value: Eq`
+ `Value: PartialEq`
+ which is required by `Value: Eq`
`Value: Hash`
help: consider annotating `Value` with `#[derive(Eq, Hash, PartialEq)]`
|
--> $DIR/issue-91550.rs:26:9
|
LL | pub struct NoDerives;
- | -------------------- doesn't satisfy `NoDerives: Eq`
+ | --------------------
+ | |
+ | doesn't satisfy `NoDerives: Eq`
+ | doesn't satisfy `NoDerives: PartialEq`
LL |
LL | struct Object<T>(T);
| ---------------- method `use_eq` not found for this struct
| ^^ ---------
| |
| unsatisfied trait bound introduced here
+ = note: the following trait bounds were not satisfied:
+ `NoDerives: PartialEq`
+ which is required by `NoDerives: Eq`
help: consider annotating `NoDerives` with `#[derive(Eq, PartialEq)]`
|
LL | #[derive(Eq, PartialEq)]
--> $DIR/issue-91550.rs:27:9
|
LL | pub struct NoDerives;
- | -------------------- doesn't satisfy `NoDerives: Ord`
+ | --------------------
+ | |
+ | doesn't satisfy `NoDerives: Eq`
+ | doesn't satisfy `NoDerives: Ord`
+ | doesn't satisfy `NoDerives: PartialEq`
+ | doesn't satisfy `NoDerives: PartialOrd`
LL |
LL | struct Object<T>(T);
| ---------------- method `use_ord` not found for this struct
| ^^^ ---------
| |
| unsatisfied trait bound introduced here
+ = note: the following trait bounds were not satisfied:
+ `NoDerives: PartialOrd`
+ which is required by `NoDerives: Ord`
+ `NoDerives: PartialEq`
+ which is required by `NoDerives: Ord`
+ `NoDerives: Eq`
+ which is required by `NoDerives: Ord`
help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]`
|
LL | #[derive(Eq, Ord, PartialEq, PartialOrd)]
LL | pub struct NoDerives;
| --------------------
| |
+ | doesn't satisfy `NoDerives: Eq`
| doesn't satisfy `NoDerives: Ord`
+ | doesn't satisfy `NoDerives: PartialEq`
| doesn't satisfy `NoDerives: PartialOrd`
LL |
LL | struct Object<T>(T);
| | |
| | unsatisfied trait bound introduced here
| unsatisfied trait bound introduced here
+ = note: the following trait bounds were not satisfied:
+ `NoDerives: PartialEq`
+ which is required by `NoDerives: Ord`
+ `NoDerives: Eq`
+ which is required by `NoDerives: Ord`
+ `NoDerives: PartialEq`
+ which is required by `NoDerives: PartialOrd`
help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]`
|
LL | #[derive(Eq, Ord, PartialEq, PartialOrd)]
| ^^^^^^ the trait `Clone` is not implemented for `T`
|
= note: required for `Box<T>` to implement `Clone`
+ = note: required for `<Self as UnsafeCopy>::Copy<T>` to implement `Copy`
note: required by a bound in `UnsafeCopy::Copy`
--> $DIR/issue-74824.rs:6:19
|
|
= note: expected type parameter `B`
found associated type `<B as Add>::Output`
+help: the type constructed contains `<B as Add>::Output` due to the type of the argument passed
+ --> $DIR/missing-bounds.rs:11:9
+ |
+LL | A(self.0 + rhs.0)
+ | ^^--------------^
+ | |
+ | this argument influences the type of `A`
note: tuple struct defined here
--> $DIR/missing-bounds.rs:5:8
|
|
= note: expected type parameter `bool` (type parameter `bool`)
found type `bool` (`bool`)
+help: the type constructed contains `bool` due to the type of the argument passed
+ --> $DIR/issue-35030.rs:9:9
+ |
+LL | Some(true)
+ | ^^^^^----^
+ | |
+ | this argument influences the type of `Some`
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
|
= note: the following trait bounds were not satisfied:
`T: Eq`
+ `T: PartialEq`
+ which is required by `T: Eq`
`T: Hash`
help: consider restricting the type parameters to satisfy the trait bounds
|
let y = 0;
//~^ ERROR unknown start of token: \u{37e}
//~^^ HELP Unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), but it is not
+ let x = 0;
+ //~^ ERROR unknown start of token: \u{a0}
+ //~^^ NOTE character appears 3 more times
+ //~^^^ HELP Unicode character ' ' (No-Break Space) looks like ' ' (Space), but it is not
}
LL | let y = 0;
| ~
-error: aborting due to previous error
+error: unknown start of token: \u{a0}
+ --> $DIR/unicode-chars.rs:5:5
+ |
+LL | let x = 0;
+ | ^^^^
+ |
+ = note: character appears 3 more times
+help: Unicode character ' ' (No-Break Space) looks like ' ' (Space), but it is not
+ |
+LL | let x = 0;
+ | ++++
+
+error: aborting due to 2 previous errors
--- /dev/null
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: aborting due to 8 previous errors
+
+Future incompatibility report: Future breakage diagnostic:
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
--- /dev/null
+PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, }
+PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "enum",
+ span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:1: 4:5 (#0),
+ },
+ Ident {
+ ident: "ProceduralMasqueradeDummyType",
+ span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6: 4:35 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "Input",
+ span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:13:5: 13:10 (#0),
+ },
+ ],
+ span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:36: 14:2 (#0),
+ },
+]
+PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, }
+PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "enum",
+ span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:1: 4:5 (#0),
+ },
+ Ident {
+ ident: "ProceduralMasqueradeDummyType",
+ span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6: 4:35 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "Input",
+ span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:13:5: 13:10 (#0),
+ },
+ ],
+ span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:36: 14:2 (#0),
+ },
+]
--- /dev/null
+error: using an old version of `rental`
+ --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+error: using an old version of `rental`
+ --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: using an old version of `rental`
+ --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: using an old version of `rental`
+ --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: using an old version of `rental`
+ --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: using an old version of `rental`
+ --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: using an old version of `rental`
+ --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: using an old version of `rental`
+ --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: aborting due to 8 previous errors
+
+Future incompatibility report: Future breakage diagnostic:
+error: using an old version of `rental`
+ --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
--- /dev/null
+PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, }
+PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "enum",
+ span: remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:1: 4:5 (#0),
+ },
+ Ident {
+ ident: "ProceduralMasqueradeDummyType",
+ span: remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6: 4:35 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "Input",
+ span: remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:13:5: 13:10 (#0),
+ },
+ ],
+ span: remapped/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:36: 14:2 (#0),
+ },
+]
+PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, }
+PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "enum",
+ span: remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:1: 4:5 (#0),
+ },
+ Ident {
+ ident: "ProceduralMasqueradeDummyType",
+ span: remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6: 4:35 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "Input",
+ span: remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:13:5: 13:10 (#0),
+ },
+ ],
+ span: remapped/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs:4:36: 14:2 (#0),
+ },
+]
// aux-build:test-macros.rs
// compile-flags: -Z span-debug
+// revisions: local remapped
+// [remapped]compile-flags: --remap-path-prefix={{src-base}}=remapped
+
+// The remapped paths are not normalized by compiletest.
+// normalize-stdout-test: "\\(proc-macro|pretty-print-hack)" -> "/$1"
+// normalize-stderr-test: "\\(proc-macro|pretty-print-hack)" -> "/$1"
#![no_std] // Don't load unnecessary hygiene information from std
extern crate std;
+++ /dev/null
-error: using an old version of `rental`
- --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
- = note: `#[deny(proc_macro_back_compat)]` on by default
-
-error: using an old version of `rental`
- --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-
-error: using an old version of `rental`
- --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-
-error: using an old version of `rental`
- --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-
-error: using an old version of `rental`
- --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-
-error: using an old version of `rental`
- --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-
-error: using an old version of `rental`
- --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-
-error: using an old version of `rental`
- --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
-
-error: aborting due to 8 previous errors
-
-Future incompatibility report: Future breakage diagnostic:
-error: using an old version of `rental`
- --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
- = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
- --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
- = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
- --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
- = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
- --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
- = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
- --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
- = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
- --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
- = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
- --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
- = note: `#[deny(proc_macro_back_compat)]` on by default
-
-Future breakage diagnostic:
-error: using an old version of `rental`
- --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
- = note: `#[deny(proc_macro_back_compat)]` on by default
-
+++ /dev/null
-PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, }
-PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input }
-PRINT-DERIVE INPUT (DEBUG): TokenStream [
- Ident {
- ident: "enum",
- span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:1: 4:5 (#0),
- },
- Ident {
- ident: "ProceduralMasqueradeDummyType",
- span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6: 4:35 (#0),
- },
- Group {
- delimiter: Brace,
- stream: TokenStream [
- Ident {
- ident: "Input",
- span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:13:5: 13:10 (#0),
- },
- ],
- span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:36: 14:2 (#0),
- },
-]
-PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, }
-PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input }
-PRINT-DERIVE INPUT (DEBUG): TokenStream [
- Ident {
- ident: "enum",
- span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:1: 4:5 (#0),
- },
- Ident {
- ident: "ProceduralMasqueradeDummyType",
- span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6: 4:35 (#0),
- },
- Group {
- delimiter: Brace,
- stream: TokenStream [
- Ident {
- ident: "Input",
- span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:13:5: 13:10 (#0),
- },
- ],
- span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:36: 14:2 (#0),
- },
-]
| ^
= note: expected tuple `(i32, bool)`
found type `{integer}`
+help: the type constructed contains `{integer}` due to the type of the argument passed
+ --> $DIR/args-instead-of-tuple-errors.rs:6:34
+ |
+LL | let _: Option<(i32, bool)> = Some(1, 2);
+ | ^^^^^-^^^^
+ | |
+ | this argument influences the type of `Some`
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
help: remove the extra argument
|
= note: expected tuple `(i32,)`
found type `usize`
+help: the type constructed contains `usize` due to the type of the argument passed
+ --> $DIR/args-instead-of-tuple-errors.rs:14:29
+ |
+LL | let _: Option<(i32,)> = Some(5_usize);
+ | ^^^^^-------^
+ | |
+ | this argument influences the type of `Some`
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
|
= note: expected tuple `(i32,)`
found type `usize`
+help: the type constructed contains `usize` due to the type of the argument passed
+ --> $DIR/args-instead-of-tuple-errors.rs:17:29
+ |
+LL | let _: Option<(i32,)> = Some((5_usize));
+ | ^^^^^---------^
+ | |
+ | this argument influences the type of `Some`
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
|
= note: expected reference `&str`
found closure `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]`
+help: the return type of this call is `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]` due to the type of the argument passed
+ --> $DIR/sugg-else-for-closure.rs:6:14
+ |
+LL | let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap());
+ | ^^^^^^^^^^^^-------------------------------^
+ | |
+ | this argument influences the return type of `unwrap_or`
note: associated function defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
help: try calling `unwrap_or_else` instead
--- /dev/null
+// There are two different instances to check that even if
+// the trait is implemented for the output of a function,
+// it will still be displayed if the function itself implements a trait.
+trait Foo {}
+
+impl Foo for fn() -> bool {}
+impl Foo for bool {}
+
+fn example() -> bool {
+ true
+}
+
+trait NoOtherFoo {}
+
+impl NoOtherFoo for fn() -> bool {}
+
+fn do_on_foo(v: impl Foo) {}
+fn do_on_single_foo(v: impl NoOtherFoo) {}
+
+fn main() {
+ do_on_foo(example);
+ //~^ ERROR the trait bound
+
+ do_on_single_foo(example);
+ //~^ ERROR the trait bound
+}
--- /dev/null
+error[E0277]: the trait bound `fn() -> bool {example}: Foo` is not satisfied
+ --> $DIR/fn-trait-cast-diagnostic.rs:21:15
+ |
+LL | do_on_foo(example);
+ | --------- ^^^^^^^ the trait `Foo` is not implemented for fn item `fn() -> bool {example}`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `do_on_foo`
+ --> $DIR/fn-trait-cast-diagnostic.rs:17:22
+ |
+LL | fn do_on_foo(v: impl Foo) {}
+ | ^^^ required by this bound in `do_on_foo`
+help: use parentheses to call this function
+ |
+LL | do_on_foo(example());
+ | ++
+help: the trait `Foo` is implemented for fn pointer `fn() -> bool`, try casting using `as`
+ |
+LL | do_on_foo(example as fn() -> bool);
+ | +++++++++++++++
+
+error[E0277]: the trait bound `fn() -> bool {example}: NoOtherFoo` is not satisfied
+ --> $DIR/fn-trait-cast-diagnostic.rs:24:22
+ |
+LL | do_on_single_foo(example);
+ | ---------------- ^^^^^^^ the trait `NoOtherFoo` is not implemented for fn item `fn() -> bool {example}`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `do_on_single_foo`
+ --> $DIR/fn-trait-cast-diagnostic.rs:18:29
+ |
+LL | fn do_on_single_foo(v: impl NoOtherFoo) {}
+ | ^^^^^^^^^^ required by this bound in `do_on_single_foo`
+help: the trait `NoOtherFoo` is implemented for fn pointer `fn() -> bool`, try casting using `as`
+ |
+LL | do_on_single_foo(example as fn() -> bool);
+ | +++++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
LL | impl<T> Complete for T {}
| ^ the trait `Copy` is not implemented for `T`
|
+note: required for `T` to implement `Partial`
+ --> $DIR/issue-43784-supertrait.rs:1:11
+ |
+LL | pub trait Partial: Copy {
+ | ^^^^^^^
note: required by a bound in `Complete`
--> $DIR/issue-43784-supertrait.rs:4:21
|
|
= note: expected type parameter `F`
found struct `Class<P>`
+help: the return type of this call is `Class<P>` due to the type of the argument passed
+ --> $DIR/issue-52893.rs:53:9
+ |
+LL | builder.push(output);
+ | ^^^^^^^^^^^^^------^
+ | |
+ | this argument influences the return type of `push`
note: associated function defined here
--> $DIR/issue-52893.rs:11:8
|
| |
| required by a bound introduced by this call
|
- = help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`
note: required by a bound in `takes`
--> $DIR/issue-99875.rs:9:18
|
LL | fn takes(_: impl Trait) {}
| ^^^^^ required by this bound in `takes`
+help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`, try casting using `as`
+ |
+LL | takes(function as fn(Argument) -> Return);
+ | +++++++++++++++++++++++++
error[E0277]: the trait bound `[closure@$DIR/issue-99875.rs:14:11: 14:34]: Trait` is not satisfied
--> $DIR/issue-99875.rs:14:11
--- /dev/null
+// These are simplifications of the tower traits by the same name:
+
+pub trait Service<Request> {
+ type Response;
+}
+
+pub trait Layer<C> {
+ type Service;
+}
+
+// Any type will do here:
+
+pub struct Req;
+pub struct Res;
+
+// This is encoding a trait alias.
+
+pub trait ParticularService:
+ Service<Req, Response = Res> {
+}
+
+impl<T> ParticularService for T
+where
+ T: Service<Req, Response = Res>,
+{
+}
+
+// This is also a trait alias.
+// The weird = <Self as ...> bound is there so that users of the trait do not
+// need to repeat the bounds. See https://github.com/rust-lang/rust/issues/20671
+// for context, and in particular the workaround in:
+// https://github.com/rust-lang/rust/issues/20671#issuecomment-529752828
+
+pub trait ParticularServiceLayer<C>:
+ Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service>
+{
+ type Service: ParticularService;
+}
+
+impl<T, C> ParticularServiceLayer<C> for T
+where
+ T: Layer<C>,
+ T::Service: ParticularService,
+{
+ type Service = T::Service;
+}
+
+// These are types that implement the traits that the trait aliases refer to.
+// They should also implement the alias traits due to the blanket impls.
+
+struct ALayer<C>(C);
+impl<C> Layer<C> for ALayer<C> {
+ type Service = AService;
+}
+
+struct AService;
+impl Service<Req> for AService {
+ // However, AService does _not_ meet the blanket implementation,
+ // since its Response type is bool, not Res as it should be.
+ type Response = bool;
+}
+
+// This is a wrapper type around ALayer that uses the trait alias
+// as a way to communicate the requirements of the provided types.
+struct Client<C>(C);
+
+// The method and the free-standing function below both have the same bounds.
+
+impl<C> Client<C>
+where
+ ALayer<C>: ParticularServiceLayer<C>,
+{
+ fn check(&self) {}
+}
+
+fn check<C>(_: C) where ALayer<C>: ParticularServiceLayer<C> {}
+
+// But, they give very different error messages.
+
+fn main() {
+ // This gives a very poor error message that does nothing to point the user
+ // at the underlying cause of why the types involved do not meet the bounds.
+ Client(()).check(); //~ ERROR E0599
+
+ // This gives a good(ish) error message that points the user at _why_ the
+ // bound isn't met, and thus how they might fix it.
+ check(()); //~ ERROR E0271
+}
--- /dev/null
+error[E0599]: the method `check` exists for struct `Client<()>`, but its trait bounds were not satisfied
+ --> $DIR/track-obligations.rs:83:16
+ |
+LL | struct ALayer<C>(C);
+ | ----------------
+ | |
+ | doesn't satisfy `<_ as Layer<()>>::Service = <ALayer<()> as ParticularServiceLayer<()>>::Service`
+ | doesn't satisfy `ALayer<()>: ParticularServiceLayer<()>`
+...
+LL | struct Client<C>(C);
+ | ---------------- method `check` not found for this struct
+...
+LL | Client(()).check();
+ | ^^^^^ method cannot be called on `Client<()>` due to unsatisfied trait bounds
+ |
+note: trait bound `<ALayer<()> as Layer<()>>::Service = <ALayer<()> as ParticularServiceLayer<()>>::Service` was not satisfied
+ --> $DIR/track-obligations.rs:35:14
+ |
+LL | pub trait ParticularServiceLayer<C>:
+ | ----------------------
+LL | Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
+note: trait bound `ALayer<()>: ParticularServiceLayer<()>` was not satisfied
+ --> $DIR/track-obligations.rs:71:16
+ |
+LL | impl<C> Client<C>
+ | ---------
+LL | where
+LL | ALayer<C>: ParticularServiceLayer<C>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
+note: the trait `ParticularServiceLayer` must be implemented
+ --> $DIR/track-obligations.rs:34:1
+ |
+LL | / pub trait ParticularServiceLayer<C>:
+LL | | Layer<C, Service = <Self as ParticularServiceLayer<C>>::Service>
+ | |____________________________________________________________________^
+
+error[E0271]: type mismatch resolving `<AService as Service<Req>>::Response == Res`
+ --> $DIR/track-obligations.rs:87:11
+ |
+LL | check(());
+ | ----- ^^ type mismatch resolving `<AService as Service<Req>>::Response == Res`
+ | |
+ | required by a bound introduced by this call
+ |
+note: expected this to be `Res`
+ --> $DIR/track-obligations.rs:60:21
+ |
+LL | type Response = bool;
+ | ^^^^
+note: required for `AService` to implement `ParticularService`
+ --> $DIR/track-obligations.rs:22:9
+ |
+LL | impl<T> ParticularService for T
+ | ^^^^^^^^^^^^^^^^^ ^
+LL | where
+LL | T: Service<Req, Response = Res>,
+ | -------------- unsatisfied trait bound introduced here
+note: required for `ALayer<_>` to implement `ParticularServiceLayer<_>`
+ --> $DIR/track-obligations.rs:40:12
+ |
+LL | impl<T, C> ParticularServiceLayer<C> for T
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ ^
+...
+LL | T::Service: ParticularService,
+ | ----------------- unsatisfied trait bound introduced here
+note: required by a bound in `check`
+ --> $DIR/track-obligations.rs:76:36
+ |
+LL | fn check<C>(_: C) where ALayer<C>: ParticularServiceLayer<C> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0271, E0599.
+For more information about an error, try `rustc --explain E0271`.
--- /dev/null
+fn function<T>(x: T, y: bool) -> T {
+ x
+}
+
+struct S {}
+impl S {
+ fn method<T>(&self, x: T) -> T {
+ x
+ }
+}
+
+fn wrong_arg_type(x: u32) -> u32 {
+ x
+}
+
+fn main() {
+ // Should not trigger.
+ let x = wrong_arg_type(0u16); //~ ERROR mismatched types
+ let x: u16 = function(0, 0u8); //~ ERROR mismatched types
+
+ // Should trigger exactly once for the first argument.
+ let x: u16 = function(0u32, 0u8); //~ ERROR arguments to this function are incorrect
+
+ // Should trigger.
+ let x: u16 = function(0u32, true); //~ ERROR mismatched types
+ let x: u16 = (S {}).method(0u32); //~ ERROR mismatched types
+ function(0u32, 8u8) //~ ERROR arguments to this function are incorrect
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:18:28
+ |
+LL | let x = wrong_arg_type(0u16);
+ | -------------- ^^^^ expected `u32`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:12:4
+ |
+LL | fn wrong_arg_type(x: u32) -> u32 {
+ | ^^^^^^^^^^^^^^ ------
+help: change the type of the numeric literal from `u16` to `u32`
+ |
+LL | let x = wrong_arg_type(0u32);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:19:30
+ |
+LL | let x: u16 = function(0, 0u8);
+ | -------- ^^^ expected `bool`, found `u8`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4
+ |
+LL | fn function<T>(x: T, y: bool) -> T {
+ | ^^^^^^^^ -------
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:22:18
+ |
+LL | let x: u16 = function(0u32, 0u8);
+ | ^^^^^^^^ ---- --- expected `bool`, found `u8`
+ | |
+ | expected `u16`, found `u32`
+ |
+help: the return type of this call is `u32` due to the type of the argument passed
+ --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:22:18
+ |
+LL | let x: u16 = function(0u32, 0u8);
+ | ^^^^^^^^^----^^^^^^
+ | |
+ | this argument influences the return type of `function`
+note: function defined here
+ --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4
+ |
+LL | fn function<T>(x: T, y: bool) -> T {
+ | ^^^^^^^^ ---- -------
+help: change the type of the numeric literal from `u32` to `u16`
+ |
+LL | let x: u16 = function(0u16, 0u8);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:25:27
+ |
+LL | let x: u16 = function(0u32, true);
+ | -------- ^^^^ expected `u16`, found `u32`
+ | |
+ | arguments to this function are incorrect
+ |
+help: the return type of this call is `u32` due to the type of the argument passed
+ --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:25:18
+ |
+LL | let x: u16 = function(0u32, true);
+ | ^^^^^^^^^----^^^^^^^
+ | |
+ | this argument influences the return type of `function`
+note: function defined here
+ --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4
+ |
+LL | fn function<T>(x: T, y: bool) -> T {
+ | ^^^^^^^^ ----
+help: change the type of the numeric literal from `u32` to `u16`
+ |
+LL | let x: u16 = function(0u16, true);
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:26:32
+ |
+LL | let x: u16 = (S {}).method(0u32);
+ | ------ ^^^^ expected `u16`, found `u32`
+ | |
+ | arguments to this method are incorrect
+ |
+help: the return type of this call is `u32` due to the type of the argument passed
+ --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:26:18
+ |
+LL | let x: u16 = (S {}).method(0u32);
+ | ^^^^^^^^^^^^^^----^
+ | |
+ | this argument influences the return type of `method`
+note: associated function defined here
+ --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:7:8
+ |
+LL | fn method<T>(&self, x: T) -> T {
+ | ^^^^^^ ----
+help: change the type of the numeric literal from `u32` to `u16`
+ |
+LL | let x: u16 = (S {}).method(0u16);
+ | ~~~
+
+error[E0308]: arguments to this function are incorrect
+ --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:27:5
+ |
+LL | function(0u32, 8u8)
+ | ^^^^^^^^ ---- --- expected `bool`, found `u8`
+ | |
+ | expected `()`, found `u32`
+ |
+help: the return type of this call is `u32` due to the type of the argument passed
+ --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:27:5
+ |
+LL | function(0u32, 8u8)
+ | ^^^^^^^^^----^^^^^^
+ | |
+ | this argument influences the return type of `function`
+note: function defined here
+ --> $DIR/wrong-call-return-type-due-to-generic-arg.rs:1:4
+ |
+LL | fn function<T>(x: T, y: bool) -> T {
+ | ^^^^^^^^ ---- -------
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
|
= note: expected enum `Option<()>`
found unit type `()`
+help: the type constructed contains `()` due to the type of the argument passed
+ --> $DIR/issue-46112.rs:9:18
+ |
+LL | fn main() { test(Ok(())); }
+ | ^^^--^
+ | |
+ | this argument influences the type of `Ok`
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
help: try wrapping the expression in `Some`
|
= note: expected tuple `(&mut u8,)`
found type `{integer}`
+help: the return type of this call is `{integer}` due to the type of the argument passed
+ --> $DIR/issue-84768.rs:7:5
+ |
+LL | <F as FnOnce(&mut u8)>::call_once(f, 1)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^
+ | |
+ | this argument influences the return type of `FnOnce`
note: associated function defined here
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
| |
| arguments to this function are incorrect
|
+help: the return type of this call is `u32` due to the type of the argument passed
+ --> $DIR/ufcs-qpath-self-mismatch.rs:7:5
+ |
+LL | <i32 as Add<i32>>::add(1u32, 2);
+ | ^^^^^^^^^^^^^^^^^^^^^^^----^^^^
+ | |
+ | this argument influences the return type of `Add`
note: associated function defined here
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
help: change the type of the numeric literal from `u32` to `i32`
| |
| arguments to this function are incorrect
|
+help: the return type of this call is `u32` due to the type of the argument passed
+ --> $DIR/ufcs-qpath-self-mismatch.rs:9:5
+ |
+LL | <i32 as Add<i32>>::add(1, 2u32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^----^
+ | |
+ | this argument influences the return type of `Add`
note: associated function defined here
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
help: change the type of the numeric literal from `u32` to `i32`
[autolabel."WG-trait-system-refactor"]
trigger_files = [
- "compiler/rustc_trait_selection/solve"
+ "compiler/rustc_trait_selection/src/solve"
]
[notify-zulip."I-prioritize"]